summaryrefslogtreecommitdiffstats
path: root/module
diff options
context:
space:
mode:
authorMatthew Macy <[email protected]>2019-12-02 10:08:27 -0800
committerBrian Behlendorf <[email protected]>2019-12-02 10:08:27 -0800
commit51420321068e905445e625def28fadc7c3625e13 (patch)
treee45349eef2df831b142fa97d5e21d86aea8cda4d /module
parent42a826eed32cd428a3f7c796c619a854c1f8f9dd (diff)
Move zfs_cmd_t copyin/copyout to platform code
FreeBSD needs to cope with multiple version of the zfs_cmd_t structure. Allowing the platform code to pre and post process the cmd structure makes it possible to work with legacy tooling. Reviewed-by: Jorgen Lundman <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Signed-off-by: Matt Macy <[email protected]> Closes #9624
Diffstat (limited to 'module')
-rw-r--r--module/os/linux/zfs/zfs_ioctl_os.c18
-rw-r--r--module/zfs/zfs_ioctl.c27
2 files changed, 24 insertions, 21 deletions
diff --git a/module/os/linux/zfs/zfs_ioctl_os.c b/module/os/linux/zfs/zfs_ioctl_os.c
index fa47c30ea..2960832a5 100644
--- a/module/os/linux/zfs/zfs_ioctl_os.c
+++ b/module/os/linux/zfs/zfs_ioctl_os.c
@@ -168,9 +168,25 @@ static long
zfsdev_ioctl(struct file *filp, unsigned cmd, unsigned long arg)
{
uint_t vecnum;
+ zfs_cmd_t *zc;
+ int error, rc;
vecnum = cmd - ZFS_IOC_FIRST;
- return (zfsdev_ioctl_common(vecnum, arg));
+
+ zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
+
+ if (ddi_copyin((void *)(uintptr_t)arg, zc, sizeof (zfs_cmd_t), 0)) {
+ error = -SET_ERROR(EFAULT);
+ goto out;
+ }
+ error = -zfsdev_ioctl_common(vecnum, zc);
+ rc = ddi_copyout(zc, (void *)(uintptr_t)arg, sizeof (zfs_cmd_t), 0);
+ if (error == 0 && rc != 0)
+ error = -SET_ERROR(EFAULT);
+out:
+ kmem_free(zc, sizeof (zfs_cmd_t));
+ return (error);
+
}
int
diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c
index 902c0b2b2..a993d02e1 100644
--- a/module/zfs/zfs_ioctl.c
+++ b/module/zfs/zfs_ioctl.c
@@ -7215,18 +7215,19 @@ zfsdev_minor_alloc(void)
}
long
-zfsdev_ioctl_common(uint_t vecnum, unsigned long arg)
+zfsdev_ioctl_common(uint_t vecnum, zfs_cmd_t *zc)
{
- zfs_cmd_t *zc;
- int error, cmd, rc, flag = 0;
+ int error, cmd, flag = 0;
const zfs_ioc_vec_t *vec;
char *saved_poolname = NULL;
nvlist_t *innvl = NULL;
fstrans_cookie_t cookie;
cmd = vecnum;
+ error = 0;
if (vecnum >= sizeof (zfs_ioc_vec) / sizeof (zfs_ioc_vec[0]))
- return (-SET_ERROR(ZFS_ERR_IOC_CMD_UNAVAIL));
+ return (SET_ERROR(ZFS_ERR_IOC_CMD_UNAVAIL));
+
vec = &zfs_ioc_vec[vecnum];
/*
@@ -7234,16 +7235,7 @@ zfsdev_ioctl_common(uint_t vecnum, unsigned long arg)
* a normal or legacy handler are registered.
*/
if (vec->zvec_func == NULL && vec->zvec_legacy_func == NULL)
- return (-SET_ERROR(ZFS_ERR_IOC_CMD_UNAVAIL));
-
- zc = kmem_zalloc(sizeof (zfs_cmd_t), KM_SLEEP);
-
- error = ddi_copyin((void *)(uintptr_t)arg, zc, sizeof (zfs_cmd_t),
- flag);
- if (error != 0) {
- error = SET_ERROR(EFAULT);
- goto out;
- }
+ return (SET_ERROR(ZFS_ERR_IOC_CMD_UNAVAIL));
zc->zc_iflags = flag & FKIOCTL;
if (zc->zc_nvlist_src_size > MAX_NVLIST_SRC_SIZE) {
@@ -7406,9 +7398,6 @@ zfsdev_ioctl_common(uint_t vecnum, unsigned long arg)
out:
nvlist_free(innvl);
- rc = ddi_copyout(zc, (void *)(uintptr_t)arg, sizeof (zfs_cmd_t), flag);
- if (error == 0 && rc != 0)
- error = SET_ERROR(EFAULT);
if (error == 0 && vec->zvec_allow_log) {
char *s = tsd_get(zfs_allow_log_key);
if (s != NULL)
@@ -7418,9 +7407,7 @@ out:
if (saved_poolname != NULL)
kmem_strfree(saved_poolname);
}
-
- kmem_free(zc, sizeof (zfs_cmd_t));
- return (-error);
+ return (error);
}
int