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>
This commit is contained in:
parent
c1a5d5f6ab
commit
0421a189bc
|
@ -2243,9 +2243,9 @@ struct mmpd_data {
|
||||||
# define ATTRIB_NORET __attribute__((noreturn))
|
# define ATTRIB_NORET __attribute__((noreturn))
|
||||||
# define NORET_AND noreturn,
|
# define NORET_AND noreturn,
|
||||||
|
|
||||||
struct ext4_xattr_ino_array {
|
struct ext4_xattr_inode_array {
|
||||||
unsigned int xia_count; /* # of used item in the array */
|
unsigned int count; /* # of used items in the array */
|
||||||
unsigned int xia_inodes[0];
|
struct inode *inodes[0];
|
||||||
};
|
};
|
||||||
/* bitmap.c */
|
/* bitmap.c */
|
||||||
extern unsigned int ext4_count_free(char *bitmap, unsigned numchars);
|
extern unsigned int ext4_count_free(char *bitmap, unsigned numchars);
|
||||||
|
|
|
@ -188,7 +188,7 @@ void ext4_evict_inode(struct inode *inode)
|
||||||
handle_t *handle;
|
handle_t *handle;
|
||||||
int err;
|
int err;
|
||||||
int extra_credits = 3;
|
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);
|
trace_ext4_evict_inode(inode);
|
||||||
|
|
||||||
|
@ -257,7 +257,7 @@ void ext4_evict_inode(struct inode *inode)
|
||||||
/*
|
/*
|
||||||
* Delete xattr inode before deleting the main 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) {
|
if (err) {
|
||||||
ext4_warning(inode->i_sb,
|
ext4_warning(inode->i_sb,
|
||||||
"couldn't delete inode's xattr (err %d)", err);
|
"couldn't delete inode's xattr (err %d)", err);
|
||||||
|
@ -345,9 +345,7 @@ void ext4_evict_inode(struct inode *inode)
|
||||||
|
|
||||||
ext4_journal_stop(handle);
|
ext4_journal_stop(handle);
|
||||||
sb_end_intwrite(inode->i_sb);
|
sb_end_intwrite(inode->i_sb);
|
||||||
|
ext4_xattr_inode_array_free(ea_inode_array);
|
||||||
if (lea_ino_array != NULL)
|
|
||||||
ext4_xattr_inode_array_free(inode, lea_ino_array);
|
|
||||||
return;
|
return;
|
||||||
no_delete:
|
no_delete:
|
||||||
ext4_clear_inode(inode); /* We must guarantee clearing of inode... */
|
ext4_clear_inode(inode); /* We must guarantee clearing of inode... */
|
||||||
|
|
|
@ -1940,44 +1940,44 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
|
||||||
|
|
||||||
#define EIA_INCR 16 /* must be 2^n */
|
#define EIA_INCR 16 /* must be 2^n */
|
||||||
#define EIA_MASK (EIA_INCR - 1)
|
#define EIA_MASK (EIA_INCR - 1)
|
||||||
/* Add the large xattr @ino into @lea_ino_array for later deletion.
|
/* Add the large xattr @inode into @ea_inode_array for later deletion.
|
||||||
* If @lea_ino_array is new or full it will be grown and the old
|
* If @ea_inode_array is new or full it will be grown and the old
|
||||||
* contents copied over.
|
* contents copied over.
|
||||||
*/
|
*/
|
||||||
static int
|
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.
|
* 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) =
|
(*ea_inode_array) =
|
||||||
kmalloc(offsetof(struct ext4_xattr_ino_array,
|
kmalloc(offsetof(struct ext4_xattr_inode_array,
|
||||||
xia_inodes[EIA_MASK]),
|
inodes[EIA_MASK]),
|
||||||
GFP_NOFS);
|
GFP_NOFS);
|
||||||
if (*lea_ino_array == NULL)
|
if (*ea_inode_array == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
(*lea_ino_array)->xia_count = 0;
|
(*ea_inode_array)->count = 0;
|
||||||
} else if (((*lea_ino_array)->xia_count & EIA_MASK) == EIA_MASK) {
|
} else if (((*ea_inode_array)->count & EIA_MASK) == EIA_MASK) {
|
||||||
/* expand the array once all 15 + n * 16 slots are full */
|
/* expand the array once all 15 + n * 16 slots are full */
|
||||||
struct ext4_xattr_ino_array *new_array = NULL;
|
struct ext4_xattr_inode_array *new_array = NULL;
|
||||||
int count = (*lea_ino_array)->xia_count;
|
int count = (*ea_inode_array)->count;
|
||||||
|
|
||||||
/* if new_array is NULL, this is essentially offsetof() */
|
/* if new_array is NULL, this is essentially offsetof() */
|
||||||
new_array = kmalloc(
|
new_array = kmalloc(
|
||||||
offsetof(struct ext4_xattr_ino_array,
|
offsetof(struct ext4_xattr_inode_array,
|
||||||
xia_inodes[count + EIA_INCR]),
|
inodes[count + EIA_INCR]),
|
||||||
GFP_NOFS);
|
GFP_NOFS);
|
||||||
if (new_array == NULL)
|
if (new_array == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
memcpy(new_array, *lea_ino_array,
|
memcpy(new_array, *ea_inode_array,
|
||||||
offsetof(struct ext4_xattr_ino_array,
|
offsetof(struct ext4_xattr_inode_array, inodes[count]));
|
||||||
xia_inodes[count]));
|
kfree(*ea_inode_array);
|
||||||
kfree(*lea_ino_array);
|
*ea_inode_array = new_array;
|
||||||
*lea_ino_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;
|
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
|
* Add xattr inode to orphan list
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ext4_xattr_inode_orphan_add(handle_t *handle, struct inode *inode,
|
ext4_xattr_inode_orphan_add(handle_t *handle, struct inode *inode, int credits,
|
||||||
int credits, struct ext4_xattr_ino_array *lea_ino_array)
|
struct ext4_xattr_inode_array *ea_inode_array)
|
||||||
{
|
{
|
||||||
struct inode *ea_inode;
|
|
||||||
int idx = 0, error = 0;
|
int idx = 0, error = 0;
|
||||||
|
struct inode *ea_inode;
|
||||||
|
|
||||||
if (lea_ino_array == NULL)
|
if (ea_inode_array == NULL)
|
||||||
return 0;
|
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)) {
|
if (!ext4_handle_has_enough_credits(handle, credits)) {
|
||||||
error = ext4_journal_extend(handle, credits);
|
error = ext4_journal_extend(handle, credits);
|
||||||
if (error > 0)
|
if (error > 0)
|
||||||
|
@ -2007,10 +2007,7 @@ ext4_xattr_inode_orphan_add(handle_t *handle, struct inode *inode,
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
error = ext4_xattr_inode_iget(inode,
|
ea_inode = ea_inode_array->inodes[idx];
|
||||||
lea_ino_array->xia_inodes[idx], &ea_inode);
|
|
||||||
if (error)
|
|
||||||
continue;
|
|
||||||
inode_lock(ea_inode);
|
inode_lock(ea_inode);
|
||||||
ext4_orphan_add(handle, ea_inode);
|
ext4_orphan_add(handle, ea_inode);
|
||||||
inode_unlock(ea_inode);
|
inode_unlock(ea_inode);
|
||||||
|
@ -2032,13 +2029,14 @@ ext4_xattr_inode_orphan_add(handle_t *handle, struct inode *inode,
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
|
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 buffer_head *bh = NULL;
|
||||||
struct ext4_xattr_ibody_header *header;
|
struct ext4_xattr_ibody_header *header;
|
||||||
struct ext4_inode *raw_inode;
|
struct ext4_inode *raw_inode;
|
||||||
struct ext4_iloc iloc;
|
struct ext4_iloc iloc;
|
||||||
struct ext4_xattr_entry *entry;
|
struct ext4_xattr_entry *entry;
|
||||||
|
struct inode *ea_inode;
|
||||||
unsigned int ea_ino;
|
unsigned int ea_ino;
|
||||||
int credits = 3, error = 0;
|
int credits = 3, error = 0;
|
||||||
|
|
||||||
|
@ -2055,8 +2053,12 @@ ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
|
||||||
if (!entry->e_value_inum)
|
if (!entry->e_value_inum)
|
||||||
continue;
|
continue;
|
||||||
ea_ino = le32_to_cpu(entry->e_value_inum);
|
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) {
|
if (error) {
|
||||||
|
iput(ea_inode);
|
||||||
brelse(iloc.bh);
|
brelse(iloc.bh);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -2068,7 +2070,7 @@ ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
|
||||||
if (!EXT4_I(inode)->i_file_acl) {
|
if (!EXT4_I(inode)->i_file_acl) {
|
||||||
/* add xattr inode to orphan list */
|
/* add xattr inode to orphan list */
|
||||||
error = ext4_xattr_inode_orphan_add(handle, inode, credits,
|
error = ext4_xattr_inode_orphan_add(handle, inode, credits,
|
||||||
*lea_ino_array);
|
*ea_inode_array);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
|
bh = sb_bread(inode->i_sb, EXT4_I(inode)->i_file_acl);
|
||||||
|
@ -2091,7 +2093,10 @@ ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
|
||||||
if (!entry->e_value_inum)
|
if (!entry->e_value_inum)
|
||||||
continue;
|
continue;
|
||||||
ea_ino = le32_to_cpu(entry->e_value_inum);
|
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)
|
if (error)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
entry->e_value_inum = 0;
|
entry->e_value_inum = 0;
|
||||||
|
@ -2099,7 +2104,7 @@ ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
|
||||||
|
|
||||||
/* add xattr inode to orphan list */
|
/* add xattr inode to orphan list */
|
||||||
error = ext4_xattr_inode_orphan_add(handle, inode, credits,
|
error = ext4_xattr_inode_orphan_add(handle, inode, credits,
|
||||||
*lea_ino_array);
|
*ea_inode_array);
|
||||||
if (error)
|
if (error)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
@ -2126,28 +2131,20 @@ ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void ext4_xattr_inode_array_free(struct ext4_xattr_inode_array *ea_inode_array)
|
||||||
ext4_xattr_inode_array_free(struct inode *inode,
|
|
||||||
struct ext4_xattr_ino_array *lea_ino_array)
|
|
||||||
{
|
{
|
||||||
struct inode *ea_inode;
|
struct inode *ea_inode;
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
int err;
|
|
||||||
|
|
||||||
if (lea_ino_array == NULL)
|
if (ea_inode_array == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (; idx < lea_ino_array->xia_count; ++idx) {
|
for (; idx < ea_inode_array->count; ++idx) {
|
||||||
err = ext4_xattr_inode_iget(inode,
|
ea_inode = ea_inode_array->inodes[idx];
|
||||||
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);
|
|
||||||
clear_nlink(ea_inode);
|
clear_nlink(ea_inode);
|
||||||
iput(ea_inode);
|
iput(ea_inode);
|
||||||
}
|
}
|
||||||
kfree(lea_ino_array);
|
kfree(ea_inode_array);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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_inode_unlink(struct inode *inode, unsigned long ea_ino);
|
||||||
extern int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
|
extern int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode,
|
||||||
struct ext4_xattr_ino_array **array);
|
struct ext4_xattr_inode_array **array);
|
||||||
extern void ext4_xattr_inode_array_free(struct inode *inode,
|
extern void ext4_xattr_inode_array_free(struct ext4_xattr_inode_array *array);
|
||||||
struct ext4_xattr_ino_array *array);
|
|
||||||
|
|
||||||
extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
|
extern int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize,
|
||||||
struct ext4_inode *raw_inode, handle_t *handle);
|
struct ext4_inode *raw_inode, handle_t *handle);
|
||||||
|
|
Loading…
Reference in New Issue