Commit 6d280f4d authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-6.8-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux

Pull btrfs fixes from David Sterba:

 - two fixes preventing deletion and manual creation of subvolume qgroup

 - unify error code returned for unknown send flags

 - fix assertion during subvolume creation when anonymous device could
   be allocated by other thread (e.g. due to backref walk)

* tag 'for-6.8-rc3-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: do not ASSERT() if the newly created subvolume already got read
  btrfs: forbid deleting live subvol qgroup
  btrfs: forbid creating subvol qgroups
  btrfs: send: return EOPNOTSUPP on unknown flags
parents 99bd3cb0 e03ee2fe
......@@ -1336,8 +1336,17 @@ static struct btrfs_root *btrfs_get_root_ref(struct btrfs_fs_info *fs_info,
again:
root = btrfs_lookup_fs_root(fs_info, objectid);
if (root) {
/* Shouldn't get preallocated anon_dev for cached roots */
ASSERT(!anon_dev);
/*
* Some other caller may have read out the newly inserted
* subvolume already (for things like backref walk etc). Not
* that common but still possible. In that case, we just need
* to free the anon_dev.
*/
if (unlikely(anon_dev)) {
free_anon_bdev(anon_dev);
anon_dev = 0;
}
if (check_ref && btrfs_root_refs(&root->root_item) == 0) {
btrfs_put_root(root);
return ERR_PTR(-ENOENT);
......
......@@ -3815,6 +3815,11 @@ static long btrfs_ioctl_qgroup_create(struct file *file, void __user *arg)
goto out;
}
if (sa->create && is_fstree(sa->qgroupid)) {
ret = -EINVAL;
goto out;
}
trans = btrfs_join_transaction(root);
if (IS_ERR(trans)) {
ret = PTR_ERR(trans);
......
......@@ -1736,6 +1736,15 @@ int btrfs_create_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
return ret;
}
static bool qgroup_has_usage(struct btrfs_qgroup *qgroup)
{
return (qgroup->rfer > 0 || qgroup->rfer_cmpr > 0 ||
qgroup->excl > 0 || qgroup->excl_cmpr > 0 ||
qgroup->rsv.values[BTRFS_QGROUP_RSV_DATA] > 0 ||
qgroup->rsv.values[BTRFS_QGROUP_RSV_META_PREALLOC] > 0 ||
qgroup->rsv.values[BTRFS_QGROUP_RSV_META_PERTRANS] > 0);
}
int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
{
struct btrfs_fs_info *fs_info = trans->fs_info;
......@@ -1755,6 +1764,11 @@ int btrfs_remove_qgroup(struct btrfs_trans_handle *trans, u64 qgroupid)
goto out;
}
if (is_fstree(qgroupid) && qgroup_has_usage(qgroup)) {
ret = -EBUSY;
goto out;
}
/* Check if there are no children of this qgroup */
if (!list_empty(&qgroup->members)) {
ret = -EBUSY;
......
......@@ -8111,7 +8111,7 @@ long btrfs_ioctl_send(struct inode *inode, struct btrfs_ioctl_send_args *arg)
}
if (arg->flags & ~BTRFS_SEND_FLAG_MASK) {
ret = -EINVAL;
ret = -EOPNOTSUPP;
goto out;
}
......
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