|
@@ -2022,6 +2022,54 @@ zeroit:
|
|
|
return -EIO;
|
|
|
}
|
|
|
|
|
|
+struct delayed_iput {
|
|
|
+ struct list_head list;
|
|
|
+ struct inode *inode;
|
|
|
+};
|
|
|
+
|
|
|
+void btrfs_add_delayed_iput(struct inode *inode)
|
|
|
+{
|
|
|
+ struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info;
|
|
|
+ struct delayed_iput *delayed;
|
|
|
+
|
|
|
+ if (atomic_add_unless(&inode->i_count, -1, 1))
|
|
|
+ return;
|
|
|
+
|
|
|
+ delayed = kmalloc(sizeof(*delayed), GFP_NOFS | __GFP_NOFAIL);
|
|
|
+ delayed->inode = inode;
|
|
|
+
|
|
|
+ spin_lock(&fs_info->delayed_iput_lock);
|
|
|
+ list_add_tail(&delayed->list, &fs_info->delayed_iputs);
|
|
|
+ spin_unlock(&fs_info->delayed_iput_lock);
|
|
|
+}
|
|
|
+
|
|
|
+void btrfs_run_delayed_iputs(struct btrfs_root *root)
|
|
|
+{
|
|
|
+ LIST_HEAD(list);
|
|
|
+ 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(&root->fs_info->cleanup_work_sem);
|
|
|
+ spin_lock(&fs_info->delayed_iput_lock);
|
|
|
+ list_splice_init(&fs_info->delayed_iputs, &list);
|
|
|
+ spin_unlock(&fs_info->delayed_iput_lock);
|
|
|
+
|
|
|
+ while (!list_empty(&list)) {
|
|
|
+ delayed = list_entry(list.next, struct delayed_iput, list);
|
|
|
+ list_del(&delayed->list);
|
|
|
+ iput(delayed->inode);
|
|
|
+ kfree(delayed);
|
|
|
+ }
|
|
|
+ up_read(&root->fs_info->cleanup_work_sem);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* This creates an orphan entry for the given inode in case something goes
|
|
|
* wrong in the middle of an unlink/truncate.
|
|
@@ -5568,7 +5616,7 @@ out_fail:
|
|
|
* some fairly slow code that needs optimization. This walks the list
|
|
|
* of all the inodes with pending delalloc and forces them to disk.
|
|
|
*/
|
|
|
-int btrfs_start_delalloc_inodes(struct btrfs_root *root)
|
|
|
+int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
|
|
|
{
|
|
|
struct list_head *head = &root->fs_info->delalloc_inodes;
|
|
|
struct btrfs_inode *binode;
|
|
@@ -5587,7 +5635,10 @@ int btrfs_start_delalloc_inodes(struct btrfs_root *root)
|
|
|
spin_unlock(&root->fs_info->delalloc_lock);
|
|
|
if (inode) {
|
|
|
filemap_flush(inode->i_mapping);
|
|
|
- iput(inode);
|
|
|
+ if (delay_iput)
|
|
|
+ btrfs_add_delayed_iput(inode);
|
|
|
+ else
|
|
|
+ iput(inode);
|
|
|
}
|
|
|
cond_resched();
|
|
|
spin_lock(&root->fs_info->delalloc_lock);
|