ext4: modify ext4_xattr_ino_array to hold struct inode *
authorTahsin Erdogan <tahsin@google.com>
Thu, 22 Jun 2017 14:26:31 +0000 (10:26 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 22 Jun 2017 14:26:31 +0000 (10:26 -0400)
Tracking struct inode * rather than the inode number eliminates the
repeated ext4_xattr_inode_iget() call later. The second call cannot
fail in practice but still requires explanation when it wants to ignore
the return value. Avoid the trouble and make things simple.

Signed-off-by: Tahsin Erdogan <tahsin@google.com>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
fs/ext4/ext4.h
fs/ext4/inode.c
fs/ext4/xattr.c
fs/ext4/xattr.h

index 9b6a10e1bf18820d7331e8a897f3140b74c0ab80..144a2863ba27e894e679146257da143177fac397 100644 (file)
@@ -2243,9 +2243,9 @@ struct mmpd_data {
 # define ATTRIB_NORET  __attribute__((noreturn))
 # define NORET_AND     noreturn,
 
-struct ext4_xattr_ino_array {
-       unsigned int xia_count;         /* # of used item in the array */
-       unsigned int xia_inodes[0];
+struct ext4_xattr_inode_array {
+       unsigned int count;             /* # of used items in the array */
+       struct inode *inodes[0];
 };
 /* bitmap.c */
 extern unsigned int ext4_count_free(char *bitmap, unsigned numchars);
index fda70fedf56d569d063ce8add1c115a813a6c511..1b2a68c5ea421e38ded07780c0ebd0367c62cec0 100644 (file)
@@ -188,7 +188,7 @@ void ext4_evict_inode(struct inode *inode)
        handle_t *handle;
        int err;
        int extra_credits = 3;
-       struct ext4_xattr_ino_array *lea_ino_array = NULL;
+       struct ext4_xattr_inode_array *ea_inode_array = NULL;
 
        trace_ext4_evict_inode(inode);
 
@@ -257,7 +257,7 @@ void ext4_evict_inode(struct inode *inode)
        /*
         * Delete xattr inode before deleting the main inode.
         */
-       err = ext4_xattr_delete_inode(handle, inode, &lea_ino_array);
+       err = ext4_xattr_delete_inode(handle, inode, &ea_inode_array);
        if (err) {
                ext4_warning(inode->i_sb,
                             "couldn't delete inode's xattr (err %d)", err);
@@ -345,9 +345,7 @@ void ext4_evict_inode(struct inode *inode)
 
        ext4_journal_stop(handle);
        sb_end_intwrite(inode->i_sb);
-
-       if (lea_ino_array != NULL)
-               ext4_xattr_inode_array_free(inode, lea_ino_array);
+       ext4_xattr_inode_array_free(ea_inode_array);
        return;
 no_delete:
        ext4_clear_inode(inode);        /* We must guarantee clearing of inode... */
index 43a2c075aa1f2e1ea5d1b38ee2cec3c670d2efc2..fed54001c9e6df633108c17f67ac3f961b067ca1 100644 (file)
@@ -1940,44 +1940,44 @@ cleanup:
 
 #define EIA_INCR 16 /* must be 2^n */
 #define EIA_MASK (EIA_INCR - 1)
-/* Add the large xattr @ino into @lea_ino_array for later deletion.
- * If @lea_ino_array is new or full it will be grown and the old
+/* Add the large xattr @inode into @ea_inode_array for later deletion.
+ * If @ea_inode_array is new or full it will be grown and the old
  * contents copied over.
  */
 static int
-ext4_expand_ino_array(struct ext4_xattr_ino_array **lea_ino_array, __u32 ino)
+ext4_expand_inode_array(struct ext4_xattr_inode_array **ea_inode_array,
+                       struct inode *inode)
 {
-       if (*lea_ino_array == NULL) {
+       if (*ea_inode_array == NULL) {
                /*
                 * Start with 15 inodes, so it fits into a power-of-two size.
-                * If *lea_ino_array is NULL, this is essentially offsetof()
+                * If *ea_inode_array is NULL, this is essentially offsetof()
                 */
-               (*lea_ino_array) =
-                       kmalloc(offsetof(struct ext4_xattr_ino_array,
-                                        xia_inodes[EIA_MASK]),
+               (*ea_inode_array) =
+                       kmalloc(offsetof(struct ext4_xattr_inode_array,
+                                        inodes[EIA_MASK]),
                                GFP_NOFS);
-               if (*lea_ino_array == NULL)
+               if (*ea_inode_array == NULL)
                        return -ENOMEM;
-               (*lea_ino_array)->xia_count = 0;
-       } else if (((*lea_ino_array)->xia_count & EIA_MASK) == EIA_MASK) {
+               (*ea_inode_array)->count = 0;
+       } else if (((*ea_inode_array)->count & EIA_MASK) == EIA_MASK) {
                /* expand the array once all 15 + n * 16 slots are full */
-               struct ext4_xattr_ino_array *new_array = NULL;
-               int count = (*lea_ino_array)->xia_count;
+               struct ext4_xattr_inode_array *new_array = NULL;
+               int count = (*ea_inode_array)->count;
 
                /* if new_array is NULL, this is essentially offsetof() */
                new_array = kmalloc(
-                               offsetof(struct ext4_xattr_ino_array,
-                                        xia_inodes[count + EIA_INCR]),
+                               offsetof(struct ext4_xattr_inode_array,
+                                        inodes[count + EIA_INCR]),
                                GFP_NOFS);
                if (new_array == NULL)
                        return -ENOMEM;
-               memcpy(new_array, *lea_ino_array,
-                      offsetof(struct ext4_xattr_ino_array,
-                               xia_inodes[count]));
-               kfree(*lea_ino_array);
-               *lea_ino_array = new_array;
+               memcpy(new_array, *ea_inode_array,
+                      offsetof(struct ext4_xattr_inode_array, inodes[count]));
+               kfree(*ea_inode_array);
+               *ea_inode_array = new_array;
        }
-       (*lea_ino_array)->xia_inodes[(*lea_ino_array)->xia_count++] = ino;
+       (*ea_inode_array)->inodes[(*ea_inode_array)->count++] = inode;
        return 0;
 }
 
@@ -1985,16 +1985,16 @@ ext4_expand_ino_array(struct ext4_xattr_ino_array **lea_ino_array, __u32 ino)
  * Add xattr inode to orphan list
  */
 static int
-ext4_xattr_inode_orphan_add(handle_t *handle, struct inode *inode,
-                       int credits, struct ext4_xattr_ino_array *lea_ino_array)
+ext4_xattr_inode_orphan_add(handle_t *handle, struct inode *inode, int credits,
+                           struct ext4_xattr_inode_array *ea_inode_array)
 {
-       struct inode *ea_inode;
        int idx = 0, error = 0;
+       struct inode *ea_inode;
 
-       if (lea_ino_array == NULL)
+       if (ea_inode_array == NULL)
                return 0;
 
-       for (; idx < lea_ino_array->xia_count; ++idx) {
+       for (; idx < ea_inode_array->count; ++idx) {
                if (!ext4_handle_has_enough_credits(handle, credits)) {
                        error = ext4_journal_extend(handle, credits);
                        if (error > 0)
@@ -2007,10 +2007,7 @@ ext4_xattr_inode_orphan_add(handle_t *handle, struct inode *inode,
                                return error;
                        }
                }
-               error = ext4_xattr_inode_iget(inode,
-                               lea_ino_array->xia_inodes[idx], &ea_inode);
-               if (error)
-                       continue;
+               ea_inode = ea_inode_array->inodes[idx];
                inode_lock(ea_inode);
                ext4_orphan_add(handle, ea_inode);
                inode_unlock(ea_inode);
@@ -2032,13 +2029,14 @@ ext4_xattr_inode_orphan_add(handle_t *handle, struct inode *inode,
  */
 int
 ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
-                       struct ext4_xattr_ino_array **lea_ino_array)
+                       struct ext4_xattr_inode_array **ea_inode_array)
 {
        struct buffer_head *bh = NULL;
        struct ext4_xattr_ibody_header *header;
        struct ext4_inode *raw_inode;
        struct ext4_iloc iloc;
        struct ext4_xattr_entry *entry;
+       struct inode *ea_inode;
        unsigned int ea_ino;
        int credits = 3, error = 0;
 
@@ -2055,8 +2053,12 @@ ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
                if (!entry->e_value_inum)
                        continue;
                ea_ino = le32_to_cpu(entry->e_value_inum);
-               error = ext4_expand_ino_array(lea_ino_array, ea_ino);
+               error = ext4_xattr_inode_iget(inode, ea_ino, &ea_inode);
+               if (error)
+                       continue;
+               error = ext4_expand_inode_array(ea_inode_array, ea_inode);
                if (error) {
+                       iput(ea_inode);
                        brelse(iloc.bh);
                        goto cleanup;
                }
@@ -2068,7 +2070,7 @@ delete_external_ea:
        if (!EXT4_I(inode)->i_file_acl) {
                /* add xattr inode to orphan list */
                error = ext4_xattr_inode_orphan_add(handle, inode, credits,
-                                                   *lea_ino_array);
+                                                   *ea_inode_array);
                goto cleanup;
        }
        bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
@@ -2091,7 +2093,10 @@ delete_external_ea:
                if (!entry->e_value_inum)
                        continue;
                ea_ino = le32_to_cpu(entry->e_value_inum);
-               error = ext4_expand_ino_array(lea_ino_array, ea_ino);
+               error = ext4_xattr_inode_iget(inode, ea_ino, &ea_inode);
+               if (error)
+                       continue;
+               error = ext4_expand_inode_array(ea_inode_array, ea_inode);
                if (error)
                        goto cleanup;
                entry->e_value_inum = 0;
@@ -2099,7 +2104,7 @@ delete_external_ea:
 
        /* add xattr inode to orphan list */
        error = ext4_xattr_inode_orphan_add(handle, inode, credits,
-                                       *lea_ino_array);
+                                       *ea_inode_array);
        if (error)
                goto cleanup;
 
@@ -2126,28 +2131,20 @@ cleanup:
        return error;
 }
 
-void
-ext4_xattr_inode_array_free(struct inode *inode,
-                           struct ext4_xattr_ino_array *lea_ino_array)
+void ext4_xattr_inode_array_free(struct ext4_xattr_inode_array *ea_inode_array)
 {
        struct inode    *ea_inode;
        int             idx = 0;
-       int             err;
 
-       if (lea_ino_array == NULL)
+       if (ea_inode_array == NULL)
                return;
 
-       for (; idx < lea_ino_array->xia_count; ++idx) {
-               err = ext4_xattr_inode_iget(inode,
-                               lea_ino_array->xia_inodes[idx], &ea_inode);
-               if (err)
-                       continue;
-               /* for inode's i_count get from ext4_xattr_delete_inode */
-               iput(ea_inode);
+       for (; idx < ea_inode_array->count; ++idx) {
+               ea_inode = ea_inode_array->inodes[idx];
                clear_nlink(ea_inode);
                iput(ea_inode);
        }
-       kfree(lea_ino_array);
+       kfree(ea_inode_array);
 }
 
 /*
index e82c5fe36a26958aef74367131e9a79ca11e5acb..323eba54f72f936579a751e64c5a6e3711438210 100644 (file)
@@ -164,9 +164,8 @@ extern int ext4_xattr_set_credits(struct inode *inode, size_t value_len);
 
 extern int ext4_xattr_inode_unlink(struct inode *inode, unsigned long ea_ino);
 extern int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
-                                  struct ext4_xattr_ino_array **array);
-extern void ext4_xattr_inode_array_free(struct inode *inode,
-                                       struct ext4_xattr_ino_array *array);
+                                  struct ext4_xattr_inode_array **array);
+extern void ext4_xattr_inode_array_free(struct ext4_xattr_inode_array *array);
 
 extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
                            struct ext4_inode *raw_inode, handle_t *handle);