libzfs_core:
- provide complete backwards compatibility (old utility, new kernel) - add zfs_cmd_t compatibility mapping in both directions - determine ioctl address in zfs_ioctl_compat.c
This commit is contained in:
parent
4f33cfb284
commit
e2b4467975
@ -43,18 +43,18 @@ static int zfs_ioctl_version = 0;
|
||||
static __inline int
|
||||
zcmd_ioctl(int fd, int request, zfs_cmd_t *zc)
|
||||
{
|
||||
unsigned long cmd;
|
||||
size_t oldsize, zfs_kernel_version_size, zfs_ioctl_version_size;
|
||||
int version, ret, cflag = ZFS_CMD_COMPAT_NONE;
|
||||
|
||||
cmd = _IOWR('Z', request, struct zfs_cmd);
|
||||
|
||||
zfs_ioctl_version_size = sizeof(zfs_ioctl_version);
|
||||
if (zfs_ioctl_version == 0) {
|
||||
sysctlbyname("vfs.zfs.version.ioctl", &zfs_ioctl_version,
|
||||
&zfs_ioctl_version_size, NULL, 0);
|
||||
}
|
||||
|
||||
if (zfs_ioctl_version == ZFS_IOCVER_DEADMAN)
|
||||
cflag = ZFS_CMD_COMPAT_DEADMAN;
|
||||
|
||||
/*
|
||||
* If vfs.zfs.version.ioctl is not defined, assume we have v28
|
||||
* compatible binaries and use vfs.zfs.version.spa to test for v15
|
||||
@ -76,7 +76,7 @@ zcmd_ioctl(int fd, int request, zfs_cmd_t *zc)
|
||||
}
|
||||
|
||||
oldsize = zc->zc_nvlist_dst_size;
|
||||
ret = zcmd_ioctl_compat(fd, cmd, zc, cflag);
|
||||
ret = zcmd_ioctl_compat(fd, request, zc, cflag);
|
||||
|
||||
if (ret == 0 && oldsize < zc->zc_nvlist_dst_size) {
|
||||
ret = -1;
|
||||
@ -85,7 +85,7 @@ zcmd_ioctl(int fd, int request, zfs_cmd_t *zc)
|
||||
|
||||
return (ret);
|
||||
}
|
||||
#define ioctl(fd, cmd, zc) zcmd_ioctl((fd), (cmd), (zc))
|
||||
#define ioctl(fd, ioc, zc) zcmd_ioctl((fd), (ioc), (zc))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <sys/nvpair.h>
|
||||
#include <sys/dsl_deleg.h>
|
||||
#include <sys/zfs_ioctl.h>
|
||||
#include "zfs_namecheck.h"
|
||||
#include "zfs_ioctl_compat.h"
|
||||
|
||||
static int zfs_version_ioctl = ZFS_IOCVER_CURRENT;
|
||||
@ -49,8 +50,53 @@ zfs_cmd_compat_get(zfs_cmd_t *zc, caddr_t addr, const int cflag)
|
||||
{
|
||||
zfs_cmd_v15_t *zc_c;
|
||||
zfs_cmd_v28_t *zc28_c;
|
||||
zfs_cmd_deadman_t *zcdm_c;
|
||||
|
||||
switch (cflag) {
|
||||
case ZFS_CMD_COMPAT_DEADMAN:
|
||||
zcdm_c = (void *)addr;
|
||||
/* zc */
|
||||
strlcpy(zc->zc_name, zcdm_c->zc_name, MAXPATHLEN);
|
||||
strlcpy(zc->zc_value, zcdm_c->zc_value, MAXPATHLEN * 2);
|
||||
strlcpy(zc->zc_string, zcdm_c->zc_string, MAXPATHLEN);
|
||||
strlcpy(zc->zc_top_ds, zcdm_c->zc_top_ds, MAXPATHLEN);
|
||||
zc->zc_guid = zcdm_c->zc_guid;
|
||||
zc->zc_nvlist_conf = zcdm_c->zc_nvlist_conf;
|
||||
zc->zc_nvlist_conf_size = zcdm_c->zc_nvlist_conf_size;
|
||||
zc->zc_nvlist_src = zcdm_c->zc_nvlist_src;
|
||||
zc->zc_nvlist_src_size = zcdm_c->zc_nvlist_src_size;
|
||||
zc->zc_nvlist_dst = zcdm_c->zc_nvlist_dst;
|
||||
zc->zc_nvlist_dst_size = zcdm_c->zc_nvlist_dst_size;
|
||||
zc->zc_cookie = zcdm_c->zc_cookie;
|
||||
zc->zc_objset_type = zcdm_c->zc_objset_type;
|
||||
zc->zc_perm_action = zcdm_c->zc_perm_action;
|
||||
zc->zc_history = zcdm_c->zc_history;
|
||||
zc->zc_history_len = zcdm_c->zc_history_len;
|
||||
zc->zc_history_offset = zcdm_c->zc_history_offset;
|
||||
zc->zc_obj = zcdm_c->zc_obj;
|
||||
zc->zc_iflags = zcdm_c->zc_iflags;
|
||||
zc->zc_share = zcdm_c->zc_share;
|
||||
zc->zc_jailid = zcdm_c->zc_jailid;
|
||||
zc->zc_objset_stats = zcdm_c->zc_objset_stats;
|
||||
zc->zc_begin_record = zcdm_c->zc_begin_record;
|
||||
zc->zc_defer_destroy = zcdm_c->zc_defer_destroy;
|
||||
zc->zc_temphold = zcdm_c->zc_temphold;
|
||||
zc->zc_action_handle = zcdm_c->zc_action_handle;
|
||||
zc->zc_cleanup_fd = zcdm_c->zc_cleanup_fd;
|
||||
zc->zc_simple = zcdm_c->zc_simple;
|
||||
bcopy(zcdm_c->zc_pad, zc->zc_pad, sizeof(zc->zc_pad));
|
||||
zc->zc_sendobj = zcdm_c->zc_sendobj;
|
||||
zc->zc_fromobj = zcdm_c->zc_fromobj;
|
||||
zc->zc_createtxg = zcdm_c->zc_createtxg;
|
||||
zc->zc_stat = zcdm_c->zc_stat;
|
||||
|
||||
/* zc_inject_record doesn't change in libzfs_core */
|
||||
zcdm_c->zc_inject_record = zc->zc_inject_record;
|
||||
|
||||
/* we always assume zc_nvlist_dst_filled is true */
|
||||
zc->zc_nvlist_dst_filled = B_TRUE;
|
||||
break;
|
||||
|
||||
case ZFS_CMD_COMPAT_V28:
|
||||
zc28_c = (void *)addr;
|
||||
|
||||
@ -178,8 +224,51 @@ zfs_cmd_compat_put(zfs_cmd_t *zc, caddr_t addr, const int cflag)
|
||||
{
|
||||
zfs_cmd_v15_t *zc_c;
|
||||
zfs_cmd_v28_t *zc28_c;
|
||||
zfs_cmd_deadman_t *zcdm_c;
|
||||
|
||||
switch (cflag) {
|
||||
case ZFS_CMD_COMPAT_DEADMAN:
|
||||
zcdm_c = (void *)addr;
|
||||
|
||||
strlcpy(zcdm_c->zc_name, zc->zc_name, MAXPATHLEN);
|
||||
strlcpy(zcdm_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
|
||||
strlcpy(zcdm_c->zc_string, zc->zc_string, MAXPATHLEN);
|
||||
strlcpy(zcdm_c->zc_top_ds, zc->zc_top_ds, MAXPATHLEN);
|
||||
zcdm_c->zc_guid = zc->zc_guid;
|
||||
zcdm_c->zc_nvlist_conf = zc->zc_nvlist_conf;
|
||||
zcdm_c->zc_nvlist_conf_size = zc->zc_nvlist_conf_size;
|
||||
zcdm_c->zc_nvlist_src = zc->zc_nvlist_src;
|
||||
zcdm_c->zc_nvlist_src_size = zc->zc_nvlist_src_size;
|
||||
zcdm_c->zc_nvlist_dst = zc->zc_nvlist_dst;
|
||||
zcdm_c->zc_nvlist_dst_size = zc->zc_nvlist_dst_size;
|
||||
zcdm_c->zc_cookie = zc->zc_cookie;
|
||||
zcdm_c->zc_objset_type = zc->zc_objset_type;
|
||||
zcdm_c->zc_perm_action = zc->zc_perm_action;
|
||||
zcdm_c->zc_history = zc->zc_history;
|
||||
zcdm_c->zc_history_len = zc->zc_history_len;
|
||||
zcdm_c->zc_history_offset = zc->zc_history_offset;
|
||||
zcdm_c->zc_obj = zc->zc_obj;
|
||||
zcdm_c->zc_iflags = zc->zc_iflags;
|
||||
zcdm_c->zc_share = zc->zc_share;
|
||||
zcdm_c->zc_jailid = zc->zc_jailid;
|
||||
zcdm_c->zc_objset_stats = zc->zc_objset_stats;
|
||||
zcdm_c->zc_begin_record = zc->zc_begin_record;
|
||||
zcdm_c->zc_defer_destroy = zc->zc_defer_destroy;
|
||||
zcdm_c->zc_temphold = zc->zc_temphold;
|
||||
zcdm_c->zc_action_handle = zc->zc_action_handle;
|
||||
zcdm_c->zc_cleanup_fd = zc->zc_cleanup_fd;
|
||||
zcdm_c->zc_simple = zc->zc_simple;
|
||||
bcopy(zc->zc_pad, zcdm_c->zc_pad, sizeof(zcdm_c->zc_pad));
|
||||
zcdm_c->zc_sendobj = zc->zc_sendobj;
|
||||
zcdm_c->zc_fromobj = zc->zc_fromobj;
|
||||
zcdm_c->zc_createtxg = zc->zc_createtxg;
|
||||
zcdm_c->zc_stat = zc->zc_stat;
|
||||
|
||||
/* zc_inject_record doesn't change in libzfs_core */
|
||||
zc->zc_inject_record = zcdm_c->zc_inject_record;
|
||||
|
||||
break;
|
||||
|
||||
case ZFS_CMD_COMPAT_V28:
|
||||
zc28_c = (void *)addr;
|
||||
|
||||
@ -476,7 +565,7 @@ zfs_ioctl_compat_pool_get_props(zfs_cmd_t *zc)
|
||||
|
||||
#ifndef _KERNEL
|
||||
int
|
||||
zcmd_ioctl_compat(int fd, unsigned long cmd, zfs_cmd_t *zc, const int cflag)
|
||||
zcmd_ioctl_compat(int fd, int request, zfs_cmd_t *zc, const int cflag)
|
||||
{
|
||||
int nc, ret;
|
||||
void *zc_c;
|
||||
@ -484,16 +573,21 @@ zcmd_ioctl_compat(int fd, unsigned long cmd, zfs_cmd_t *zc, const int cflag)
|
||||
|
||||
switch (cflag) {
|
||||
case ZFS_CMD_COMPAT_NONE:
|
||||
ret = ioctl(fd, cmd, zc);
|
||||
ncmd = _IOWR('Z', request, struct zfs_cmd);
|
||||
ret = ioctl(fd, ncmd, zc);
|
||||
return (ret);
|
||||
case ZFS_CMD_COMPAT_DEADMAN:
|
||||
zc_c = malloc(sizeof(zfs_cmd_deadman_t));
|
||||
ncmd = _IOWR('Z', request, struct zfs_cmd_deadman);
|
||||
break;
|
||||
case ZFS_CMD_COMPAT_V28:
|
||||
zc_c = malloc(sizeof(zfs_cmd_v28_t));
|
||||
ncmd = _IOWR('Z', ZFS_IOCREQ(cmd), struct zfs_cmd_v28);
|
||||
ncmd = _IOWR('Z', request, struct zfs_cmd_v28);
|
||||
break;
|
||||
case ZFS_CMD_COMPAT_V15:
|
||||
nc = zfs_ioctl_v28_to_v15[ZFS_IOCREQ(cmd)];
|
||||
nc = zfs_ioctl_v28_to_v15[request];
|
||||
zc_c = malloc(sizeof(zfs_cmd_v15_t));
|
||||
ncmd = _IOWR('Z', nc, struct zfs_cmd_v15);
|
||||
ncmd = _IOWR('Z', request, struct zfs_cmd_v15);
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
@ -505,18 +599,18 @@ zcmd_ioctl_compat(int fd, unsigned long cmd, zfs_cmd_t *zc, const int cflag)
|
||||
zfs_cmd_compat_put(zc, (caddr_t)zc_c, cflag);
|
||||
ret = ioctl(fd, ncmd, zc_c);
|
||||
if (cflag == ZFS_CMD_COMPAT_V15 &&
|
||||
nc == 2 /* ZFS_IOC_POOL_IMPORT */)
|
||||
ret = ioctl(fd, _IOWR('Z', 4 /* ZFS_IOC_POOL_CONFIGS */,
|
||||
nc == ZFS_IOC_POOL_IMPORT)
|
||||
ret = ioctl(fd, _IOWR('Z', ZFS_IOC_POOL_CONFIGS,
|
||||
struct zfs_cmd_v15), zc_c);
|
||||
zfs_cmd_compat_get(zc, (caddr_t)zc_c, cflag);
|
||||
free(zc_c);
|
||||
|
||||
if (cflag == ZFS_CMD_COMPAT_V15) {
|
||||
switch (nc) {
|
||||
case 2: /* ZFS_IOC_POOL_IMPORT */
|
||||
case 4: /* ZFS_IOC_POOL_CONFIGS */
|
||||
case 5: /* ZFS_IOC_POOL_STATS */
|
||||
case 6: /* ZFS_IOC_POOL_TRYIMPORT */
|
||||
case ZFS_IOC_POOL_IMPORT:
|
||||
case ZFS_IOC_POOL_CONFIGS:
|
||||
case ZFS_IOC_POOL_STATS:
|
||||
case ZFS_IOC_POOL_TRYIMPORT:
|
||||
zfs_ioctl_compat_fix_stats(zc, nc);
|
||||
break;
|
||||
case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */
|
||||
@ -528,16 +622,25 @@ zcmd_ioctl_compat(int fd, unsigned long cmd, zfs_cmd_t *zc, const int cflag)
|
||||
return (ret);
|
||||
}
|
||||
#else /* _KERNEL */
|
||||
void
|
||||
int
|
||||
zfs_ioctl_compat_pre(zfs_cmd_t *zc, int *vec, const int cflag)
|
||||
{
|
||||
if (cflag == ZFS_CMD_COMPAT_V15)
|
||||
int error = 0;
|
||||
|
||||
/* are we creating a clone? */
|
||||
if (*vec == ZFS_IOC_CREATE && zc->zc_value[0] != '\0')
|
||||
*vec = ZFS_IOC_CLONE;
|
||||
|
||||
if (cflag == ZFS_CMD_COMPAT_V15) {
|
||||
switch (*vec) {
|
||||
|
||||
case 7: /* ZFS_IOC_POOL_SCRUB (v15) */
|
||||
zc->zc_cookie = POOL_SCAN_SCRUB;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
void
|
||||
@ -545,9 +648,9 @@ zfs_ioctl_compat_post(zfs_cmd_t *zc, int vec, const int cflag)
|
||||
{
|
||||
if (cflag == ZFS_CMD_COMPAT_V15) {
|
||||
switch (vec) {
|
||||
case 4: /* ZFS_IOC_POOL_CONFIGS */
|
||||
case 5: /* ZFS_IOC_POOL_STATS */
|
||||
case 6: /* ZFS_IOC_POOL_TRYIMPORT */
|
||||
case ZFS_IOC_POOL_CONFIGS:
|
||||
case ZFS_IOC_POOL_STATS:
|
||||
case ZFS_IOC_POOL_TRYIMPORT:
|
||||
zfs_ioctl_compat_fix_stats(zc, vec);
|
||||
break;
|
||||
case 41: /* ZFS_IOC_POOL_GET_PROPS (v15) */
|
||||
@ -556,4 +659,127 @@ zfs_ioctl_compat_post(zfs_cmd_t *zc, int vec, const int cflag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nvlist_t *
|
||||
zfs_ioctl_compat_innvl(zfs_cmd_t *zc, nvlist_t * innvl, const int vec,
|
||||
const int cflag)
|
||||
{
|
||||
nvlist_t *nvl, *tmpnvl;
|
||||
char *poolname, *snapname;
|
||||
int err;
|
||||
|
||||
if (cflag == ZFS_CMD_COMPAT_NONE)
|
||||
goto out;
|
||||
|
||||
switch (vec) {
|
||||
case ZFS_IOC_CREATE:
|
||||
nvl = fnvlist_alloc();
|
||||
fnvlist_add_int32(nvl, "type", zc->zc_objset_type);
|
||||
if (innvl != NULL) {
|
||||
fnvlist_add_nvlist(nvl, "props", innvl);
|
||||
nvlist_free(innvl);
|
||||
}
|
||||
return (nvl);
|
||||
break;
|
||||
case ZFS_IOC_CLONE:
|
||||
nvl = fnvlist_alloc();
|
||||
fnvlist_add_string(nvl, "origin", zc->zc_value);
|
||||
if (innvl != NULL) {
|
||||
fnvlist_add_nvlist(nvl, "props", innvl);
|
||||
nvlist_free(innvl);
|
||||
}
|
||||
return (nvl);
|
||||
break;
|
||||
case ZFS_IOC_SNAPSHOT:
|
||||
if (innvl == NULL)
|
||||
goto out;
|
||||
nvl = fnvlist_alloc();
|
||||
fnvlist_add_nvlist(nvl, "props", innvl);
|
||||
tmpnvl = fnvlist_alloc();
|
||||
snapname = kmem_asprintf("%s@%s", zc->zc_name, zc->zc_value);
|
||||
fnvlist_add_boolean(tmpnvl, snapname);
|
||||
kmem_free(snapname, strlen(snapname + 1));
|
||||
/* check if we are doing a recursive snapshot */
|
||||
if (zc->zc_cookie)
|
||||
dmu_get_recursive_snaps_nvl(zc->zc_name, zc->zc_value,
|
||||
tmpnvl);
|
||||
fnvlist_add_nvlist(nvl, "snaps", tmpnvl);
|
||||
fnvlist_free(tmpnvl);
|
||||
nvlist_free(innvl);
|
||||
/* strip dataset part from zc->zc_name */
|
||||
zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
|
||||
return (nvl);
|
||||
break;
|
||||
case ZFS_IOC_SPACE_SNAPS:
|
||||
nvl = fnvlist_alloc();
|
||||
fnvlist_add_string(nvl, "firstsnap", zc->zc_value);
|
||||
if (innvl != NULL)
|
||||
nvlist_free(innvl);
|
||||
return (nvl);
|
||||
break;
|
||||
case ZFS_IOC_DESTROY_SNAPS:
|
||||
if (innvl == NULL && cflag == ZFS_CMD_COMPAT_DEADMAN)
|
||||
goto out;
|
||||
nvl = fnvlist_alloc();
|
||||
if (innvl != NULL) {
|
||||
fnvlist_add_nvlist(nvl, "snaps", innvl);
|
||||
} else {
|
||||
/*
|
||||
* We are probably called by even older binaries,
|
||||
* allocate and populate nvlist with recursive
|
||||
* snapshots
|
||||
*/
|
||||
if (snapshot_namecheck(zc->zc_value, NULL,
|
||||
NULL) == 0) {
|
||||
tmpnvl = fnvlist_alloc();
|
||||
if (dmu_get_recursive_snaps_nvl(zc->zc_name,
|
||||
zc->zc_value, tmpnvl) == 0)
|
||||
fnvlist_add_nvlist(nvl, "snaps",
|
||||
tmpnvl);
|
||||
nvlist_free(tmpnvl);
|
||||
}
|
||||
}
|
||||
if (innvl != NULL)
|
||||
nvlist_free(innvl);
|
||||
/* strip dataset part from zc->zc_name */
|
||||
zc->zc_name[strcspn(zc->zc_name, "/@")] = '\0';
|
||||
return (nvl);
|
||||
break;
|
||||
}
|
||||
out:
|
||||
return (innvl);
|
||||
}
|
||||
|
||||
nvlist_t *
|
||||
zfs_ioctl_compat_outnvl(zfs_cmd_t *zc, nvlist_t * outnvl, const int vec,
|
||||
const int cflag)
|
||||
{
|
||||
nvlist_t *tmpnvl;
|
||||
|
||||
if (cflag == ZFS_CMD_COMPAT_NONE)
|
||||
return (outnvl);
|
||||
|
||||
switch (vec) {
|
||||
case ZFS_IOC_SPACE_SNAPS:
|
||||
(void) nvlist_lookup_uint64(outnvl, "used", &zc->zc_cookie);
|
||||
(void) nvlist_lookup_uint64(outnvl, "compressed",
|
||||
&zc->zc_objset_type);
|
||||
(void) nvlist_lookup_uint64(outnvl, "uncompressed",
|
||||
&zc->zc_perm_action);
|
||||
nvlist_free(outnvl);
|
||||
/* return empty outnvl */
|
||||
tmpnvl = fnvlist_alloc();
|
||||
return (tmpnvl);
|
||||
break;
|
||||
case ZFS_IOC_CREATE:
|
||||
case ZFS_IOC_CLONE:
|
||||
nvlist_free(outnvl);
|
||||
/* return empty outnvl */
|
||||
tmpnvl = fnvlist_alloc();
|
||||
return (tmpnvl);
|
||||
break;
|
||||
}
|
||||
|
||||
return (outnvl);
|
||||
}
|
||||
#endif /* KERNEL */
|
||||
|
@ -45,13 +45,15 @@ extern "C" {
|
||||
*/
|
||||
|
||||
/* ioctl versions for vfs.zfs.version.ioctl */
|
||||
#define ZFS_IOCVER_LZC 2
|
||||
#define ZFS_IOCVER_DEADMAN 1
|
||||
#define ZFS_IOCVER_CURRENT ZFS_IOCVER_DEADMAN
|
||||
#define ZFS_IOCVER_CURRENT ZFS_IOCVER_LZC
|
||||
|
||||
/* compatibility conversion flag */
|
||||
#define ZFS_CMD_COMPAT_NONE 0
|
||||
#define ZFS_CMD_COMPAT_V15 1
|
||||
#define ZFS_CMD_COMPAT_V28 2
|
||||
#define ZFS_CMD_COMPAT_DEADMAN 3
|
||||
|
||||
#define ZFS_IOC_COMPAT_PASS 254
|
||||
#define ZFS_IOC_COMPAT_FAIL 255
|
||||
@ -150,6 +152,44 @@ typedef struct zfs_cmd_v28 {
|
||||
zfs_stat_t zc_stat;
|
||||
} zfs_cmd_v28_t;
|
||||
|
||||
typedef struct zfs_cmd_deadman {
|
||||
char zc_name[MAXPATHLEN];
|
||||
char zc_value[MAXPATHLEN * 2];
|
||||
char zc_string[MAXNAMELEN];
|
||||
char zc_top_ds[MAXPATHLEN];
|
||||
uint64_t zc_guid;
|
||||
uint64_t zc_nvlist_conf; /* really (char *) */
|
||||
uint64_t zc_nvlist_conf_size;
|
||||
uint64_t zc_nvlist_src; /* really (char *) */
|
||||
uint64_t zc_nvlist_src_size;
|
||||
uint64_t zc_nvlist_dst; /* really (char *) */
|
||||
uint64_t zc_nvlist_dst_size;
|
||||
uint64_t zc_cookie;
|
||||
uint64_t zc_objset_type;
|
||||
uint64_t zc_perm_action;
|
||||
uint64_t zc_history; /* really (char *) */
|
||||
uint64_t zc_history_len;
|
||||
uint64_t zc_history_offset;
|
||||
uint64_t zc_obj;
|
||||
uint64_t zc_iflags; /* internal to zfs(7fs) */
|
||||
zfs_share_t zc_share;
|
||||
uint64_t zc_jailid;
|
||||
dmu_objset_stats_t zc_objset_stats;
|
||||
struct drr_begin zc_begin_record;
|
||||
/* zc_inject_record doesn't change in libzfs_core */
|
||||
zinject_record_t zc_inject_record;
|
||||
boolean_t zc_defer_destroy;
|
||||
boolean_t zc_temphold;
|
||||
uint64_t zc_action_handle;
|
||||
int zc_cleanup_fd;
|
||||
uint8_t zc_simple;
|
||||
uint8_t zc_pad[3]; /* alignment */
|
||||
uint64_t zc_sendobj;
|
||||
uint64_t zc_fromobj;
|
||||
uint64_t zc_createtxg;
|
||||
zfs_stat_t zc_stat;
|
||||
} zfs_cmd_deadman_t;
|
||||
|
||||
#ifdef _KERNEL
|
||||
unsigned static long zfs_ioctl_v15_to_v28[] = {
|
||||
0, /* 0 ZFS_IOC_POOL_CREATE */
|
||||
@ -274,10 +314,14 @@ unsigned static long zfs_ioctl_v28_to_v15[] = {
|
||||
#endif /* ! _KERNEL */
|
||||
|
||||
#ifdef _KERNEL
|
||||
void zfs_ioctl_compat_pre(zfs_cmd_t *, int *, const int);
|
||||
int zfs_ioctl_compat_pre(zfs_cmd_t *, int *, const int);
|
||||
void zfs_ioctl_compat_post(zfs_cmd_t *, const int, const int);
|
||||
nvlist_t *zfs_ioctl_compat_innvl(zfs_cmd_t *, nvlist_t *, const int,
|
||||
const int);
|
||||
nvlist_t *zfs_ioctl_compat_outnvl(zfs_cmd_t *, nvlist_t *, const int,
|
||||
const int);
|
||||
#else
|
||||
int zcmd_ioctl_compat(int, unsigned long, zfs_cmd_t *, const int);
|
||||
int zcmd_ioctl_compat(int, int, zfs_cmd_t *, const int);
|
||||
#endif /* _KERNEL */
|
||||
void zfs_cmd_compat_get(zfs_cmd_t *, caddr_t, const int);
|
||||
void zfs_cmd_compat_put(zfs_cmd_t *, caddr_t, const int);
|
||||
|
@ -5805,7 +5805,7 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t arg, int flag,
|
||||
#ifdef illumos
|
||||
minor_t minor = getminor(dev);
|
||||
#else
|
||||
int cflag, cmd;
|
||||
int cflag, cmd, oldvecnum;
|
||||
cred_t *cr = td->td_ucred;
|
||||
#endif
|
||||
const zfs_ioc_vec_t *vec;
|
||||
@ -5821,7 +5821,10 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t arg, int flag,
|
||||
* and translate zfs_cmd if necessary
|
||||
*/
|
||||
if (len < sizeof(zfs_cmd_t))
|
||||
if (len == sizeof(zfs_cmd_v28_t)) {
|
||||
if (len == sizeof(zfs_cmd_deadman_t)) {
|
||||
cflag = ZFS_CMD_COMPAT_DEADMAN;
|
||||
vecnum = cmd;
|
||||
} else if (len == sizeof(zfs_cmd_v28_t)) {
|
||||
cflag = ZFS_CMD_COMPAT_V28;
|
||||
vecnum = cmd;
|
||||
} else if (len == sizeof(zfs_cmd_v15_t)) {
|
||||
@ -5870,7 +5873,12 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t arg, int flag,
|
||||
zc = kmem_zalloc(sizeof(zfs_cmd_t), KM_SLEEP);
|
||||
bzero(zc, sizeof(zfs_cmd_t));
|
||||
zfs_cmd_compat_get(zc, arg, cflag);
|
||||
zfs_ioctl_compat_pre(zc, &vecnum, cflag);
|
||||
oldvecnum = vecnum;
|
||||
error = zfs_ioctl_compat_pre(zc, &vecnum, cflag);
|
||||
if (error != 0)
|
||||
goto out;
|
||||
if (oldvecnum != vecnum)
|
||||
vec = &zfs_ioc_vec[vecnum];
|
||||
} else
|
||||
zc = (void *)arg;
|
||||
|
||||
@ -5882,6 +5890,10 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t arg, int flag,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* rewrite innvl for backwards compatibility */
|
||||
if (cflag != ZFS_CMD_COMPAT_NONE)
|
||||
innvl = zfs_ioctl_compat_innvl(zc, innvl, vecnum, cflag);
|
||||
|
||||
/*
|
||||
* Ensure that all pool/dataset names are valid before we pass down to
|
||||
* the lower layers.
|
||||
@ -5955,6 +5967,11 @@ zfsdev_ioctl(struct cdev *dev, u_long zcmd, caddr_t arg, int flag,
|
||||
}
|
||||
fnvlist_free(lognv);
|
||||
|
||||
/* rewrite outnvl for backwards compatibility */
|
||||
if (cflag != ZFS_CMD_COMPAT_NONE)
|
||||
outnvl = zfs_ioctl_compat_outnvl(zc, outnvl, vecnum,
|
||||
cflag);
|
||||
|
||||
if (!nvlist_empty(outnvl) || zc->zc_nvlist_dst_size != 0) {
|
||||
int smusherror = 0;
|
||||
if (vec->zvec_smush_outnvlist) {
|
||||
|
Loading…
Reference in New Issue
Block a user