changeset 19273:7b163ea27278

11950 diff_cb() does not handle large dnodes Portions contributed by: Jason King <jason.king@joyent.com> Reviewed by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed by: Tom Caputi <tcaputi@datto.com> Reviewed by: Ryan Moeller <ryan@ixsystems.com> Reviewed by: Kody Kantor <kody.kantor@joyent.com> Reviewed by: Matthias Scheler <mscheler@tintri.com> Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Andy Fiddaman <andy@omniosce.org> Approved by: Dan McDonald <danmcd@joyent.com>
author loli10K <loli10K@users.noreply.github.com>
date Mon, 11 Nov 2019 20:06:07 -0600
parents 18c3b8d11ca1
children 464b9cce4c27
files usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_encrypted.ksh usr/src/uts/common/fs/zfs/dmu_diff.c
diffstat 2 files changed, 14 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_encrypted.ksh	Tue Nov 27 11:31:26 2018 +0200
+++ b/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_diff/zfs_diff_encrypted.ksh	Mon Nov 11 20:06:07 2019 -0600
@@ -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 Nov 27 11:31:26 2018 +0200
+++ b/usr/src/uts/common/fs/zfs/dmu_diff.c	Mon Nov 11 20:06:07 2019 -0600
@@ -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);