summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTahsin Erdogan <tahsin@google.com>2017-06-22 16:26:31 +0200
committerTheodore Ts'o <tytso@mit.edu>2017-06-22 16:26:31 +0200
commit0421a189bc8cdefa18a34aee962ac0558679b944 (patch)
tree3e701dfeeca3c987d1c815e8fa1461ea979bf8b8
parentext4: improve journal credit handling in set xattr paths (diff)
downloadlinux-0421a189bc8cdefa18a34aee962ac0558679b944.tar.xz
linux-0421a189bc8cdefa18a34aee962ac0558679b944.zip
ext4: modify ext4_xattr_ino_array to hold struct inode *
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>
-rw-r--r--fs/ext4/ext4.h6
-rw-r--r--fs/ext4/inode.c8
-rw-r--r--fs/ext4/xattr.c93
-rw-r--r--fs/ext4/xattr.h5
4 files changed, 53 insertions, 59 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 9b6a10e1bf18..144a2863ba27 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -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);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index fda70fedf56d..1b2a68c5ea42 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -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... */
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 43a2c075aa1f..fed54001c9e6 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -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);
}
/*
diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
index e82c5fe36a26..323eba54f72f 100644
--- a/fs/ext4/xattr.h
+++ b/fs/ext4/xattr.h
@@ -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);