Btrfs: Add some simple throttling to wait for data=ordered and snapshot deletion
authorChris Mason <chris.mason@oracle.com>
Tue, 8 Jan 2008 20:46:30 +0000 (15:46 -0500)
committerChris Mason <chris.mason@oracle.com>
Thu, 25 Sep 2008 15:03:59 +0000 (11:03 -0400)
Signed-off-by: Chris Mason <chris.mason@oracle.com>
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/disk-io.h
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/transaction.c

index b55dba58dfaad4e39896cb9540fe5b1a8d35145d..f0fb1978553cf6d38304caddfc133130b9480010 100644 (file)
@@ -345,6 +345,7 @@ struct btrfs_fs_info {
        struct completion kobj_unregister;
        int do_barriers;
        int closing;
+       unsigned long throttles;
 
        u64 total_pinned;
        spinlock_t delalloc_lock;
index 34cf1f1f47be41a1ac037fe8ce70b08e4bebada9..e0940a39ff07800e8c44e2e5bfdfdbc160bca296 100644 (file)
@@ -631,6 +631,7 @@ struct btrfs_root *open_ctree(struct super_block *sb)
        fs_info->tree_root = tree_root;
        fs_info->extent_root = extent_root;
        fs_info->sb = sb;
+       fs_info->throttles = 0;
        fs_info->mount_opt = 0;
        fs_info->max_extent = (u64)-1;
        fs_info->delalloc_bytes = 0;
@@ -889,6 +890,12 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
        set_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree, buf);
 }
 
+void btrfs_throttle(struct btrfs_root *root)
+{
+       if (root->fs_info->throttles)
+               congestion_wait(WRITE, HZ/10);
+}
+
 void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr)
 {
        balance_dirty_pages_ratelimited_nr(
index dae9fba8efcd9587969b745b79f44a579a1f15c5..828f3a2081b6d2a148d68d378525cfe5f1cd1dbb 100644 (file)
@@ -64,4 +64,5 @@ int btrfs_clear_buffer_defrag_done(struct extent_buffer *buf);
 int btrfs_read_buffer(struct extent_buffer *buf);
 u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len);
 void btrfs_csum_final(u32 crc, char *result);
+void btrfs_throttle(struct btrfs_root *root);
 #endif
index 0a5f4defe59b1620ff88fbbc75073d5c213a5ecc..897242e87fa79032c59987ed11c33d1684091041 100644 (file)
@@ -800,6 +800,7 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
                balance_dirty_pages_ratelimited_nr(inode->i_mapping, num_pages);
                if (num_pages < (root->leafsize >> PAGE_CACHE_SHIFT) + 1)
                        btrfs_btree_balance_dirty(root, 1);
+               btrfs_throttle(root);
                cond_resched();
        }
 out:
index 10cece11dbd832eef404621bdc8200f62f2e34e3..2cb2dd32407e6390b00c6724876f16b78af1aa63 100644 (file)
@@ -610,6 +610,7 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
 fail:
        mutex_unlock(&root->fs_info->fs_mutex);
        btrfs_btree_balance_dirty(root, nr);
+       btrfs_throttle(root);
        return ret;
 }
 
@@ -644,6 +645,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
 fail:
        mutex_unlock(&root->fs_info->fs_mutex);
        btrfs_btree_balance_dirty(root, nr);
+       btrfs_throttle(root);
 
        if (ret && !err)
                err = ret;
@@ -1010,6 +1012,7 @@ void btrfs_delete_inode(struct inode *inode)
        btrfs_end_transaction(trans, root);
        mutex_unlock(&root->fs_info->fs_mutex);
        btrfs_btree_balance_dirty(root, nr);
+       btrfs_throttle(root);
        return;
 
 no_delete_lock:
@@ -1017,6 +1020,7 @@ no_delete_lock:
        btrfs_end_transaction(trans, root);
        mutex_unlock(&root->fs_info->fs_mutex);
        btrfs_btree_balance_dirty(root, nr);
+       btrfs_throttle(root);
 no_delete:
        clear_inode(inode);
 }
@@ -1574,6 +1578,7 @@ fail:
                iput(inode);
        }
        btrfs_btree_balance_dirty(root, nr);
+       btrfs_throttle(root);
        return err;
 }
 
@@ -1633,6 +1638,7 @@ fail:
                iput(inode);
        }
        btrfs_btree_balance_dirty(root, nr);
+       btrfs_throttle(root);
        return err;
 }
 
@@ -1684,6 +1690,7 @@ fail:
                iput(inode);
        }
        btrfs_btree_balance_dirty(root, nr);
+       btrfs_throttle(root);
        return err;
 }
 
@@ -1752,6 +1759,7 @@ out_unlock:
        if (drop_on_err)
                iput(inode);
        btrfs_btree_balance_dirty(root, nr);
+       btrfs_throttle(root);
        return err;
 }
 
@@ -2117,6 +2125,7 @@ static void btrfs_truncate(struct inode *inode)
        BUG_ON(ret);
        mutex_unlock(&root->fs_info->fs_mutex);
        btrfs_btree_balance_dirty(root, nr);
+       btrfs_throttle(root);
 }
 
 static int noinline create_subvol(struct btrfs_root *root, char *name,
@@ -2245,6 +2254,7 @@ fail:
 fail_commit:
        mutex_unlock(&root->fs_info->fs_mutex);
        btrfs_btree_balance_dirty(root, nr);
+       btrfs_throttle(root);
        return ret;
 }
 
@@ -2287,6 +2297,7 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen)
 fail_unlock:
        mutex_unlock(&root->fs_info->fs_mutex);
        btrfs_btree_balance_dirty(root, nr);
+       btrfs_throttle(root);
        return ret;
 }
 
@@ -2827,6 +2838,7 @@ out_fail:
                iput(inode);
        }
        btrfs_btree_balance_dirty(root, nr);
+       btrfs_throttle(root);
        return err;
 }
 
index dc9865323e38ea73253afdd331ba19929fa43175..614903f5c88444f9faaf1d13b086d384646b3e0e 100644 (file)
@@ -424,6 +424,7 @@ static int drop_dirty_roots(struct btrfs_root *tree_root,
 
                num_bytes = btrfs_root_used(&dirty->root->root_item);
                root = dirty->latest_root;
+               root->fs_info->throttles++;
 
                while(1) {
                        trans = btrfs_start_transaction(tree_root, 1);
@@ -447,6 +448,7 @@ static int drop_dirty_roots(struct btrfs_root *tree_root,
                        mutex_lock(&tree_root->fs_info->fs_mutex);
                }
                BUG_ON(ret);
+               root->fs_info->throttles--;
 
                num_bytes -= btrfs_root_used(&dirty->root->root_item);
                bytes_used = btrfs_root_used(&root->root_item);
@@ -484,6 +486,7 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans,
        u64 objectid = 0;
        int ret;
 
+       root->fs_info->throttles++;
        while(1) {
                ret = btrfs_find_first_ordered_inode(
                                &cur_trans->ordered_inode_tree,
@@ -523,6 +526,7 @@ int btrfs_write_ordered_inodes(struct btrfs_trans_handle *trans,
                mutex_lock(&root->fs_info->fs_mutex);
                mutex_lock(&root->fs_info->trans_mutex);
        }
+       root->fs_info->throttles--;
        return 0;
 }