OSDN Git Service

Teach ext2fs_extent_delete() to remove an empty extent node from the tree
authorEric Sandeen <sandeen@redhat.com>
Tue, 20 May 2008 21:13:41 +0000 (16:13 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Mon, 2 Jun 2008 22:52:12 +0000 (18:52 -0400)
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 <sandeen@redhat.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
lib/ext2fs/ext2fs.h
lib/ext2fs/extent.c

index 8afdb35..3ef3b0d 100644 (file)
@@ -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
index fd28bb4..d4c84d0 100644 (file)
@@ -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;
 }