Commit 6d280f4d authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
Loading
Loading
Loading
Loading
+11 −2
Original line number Diff line number Diff line
@@ -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);
+5 −0
Original line number Diff line number Diff line
@@ -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);
+14 −0
Original line number Diff line number Diff line
@@ -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;
+1 −1
Original line number Diff line number Diff line
@@ -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;
	}