git: 59288c719dc2 - releng/13.1 - stand: zfs: handle holes at the tail end correctly

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Sun, 24 Apr 2022 23:15:39 UTC
The branch releng/13.1 has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=59288c719dc2af9b59e33a88f9b138c5bac38335

commit 59288c719dc2af9b59e33a88f9b138c5bac38335
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2022-04-21 19:57:24 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2022-04-24 23:15:07 +0000

    stand: zfs: handle holes at the tail end correctly
    
    This mirrors dmu_read_impl(), zeroing out the tail end of the buffer and
    clipping the read to what's contained by the block that exists.
    
    This fixes an issue that arose during the 13.1 release process; in
    13.1-RC1 and later, setting up GELI+ZFS will result in a failure to
    boot.  The culprit is this, which causes us to fail to load geom_eli.ko
    as there's a residual portion after the single datablk that should be
    zeroed out.
    
    PR:             263407
    Reviewed by:    tsoome
    Approved by:    re (gjb)
    
    (cherry picked from commit 914dc91d12198352b7878a88d30e2a6373a936e1)
    (cherry picked from commit 0c9c8a4c6459a8cd1b7290ae7dcd9452d3a4dbc1)
---
 stand/libsa/zfs/zfsimpl.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/stand/libsa/zfs/zfsimpl.c b/stand/libsa/zfs/zfsimpl.c
index ceaeeb2e77f3..2240eb765c41 100644
--- a/stand/libsa/zfs/zfsimpl.c
+++ b/stand/libsa/zfs/zfsimpl.c
@@ -2349,6 +2349,19 @@ dnode_read(const spa_t *spa, const dnode_phys_t *dnode, off_t offset,
 		return (EIO);
 	}
 
+	/*
+	 * Handle odd block sizes, mirrors dmu_read_impl().  Data can't exist
+	 * past the first block, so we'll clip the read to the portion of the
+	 * buffer within bsize and zero out the remainder.
+	 */
+	if (dnode->dn_maxblkid == 0) {
+		size_t newbuflen;
+
+		newbuflen = offset > bsize ? 0 : MIN(buflen, bsize - offset);
+		bzero((char *)buf + newbuflen, buflen - newbuflen);
+		buflen = newbuflen;
+	}
+
 	/*
 	 * Note: bsize may not be a power of two here so we need to do an
 	 * actual divide rather than a bitshift.