ocfs2: fix leaf start calculation in ocfs2_dx_dir_rebalance()
authorMark Fasheh <mfasheh@suse.com>
Thu, 19 Feb 2009 21:17:05 +0000 (13:17 -0800)
committerMark Fasheh <mfasheh@suse.com>
Fri, 3 Apr 2009 18:39:17 +0000 (11:39 -0700)
ocfs2_dx_dir_rebalance() is passed the block offset of a dx leaf which needs
rebalancing. Since we rebalance an entire cluster at a time however, this
function needs to calculate the beginning of that cluster, in blocks. The
calculation was wrong, which would result in a read of non-leaf blocks. Fix
the calculation by adding ocfs2_block_to_cluster_start() which is a more
straight-forward way of determining this.

Reported-by: Tristan Ye <tristan.ye@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
fs/ocfs2/dir.c
fs/ocfs2/ocfs2.h

index 5e6aeb00cb43fa86ee483d5deb806427013263af..e71160cda1100a1d5b9c840fbbbe784058a682fe 100644 (file)
@@ -3941,8 +3941,7 @@ static int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir,
                goto out_commit;
        }
 
-       orig_leaves_start = leaf_blkno & ~(osb->s_clustersize_bits -
-                                     osb->sb->s_blocksize_bits);
+       orig_leaves_start = ocfs2_block_to_cluster_start(dir->i_sb, leaf_blkno);
        ret = ocfs2_read_dx_leaves(dir, orig_leaves_start, num_dx_leaves,
                                   orig_dx_leaves);
        if (ret) {
index fa3c6d3f0bd2d5a52fb41b1da91226fa1ecdc48b..e1844d5736c4f3d5ef423a305535cfbe8320db8a 100644 (file)
@@ -582,6 +582,16 @@ static inline u64 ocfs2_clusters_to_bytes(struct super_block *sb,
        return (u64)clusters << OCFS2_SB(sb)->s_clustersize_bits;
 }
 
+static inline u64 ocfs2_block_to_cluster_start(struct super_block *sb,
+                                              u64 blocks)
+{
+       int bits = OCFS2_SB(sb)->s_clustersize_bits - sb->s_blocksize_bits;
+       unsigned int clusters;
+
+       clusters = ocfs2_blocks_to_clusters(sb, blocks);
+       return (u64)clusters << bits;
+}
+
 static inline u64 ocfs2_align_bytes_to_clusters(struct super_block *sb,
                                                u64 bytes)
 {