Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab78c84d authored by Chris Mason's avatar Chris Mason
Browse files

Btrfs: Throttle operations if the reference cache gets too large



A large reference cache is directly related to a lot of work pending
for the cleaner thread.  This throttles back new operations based on
the size of the reference cache so the cleaner thread will be able to keep
up.

Overall, this actually makes the FS faster because the cleaner thread will
be more likely to find things in cache.

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 1a3f5d04
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -580,6 +580,7 @@ struct btrfs_fs_info {
	int do_barriers;
	int closing;
	atomic_t throttles;
	atomic_t throttle_gen;

	u64 total_pinned;
	struct list_head dirty_cowonly_roots;
+5 −2
Original line number Diff line number Diff line
@@ -1171,8 +1171,10 @@ static int transaction_kthread(void *arg)
		vfs_check_frozen(root->fs_info->sb, SB_FREEZE_WRITE);
		mutex_lock(&root->fs_info->transaction_kthread_mutex);

		if (root->fs_info->total_ref_cache_size > 20 * 1024 * 1024) {
			printk("btrfs: total reference cache size %Lu\n",
				root->fs_info->total_ref_cache_size);
		}

		mutex_lock(&root->fs_info->trans_mutex);
		cur = root->fs_info->running_transaction;
@@ -1256,6 +1258,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
	btrfs_mapping_init(&fs_info->mapping_tree);
	atomic_set(&fs_info->nr_async_submits, 0);
	atomic_set(&fs_info->throttles, 0);
	atomic_set(&fs_info->throttle_gen, 0);
	fs_info->sb = sb;
	fs_info->max_extent = (u64)-1;
	fs_info->max_inline = 8192 * 1024;
+1 −0
Original line number Diff line number Diff line
@@ -2650,6 +2650,7 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root
		}
	}
	while(1) {
		atomic_inc(&root->fs_info->throttle_gen);
		wret = walk_down_tree(trans, root, path, &level);
		if (wret > 0)
			break;
+1 −0
Original line number Diff line number Diff line
@@ -974,6 +974,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:
+5 −5
Original line number Diff line number Diff line
@@ -2482,7 +2482,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
	btrfs_update_inode_block_group(trans, dir);
out_unlock:
	nr = trans->blocks_used;
	btrfs_end_transaction(trans, root);
	btrfs_end_transaction_throttle(trans, root);
fail:
	if (drop_inode) {
		inode_dec_link_count(inode);
@@ -2535,7 +2535,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
		drop_inode = 1;

	nr = trans->blocks_used;
	btrfs_end_transaction(trans, root);
	btrfs_end_transaction_throttle(trans, root);
fail:
	if (drop_inode) {
		inode_dec_link_count(inode);
@@ -2609,7 +2609,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)

out_fail:
	nr = trans->blocks_used;
	btrfs_end_transaction(trans, root);
	btrfs_end_transaction_throttle(trans, root);

out_unlock:
	if (drop_on_err)
@@ -3434,7 +3434,7 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry,
		goto out_fail;

out_fail:
	btrfs_end_transaction(trans, root);
	btrfs_end_transaction_throttle(trans, root);
out_unlock:
	return ret;
}
@@ -3548,7 +3548,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,

out_unlock:
	nr = trans->blocks_used;
	btrfs_end_transaction(trans, root);
	btrfs_end_transaction_throttle(trans, root);
out_fail:
	if (drop_inode) {
		inode_dec_link_count(inode);
Loading