Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 5 Oct 2023 15:10:21 GMT
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 3042b1d8159a - releng/14.0 - makefs/zfs: Ensure that the last block of a file has the right size
Message-ID:  <202310051510.395FALsq071541@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch releng/14.0 has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=3042b1d8159a44faa2bac8c28810ec05025ebfbb

commit 3042b1d8159a44faa2bac8c28810ec05025ebfbb
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2023-09-28 20:16:17 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2023-10-05 14:01:29 +0000

    makefs/zfs: Ensure that the last block of a file has the right size
    
    When copying a file's contents into the pool, a loop copies blocks of
    the maximum size (128KB), allocating space from the vdev for each block.
    The space allocator rounds up to the nearest block size, but for files
    larger than the maximum size, this can result in the last block having a
    smaller logical size than the rest of the blocks belonging to that
    dnode.  This violates some ZFS invariants when appending to that file.
    
    Modify fs_populate_file() to use the same block size for the final
    block.
    
    Approved by:    re (gjb)
    Reported by:    cperciva
    MFC after:      1 week
    Sponsored by:   The FreeBSD Foundation
    
    (cherry picked from commit ef20cd33d3287ebead0d30f2e177fc57a97dc2d5)
    (cherry picked from commit 5175923ef4acb6faff370177fb60700721f13f92)
---
 usr.sbin/makefs/zfs/fs.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/usr.sbin/makefs/zfs/fs.c b/usr.sbin/makefs/zfs/fs.c
index 0d85ea8eb9d8..b0a4c639f256 100644
--- a/usr.sbin/makefs/zfs/fs.c
+++ b/usr.sbin/makefs/zfs/fs.c
@@ -515,7 +515,7 @@ fs_populate_file(fsnode *cur, struct fs_populate_arg *arg)
 	uint64_t dnid;
 	ssize_t n;
 	size_t bufsz;
-	off_t size, target;
+	off_t nbytes, reqbytes, size;
 	int fd;
 
 	assert(cur->type == S_IFREG);
@@ -546,29 +546,30 @@ fs_populate_file(fsnode *cur, struct fs_populate_arg *arg)
 	bufsz = sizeof(zfs->filebuf);
 	size = cur->inode->st.st_size;
 	c = dnode_cursor_init(zfs, arg->fs->os, dnode, size, 0);
-	for (off_t foff = 0; foff < size; foff += target) {
+	for (off_t foff = 0; foff < size; foff += nbytes) {
 		off_t loc, sofar;
 
 		/*
 		 * Fill up our buffer, handling partial reads.
 		 */
 		sofar = 0;
-		target = MIN(size - foff, (off_t)bufsz);
+		nbytes = MIN(size - foff, (off_t)bufsz);
 		do {
-			n = read(fd, buf + sofar, target);
+			n = read(fd, buf + sofar, nbytes);
 			if (n < 0)
 				err(1, "reading from '%s'", cur->name);
 			if (n == 0)
 				errx(1, "unexpected EOF reading '%s'",
 				    cur->name);
 			sofar += n;
-		} while (sofar < target);
+		} while (sofar < nbytes);
 
-		if (target < (off_t)bufsz)
-			memset(buf + target, 0, bufsz - target);
+		if (nbytes < (off_t)bufsz)
+			memset(buf + nbytes, 0, bufsz - nbytes);
 
-		loc = objset_space_alloc(zfs, arg->fs->os, &target);
-		vdev_pwrite_dnode_indir(zfs, dnode, 0, 1, buf, target, loc,
+		reqbytes = foff == 0 ? nbytes : MAXBLOCKSIZE;
+		loc = objset_space_alloc(zfs, arg->fs->os, &reqbytes);
+		vdev_pwrite_dnode_indir(zfs, dnode, 0, 1, buf, reqbytes, loc,
 		    dnode_cursor_next(zfs, c, foff));
 	}
 	eclose(fd);



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