ext4: let ext4_delete_entry() handle inline data
authorTao Ma <boyu.mt@taobao.com>
Mon, 10 Dec 2012 19:06:00 +0000 (14:06 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Mon, 10 Dec 2012 19:06:00 +0000 (14:06 -0500)
Signed-off-by: Tao Ma <boyu.mt@taobao.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
fs/ext4/inline.c
fs/ext4/namei.c
fs/ext4/xattr.h

index 0a8f5a8..f5e9c0e 100644 (file)
@@ -1510,6 +1510,61 @@ out_find:
        return iloc.bh;
 }
 
+int ext4_delete_inline_entry(handle_t *handle,
+                            struct inode *dir,
+                            struct ext4_dir_entry_2 *de_del,
+                            struct buffer_head *bh,
+                            int *has_inline_data)
+{
+       int err, inline_size;
+       struct ext4_iloc iloc;
+       void *inline_start;
+
+       err = ext4_get_inode_loc(dir, &iloc);
+       if (err)
+               return err;
+
+       down_write(&EXT4_I(dir)->xattr_sem);
+       if (!ext4_has_inline_data(dir)) {
+               *has_inline_data = 0;
+               goto out;
+       }
+
+       if ((void *)de_del - ((void *)ext4_raw_inode(&iloc)->i_block) <
+               EXT4_MIN_INLINE_DATA_SIZE) {
+               inline_start = (void *)ext4_raw_inode(&iloc)->i_block +
+                                       EXT4_INLINE_DOTDOT_SIZE;
+               inline_size = EXT4_MIN_INLINE_DATA_SIZE -
+                               EXT4_INLINE_DOTDOT_SIZE;
+       } else {
+               inline_start = ext4_get_inline_xattr_pos(dir, &iloc);
+               inline_size = ext4_get_inline_size(dir) -
+                               EXT4_MIN_INLINE_DATA_SIZE;
+       }
+
+       err = ext4_journal_get_write_access(handle, bh);
+       if (err)
+               goto out;
+
+       err = ext4_generic_delete_entry(handle, dir, de_del, bh,
+                                       inline_start, inline_size, 0);
+       if (err)
+               goto out;
+
+       BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
+       err = ext4_mark_inode_dirty(handle, dir);
+       if (unlikely(err))
+               goto out;
+
+       ext4_show_inline_dir(dir, iloc.bh, inline_start, inline_size);
+out:
+       up_write(&EXT4_I(dir)->xattr_sem);
+       brelse(iloc.bh);
+       if (err != -ENOENT)
+               ext4_std_error(dir->i_sb, err);
+       return err;
+}
+
 int ext4_destroy_inline_data(handle_t *handle, struct inode *inode)
 {
        int ret;
index c10fc26..a32228a 100644 (file)
@@ -2158,6 +2158,14 @@ static int ext4_delete_entry(handle_t *handle,
 {
        int err, csum_size = 0;
 
+       if (ext4_has_inline_data(dir)) {
+               int has_inline_data = 1;
+               err = ext4_delete_inline_entry(handle, dir, de_del, bh,
+                                              &has_inline_data);
+               if (has_inline_data)
+                       return err;
+       }
+
        if (EXT4_HAS_RO_COMPAT_FEATURE(dir->i_sb,
                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
                csum_size = sizeof(struct ext4_dir_entry_tail);
index c6f3dea..f86e424 100644 (file)
@@ -175,6 +175,11 @@ extern struct buffer_head *ext4_find_inline_entry(struct inode *dir,
                                        const struct qstr *d_name,
                                        struct ext4_dir_entry_2 **res_dir,
                                        int *has_inline_data);
+extern int ext4_delete_inline_entry(handle_t *handle,
+                                   struct inode *dir,
+                                   struct ext4_dir_entry_2 *de_del,
+                                   struct buffer_head *bh,
+                                   int *has_inline_data);
 # else  /* CONFIG_EXT4_FS_XATTR */
 
 static inline int
@@ -368,6 +373,14 @@ ext4_find_inline_entry(struct inode *dir,
 {
        return NULL;
 }
+static inline int ext4_delete_inline_entry(handle_t *handle,
+                                          struct inode *dir,
+                                          struct ext4_dir_entry_2 *de_del,
+                                          struct buffer_head *bh,
+                                          int *has_inline_data)
+{
+       return 0;
+}
 # endif  /* CONFIG_EXT4_FS_XATTR */
 
 #ifdef CONFIG_EXT4_FS_SECURITY