Btrfs: Add some simple throttling to wait for data=ordered and snapshot deletion
Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
@@ -345,6 +345,7 @@ struct btrfs_fs_info {
|
|||||||
struct completion kobj_unregister;
|
struct completion kobj_unregister;
|
||||||
int do_barriers;
|
int do_barriers;
|
||||||
int closing;
|
int closing;
|
||||||
|
unsigned long throttles;
|
||||||
|
|
||||||
u64 total_pinned;
|
u64 total_pinned;
|
||||||
spinlock_t delalloc_lock;
|
spinlock_t delalloc_lock;
|
||||||
|
@@ -631,6 +631,7 @@ struct btrfs_root *open_ctree(struct super_block *sb)
|
|||||||
fs_info->tree_root = tree_root;
|
fs_info->tree_root = tree_root;
|
||||||
fs_info->extent_root = extent_root;
|
fs_info->extent_root = extent_root;
|
||||||
fs_info->sb = sb;
|
fs_info->sb = sb;
|
||||||
|
fs_info->throttles = 0;
|
||||||
fs_info->mount_opt = 0;
|
fs_info->mount_opt = 0;
|
||||||
fs_info->max_extent = (u64)-1;
|
fs_info->max_extent = (u64)-1;
|
||||||
fs_info->delalloc_bytes = 0;
|
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);
|
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)
|
void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr)
|
||||||
{
|
{
|
||||||
balance_dirty_pages_ratelimited_nr(
|
balance_dirty_pages_ratelimited_nr(
|
||||||
|
@@ -64,4 +64,5 @@ int btrfs_clear_buffer_defrag_done(struct extent_buffer *buf);
|
|||||||
int btrfs_read_buffer(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);
|
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_csum_final(u32 crc, char *result);
|
||||||
|
void btrfs_throttle(struct btrfs_root *root);
|
||||||
#endif
|
#endif
|
||||||
|
@@ -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);
|
balance_dirty_pages_ratelimited_nr(inode->i_mapping, num_pages);
|
||||||
if (num_pages < (root->leafsize >> PAGE_CACHE_SHIFT) + 1)
|
if (num_pages < (root->leafsize >> PAGE_CACHE_SHIFT) + 1)
|
||||||
btrfs_btree_balance_dirty(root, 1);
|
btrfs_btree_balance_dirty(root, 1);
|
||||||
|
btrfs_throttle(root);
|
||||||
cond_resched();
|
cond_resched();
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
|
@@ -610,6 +610,7 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
|
|||||||
fail:
|
fail:
|
||||||
mutex_unlock(&root->fs_info->fs_mutex);
|
mutex_unlock(&root->fs_info->fs_mutex);
|
||||||
btrfs_btree_balance_dirty(root, nr);
|
btrfs_btree_balance_dirty(root, nr);
|
||||||
|
btrfs_throttle(root);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -644,6 +645,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
|
|||||||
fail:
|
fail:
|
||||||
mutex_unlock(&root->fs_info->fs_mutex);
|
mutex_unlock(&root->fs_info->fs_mutex);
|
||||||
btrfs_btree_balance_dirty(root, nr);
|
btrfs_btree_balance_dirty(root, nr);
|
||||||
|
btrfs_throttle(root);
|
||||||
|
|
||||||
if (ret && !err)
|
if (ret && !err)
|
||||||
err = ret;
|
err = ret;
|
||||||
@@ -1010,6 +1012,7 @@ void btrfs_delete_inode(struct inode *inode)
|
|||||||
btrfs_end_transaction(trans, root);
|
btrfs_end_transaction(trans, root);
|
||||||
mutex_unlock(&root->fs_info->fs_mutex);
|
mutex_unlock(&root->fs_info->fs_mutex);
|
||||||
btrfs_btree_balance_dirty(root, nr);
|
btrfs_btree_balance_dirty(root, nr);
|
||||||
|
btrfs_throttle(root);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
no_delete_lock:
|
no_delete_lock:
|
||||||
@@ -1017,6 +1020,7 @@ no_delete_lock:
|
|||||||
btrfs_end_transaction(trans, root);
|
btrfs_end_transaction(trans, root);
|
||||||
mutex_unlock(&root->fs_info->fs_mutex);
|
mutex_unlock(&root->fs_info->fs_mutex);
|
||||||
btrfs_btree_balance_dirty(root, nr);
|
btrfs_btree_balance_dirty(root, nr);
|
||||||
|
btrfs_throttle(root);
|
||||||
no_delete:
|
no_delete:
|
||||||
clear_inode(inode);
|
clear_inode(inode);
|
||||||
}
|
}
|
||||||
@@ -1574,6 +1578,7 @@ fail:
|
|||||||
iput(inode);
|
iput(inode);
|
||||||
}
|
}
|
||||||
btrfs_btree_balance_dirty(root, nr);
|
btrfs_btree_balance_dirty(root, nr);
|
||||||
|
btrfs_throttle(root);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1633,6 +1638,7 @@ fail:
|
|||||||
iput(inode);
|
iput(inode);
|
||||||
}
|
}
|
||||||
btrfs_btree_balance_dirty(root, nr);
|
btrfs_btree_balance_dirty(root, nr);
|
||||||
|
btrfs_throttle(root);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1684,6 +1690,7 @@ fail:
|
|||||||
iput(inode);
|
iput(inode);
|
||||||
}
|
}
|
||||||
btrfs_btree_balance_dirty(root, nr);
|
btrfs_btree_balance_dirty(root, nr);
|
||||||
|
btrfs_throttle(root);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1752,6 +1759,7 @@ out_unlock:
|
|||||||
if (drop_on_err)
|
if (drop_on_err)
|
||||||
iput(inode);
|
iput(inode);
|
||||||
btrfs_btree_balance_dirty(root, nr);
|
btrfs_btree_balance_dirty(root, nr);
|
||||||
|
btrfs_throttle(root);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2117,6 +2125,7 @@ static void btrfs_truncate(struct inode *inode)
|
|||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
mutex_unlock(&root->fs_info->fs_mutex);
|
mutex_unlock(&root->fs_info->fs_mutex);
|
||||||
btrfs_btree_balance_dirty(root, nr);
|
btrfs_btree_balance_dirty(root, nr);
|
||||||
|
btrfs_throttle(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int noinline create_subvol(struct btrfs_root *root, char *name,
|
static int noinline create_subvol(struct btrfs_root *root, char *name,
|
||||||
@@ -2245,6 +2254,7 @@ fail:
|
|||||||
fail_commit:
|
fail_commit:
|
||||||
mutex_unlock(&root->fs_info->fs_mutex);
|
mutex_unlock(&root->fs_info->fs_mutex);
|
||||||
btrfs_btree_balance_dirty(root, nr);
|
btrfs_btree_balance_dirty(root, nr);
|
||||||
|
btrfs_throttle(root);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2287,6 +2297,7 @@ static int create_snapshot(struct btrfs_root *root, char *name, int namelen)
|
|||||||
fail_unlock:
|
fail_unlock:
|
||||||
mutex_unlock(&root->fs_info->fs_mutex);
|
mutex_unlock(&root->fs_info->fs_mutex);
|
||||||
btrfs_btree_balance_dirty(root, nr);
|
btrfs_btree_balance_dirty(root, nr);
|
||||||
|
btrfs_throttle(root);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2827,6 +2838,7 @@ out_fail:
|
|||||||
iput(inode);
|
iput(inode);
|
||||||
}
|
}
|
||||||
btrfs_btree_balance_dirty(root, nr);
|
btrfs_btree_balance_dirty(root, nr);
|
||||||
|
btrfs_throttle(root);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -424,6 +424,7 @@ static int drop_dirty_roots(struct btrfs_root *tree_root,
|
|||||||
|
|
||||||
num_bytes = btrfs_root_used(&dirty->root->root_item);
|
num_bytes = btrfs_root_used(&dirty->root->root_item);
|
||||||
root = dirty->latest_root;
|
root = dirty->latest_root;
|
||||||
|
root->fs_info->throttles++;
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
trans = btrfs_start_transaction(tree_root, 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);
|
mutex_lock(&tree_root->fs_info->fs_mutex);
|
||||||
}
|
}
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
|
root->fs_info->throttles--;
|
||||||
|
|
||||||
num_bytes -= btrfs_root_used(&dirty->root->root_item);
|
num_bytes -= btrfs_root_used(&dirty->root->root_item);
|
||||||
bytes_used = btrfs_root_used(&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;
|
u64 objectid = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
root->fs_info->throttles++;
|
||||||
while(1) {
|
while(1) {
|
||||||
ret = btrfs_find_first_ordered_inode(
|
ret = btrfs_find_first_ordered_inode(
|
||||||
&cur_trans->ordered_inode_tree,
|
&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->fs_mutex);
|
||||||
mutex_lock(&root->fs_info->trans_mutex);
|
mutex_lock(&root->fs_info->trans_mutex);
|
||||||
}
|
}
|
||||||
|
root->fs_info->throttles--;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user