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

Commit fdfb1e4f authored by Li Zefan's avatar Li Zefan Committed by Chris Mason
Browse files

Btrfs: Make async snapshot ioctl more generic



If we had reserved some bytes in struct btrfs_ioctl_vol_args, we
wouldn't have to create a new structure for async snapshot creation.

Here we convert async snapshot ioctl to use a more generic ABI, as
we'll add more ioctls for snapshots/subvolumes in the future, readonly
snapshots for example.

Signed-off-by: default avatarLi Zefan <lizf@cn.fujitsu.com>
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 914ee295
Loading
Loading
Loading
Loading
+27 −17
Original line number Diff line number Diff line
@@ -947,31 +947,41 @@ static noinline int btrfs_ioctl_snap_create_transid(struct file *file,

static noinline int btrfs_ioctl_snap_create(struct file *file,
					    void __user *arg, int subvol,
					    int async)
					    int v2)
{
	struct btrfs_ioctl_vol_args *vol_args = NULL;
	struct btrfs_ioctl_async_vol_args *async_vol_args = NULL;
	struct btrfs_ioctl_vol_args_v2 *vol_args_v2 = NULL;
	char *name;
	u64 fd;
	u64 transid = 0;
	int ret;

	if (async) {
		async_vol_args = memdup_user(arg, sizeof(*async_vol_args));
		if (IS_ERR(async_vol_args))
			return PTR_ERR(async_vol_args);
	if (v2) {
		u64 transid = 0;
		u64 *ptr = NULL;

		vol_args_v2 = memdup_user(arg, sizeof(*vol_args_v2));
		if (IS_ERR(vol_args_v2))
			return PTR_ERR(vol_args_v2);

		if (vol_args_v2->flags & ~BTRFS_SUBVOL_CREATE_ASYNC) {
			ret = -EINVAL;
			goto out;
		}

		name = vol_args_v2->name;
		fd = vol_args_v2->fd;
		vol_args_v2->name[BTRFS_SUBVOL_NAME_MAX] = '\0';

		name = async_vol_args->name;
		fd = async_vol_args->fd;
		async_vol_args->name[BTRFS_SNAPSHOT_NAME_MAX] = '\0';
		if (vol_args_v2->flags & BTRFS_SUBVOL_CREATE_ASYNC)
			ptr = &transid;

		ret = btrfs_ioctl_snap_create_transid(file, name, fd,
						      subvol, &transid);
						      subvol, ptr);

		if (ret == 0 &&
		if (ret == 0 && ptr &&
		    copy_to_user(arg +
				 offsetof(struct btrfs_ioctl_async_vol_args,
					  transid), &transid, sizeof(transid)))
				 offsetof(struct btrfs_ioctl_vol_args_v2,
					  transid), ptr, sizeof(*ptr)))
			ret = -EFAULT;
	} else {
		vol_args = memdup_user(arg, sizeof(*vol_args));
@@ -984,9 +994,9 @@ static noinline int btrfs_ioctl_snap_create(struct file *file,
		ret = btrfs_ioctl_snap_create_transid(file, name, fd,
						      subvol, NULL);
	}

out:
	kfree(vol_args);
	kfree(async_vol_args);
	kfree(vol_args_v2);

	return ret;
}
@@ -2248,7 +2258,7 @@ long btrfs_ioctl(struct file *file, unsigned int
		return btrfs_ioctl_getversion(file, argp);
	case BTRFS_IOC_SNAP_CREATE:
		return btrfs_ioctl_snap_create(file, argp, 0, 0);
	case BTRFS_IOC_SNAP_CREATE_ASYNC:
	case BTRFS_IOC_SNAP_CREATE_V2:
		return btrfs_ioctl_snap_create(file, argp, 0, 1);
	case BTRFS_IOC_SUBVOL_CREATE:
		return btrfs_ioctl_snap_create(file, argp, 1, 0);
+9 −5
Original line number Diff line number Diff line
@@ -30,11 +30,15 @@ struct btrfs_ioctl_vol_args {
	char name[BTRFS_PATH_NAME_MAX + 1];
};

#define BTRFS_SNAPSHOT_NAME_MAX 4079
struct btrfs_ioctl_async_vol_args {
#define BTRFS_SUBVOL_CREATE_ASYNC	(1ULL << 0)

#define BTRFS_SUBVOL_NAME_MAX 4039
struct btrfs_ioctl_vol_args_v2 {
	__s64 fd;
	__u64 transid;
	char name[BTRFS_SNAPSHOT_NAME_MAX + 1];
	__u64 flags;
	__u64 unused[4];
	char name[BTRFS_SUBVOL_NAME_MAX + 1];
};

#define BTRFS_INO_LOOKUP_PATH_MAX 4080
@@ -187,6 +191,6 @@ struct btrfs_ioctl_space_args {
				    struct btrfs_ioctl_space_args)
#define BTRFS_IOC_START_SYNC _IOR(BTRFS_IOCTL_MAGIC, 24, __u64)
#define BTRFS_IOC_WAIT_SYNC  _IOW(BTRFS_IOCTL_MAGIC, 22, __u64)
#define BTRFS_IOC_SNAP_CREATE_ASYNC _IOW(BTRFS_IOCTL_MAGIC, 23, \
				   struct btrfs_ioctl_async_vol_args)
#define BTRFS_IOC_SNAP_CREATE_V2 _IOW(BTRFS_IOCTL_MAGIC, 23, \
				   struct btrfs_ioctl_vol_args_v2)
#endif