changeset 24345:a5baef786b4a

[illumos-gate merge] commit 99d3b4e271d47a93935645d0c2d348d161f90c80 11950 diff_cb() does not handle large dnodes commit c4fc965c904c30ee88c7ec42768b39cdbb328de9 11979 libshell: bitwise comparison always evaluates to false commit e63ea1f970505bef26ee06b3cef54076ad25b94e 12043 Streams ioctl for _I_CMD within kernel causes EFAULT
author Jerry Jelinek <jerry.jelinek@joyent.com>
date Wed, 04 Dec 2019 12:40:25 +0000
parents afc8877b607a (current diff) 7b163ea27278 (diff)
children f0c1751b3aaa
files usr/src/uts/common/os/streamio.c
diffstat 4 files changed, 35 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/lib/libshell/common/sh/nvtree.c	Tue Dec 03 12:37:33 2019 +0000
+++ b/usr/src/lib/libshell/common/sh/nvtree.c	Wed Dec 04 12:40:25 2019 +0000
@@ -428,7 +428,7 @@
 
 	if ((attr=nv_isattr(np,~NV_NOFREE)) || fp)
 	{
-		if((attr&NV_NOPRINT|NV_INTEGER)==NV_NOPRINT)
+		if((attr&(NV_NOPRINT|NV_INTEGER))==NV_NOPRINT)
 			attr &= ~NV_NOPRINT;
 		if(!attr && !fp)
 			return;
--- a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_encrypted.ksh	Tue Dec 03 12:37:33 2019 +0000
+++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_encrypted.ksh	Wed Dec 04 12:40:25 2019 +0000
@@ -31,8 +31,8 @@
 
 function cleanup
 {
-	datasetexists $TESTPOOL/$TESTFS1 && \
-		log_must zfs destroy -r $TESTPOOL/$TESTFS1
+	destroy_dataset "$TESTPOOL/$TESTFS1" "-r"
+	destroy_dataset "$TESTPOOL/$TESTFS2" "-r"
 }
 
 log_assert "'zfs diff' should work with encrypted datasets"
@@ -51,4 +51,13 @@
 # 3. Perform 'zfs diff' and verify no errors occur
 log_must zfs diff -Ft $TESTPOOL/$TESTFS1@snap1 $TESTPOOL/$TESTFS1@snap2
 
+# 4. Perform the same test on a dataset with large dnodes
+log_must eval "echo 'password' | zfs create -o dnodesize=4k \
+	-o encryption=on -o keyformat=passphrase $TESTPOOL/$TESTFS2"
+MNTPOINT="$(get_prop mountpoint $TESTPOOL/$TESTFS2)"
+log_must zfs snapshot $TESTPOOL/$TESTFS2@snap1
+log_must touch "$MNTPOINT/file"
+log_must zfs snapshot $TESTPOOL/$TESTFS2@snap2
+log_must zfs diff -Ft $TESTPOOL/$TESTFS2@snap1 $TESTPOOL/$TESTFS2@snap2
+
 log_pass "'zfs diff' works with encrypted datasets"
--- a/usr/src/uts/common/fs/zfs/dmu_diff.c	Tue Dec 03 12:37:33 2019 +0000
+++ b/usr/src/uts/common/fs/zfs/dmu_diff.c	Wed Dec 04 12:40:25 2019 +0000
@@ -21,6 +21,7 @@
 /*
  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2019, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
  */
 
 #include <sys/dmu.h>
@@ -130,7 +131,7 @@
 		dnode_phys_t *blk;
 		arc_buf_t *abuf;
 		arc_flags_t aflags = ARC_FLAG_WAIT;
-		int blksz = BP_GET_LSIZE(bp);
+		int epb = BP_GET_LSIZE(bp) >> DNODE_SHIFT;
 		int zio_flags = ZIO_FLAG_CANFAIL;
 		int i;
 
@@ -142,7 +143,7 @@
 			return (SET_ERROR(EIO));
 
 		blk = abuf->b_data;
-		for (i = 0; i < blksz >> DNODE_SHIFT; i++) {
+		for (i = 0; i < epb; i += blk[i].dn_extra_slots + 1) {
 			uint64_t dnobj = (zb->zb_blkid <<
 			    (DNODE_BLOCK_SHIFT - DNODE_SHIFT)) + i;
 			err = report_dnode(da, dnobj, blk+i);
--- a/usr/src/uts/common/os/streamio.c	Tue Dec 03 12:37:33 2019 +0000
+++ b/usr/src/uts/common/os/streamio.c	Wed Dec 04 12:40:25 2019 +0000
@@ -3613,29 +3613,39 @@
 		if (stp->sd_flag & STRHUP)
 			return (ENXIO);
 
-		if ((scp = kmem_alloc(sizeof (strcmd_t), KM_NOSLEEP)) == NULL)
-			return (ENOMEM);
-
-		if (copyin((void *)arg, scp, sizeof (strcmd_t))) {
-			kmem_free(scp, sizeof (strcmd_t));
-			return (EFAULT);
+		if (copyflag == U_TO_K) {
+			if ((scp = kmem_alloc(sizeof (strcmd_t),
+			    KM_NOSLEEP)) == NULL) {
+				return (ENOMEM);
+			}
+
+			if (copyin((void *)arg, scp, sizeof (strcmd_t))) {
+				kmem_free(scp, sizeof (strcmd_t));
+				return (EFAULT);
+			}
+		} else {
+			scp = (strcmd_t *)arg;
 		}
 
 		access = job_control_type(scp->sc_cmd);
 		mutex_enter(&stp->sd_lock);
 		if (access != -1 && (error = i_straccess(stp, access)) != 0) {
 			mutex_exit(&stp->sd_lock);
-			kmem_free(scp, sizeof (strcmd_t));
+			if (copyflag == U_TO_K)
+				kmem_free(scp, sizeof (strcmd_t));
 			return (error);
 		}
 		mutex_exit(&stp->sd_lock);
 
 		*rvalp = 0;
 		if ((error = strdocmd(stp, scp, crp)) == 0) {
-			if (copyout(scp, (void *)arg, sizeof (strcmd_t)))
+			if (copyflag == U_TO_K &&
+			    copyout(scp, (void *)arg, sizeof (strcmd_t))) {
 				error = EFAULT;
-		}
-		kmem_free(scp, sizeof (strcmd_t));
+			}
+		}
+		if (copyflag == U_TO_K)
+			kmem_free(scp, sizeof (strcmd_t));
 		return (error);
 
 	case I_NREAD: