Commit 6113077c authored by Wang Shilong's avatar Wang Shilong Committed by Chris Mason

Btrfs: fix missing qgroup reservation before fallocating

Steps to reproduce:
	mkfs.btrfs <disk>
	mount <disk> <mnt>
	btrfs quota enable <mnt>
	btrfs sub create <mnt>/subv
	btrfs qgroup limit 10M <mnt>/subv
	fallocate --length 20M <mnt>/subv/data

For the above example, fallocating will return successfully which
is not expected, we try to fix it by doing qgroup reservation before
fallocating.
Signed-off-by: default avatarWang Shilong <wangsl-fnst@cn.fujitsu.com>
Reviewed-by: default avatarMiao Xie <miaox@cn.fujitsu.com>
Signed-off-by: default avatarJosef Bacik <jbacik@fusionio.com>
Signed-off-by: default avatarChris Mason <chris.mason@fusionio.com>
parent 835d974f
...@@ -2142,6 +2142,7 @@ static long btrfs_fallocate(struct file *file, int mode, ...@@ -2142,6 +2142,7 @@ static long btrfs_fallocate(struct file *file, int mode,
{ {
struct inode *inode = file->f_path.dentry->d_inode; struct inode *inode = file->f_path.dentry->d_inode;
struct extent_state *cached_state = NULL; struct extent_state *cached_state = NULL;
struct btrfs_root *root = BTRFS_I(inode)->root;
u64 cur_offset; u64 cur_offset;
u64 last_byte; u64 last_byte;
u64 alloc_start; u64 alloc_start;
...@@ -2169,6 +2170,11 @@ static long btrfs_fallocate(struct file *file, int mode, ...@@ -2169,6 +2170,11 @@ static long btrfs_fallocate(struct file *file, int mode,
ret = btrfs_check_data_free_space(inode, alloc_end - alloc_start); ret = btrfs_check_data_free_space(inode, alloc_end - alloc_start);
if (ret) if (ret)
return ret; return ret;
if (root->fs_info->quota_enabled) {
ret = btrfs_qgroup_reserve(root, alloc_end - alloc_start);
if (ret)
goto out_reserve_fail;
}
/* /*
* wait for ordered IO before we have any locks. We'll loop again * wait for ordered IO before we have any locks. We'll loop again
...@@ -2272,6 +2278,9 @@ static long btrfs_fallocate(struct file *file, int mode, ...@@ -2272,6 +2278,9 @@ static long btrfs_fallocate(struct file *file, int mode,
&cached_state, GFP_NOFS); &cached_state, GFP_NOFS);
out: out:
mutex_unlock(&inode->i_mutex); mutex_unlock(&inode->i_mutex);
if (root->fs_info->quota_enabled)
btrfs_qgroup_free(root, alloc_end - alloc_start);
out_reserve_fail:
/* Let go of our reservation. */ /* Let go of our reservation. */
btrfs_free_reserved_data_space(inode, alloc_end - alloc_start); btrfs_free_reserved_data_space(inode, alloc_end - alloc_start);
return ret; return ret;
......
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