Skip to content

Commit

Permalink
nilfs2: fix incorrect block address termination in node concatenation
Browse files Browse the repository at this point in the history
nilfs_btree_delete function wrongly terminates virtual block address
of the btree node held by its parent at index 0.  When concatenating
the index-0 node with its right sibling node, nilfs_btree_delete
terminates the block address of index-0 node instead of the right
sibling node which should be deleted.

This bug not only wears disk space in the long run, but also causes
file system corruption.  This will fix it.

Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
  • Loading branch information
Ryusuke Konishi committed Jun 11, 2011
1 parent 59c5f46 commit fe744fd
Showing 1 changed file with 13 additions and 5 deletions.
18 changes: 13 additions & 5 deletions fs/nilfs2/btree.c
Original file line number Diff line number Diff line change
Expand Up @@ -1356,20 +1356,19 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree,
struct buffer_head *bh;
struct nilfs_btree_node *node, *parent, *sib;
__u64 sibptr;
int pindex, level, ncmin, ncmax, ncblk, ret;
int pindex, dindex, level, ncmin, ncmax, ncblk, ret;

ret = 0;
stats->bs_nblocks = 0;
ncmin = NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree));
ncblk = nilfs_btree_nchildren_per_block(btree);

for (level = NILFS_BTREE_LEVEL_NODE_MIN;
for (level = NILFS_BTREE_LEVEL_NODE_MIN, dindex = path[level].bp_index;
level < nilfs_btree_height(btree) - 1;
level++) {
node = nilfs_btree_get_nonroot_node(path, level);
path[level].bp_oldreq.bpr_ptr =
nilfs_btree_node_get_ptr(node, path[level].bp_index,
ncblk);
nilfs_btree_node_get_ptr(node, dindex, ncblk);
ret = nilfs_bmap_prepare_end_ptr(btree,
&path[level].bp_oldreq, dat);
if (ret < 0)
Expand All @@ -1383,6 +1382,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree,

parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax);
pindex = path[level + 1].bp_index;
dindex = pindex;

if (pindex > 0) {
/* left sibling */
Expand Down Expand Up @@ -1421,6 +1421,14 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree,
path[level].bp_sib_bh = bh;
path[level].bp_op = nilfs_btree_concat_right;
stats->bs_nblocks++;
/*
* When merging right sibling node
* into the current node, pointer to
* the right sibling node must be
* terminated instead. The adjustment
* below is required for that.
*/
dindex = pindex + 1;
/* continue; */
}
} else {
Expand All @@ -1443,7 +1451,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree,

node = nilfs_btree_get_root(btree);
path[level].bp_oldreq.bpr_ptr =
nilfs_btree_node_get_ptr(node, path[level].bp_index,
nilfs_btree_node_get_ptr(node, dindex,
NILFS_BTREE_ROOT_NCHILDREN_MAX);

ret = nilfs_bmap_prepare_end_ptr(btree, &path[level].bp_oldreq, dat);
Expand Down

0 comments on commit fe744fd

Please sign in to comment.