From c802ad9ed6c6756dfb65d31f0f559e90df3825d5 Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Tue, 20 May 2008 16:13:41 -0500 Subject: [PATCH] Teach ext2fs_extent_delete() to remove an empty extent node from the tree ext2fs_extent_delete() will also update the parent node and decrement the inode block count. Passing in the EXT2_EXTENT_DELETE_KEEP_EMPTY flag will allow the empty node to remain. Signed-off-by: Eric Sandeen Signed-off-by: Theodore Ts'o --- lib/ext2fs/ext2fs.h | 5 +++++ lib/ext2fs/extent.c | 31 ++++++++++++++++++++++++------- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h index 8afdb35..3ef3b0d 100644 --- a/lib/ext2fs/ext2fs.h +++ b/lib/ext2fs/ext2fs.h @@ -336,6 +336,11 @@ typedef struct ext2_extent_path *ext2_extent_path_t; #define EXT2_EXTENT_INSERT_NOSPLIT 0x0002 /* insert may not cause split */ /* + * Flags used by ext2fs_extent_delete() + */ +#define EXT2_EXTENT_DELETE_KEEP_EMPTY 0x001 /* keep node if last extnt gone */ + +/* * Flags used by ext2fs_extent_set_bmap() */ #define EXT2_EXTENT_SET_BMAP_UNINIT 0x0001 diff --git a/lib/ext2fs/extent.c b/lib/ext2fs/extent.c index fd28bb4..d4c84d0 100644 --- a/lib/ext2fs/extent.c +++ b/lib/ext2fs/extent.c @@ -1261,8 +1261,7 @@ done: return retval; } -errcode_t ext2fs_extent_delete(ext2_extent_handle_t handle, - int flags EXT2FS_ATTR((unused))) +errcode_t ext2fs_extent_delete(ext2_extent_handle_t handle, int flags) { struct extent_path *path; char *cp; @@ -1292,15 +1291,33 @@ errcode_t ext2fs_extent_delete(ext2_extent_handle_t handle, ix--; path->curr = ix; } - path->entries--; - if (path->entries == 0) + if (--path->entries == 0) path->curr = 0; - eh = (struct ext3_extent_header *) path->buf; - eh->eh_entries = ext2fs_cpu_to_le16(path->entries); + /* if non-root node has no entries left, remove it & parent ptr to it */ + if (path->entries == 0 && handle->level) { + if (!(flags & EXT2_EXTENT_DELETE_KEEP_EMPTY)) { + struct ext2fs_extent extent; - retval = update_path(handle); + retval = ext2fs_extent_get(handle, EXT2_EXTENT_UP, + &extent); + if (retval) + return retval; + retval = ext2fs_extent_delete(handle, flags); + handle->inode->i_blocks -= handle->fs->blocksize / 512; + retval = ext2fs_write_inode_full(handle->fs, + handle->ino, handle->inode, + EXT2_INODE_SIZE(handle->fs->super)); + ext2fs_block_alloc_stats(handle->fs, extent.e_pblk, -1); + } + } else { + eh = (struct ext3_extent_header *) path->buf; + eh->eh_entries = ext2fs_cpu_to_le16(path->entries); + if ((path->entries == 0) && (handle->level == 0)) + eh->eh_depth = handle->max_depth = 0; + retval = update_path(handle); + } return retval; } -- 1.8.3.1