Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 1 Sep 2016 14:06:31 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r305197 - in head/sys/cddl/contrib/opensolaris: common/zfs uts/common/fs/zfs uts/common/fs/zfs/sys
Message-ID:  <201609011406.u81E6VTh097431@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Thu Sep  1 14:06:30 2016
New Revision: 305197
URL: https://svnweb.freebsd.org/changeset/base/305197

Log:
  MFV r302646:
  6980 6902 causes zfs send to break due to 32-bit/64-bit struct mismatch
  
  illumos/illumos-gate@ea4a67f462de0a39a9adea8197bcdef849de5371
  https://github.com/illumos/illumos-gate/commit/ea4a67f462de0a39a9adea8197bcdef84
  9de5371
  
  https://www.illumos.org/issues/6980
    doing zfs send -i snap1 snap2 >testfile results in
    internal error: Invalid argument
    Abort (core dumped)
  
  Reviewed by: Paul Dagnelie <pcd@delphix.com>
  Reviewed by: George Wilson <george.wilson@delphix.com>
  Approved by: Robert Mustacchi <rm@joyent.com>
  Author: Matthew Ahrens <mahrens@delphix.com>

Modified:
  head/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c
  head/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
Directory Properties:
  head/sys/cddl/contrib/opensolaris/   (props changed)

Modified: head/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c	Thu Sep  1 13:38:46 2016	(r305196)
+++ head/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c	Thu Sep  1 14:06:30 2016	(r305197)
@@ -55,8 +55,52 @@ zfs_cmd_compat_get(zfs_cmd_t *zc, caddr_
 	zfs_cmd_zcmd_t *zcmd_c;
 	zfs_cmd_edbp_t *edbp_c;
 	zfs_cmd_resume_t *resume_c;
+	zfs_cmd_inlanes_t *inlanes_c;
 
 	switch (cflag) {
+	case ZFS_CMD_COMPAT_INLANES:
+		inlanes_c = (void *)addr;
+		/* zc */
+		strlcpy(zc->zc_name, inlanes_c->zc_name, MAXPATHLEN);
+		strlcpy(zc->zc_value, inlanes_c->zc_value, MAXPATHLEN * 2);
+		strlcpy(zc->zc_string, inlanes_c->zc_string, MAXPATHLEN);
+
+#define FIELD_COPY(field) zc->field = inlanes_c->field
+		FIELD_COPY(zc_nvlist_src);
+		FIELD_COPY(zc_nvlist_src_size);
+		FIELD_COPY(zc_nvlist_dst);
+		FIELD_COPY(zc_nvlist_dst_size);
+		FIELD_COPY(zc_nvlist_dst_filled);
+		FIELD_COPY(zc_pad2);
+		FIELD_COPY(zc_history);
+		FIELD_COPY(zc_guid);
+		FIELD_COPY(zc_nvlist_conf);
+		FIELD_COPY(zc_nvlist_conf_size);
+		FIELD_COPY(zc_cookie);
+		FIELD_COPY(zc_objset_type);
+		FIELD_COPY(zc_perm_action);
+		FIELD_COPY(zc_history_len);
+		FIELD_COPY(zc_history_offset);
+		FIELD_COPY(zc_obj);
+		FIELD_COPY(zc_iflags);
+		FIELD_COPY(zc_share);
+		FIELD_COPY(zc_jailid);
+		FIELD_COPY(zc_objset_stats);
+		FIELD_COPY(zc_begin_record);
+		FIELD_COPY(zc_inject_record);
+		FIELD_COPY(zc_defer_destroy);
+		FIELD_COPY(zc_flags);
+		FIELD_COPY(zc_action_handle);
+		FIELD_COPY(zc_cleanup_fd);
+		FIELD_COPY(zc_simple);
+		FIELD_COPY(zc_resumable);
+		FIELD_COPY(zc_sendobj);
+		FIELD_COPY(zc_fromobj);
+		FIELD_COPY(zc_createtxg);
+		FIELD_COPY(zc_stat);
+#undef FIELD_COPY
+		break;
+
 	case ZFS_CMD_COMPAT_RESUME:
 		resume_c = (void *)addr;
 		/* zc */
@@ -434,8 +478,50 @@ zfs_cmd_compat_put(zfs_cmd_t *zc, caddr_
 	zfs_cmd_zcmd_t *zcmd_c;
 	zfs_cmd_edbp_t *edbp_c;
 	zfs_cmd_resume_t *resume_c;
+	zfs_cmd_inlanes_t *inlanes_c;
 
 	switch (cflag) {
+	case ZFS_CMD_COMPAT_INLANES:
+		inlanes_c = (void *)addr;
+		strlcpy(inlanes_c->zc_name, zc->zc_name, MAXPATHLEN);
+		strlcpy(inlanes_c->zc_value, zc->zc_value, MAXPATHLEN * 2);
+		strlcpy(inlanes_c->zc_string, zc->zc_string, MAXPATHLEN);
+
+#define FIELD_COPY(field) inlanes_c->field = zc->field
+		FIELD_COPY(zc_nvlist_src);
+		FIELD_COPY(zc_nvlist_src_size);
+		FIELD_COPY(zc_nvlist_dst);
+		FIELD_COPY(zc_nvlist_dst_size);
+		FIELD_COPY(zc_nvlist_dst_filled);
+		FIELD_COPY(zc_pad2);
+		FIELD_COPY(zc_history);
+		FIELD_COPY(zc_guid);
+		FIELD_COPY(zc_nvlist_conf);
+		FIELD_COPY(zc_nvlist_conf_size);
+		FIELD_COPY(zc_cookie);
+		FIELD_COPY(zc_objset_type);
+		FIELD_COPY(zc_perm_action);
+		FIELD_COPY(zc_history_len);
+		FIELD_COPY(zc_history_offset);
+		FIELD_COPY(zc_obj);
+		FIELD_COPY(zc_iflags);
+		FIELD_COPY(zc_share);
+		FIELD_COPY(zc_jailid);
+		FIELD_COPY(zc_objset_stats);
+		FIELD_COPY(zc_begin_record);
+		FIELD_COPY(zc_inject_record);
+		FIELD_COPY(zc_defer_destroy);
+		FIELD_COPY(zc_flags);
+		FIELD_COPY(zc_action_handle);
+		FIELD_COPY(zc_cleanup_fd);
+		FIELD_COPY(zc_simple);
+		FIELD_COPY(zc_sendobj);
+		FIELD_COPY(zc_fromobj);
+		FIELD_COPY(zc_createtxg);
+		FIELD_COPY(zc_stat);
+#undef FIELD_COPY
+		break;
+
 	case ZFS_CMD_COMPAT_RESUME:
 		resume_c = (void *)addr;
 		strlcpy(resume_c->zc_name, zc->zc_name, MAXPATHLEN);
@@ -987,6 +1073,12 @@ zcmd_ioctl_compat(int fd, int request, z
 		zp.zfs_cmd_size = sizeof(zfs_cmd_t);
 		zp.zfs_ioctl_version = ZFS_IOCVER_CURRENT;
 		return (ioctl(fd, ncmd, &zp));
+	case ZFS_CMD_COMPAT_INLANES:
+		ncmd = _IOWR('Z', request, struct zfs_iocparm);
+		zp.zfs_cmd = (uint64_t)zc;
+		zp.zfs_cmd_size = sizeof(zfs_cmd_inlanes_t);
+		zp.zfs_ioctl_version = ZFS_IOCVER_INLANES;
+		return (ioctl(fd, ncmd, &zp));
 	case ZFS_CMD_COMPAT_RESUME:
 		ncmd = _IOWR('Z', request, struct zfs_iocparm);
 		zp.zfs_cmd = (uint64_t)zc;
@@ -1104,7 +1196,7 @@ zfs_ioctl_compat_innvl(zfs_cmd_t *zc, nv
 
 	if (cflag == ZFS_CMD_COMPAT_NONE || cflag == ZFS_CMD_COMPAT_LZC ||
 	    cflag == ZFS_CMD_COMPAT_ZCMD || cflag == ZFS_CMD_COMPAT_EDBP ||
-	    cflag == ZFS_CMD_COMPAT_RESUME)
+	    cflag == ZFS_CMD_COMPAT_RESUME || cflag == ZFS_CMD_COMPAT_INLANES)
 		goto out;
 
 	switch (vec) {
@@ -1257,7 +1349,7 @@ zfs_ioctl_compat_outnvl(zfs_cmd_t *zc, n
 
 	if (cflag == ZFS_CMD_COMPAT_NONE || cflag == ZFS_CMD_COMPAT_LZC ||
 	    cflag == ZFS_CMD_COMPAT_ZCMD || cflag == ZFS_CMD_COMPAT_EDBP ||
-	    cflag == ZFS_CMD_COMPAT_RESUME)
+	    cflag == ZFS_CMD_COMPAT_RESUME || cflag == ZFS_CMD_COMPAT_INLANES)
 		return (outnvl);
 
 	switch (vec) {

Modified: head/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h
==============================================================================
--- head/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h	Thu Sep  1 13:38:46 2016	(r305196)
+++ head/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.h	Thu Sep  1 14:06:30 2016	(r305197)
@@ -54,7 +54,8 @@ extern "C" {
 #define	ZFS_IOCVER_EDBP		4
 #define	ZFS_IOCVER_RESUME	5
 #define	ZFS_IOCVER_INLANES	6
-#define	ZFS_IOCVER_CURRENT	ZFS_IOCVER_INLANES
+#define	ZFS_IOCVER_PAD		7
+#define	ZFS_IOCVER_CURRENT	ZFS_IOCVER_PAD
 
 /* compatibility conversion flag */
 #define	ZFS_CMD_COMPAT_NONE	0
@@ -65,6 +66,7 @@ extern "C" {
 #define	ZFS_CMD_COMPAT_ZCMD	5
 #define	ZFS_CMD_COMPAT_EDBP	6
 #define	ZFS_CMD_COMPAT_RESUME	7
+#define	ZFS_CMD_COMPAT_INLANES	8
 
 #define	ZFS_IOC_COMPAT_PASS	254
 #define	ZFS_IOC_COMPAT_FAIL	255
@@ -355,6 +357,49 @@ typedef struct zfs_cmd_resume {
 	zfs_stat_t	zc_stat;
 } zfs_cmd_resume_t;
 
+typedef struct zfs_cmd_inlanes {
+	char		zc_name[MAXPATHLEN];	/* name of pool or dataset */
+	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;
+	boolean_t	zc_nvlist_dst_filled;	/* put an nvlist in dst? */
+	int		zc_pad2;
+
+	/*
+	 * The following members are for legacy ioctls which haven't been
+	 * converted to the new method.
+	 */
+	uint64_t	zc_history;		/* really (char *) */
+	char		zc_value[MAXPATHLEN * 2];
+	char		zc_string[MAXNAMELEN];
+	uint64_t	zc_guid;
+	uint64_t	zc_nvlist_conf;		/* really (char *) */
+	uint64_t	zc_nvlist_conf_size;
+	uint64_t	zc_cookie;
+	uint64_t	zc_objset_type;
+	uint64_t	zc_perm_action;
+	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;
+	dmu_replay_record_t zc_begin_record;
+	zinject_record_t zc_inject_record;
+	uint32_t	zc_defer_destroy;
+	uint32_t	zc_flags;
+	uint64_t	zc_action_handle;
+	int		zc_cleanup_fd;
+	uint8_t		zc_simple;
+	boolean_t	zc_resumable;
+	uint64_t	zc_sendobj;
+	uint64_t	zc_fromobj;
+	uint64_t	zc_createtxg;
+	zfs_stat_t	zc_stat;
+} zfs_cmd_inlanes_t;
+
 #ifdef _KERNEL
 unsigned static long zfs_ioctl_v15_to_v28[] = {
 	0,	/*  0 ZFS_IOC_POOL_CREATE */

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h	Thu Sep  1 13:38:46 2016	(r305196)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfs_ioctl.h	Thu Sep  1 14:06:30 2016	(r305197)
@@ -353,6 +353,12 @@ typedef enum zfs_case {
 	ZFS_CASE_MIXED
 } zfs_case_t;
 
+/*
+ * Note: this struct must have the same layout in 32-bit and 64-bit, so
+ * that 32-bit processes (like /sbin/zfs) can pass it to the 64-bit
+ * kernel.  Therefore, we add padding to it so that no "hidden" padding
+ * is automatically added on 64-bit (but not on 32-bit).
+ */
 typedef struct zfs_cmd {
 	char		zc_name[MAXPATHLEN];	/* name of pool or dataset */
 	uint64_t	zc_nvlist_src;		/* really (char *) */
@@ -389,7 +395,9 @@ typedef struct zfs_cmd {
 	uint64_t	zc_action_handle;
 	int		zc_cleanup_fd;
 	uint8_t		zc_simple;
+	uint8_t		zc_pad3[3];
 	boolean_t	zc_resumable;
+	uint32_t	zc_pad4;
 	uint64_t	zc_sendobj;
 	uint64_t	zc_fromobj;
 	uint64_t	zc_createtxg;

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c	Thu Sep  1 13:38:46 2016	(r305196)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c	Thu Sep  1 14:06:30 2016	(r305197)
@@ -6252,6 +6252,14 @@ zfsdev_ioctl(struct cdev *dev, u_long zc
 				goto out;
 			}
 			break;
+		case ZFS_IOCVER_INLANES:
+			if (zc_iocparm->zfs_cmd_size != sizeof(zfs_cmd_inlanes_t)) {
+				error = SET_ERROR(EFAULT);
+				goto out;
+			}
+			compat = B_TRUE;
+			cflag = ZFS_CMD_COMPAT_INLANES;
+			break;
 		case ZFS_IOCVER_RESUME:
 			if (zc_iocparm->zfs_cmd_size != sizeof(zfs_cmd_resume_t)) {
 				error = SET_ERROR(EFAULT);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201609011406.u81E6VTh097431>