svn commit: r220447 - in head/sys/cddl: compat/opensolaris/sys contrib/opensolaris/common/zfs

Martin Matuska mm at FreeBSD.org
Fri Apr 8 11:08:27 UTC 2011


Author: mm
Date: Fri Apr  8 11:08:26 2011
New Revision: 220447
URL: http://svn.freebsd.org/changeset/base/220447

Log:
  Partially fix ZFS compat code for sparc64.
  Some endianess bugs still need to be resolved.
  
  Submitted by:	marius (parts of the fix)
  MFC after:	1 month

Modified:
  head/sys/cddl/compat/opensolaris/sys/sunddi.h
  head/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c

Modified: head/sys/cddl/compat/opensolaris/sys/sunddi.h
==============================================================================
--- head/sys/cddl/compat/opensolaris/sys/sunddi.h	Fri Apr  8 09:56:31 2011	(r220446)
+++ head/sys/cddl/compat/opensolaris/sys/sunddi.h	Fri Apr  8 11:08:26 2011	(r220447)
@@ -37,8 +37,10 @@
 
 #define	strdup(ptr)				strdup((ptr), M_SOLARIS)
 #define	ddi_driver_major(zfs_dip)		(0)
-#define	ddi_copyin(from, to, size, flag)	(bcopy((from), (to), (size)), 0)
-#define	ddi_copyout(from, to, size, flag)	(bcopy((from), (to), (size)), 0)
+#define	ddi_copyin(from, to, size, flag)				\
+	(copyin((from), (to), (size)), 0)
+#define	ddi_copyout(from, to, size, flag)				\
+	(copyout((from), (to), (size)), 0)
 int ddi_strtol(const char *str, char **nptr, int base, long *result);
 int ddi_strtoul(const char *str, char **nptr, int base, unsigned long *result);
 int ddi_strtoull(const char *str, char **nptr, int base,

Modified: head/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c	Fri Apr  8 09:56:31 2011	(r220446)
+++ head/sys/cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c	Fri Apr  8 11:08:26 2011	(r220447)
@@ -20,6 +20,8 @@
  */
 /*
  * Copyright 2010 Martin Matuska <mm at FreeBSD.org>. All rights reserved.
+ * Portions Copyright 2005, 2010, Oracle and/or its affiliates.
+ * All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -151,17 +153,69 @@ zfs_cmd_compat_put(zfs_cmd_t *zc, caddr_
 }
 
 static int
-zfs_ioctl_compat_write_nvlist_dst(zfs_cmd_t *zc, nvlist_t *nvl, size_t nvsize)
+zfs_ioctl_compat_get_nvlist(uint64_t nvl, size_t size, int iflag,
+    nvlist_t **nvp)
 {
-	char *packed = (void *)(uintptr_t)zc->zc_nvlist_dst;
-	int err;
+	char *packed;
+	int error;
+	nvlist_t *list = NULL;
+
+	/*
+	 * Read in and unpack the user-supplied nvlist.
+	 */
+	if (size == 0)
+		return (EINVAL);
+
+#ifdef _KERNEL
+	packed = kmem_alloc(size, KM_SLEEP);
+	if ((error = ddi_copyin((void *)(uintptr_t)nvl, packed, size,
+	    iflag)) != 0) {
+		kmem_free(packed, size);
+		return (error);
+	}
+#else
+	packed = (void *)(uintptr_t)nvl;
+#endif
 
-	err = nvlist_pack(nvl, &packed, &nvsize,
-	    NV_ENCODE_NATIVE, 0);
-	if (err == 0)
-		zc->zc_nvlist_dst_size = nvsize;
+	error = nvlist_unpack(packed, size, &list, 0);
 
-	return (err);
+#ifdef _KERNEL
+	kmem_free(packed, size);
+#endif
+
+	if (error != 0)
+		return (error);
+
+	*nvp = list;
+	return (0);
+}
+
+static int
+zfs_ioctl_compat_put_nvlist(zfs_cmd_t *zc, nvlist_t *nvl)
+{
+	char *packed = NULL;
+	int error = 0;
+	size_t size;
+
+	VERIFY(nvlist_size(nvl, &size, NV_ENCODE_NATIVE) == 0);
+
+#ifdef _KERNEL
+	packed = kmem_alloc(size, KM_SLEEP);
+	VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE,
+	    KM_SLEEP) == 0);
+
+	if (ddi_copyout(packed,
+	    (void *)(uintptr_t)zc->zc_nvlist_dst, size, zc->zc_iflags) != 0)
+		error = EFAULT;
+	kmem_free(packed, size);
+#else
+	packed = (void *)(uintptr_t)zc->zc_nvlist_dst;
+	VERIFY(nvlist_pack(nvl, &packed, &size, NV_ENCODE_NATIVE,
+	    0) == 0);
+#endif
+
+	zc->zc_nvlist_dst_size = size;
+	return (error);
 }
 
 static void
@@ -205,17 +259,16 @@ zfs_ioctl_compat_fix_stats_nvlist(nvlist
 	}
 }
 
-static void
+static int
 zfs_ioctl_compat_fix_stats(zfs_cmd_t *zc, const int cflag)
 {
 	nvlist_t *nv, *nvp = NULL;
 	nvpair_t *elem;
-	size_t nvsize;
-	char *packed;
+	int error;
 
-	if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst,
-	    zc->zc_nvlist_dst_size, &nv, 0) != 0)
-		return;
+	if ((error = zfs_ioctl_compat_get_nvlist(zc->zc_nvlist_dst,
+	    zc->zc_nvlist_dst_size, zc->zc_iflags, &nv)) != 0)
+		return (error);
 
 	if (cflag == 5) { /* ZFS_IOC_POOL_STATS */
 		elem = NULL;
@@ -227,21 +280,22 @@ zfs_ioctl_compat_fix_stats(zfs_cmd_t *zc
 	} else
 		zfs_ioctl_compat_fix_stats_nvlist(nv);
 
-	VERIFY(nvlist_size(nv, &nvsize, NV_ENCODE_NATIVE) == 0);
-	zfs_ioctl_compat_write_nvlist_dst(zc, nv, nvsize);
+	error = zfs_ioctl_compat_put_nvlist(zc, nv);
 
 	nvlist_free(nv);
+
+	return (error);
 }
 
-static void
+static int
 zfs_ioctl_compat_pool_get_props(zfs_cmd_t *zc)
 {
 	nvlist_t *nv, *nva = NULL;
-	size_t nvsize;
+	int error;
 
-	if (nvlist_unpack((void *)(uintptr_t)zc->zc_nvlist_dst,
-	    zc->zc_nvlist_dst_size, &nv, 0) != 0)
-		return;
+	if ((error = zfs_ioctl_compat_get_nvlist(zc->zc_nvlist_dst,
+	    zc->zc_nvlist_dst_size, zc->zc_iflags, &nv)) != 0)
+		return (error);
 
 #ifdef _KERNEL
 	if (nvlist_lookup_nvlist(nv, "allocated", &nva) == 0) {
@@ -265,10 +319,11 @@ zfs_ioctl_compat_pool_get_props(zfs_cmd_
 	}
 #endif
 
-	VERIFY(nvlist_size(nv, &nvsize, NV_ENCODE_NATIVE) == 0);
-	zfs_ioctl_compat_write_nvlist_dst(zc, nv, nvsize);
+	error = zfs_ioctl_compat_put_nvlist(zc, nv);
 
 	nvlist_free(nv);
+
+	return (error);
 }
 
 #ifndef _KERNEL


More information about the svn-src-all mailing list