Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

nilfs2: fix missing block address termination in btree node shrinking

nilfs_btree_delete function does not terminate part of virtual block
addresses when shrinking the last remaining child node into the root
node. The missing address termination causes that dead btree node
blocks persist and chip away free disk space.

This fixes the leak bug on the btree node deletion.

Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>

+14 -7
+14 -7
fs/nilfs2/btree.c
··· 1346 1346 path[level].bp_bh = NULL; 1347 1347 } 1348 1348 1349 + static void nilfs_btree_nop(struct nilfs_bmap *btree, 1350 + struct nilfs_btree_path *path, 1351 + int level, __u64 *keyp, __u64 *ptrp) 1352 + { 1353 + } 1349 1354 1350 1355 static int nilfs_btree_prepare_delete(struct nilfs_bmap *btree, 1351 1356 struct nilfs_btree_path *path, ··· 1444 1439 NILFS_BTREE_ROOT_NCHILDREN_MAX) { 1445 1440 path[level].bp_op = nilfs_btree_shrink; 1446 1441 stats->bs_nblocks += 2; 1442 + level++; 1443 + path[level].bp_op = nilfs_btree_nop; 1444 + goto shrink_root_child; 1447 1445 } else { 1448 1446 path[level].bp_op = nilfs_btree_do_delete; 1449 1447 stats->bs_nblocks++; 1448 + goto out; 1450 1449 } 1451 - 1452 - goto out; 1453 - 1454 1450 } 1455 1451 } 1456 1452 1453 + /* child of the root node is deleted */ 1454 + path[level].bp_op = nilfs_btree_do_delete; 1455 + stats->bs_nblocks++; 1456 + 1457 + shrink_root_child: 1457 1458 node = nilfs_btree_get_root(btree); 1458 1459 path[level].bp_oldreq.bpr_ptr = 1459 1460 nilfs_btree_node_get_ptr(node, dindex, ··· 1468 1457 ret = nilfs_bmap_prepare_end_ptr(btree, &path[level].bp_oldreq, dat); 1469 1458 if (ret < 0) 1470 1459 goto err_out_child_node; 1471 - 1472 - /* child of the root node is deleted */ 1473 - path[level].bp_op = nilfs_btree_do_delete; 1474 - stats->bs_nblocks++; 1475 1460 1476 1461 /* success */ 1477 1462 out: