[Ocfs2-tools-devel] [PATCH 05/23] libocfs2: Fill out the ocfs2_XXX_to_YYY() conversion APIs.

Joel Becker joel.becker at oracle.com
Mon Aug 11 17:31:57 PDT 2008


ocfs2 often needs to convert sizes from clusters to blocks to bytes.  We
only provided a few of these functions in ocfs2.h.  This adds the
complete set:

ocfs2_clusters_to_blocks()
ocfs2_blocks_to_clusters()
ocfs2_clusters_to_bytes()
ocfs2_bytes_to_clusters()
ocfs2_blocks_to_bytes()
ocfs2_bytes_to_blocks()
ocfs2_clusters_in_blocks()
ocfs2_clusters_in_bytes()
ocfs2_blocks_in_bytes()

The container functions (ocfs2_XXX_in_YYY()) only go one direction; the
other direction is answered correctly by ocfs2_YYY_to_XXX().

While we're here, we standardize the handling of value overflows.  Some
of the existing functions would cast an uint64_t to uint32_t without
checking.  The caller just gets the lower 32bits, regardless of how they
wrapped.  All functions now return UINTxx_MAX on overflow.  This is not
a value that can be checked - UINTxx_MAX could have been the exact
answer - but it is a safer return than the lower 32bits.  Users of this
function should prevent overflow by checking bounds before calling the
conversion.

Signed-off-by: Joel Becker <joel.becker at oracle.com>
---
 include/ocfs2/ocfs2.h |   86 +++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 79 insertions(+), 7 deletions(-)

diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index d69223e..fbc3146 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -676,6 +676,11 @@ errcode_t ocfs2_set_backup_super(ocfs2_filesys *fs,
  *
  * ${foo}_in_${bar} is a ceiling function.  clusters_in_blocks will give
  * the number of clusters needed to hold a given number of blocks.
+ *
+ * These functions return UINTxx_MAX when they overflow, but UINTxx_MAX
+ * cannot be used to check overflow.  UINTxx_MAX is a valid value in much
+ * of ocfs2.  The caller is responsible for preventing overflow before
+ * using these functions.
  */
 
 static inline uint64_t ocfs2_clusters_to_blocks(ocfs2_filesys *fs,
@@ -694,18 +699,54 @@ static inline uint32_t ocfs2_blocks_to_clusters(ocfs2_filesys *fs,
 	int b_to_c_bits =
 		OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits -
 		OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits;
+	uint64_t ret = blocks >> b_to_c_bits;
+
+	if (ret > UINT32_MAX)
+		ret = UINT32_MAX;
 
-	return (uint32_t)(blocks >> b_to_c_bits);
+	return (uint32_t)ret;
 }
 
-static inline uint64_t ocfs2_blocks_in_bytes(ocfs2_filesys *fs, uint64_t bytes)
+static inline uint64_t ocfs2_clusters_to_bytes(ocfs2_filesys *fs,
+					       uint32_t clusters)
 {
-	uint64_t ret = bytes + fs->fs_blocksize - 1;
+	uint64_t ret = clusters;
 
-	if (ret < bytes) /* deal with wrapping */
-		return UINT64_MAX;
+	ret = ret << OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits;
+	if (ret < clusters)
+		ret = UINT64_MAX;
 
-	return ret >> OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits;
+	return ret;
+}
+
+static inline uint32_t ocfs2_bytes_to_clusters(ocfs2_filesys *fs,
+					       uint64_t bytes)
+{
+	uint64_t ret =
+		bytes >> OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits;
+
+	if (ret > UINT32_MAX)
+		ret = UINT32_MAX;
+
+	return (uint32_t)ret;
+}
+
+static inline uint64_t ocfs2_blocks_to_bytes(ocfs2_filesys *fs,
+					     uint64_t blocks)
+{
+	uint64_t ret =
+		blocks << OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits;
+
+	if (ret < blocks)
+		ret = UINT64_MAX;
+
+	return ret;
+}
+
+static inline uint64_t ocfs2_bytes_to_blocks(ocfs2_filesys *fs,
+					     uint64_t bytes)
+{
+	return bytes >> OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits;
 }
 
 static inline uint32_t ocfs2_clusters_in_blocks(ocfs2_filesys *fs, 
@@ -718,9 +759,40 @@ static inline uint32_t ocfs2_clusters_in_blocks(ocfs2_filesys *fs,
 	if (ret < blocks) /* deal with wrapping */
 		ret = UINT64_MAX;
 
-	return (uint32_t)(ret >> c_to_b_bits);
+	ret = ret >> c_to_b_bits;
+	if (ret > UINT32_MAX)
+		ret = UINT32_MAX;
+
+	return (uint32_t)ret;
+}
+
+static inline uint32_t ocfs2_clusters_in_bytes(ocfs2_filesys *fs,
+					       uint64_t bytes)
+{
+	uint64_t ret = bytes + fs->fs_clustersize - 1;
+
+	if (ret < bytes) /* deal with wrapping */
+		ret = UINT64_MAX;
+
+	ret = ret >> OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits;
+	if (ret > UINT32_MAX)
+		ret = UINT32_MAX;
+
+	return (uint32_t)ret;
 }
 
+static inline uint64_t ocfs2_blocks_in_bytes(ocfs2_filesys *fs,
+					     uint64_t bytes)
+{
+	uint64_t ret = bytes + fs->fs_blocksize - 1;
+
+	if (ret < bytes) /* deal with wrapping */
+		return UINT64_MAX;
+
+	return ret >> OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits;
+}
+
+
 /* given a cluster offset, calculate which block group it belongs to
  * and return that block offset. */
 static inline uint64_t ocfs2_which_cluster_group(ocfs2_filesys *fs,
-- 
1.5.6.3




More information about the Ocfs2-tools-devel mailing list