aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nilfs2/btree.c
diff options
context:
space:
mode:
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2011-05-25 10:00:27 -0400
committerRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>2011-06-11 02:51:15 -0400
commitfe744fdb74f2417d8571faefa45f72b0ead25f89 (patch)
tree516655aad7800018483724cce93c24c2418fc1f4 /fs/nilfs2/btree.c
parent59c5f46fbe01a00eedf54a23789634438bb80603 (diff)
nilfs2: fix incorrect block address termination in node concatenation
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>
Diffstat (limited to 'fs/nilfs2/btree.c')
-rw-r--r--fs/nilfs2/btree.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c
index 7eafe468a29c..fd4f05b91942 100644
--- a/fs/nilfs2/btree.c
+++ b/fs/nilfs2/btree.c
@@ -1356,20 +1356,19 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree,
1356 struct buffer_head *bh; 1356 struct buffer_head *bh;
1357 struct nilfs_btree_node *node, *parent, *sib; 1357 struct nilfs_btree_node *node, *parent, *sib;
1358 __u64 sibptr; 1358 __u64 sibptr;
1359 int pindex, level, ncmin, ncmax, ncblk, ret; 1359 int pindex, dindex, level, ncmin, ncmax, ncblk, ret;
1360 1360
1361 ret = 0; 1361 ret = 0;
1362 stats->bs_nblocks = 0; 1362 stats->bs_nblocks = 0;
1363 ncmin = NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree)); 1363 ncmin = NILFS_BTREE_NODE_NCHILDREN_MIN(nilfs_btree_node_size(btree));
1364 ncblk = nilfs_btree_nchildren_per_block(btree); 1364 ncblk = nilfs_btree_nchildren_per_block(btree);
1365 1365
1366 for (level = NILFS_BTREE_LEVEL_NODE_MIN; 1366 for (level = NILFS_BTREE_LEVEL_NODE_MIN, dindex = path[level].bp_index;
1367 level < nilfs_btree_height(btree) - 1; 1367 level < nilfs_btree_height(btree) - 1;
1368 level++) { 1368 level++) {
1369 node = nilfs_btree_get_nonroot_node(path, level); 1369 node = nilfs_btree_get_nonroot_node(path, level);
1370 path[level].bp_oldreq.bpr_ptr = 1370 path[level].bp_oldreq.bpr_ptr =
1371 nilfs_btree_node_get_ptr(node, path[level].bp_index, 1371 nilfs_btree_node_get_ptr(node, dindex, ncblk);
1372 ncblk);
1373 ret = nilfs_bmap_prepare_end_ptr(btree, 1372 ret = nilfs_bmap_prepare_end_ptr(btree,
1374 &path[level].bp_oldreq, dat); 1373 &path[level].bp_oldreq, dat);
1375 if (ret < 0) 1374 if (ret < 0)
@@ -1383,6 +1382,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree,
1383 1382
1384 parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax); 1383 parent = nilfs_btree_get_node(btree, path, level + 1, &ncmax);
1385 pindex = path[level + 1].bp_index; 1384 pindex = path[level + 1].bp_index;
1385 dindex = pindex;
1386 1386
1387 if (pindex > 0) { 1387 if (pindex > 0) {
1388 /* left sibling */ 1388 /* left sibling */
@@ -1421,6 +1421,14 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree,
1421 path[level].bp_sib_bh = bh; 1421 path[level].bp_sib_bh = bh;
1422 path[level].bp_op = nilfs_btree_concat_right; 1422 path[level].bp_op = nilfs_btree_concat_right;
1423 stats->bs_nblocks++; 1423 stats->bs_nblocks++;
1424 /*
1425 * When merging right sibling node
1426 * into the current node, pointer to
1427 * the right sibling node must be
1428 * terminated instead. The adjustment
1429 * below is required for that.
1430 */
1431 dindex = pindex + 1;
1424 /* continue; */ 1432 /* continue; */
1425 } 1433 }
1426 } else { 1434 } else {
@@ -1443,7 +1451,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree,
1443 1451
1444 node = nilfs_btree_get_root(btree); 1452 node = nilfs_btree_get_root(btree);
1445 path[level].bp_oldreq.bpr_ptr = 1453 path[level].bp_oldreq.bpr_ptr =
1446 nilfs_btree_node_get_ptr(node, path[level].bp_index, 1454 nilfs_btree_node_get_ptr(node, dindex,
1447 NILFS_BTREE_ROOT_NCHILDREN_MAX); 1455 NILFS_BTREE_ROOT_NCHILDREN_MAX);
1448 1456
1449 ret = nilfs_bmap_prepare_end_ptr(btree, &path[level].bp_oldreq, dat); 1457 ret = nilfs_bmap_prepare_end_ptr(btree, &path[level].bp_oldreq, dat);