Commit 8089fe62 authored by David Sterba's avatar David Sterba Committed by David Sterba

btrfs: put delayed item hook into inode

Inodes for delayed iput allocate a trivial helper structure, let's place
the list hook directly into the inode and save a kmalloc (killing a
__GFP_NOFAIL as a bonus) at the cost of increasing size of btrfs_inode.

The inode can be put into the delayed_iputs list more than once and we
have to keep the count. This means we can't use the list_splice to
process a bunch of inodes because we'd lost track of the count if the
inode is put into the delayed iputs again while it's processed.
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent c5ca8781
...@@ -192,6 +192,10 @@ struct btrfs_inode { ...@@ -192,6 +192,10 @@ struct btrfs_inode {
/* File creation time. */ /* File creation time. */
struct timespec i_otime; struct timespec i_otime;
/* Hook into fs_info->delayed_iputs */
struct list_head delayed_iput;
long delayed_iput_count;
struct inode vfs_inode; struct inode vfs_inode;
}; };
......
...@@ -3106,55 +3106,47 @@ static int btrfs_readpage_end_io_hook(struct btrfs_io_bio *io_bio, ...@@ -3106,55 +3106,47 @@ static int btrfs_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
start, (size_t)(end - start + 1)); start, (size_t)(end - start + 1));
} }
struct delayed_iput {
struct list_head list;
struct inode *inode;
};
/* JDM: If this is fs-wide, why can't we add a pointer to
* btrfs_inode instead and avoid the allocation? */
void btrfs_add_delayed_iput(struct inode *inode) void btrfs_add_delayed_iput(struct inode *inode)
{ {
struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info; struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info;
struct delayed_iput *delayed; struct btrfs_inode *binode = BTRFS_I(inode);
if (atomic_add_unless(&inode->i_count, -1, 1)) if (atomic_add_unless(&inode->i_count, -1, 1))
return; return;
delayed = kmalloc(sizeof(*delayed), GFP_NOFS | __GFP_NOFAIL);
delayed->inode = inode;
spin_lock(&fs_info->delayed_iput_lock); spin_lock(&fs_info->delayed_iput_lock);
list_add_tail(&delayed->list, &fs_info->delayed_iputs); if (binode->delayed_iput_count == 0) {
ASSERT(list_empty(&binode->delayed_iput));
list_add_tail(&binode->delayed_iput, &fs_info->delayed_iputs);
} else {
binode->delayed_iput_count++;
}
spin_unlock(&fs_info->delayed_iput_lock); spin_unlock(&fs_info->delayed_iput_lock);
} }
void btrfs_run_delayed_iputs(struct btrfs_root *root) void btrfs_run_delayed_iputs(struct btrfs_root *root)
{ {
LIST_HEAD(list);
struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_fs_info *fs_info = root->fs_info;
struct delayed_iput *delayed;
int empty;
spin_lock(&fs_info->delayed_iput_lock);
empty = list_empty(&fs_info->delayed_iputs);
spin_unlock(&fs_info->delayed_iput_lock);
if (empty)
return;
down_read(&fs_info->delayed_iput_sem); down_read(&fs_info->delayed_iput_sem);
spin_lock(&fs_info->delayed_iput_lock); spin_lock(&fs_info->delayed_iput_lock);
list_splice_init(&fs_info->delayed_iputs, &list); while (!list_empty(&fs_info->delayed_iputs)) {
spin_unlock(&fs_info->delayed_iput_lock); struct btrfs_inode *inode;
while (!list_empty(&list)) { inode = list_first_entry(&fs_info->delayed_iputs,
delayed = list_entry(list.next, struct delayed_iput, list); struct btrfs_inode, delayed_iput);
list_del(&delayed->list); if (inode->delayed_iput_count) {
iput(delayed->inode); inode->delayed_iput_count--;
kfree(delayed); list_move_tail(&inode->delayed_iput,
&fs_info->delayed_iputs);
} else {
list_del_init(&inode->delayed_iput);
}
spin_unlock(&fs_info->delayed_iput_lock);
iput(&inode->vfs_inode);
spin_lock(&fs_info->delayed_iput_lock);
} }
spin_unlock(&fs_info->delayed_iput_lock);
up_read(&root->fs_info->delayed_iput_sem); up_read(&root->fs_info->delayed_iput_sem);
} }
...@@ -9037,6 +9029,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) ...@@ -9037,6 +9029,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
ei->dir_index = 0; ei->dir_index = 0;
ei->last_unlink_trans = 0; ei->last_unlink_trans = 0;
ei->last_log_commit = 0; ei->last_log_commit = 0;
ei->delayed_iput_count = 0;
spin_lock_init(&ei->lock); spin_lock_init(&ei->lock);
ei->outstanding_extents = 0; ei->outstanding_extents = 0;
...@@ -9061,6 +9054,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) ...@@ -9061,6 +9054,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
mutex_init(&ei->delalloc_mutex); mutex_init(&ei->delalloc_mutex);
btrfs_ordered_inode_tree_init(&ei->ordered_tree); btrfs_ordered_inode_tree_init(&ei->ordered_tree);
INIT_LIST_HEAD(&ei->delalloc_inodes); INIT_LIST_HEAD(&ei->delalloc_inodes);
INIT_LIST_HEAD(&ei->delayed_iput);
RB_CLEAR_NODE(&ei->rb_node); RB_CLEAR_NODE(&ei->rb_node);
return inode; return inode;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment