diff --git a/sys/contrib/openzfs/cmd/zdb/zdb.c b/sys/contrib/openzfs/cmd/zdb/zdb.c
index cd934b2ae9a..2062f4fa102 100644
--- a/sys/contrib/openzfs/cmd/zdb/zdb.c
+++ b/sys/contrib/openzfs/cmd/zdb/zdb.c
@@ -2360,7 +2360,7 @@ static void
snprintf_zstd_header(spa_t *spa, char *blkbuf, size_t buflen,
const blkptr_t *bp)
{
- abd_t *pabd;
+ static abd_t *pabd = NULL;
void *buf;
zio_t *zio;
zfs_zstdhdr_t zstd_hdr;
@@ -2391,7 +2391,8 @@ snprintf_zstd_header(spa_t *spa, char *blkbuf, size_t buflen,
return;
}
- pabd = abd_alloc_for_io(SPA_MAXBLOCKSIZE, B_FALSE);
+ if (!pabd)
+ pabd = abd_alloc_for_io(SPA_MAXBLOCKSIZE, B_FALSE);
zio = zio_root(spa, NULL, NULL, 0);
/* Decrypt but don't decompress so we can read the compression header */
@@ -8487,11 +8488,45 @@ zdb_parse_block_sizes(char *sizes, uint64_t *lsize, uint64_t *psize)
#define ZIO_COMPRESS_MASK(alg) (1ULL << (ZIO_COMPRESS_##alg))
static boolean_t
+try_decompress_block(abd_t *pabd, uint64_t lsize, uint64_t psize,
+ int flags, int cfunc, void *lbuf, void *lbuf2)
+{
+ if (flags & ZDB_FLAG_VERBOSE) {
+ (void) fprintf(stderr,
+ "Trying %05llx -> %05llx (%s)\n",
+ (u_longlong_t)psize,
+ (u_longlong_t)lsize,
+ zio_compress_table[cfunc].ci_name);
+ }
+
+ /*
+ * We set lbuf to all zeros and lbuf2 to all
+ * ones, then decompress to both buffers and
+ * compare their contents. This way we can
+ * know if decompression filled exactly to
+ * lsize or if it left some bytes unwritten.
+ */
+
+ memset(lbuf, 0x00, lsize);
+ memset(lbuf2, 0xff, lsize);
+
+ if (zio_decompress_data(cfunc, pabd,
+ lbuf, psize, lsize, NULL) == 0 &&
+ zio_decompress_data(cfunc, pabd,
+ lbuf2, psize, lsize, NULL) == 0 &&
+ memcmp(lbuf, lbuf2, lsize) == 0)
+ return (B_TRUE);
+ return (B_FALSE);
+}
+
+static uint64_t
zdb_decompress_block(abd_t *pabd, void *buf, void *lbuf, uint64_t lsize,
uint64_t psize, int flags)
{
(void) buf;
- boolean_t exceeded = B_FALSE;
+ uint64_t orig_lsize = lsize;
+ boolean_t tryzle = ((getenv("ZDB_NO_ZLE") == NULL));
+ boolean_t found = B_FALSE;
/*
* We don't know how the data was compressed, so just try
* every decompress function at every inflated blocksize.
@@ -8502,10 +8537,18 @@ zdb_decompress_block(abd_t *pabd, void *buf, void *lbuf, uint64_t lsize,
uint64_t maxlsize = SPA_MAXBLOCKSIZE;
uint64_t mask = ZIO_COMPRESS_MASK(ON) | ZIO_COMPRESS_MASK(OFF) |
ZIO_COMPRESS_MASK(INHERIT) | ZIO_COMPRESS_MASK(EMPTY) |
- (getenv("ZDB_NO_ZLE") ? ZIO_COMPRESS_MASK(ZLE) : 0);
+ ZIO_COMPRESS_MASK(ZLE);
*cfuncp++ = ZIO_COMPRESS_LZ4;
*cfuncp++ = ZIO_COMPRESS_LZJB;
mask |= ZIO_COMPRESS_MASK(LZ4) | ZIO_COMPRESS_MASK(LZJB);
+ /*
+ * Every gzip level has the same decompressor, no need to
+ * run it 9 times per bruteforce attempt.
+ */
+ mask |= ZIO_COMPRESS_MASK(GZIP_2) | ZIO_COMPRESS_MASK(GZIP_3);
+ mask |= ZIO_COMPRESS_MASK(GZIP_4) | ZIO_COMPRESS_MASK(GZIP_5);
+ mask |= ZIO_COMPRESS_MASK(GZIP_6) | ZIO_COMPRESS_MASK(GZIP_7);
+ mask |= ZIO_COMPRESS_MASK(GZIP_8) | ZIO_COMPRESS_MASK(GZIP_9);
for (int c = 0; c < ZIO_COMPRESS_FUNCTIONS; c++)
if (((1ULL << c) & mask) == 0)
*cfuncp++ = c;
@@ -8521,49 +8564,38 @@ zdb_decompress_block(abd_t *pabd, void *buf, void *lbuf, uint64_t lsize,
lsize += SPA_MINBLOCKSIZE;
else
maxlsize = lsize;
+
for (; lsize <= maxlsize; lsize += SPA_MINBLOCKSIZE) {
for (cfuncp = cfuncs; *cfuncp; cfuncp++) {
- if (flags & ZDB_FLAG_VERBOSE) {
- (void) fprintf(stderr,
- "Trying %05llx -> %05llx (%s)\n",
- (u_longlong_t)psize,
- (u_longlong_t)lsize,
- zio_compress_table[*cfuncp].\
- ci_name);
- }
-
- /*
- * We set lbuf to all zeros and lbuf2 to all
- * ones, then decompress to both buffers and
- * compare their contents. This way we can
- * know if decompression filled exactly to
- * lsize or if it left some bytes unwritten.
- */
- memset(lbuf, 0x00, lsize);
- memset(lbuf2, 0xff, lsize);
-
- if (zio_decompress_data(*cfuncp, pabd,
- lbuf, psize, lsize, NULL) == 0 &&
- zio_decompress_data(*cfuncp, pabd,
- lbuf2, psize, lsize, NULL) == 0 &&
- memcmp(lbuf, lbuf2, lsize) == 0)
+ if (try_decompress_block(pabd, lsize, psize, flags,
+ *cfuncp, lbuf, lbuf2)) {
+ found = B_TRUE;
break;
+ }
}
if (*cfuncp != 0)
break;
}
+ if (!found && tryzle) {
+ for (lsize = orig_lsize; lsize <= maxlsize;
+ lsize += SPA_MINBLOCKSIZE) {
+ if (try_decompress_block(pabd, lsize, psize, flags,
+ ZIO_COMPRESS_ZLE, lbuf, lbuf2)) {
+ *cfuncp = ZIO_COMPRESS_ZLE;
+ found = B_TRUE;
+ break;
+ }
+ }
+ }
umem_free(lbuf2, SPA_MAXBLOCKSIZE);
- if (lsize > maxlsize) {
- exceeded = B_TRUE;
- }
if (*cfuncp == ZIO_COMPRESS_ZLE) {
printf("\nZLE decompression was selected. If you "
"suspect the results are wrong,\ntry avoiding ZLE "
"by setting and exporting ZDB_NO_ZLE=\"true\"\n");
}
- return (exceeded);
+ return (lsize > maxlsize ? -1 : lsize);
}
/*
@@ -8742,9 +8774,9 @@ zdb_read_block(char *thing, spa_t *spa)
uint64_t orig_lsize = lsize;
buf = lbuf;
if (flags & ZDB_FLAG_DECOMPRESS) {
- boolean_t failed = zdb_decompress_block(pabd, buf, lbuf,
+ lsize = zdb_decompress_block(pabd, buf, lbuf,
lsize, psize, flags);
- if (failed) {
+ if (lsize == -1) {
(void) printf("Decompress of %s failed\n", thing);
goto out;
}
@@ -8765,11 +8797,11 @@ zdb_read_block(char *thing, spa_t *spa)
abd_return_buf_copy(pabd, buf, lsize);
borrowed = B_FALSE;
buf = lbuf;
- boolean_t failed = zdb_decompress_block(pabd, buf,
+ lsize = zdb_decompress_block(pabd, buf,
lbuf, lsize, psize, flags);
b = (const blkptr_t *)(void *)
((uintptr_t)buf + (uintptr_t)blkptr_offset);
- if (failed || zfs_blkptr_verify(spa, b,
+ if (lsize == -1 || zfs_blkptr_verify(spa, b,
BLK_CONFIG_NEEDED, BLK_VERIFY_LOG) == B_FALSE) {
printf("invalid block pointer at this DVA\n");
goto out;
diff --git a/sys/contrib/openzfs/cmd/zfs/zfs_main.c b/sys/contrib/openzfs/cmd/zfs/zfs_main.c
index da9b2e583d7..d7bee3615df 100644
--- a/sys/contrib/openzfs/cmd/zfs/zfs_main.c
+++ b/sys/contrib/openzfs/cmd/zfs/zfs_main.c
@@ -7234,7 +7234,8 @@ share_mount(int op, int argc, char **argv)
pthread_mutex_init(&share_mount_state.sm_lock, NULL);
/* For a 'zfs share -a' operation start with a clean slate. */
- zfs_truncate_shares(NULL);
+ if (op == OP_SHARE)
+ zfs_truncate_shares(NULL);
/*
* libshare isn't mt-safe, so only do the operation in parallel
diff --git a/sys/contrib/openzfs/config/rpm.am b/sys/contrib/openzfs/config/rpm.am
index 13bd54a625b..85c56c0b2e3 100644
--- a/sys/contrib/openzfs/config/rpm.am
+++ b/sys/contrib/openzfs/config/rpm.am
@@ -83,6 +83,11 @@ srpm-common:
rpm-local || exit 1; \
LANG=C $(RPMBUILD) \
--define "_tmppath $$rpmbuild/TMP" \
+ --define "_builddir $$rpmbuild/BUILD" \
+ --define "_rpmdir $$rpmbuild/RPMS" \
+ --define "_srcrpmdir $$rpmbuild/SRPMS" \
+ --define "_specdir $$rpmbuild/SPECS" \
+ --define "_sourcedir $$rpmbuild/SOURCES" \
--define "_topdir $$rpmbuild" \
$(def) -bs $$rpmbuild/SPECS/$$rpmspec || exit 1; \
cp $$rpmbuild/SRPMS/$$rpmpkg . || exit 1; \
@@ -99,6 +104,11 @@ rpm-common:
rpm-local || exit 1; \
LANG=C ${RPMBUILD} \
--define "_tmppath $$rpmbuild/TMP" \
+ --define "_builddir $$rpmbuild/BUILD" \
+ --define "_rpmdir $$rpmbuild/RPMS" \
+ --define "_srcrpmdir $$rpmbuild/SRPMS" \
+ --define "_specdir $$rpmbuild/SPECS" \
+ --define "_sourcedir $$rpmbuild/SOURCES" \
--define "_topdir $$rpmbuild" \
$(def) --rebuild $$rpmpkg || exit 1; \
cp $$rpmbuild/RPMS/*/* . || exit 1; \
diff --git a/sys/contrib/openzfs/include/sys/spa_impl.h b/sys/contrib/openzfs/include/sys/spa_impl.h
index ee91816ac48..0cd0c4720fb 100644
--- a/sys/contrib/openzfs/include/sys/spa_impl.h
+++ b/sys/contrib/openzfs/include/sys/spa_impl.h
@@ -278,6 +278,7 @@ struct spa {
spa_aux_vdev_t spa_spares; /* hot spares */
spa_aux_vdev_t spa_l2cache; /* L2ARC cache devices */
+ boolean_t spa_aux_sync_uber; /* need to sync aux uber */
nvlist_t *spa_label_features; /* Features for reading MOS */
uint64_t spa_config_object; /* MOS object for pool config */
uint64_t spa_config_generation; /* config generation number */
diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_import.c b/sys/contrib/openzfs/lib/libzfs/libzfs_import.c
index 2a7c5a76a0a..e2d40a7b3bf 100644
--- a/sys/contrib/openzfs/lib/libzfs/libzfs_import.c
+++ b/sys/contrib/openzfs/lib/libzfs/libzfs_import.c
@@ -291,10 +291,8 @@ zpool_in_use(libzfs_handle_t *hdl, int fd, pool_state_t *state, char **namestr,
*inuse = B_FALSE;
- if (zpool_read_label(fd, &config, NULL) != 0) {
- (void) no_memory(hdl);
+ if (zpool_read_label(fd, &config, NULL) != 0)
return (-1);
- }
if (config == NULL)
return (0);
diff --git a/sys/contrib/openzfs/lib/libzutil/zutil_import.c b/sys/contrib/openzfs/lib/libzutil/zutil_import.c
index d023dd10535..eb913119045 100644
--- a/sys/contrib/openzfs/lib/libzutil/zutil_import.c
+++ b/sys/contrib/openzfs/lib/libzutil/zutil_import.c
@@ -1056,10 +1056,21 @@ zpool_read_label(int fd, nvlist_t **config, int *num_labels)
case EINVAL:
break;
case EINPROGRESS:
- // This shouldn't be possible to
- // encounter, die if we do.
+ /*
+ * This shouldn't be possible to
+ * encounter, die if we do.
+ */
ASSERT(B_FALSE);
zfs_fallthrough;
+ case EREMOTEIO:
+ /*
+ * May be returned by an NVMe device
+ * which is visible in /dev/ but due
+ * to a low-level format change, or
+ * other error, needs to be rescanned.
+ * Try the slow method.
+ */
+ zfs_fallthrough;
case EOPNOTSUPP:
case ENOSYS:
do_slow = B_TRUE;
@@ -1210,13 +1221,26 @@ label_paths(libpc_handle_t *hdl, nvlist_t *label, const char **path,
nvlist_t *nvroot;
uint64_t pool_guid;
uint64_t vdev_guid;
+ uint64_t state;
*path = NULL;
*devid = NULL;
+ if (nvlist_lookup_uint64(label, ZPOOL_CONFIG_GUID, &vdev_guid) != 0)
+ return (ENOENT);
+
+ /*
+ * In case of spare or l2cache, we directly return path/devid from the
+ * label.
+ */
+ if (!(nvlist_lookup_uint64(label, ZPOOL_CONFIG_POOL_STATE, &state)) &&
+ (state == POOL_STATE_SPARE || state == POOL_STATE_L2CACHE)) {
+ (void) nvlist_lookup_string(label, ZPOOL_CONFIG_PATH, path);
+ (void) nvlist_lookup_string(label, ZPOOL_CONFIG_DEVID, devid);
+ return (0);
+ }
if (nvlist_lookup_nvlist(label, ZPOOL_CONFIG_VDEV_TREE, &nvroot) ||
- nvlist_lookup_uint64(label, ZPOOL_CONFIG_POOL_GUID, &pool_guid) ||
- nvlist_lookup_uint64(label, ZPOOL_CONFIG_GUID, &vdev_guid))
+ nvlist_lookup_uint64(label, ZPOOL_CONFIG_POOL_GUID, &pool_guid))
return (ENOENT);
return (label_paths_impl(hdl, nvroot, pool_guid, vdev_guid, path,
diff --git a/sys/contrib/openzfs/module/os/linux/spl/spl-condvar.c b/sys/contrib/openzfs/module/os/linux/spl/spl-condvar.c
index e87954714e3..5898789ad53 100644
--- a/sys/contrib/openzfs/module/os/linux/spl/spl-condvar.c
+++ b/sys/contrib/openzfs/module/os/linux/spl/spl-condvar.c
@@ -20,7 +20,7 @@
* You should have received a copy of the GNU General Public License along
* with the SPL. If not, see .
*
- * Solaris Porting Layer (SPL) Credential Implementation.
+ * Solaris Porting Layer (SPL) Condition Variables Implementation.
*/
#include
diff --git a/sys/contrib/openzfs/module/os/linux/spl/spl-kmem-cache.c b/sys/contrib/openzfs/module/os/linux/spl/spl-kmem-cache.c
index a2920c74667..4b15081715a 100644
--- a/sys/contrib/openzfs/module/os/linux/spl/spl-kmem-cache.c
+++ b/sys/contrib/openzfs/module/os/linux/spl/spl-kmem-cache.c
@@ -91,7 +91,8 @@ MODULE_PARM_DESC(spl_kmem_cache_max_size, "Maximum size of slab in MB");
* of 16K was determined to be optimal for architectures using 4K pages and
* to also work well on architecutres using larger 64K page sizes.
*/
-static unsigned int spl_kmem_cache_slab_limit = 16384;
+static unsigned int spl_kmem_cache_slab_limit =
+ SPL_MAX_KMEM_ORDER_NR_PAGES * PAGE_SIZE;
module_param(spl_kmem_cache_slab_limit, uint, 0644);
MODULE_PARM_DESC(spl_kmem_cache_slab_limit,
"Objects less than N bytes use the Linux slab");
@@ -783,7 +784,7 @@ spl_kmem_cache_create(const char *name, size_t size, size_t align,
} else {
unsigned long slabflags = 0;
- if (size > (SPL_MAX_KMEM_ORDER_NR_PAGES * PAGE_SIZE))
+ if (size > spl_kmem_cache_slab_limit)
goto out;
#if defined(SLAB_USERCOPY)
diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zfs_vnops_os.c b/sys/contrib/openzfs/module/os/linux/zfs/zfs_vnops_os.c
index 10162f62cda..b7b89b8afc5 100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/zfs_vnops_os.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/zfs_vnops_os.c
@@ -1856,7 +1856,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zidmap_t *mnt_ns)
{
struct inode *ip;
zfsvfs_t *zfsvfs = ZTOZSB(zp);
- objset_t *os = zfsvfs->z_os;
+ objset_t *os;
zilog_t *zilog;
dmu_tx_t *tx;
vattr_t oldva;
@@ -1888,6 +1888,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zidmap_t *mnt_ns)
if ((err = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
return (err);
ip = ZTOI(zp);
+ os = zfsvfs->z_os;
/*
* If this is a xvattr_t, then get a pointer to the structure of
@@ -2438,9 +2439,8 @@ top:
if ((mask & ATTR_ATIME) || zp->z_atime_dirty) {
zp->z_atime_dirty = B_FALSE;
- inode_timespec_t tmp_atime;
+ inode_timespec_t tmp_atime = zpl_inode_get_atime(ip);
ZFS_TIME_ENCODE(&tmp_atime, atime);
- zpl_inode_set_atime_to_ts(ZTOI(zp), tmp_atime);
SA_ADD_BULK_ATTR(bulk, count, SA_ZPL_ATIME(zfsvfs), NULL,
&atime, sizeof (atime));
}
diff --git a/sys/contrib/openzfs/module/zfs/spa.c b/sys/contrib/openzfs/module/zfs/spa.c
index dc8a99e7bd2..b144d065293 100644
--- a/sys/contrib/openzfs/module/zfs/spa.c
+++ b/sys/contrib/openzfs/module/zfs/spa.c
@@ -1392,7 +1392,7 @@ spa_taskq_param_set(zio_type_t t, char *cfg)
}
static int
-spa_taskq_param_get(zio_type_t t, char *buf)
+spa_taskq_param_get(zio_type_t t, char *buf, boolean_t add_newline)
{
int pos = 0;
@@ -1410,7 +1410,8 @@ spa_taskq_param_get(zio_type_t t, char *buf)
sep = " ";
}
- buf[pos++] = '\n';
+ if (add_newline)
+ buf[pos++] = '\n';
buf[pos] = '\0';
return (pos);
@@ -1428,7 +1429,7 @@ spa_taskq_read_param_set(const char *val, zfs_kernel_param_t *kp)
static int
spa_taskq_read_param_get(char *buf, zfs_kernel_param_t *kp)
{
- return (spa_taskq_param_get(ZIO_TYPE_READ, buf));
+ return (spa_taskq_param_get(ZIO_TYPE_READ, buf, TRUE));
}
static int
@@ -1442,7 +1443,7 @@ spa_taskq_write_param_set(const char *val, zfs_kernel_param_t *kp)
static int
spa_taskq_write_param_get(char *buf, zfs_kernel_param_t *kp)
{
- return (spa_taskq_param_get(ZIO_TYPE_WRITE, buf));
+ return (spa_taskq_param_get(ZIO_TYPE_WRITE, buf, TRUE));
}
#else
/*
@@ -1457,7 +1458,7 @@ spa_taskq_read_param(ZFS_MODULE_PARAM_ARGS)
char buf[SPA_TASKQ_PARAM_MAX];
int err;
- (void) spa_taskq_param_get(ZIO_TYPE_READ, buf);
+ (void) spa_taskq_param_get(ZIO_TYPE_READ, buf, FALSE);
err = sysctl_handle_string(oidp, buf, sizeof (buf), req);
if (err || req->newptr == NULL)
return (err);
@@ -1470,7 +1471,7 @@ spa_taskq_write_param(ZFS_MODULE_PARAM_ARGS)
char buf[SPA_TASKQ_PARAM_MAX];
int err;
- (void) spa_taskq_param_get(ZIO_TYPE_WRITE, buf);
+ (void) spa_taskq_param_get(ZIO_TYPE_WRITE, buf, FALSE);
err = sysctl_handle_string(oidp, buf, sizeof (buf), req);
if (err || req->newptr == NULL)
return (err);
diff --git a/sys/contrib/openzfs/module/zfs/vdev_label.c b/sys/contrib/openzfs/module/zfs/vdev_label.c
index 4c6501cc9a0..c31f48028bb 100644
--- a/sys/contrib/openzfs/module/zfs/vdev_label.c
+++ b/sys/contrib/openzfs/module/zfs/vdev_label.c
@@ -1031,6 +1031,10 @@ vdev_label_init(vdev_t *vd, uint64_t crtxg, vdev_labeltype_t reason)
int error;
uint64_t spare_guid = 0, l2cache_guid = 0;
int flags = ZIO_FLAG_CONFIG_WRITER | ZIO_FLAG_CANFAIL;
+ boolean_t reason_spare = (reason == VDEV_LABEL_SPARE || (reason ==
+ VDEV_LABEL_REMOVE && vd->vdev_isspare));
+ boolean_t reason_l2cache = (reason == VDEV_LABEL_L2CACHE || (reason ==
+ VDEV_LABEL_REMOVE && vd->vdev_isl2cache));
ASSERT(spa_config_held(spa, SCL_ALL, RW_WRITER) == SCL_ALL);
@@ -1116,34 +1120,20 @@ vdev_label_init(vdev_t *vd, uint64_t crtxg, vdev_labeltype_t reason)
* really part of an active pool just yet. The labels will
* be written again with a meaningful txg by spa_sync().
*/
- if (reason == VDEV_LABEL_SPARE ||
- (reason == VDEV_LABEL_REMOVE && vd->vdev_isspare)) {
+ if (reason_spare || reason_l2cache) {
/*
- * For inactive hot spares, we generate a special label that
- * identifies as a mutually shared hot spare. We write the
- * label if we are adding a hot spare, or if we are removing an
- * active hot spare (in which case we want to revert the
- * labels).
+ * For inactive hot spares and level 2 ARC devices, we generate
+ * a special label that identifies as a mutually shared hot
+ * spare or l2cache device. We write the label in case of
+ * addition or removal of hot spare or l2cache vdev (in which
+ * case we want to revert the labels).
*/
VERIFY(nvlist_alloc(&label, NV_UNIQUE_NAME, KM_SLEEP) == 0);
VERIFY(nvlist_add_uint64(label, ZPOOL_CONFIG_VERSION,
spa_version(spa)) == 0);
VERIFY(nvlist_add_uint64(label, ZPOOL_CONFIG_POOL_STATE,
- POOL_STATE_SPARE) == 0);
- VERIFY(nvlist_add_uint64(label, ZPOOL_CONFIG_GUID,
- vd->vdev_guid) == 0);
- } else if (reason == VDEV_LABEL_L2CACHE ||
- (reason == VDEV_LABEL_REMOVE && vd->vdev_isl2cache)) {
- /*
- * For level 2 ARC devices, add a special label.
- */
- VERIFY(nvlist_alloc(&label, NV_UNIQUE_NAME, KM_SLEEP) == 0);
-
- VERIFY(nvlist_add_uint64(label, ZPOOL_CONFIG_VERSION,
- spa_version(spa)) == 0);
- VERIFY(nvlist_add_uint64(label, ZPOOL_CONFIG_POOL_STATE,
- POOL_STATE_L2CACHE) == 0);
+ reason_spare ? POOL_STATE_SPARE : POOL_STATE_L2CACHE) == 0);
VERIFY(nvlist_add_uint64(label, ZPOOL_CONFIG_GUID,
vd->vdev_guid) == 0);
@@ -1154,8 +1144,34 @@ vdev_label_init(vdev_t *vd, uint64_t crtxg, vdev_labeltype_t reason)
* spa->spa_l2cache->sav_config (populated in
* spa_ld_open_aux_vdevs()).
*/
- VERIFY(nvlist_add_uint64(label, ZPOOL_CONFIG_ASHIFT,
- vd->vdev_ashift) == 0);
+ if (reason_l2cache) {
+ VERIFY(nvlist_add_uint64(label, ZPOOL_CONFIG_ASHIFT,
+ vd->vdev_ashift) == 0);
+ }
+
+ /*
+ * Add path information to help find it during pool import
+ */
+ if (vd->vdev_path != NULL) {
+ VERIFY(nvlist_add_string(label, ZPOOL_CONFIG_PATH,
+ vd->vdev_path) == 0);
+ }
+ if (vd->vdev_devid != NULL) {
+ VERIFY(nvlist_add_string(label, ZPOOL_CONFIG_DEVID,
+ vd->vdev_devid) == 0);
+ }
+ if (vd->vdev_physpath != NULL) {
+ VERIFY(nvlist_add_string(label, ZPOOL_CONFIG_PHYS_PATH,
+ vd->vdev_physpath) == 0);
+ }
+
+ /*
+ * When spare or l2cache (aux) vdev is added during pool
+ * creation, spa->spa_uberblock is not written until this
+ * point. Write it on next config sync.
+ */
+ if (uberblock_verify(&spa->spa_uberblock))
+ spa->spa_aux_sync_uber = B_TRUE;
} else {
uint64_t txg = 0ULL;
@@ -1794,6 +1810,16 @@ vdev_uberblock_sync_list(vdev_t **svd, int svdcount, uberblock_t *ub, int flags)
for (int v = 0; v < svdcount; v++)
vdev_uberblock_sync(zio, &good_writes, ub, svd[v], flags);
+ if (spa->spa_aux_sync_uber) {
+ for (int v = 0; v < spa->spa_spares.sav_count; v++) {
+ vdev_uberblock_sync(zio, &good_writes, ub,
+ spa->spa_spares.sav_vdevs[v], flags);
+ }
+ for (int v = 0; v < spa->spa_l2cache.sav_count; v++) {
+ vdev_uberblock_sync(zio, &good_writes, ub,
+ spa->spa_l2cache.sav_vdevs[v], flags);
+ }
+ }
(void) zio_wait(zio);
/*
@@ -1808,6 +1834,19 @@ vdev_uberblock_sync_list(vdev_t **svd, int svdcount, uberblock_t *ub, int flags)
zio_flush(zio, svd[v]);
}
}
+ if (spa->spa_aux_sync_uber) {
+ spa->spa_aux_sync_uber = B_FALSE;
+ for (int v = 0; v < spa->spa_spares.sav_count; v++) {
+ if (vdev_writeable(spa->spa_spares.sav_vdevs[v])) {
+ zio_flush(zio, spa->spa_spares.sav_vdevs[v]);
+ }
+ }
+ for (int v = 0; v < spa->spa_l2cache.sav_count; v++) {
+ if (vdev_writeable(spa->spa_l2cache.sav_vdevs[v])) {
+ zio_flush(zio, spa->spa_l2cache.sav_vdevs[v]);
+ }
+ }
+ }
(void) zio_wait(zio);
diff --git a/sys/contrib/openzfs/module/zfs/vdev_trim.c b/sys/contrib/openzfs/module/zfs/vdev_trim.c
index 1c54eae4035..7e3c5f68470 100644
--- a/sys/contrib/openzfs/module/zfs/vdev_trim.c
+++ b/sys/contrib/openzfs/module/zfs/vdev_trim.c
@@ -196,7 +196,8 @@ vdev_autotrim_wait_kick(vdev_t *vd, int num_of_kick)
for (int i = 0; i < num_of_kick; i++) {
if (vd->vdev_autotrim_exit_wanted)
break;
- cv_wait(&vd->vdev_autotrim_kick_cv, &vd->vdev_autotrim_lock);
+ cv_wait_idle(&vd->vdev_autotrim_kick_cv,
+ &vd->vdev_autotrim_lock);
}
boolean_t exit_wanted = vd->vdev_autotrim_exit_wanted;
mutex_exit(&vd->vdev_autotrim_lock);
diff --git a/sys/contrib/openzfs/module/zfs/zfs_vnops.c b/sys/contrib/openzfs/module/zfs/zfs_vnops.c
index 384cdf0dca9..c8ff7b6432f 100644
--- a/sys/contrib/openzfs/module/zfs/zfs_vnops.c
+++ b/sys/contrib/openzfs/module/zfs/zfs_vnops.c
@@ -795,11 +795,11 @@ zfs_setsecattr(znode_t *zp, vsecattr_t *vsecp, int flag, cred_t *cr)
zfsvfs_t *zfsvfs = ZTOZSB(zp);
int error;
boolean_t skipaclchk = (flag & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE;
- zilog_t *zilog = zfsvfs->z_log;
+ zilog_t *zilog;
if ((error = zfs_enter_verify_zp(zfsvfs, zp, FTAG)) != 0)
return (error);
-
+ zilog = zfsvfs->z_log;
error = zfs_setacl(zp, vsecp, skipaclchk, cr);
if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
@@ -1349,6 +1349,10 @@ zfs_clone_range(znode_t *inzp, uint64_t *inoffp, znode_t *outzp,
break;
}
+ if (zn_has_cached_data(outzp, outoff, outoff + size - 1)) {
+ update_pages(outzp, outoff, size, outos);
+ }
+
zfs_clear_setid_bits_if_necessary(outzfsvfs, outzp, cr,
&clear_setid_bits_txg, tx);
diff --git a/sys/contrib/openzfs/rpm/generic/zfs-kmod.spec.in b/sys/contrib/openzfs/rpm/generic/zfs-kmod.spec.in
index 3c73e2ff2d6..4cc075585d4 100644
--- a/sys/contrib/openzfs/rpm/generic/zfs-kmod.spec.in
+++ b/sys/contrib/openzfs/rpm/generic/zfs-kmod.spec.in
@@ -150,6 +150,30 @@ for kernel_version in %{?kernel_versions}; do
done
+# Module signing (modsign)
+#
+# This must be run _after_ find-debuginfo.sh runs, otherwise that will strip
+# the signature off of the modules.
+# (Based on Fedora's kernel.spec workaround)
+%define __modsign_install_post \
+ sign_pem="%{ksrc}/certs/signing_key.pem"; \
+ sign_x509="%{ksrc}/certs/signing_key.x509"; \
+ if [ -f "${sign_x509}" ]\
+ then \
+ echo "Signing kernel modules ..."; \
+ for kmod in $(find ${RPM_BUILD_ROOT}%{kmodinstdir_prefix}/*/extra/ -name \*.ko); do \
+ %{ksrc}/scripts/sign-file sha256 ${sign_pem} ${sign_x509} ${kmod}; \
+ done \
+ fi \
+%{nil}
+
+# hack to ensure signing happens after find-debuginfo.sh runs
+%define __spec_install_post \
+ %{?__debug_package:%{__debug_install_post}}\
+ %{__arch_install_post}\
+ %{__os_install_post}\
+ %{__modsign_install_post}
+
%install
rm -rf ${RPM_BUILD_ROOT}
diff --git a/sys/contrib/openzfs/rpm/redhat/zfs-kmod.spec.in b/sys/contrib/openzfs/rpm/redhat/zfs-kmod.spec.in
index f59551c0b43..9c836786bae 100644
--- a/sys/contrib/openzfs/rpm/redhat/zfs-kmod.spec.in
+++ b/sys/contrib/openzfs/rpm/redhat/zfs-kmod.spec.in
@@ -72,6 +72,30 @@ fi
%{?kernel_llvm}
make %{?_smp_mflags}
+# Module signing (modsign)
+#
+# This must be run _after_ find-debuginfo.sh runs, otherwise that will strip
+# the signature off of the modules.
+# (Based on Fedora's kernel.spec workaround)
+%define __modsign_install_post \
+ sign_pem="%{ksrc}/certs/signing_key.pem"; \
+ sign_x509="%{ksrc}/certs/signing_key.x509"; \
+ if [ -f "${sign_x509}" ]\
+ then \
+ echo "Signing kernel modules ..."; \
+ for kmod in $(find %{buildroot}/lib/modules/%{kverrel}/extra/ -name \*.ko); do \
+ %{ksrc}/scripts/sign-file sha256 ${sign_pem} ${sign_x509} ${kmod}; \
+ done \
+ fi \
+%{nil}
+
+# hack to ensure signing happens after find-debuginfo.sh runs
+%define __spec_install_post \
+ %{?__debug_package:%{__debug_install_post}}\
+ %{__arch_install_post}\
+ %{__os_install_post}\
+ %{__modsign_install_post}
+
%install
make install \
DESTDIR=${RPM_BUILD_ROOT} \
diff --git a/sys/contrib/openzfs/tests/runfiles/common.run b/sys/contrib/openzfs/tests/runfiles/common.run
index 48ec059de6b..7f0cce25237 100644
--- a/sys/contrib/openzfs/tests/runfiles/common.run
+++ b/sys/contrib/openzfs/tests/runfiles/common.run
@@ -71,6 +71,19 @@ tests = ['bclone_crossfs_corner_cases_limited',
tags = ['functional', 'bclone']
timeout = 7200
+[tests/functional/block_cloning]
+tests = ['block_cloning_clone_mmap_cached',
+ 'block_cloning_copyfilerange',
+ 'block_cloning_copyfilerange_partial',
+ 'block_cloning_copyfilerange_fallback',
+ 'block_cloning_disabled_copyfilerange',
+ 'block_cloning_copyfilerange_cross_dataset',
+ 'block_cloning_cross_enc_dataset',
+ 'block_cloning_copyfilerange_fallback_same_txg',
+ 'block_cloning_replay', 'block_cloning_replay_encrypted',
+ 'block_cloning_lwb_buffer_overflow', 'block_cloning_clone_mmap_write']
+tags = ['functional', 'block_cloning']
+
[tests/functional/bootfs]
tests = ['bootfs_001_pos', 'bootfs_002_neg', 'bootfs_003_pos',
'bootfs_004_neg', 'bootfs_005_neg', 'bootfs_006_pos', 'bootfs_007_pos',
@@ -305,7 +318,8 @@ tags = ['functional', 'cli_root', 'zfs_set']
[tests/functional/cli_root/zfs_share]
tests = ['zfs_share_001_pos', 'zfs_share_002_pos', 'zfs_share_003_pos',
'zfs_share_004_pos', 'zfs_share_006_pos', 'zfs_share_008_neg',
- 'zfs_share_010_neg', 'zfs_share_011_pos', 'zfs_share_concurrent_shares']
+ 'zfs_share_010_neg', 'zfs_share_011_pos', 'zfs_share_concurrent_shares',
+ 'zfs_share_after_mount']
tags = ['functional', 'cli_root', 'zfs_share']
[tests/functional/cli_root/zfs_snapshot]
diff --git a/sys/contrib/openzfs/tests/runfiles/linux.run b/sys/contrib/openzfs/tests/runfiles/linux.run
index c7c17f27176..6a4cd3fe691 100644
--- a/sys/contrib/openzfs/tests/runfiles/linux.run
+++ b/sys/contrib/openzfs/tests/runfiles/linux.run
@@ -35,17 +35,9 @@ tests = ['atime_003_pos', 'root_relatime_on']
tags = ['functional', 'atime']
[tests/functional/block_cloning:Linux]
-tests = ['block_cloning_copyfilerange', 'block_cloning_copyfilerange_partial',
- 'block_cloning_copyfilerange_fallback',
- 'block_cloning_ficlone', 'block_cloning_ficlonerange',
- 'block_cloning_ficlonerange_partial',
- 'block_cloning_disabled_copyfilerange', 'block_cloning_disabled_ficlone',
- 'block_cloning_disabled_ficlonerange',
- 'block_cloning_copyfilerange_cross_dataset',
- 'block_cloning_cross_enc_dataset',
- 'block_cloning_copyfilerange_fallback_same_txg',
- 'block_cloning_replay', 'block_cloning_replay_encrypted',
- 'block_cloning_lwb_buffer_overflow']
+tests = ['block_cloning_ficlone', 'block_cloning_ficlonerange',
+ 'block_cloning_ficlonerange_partial', 'block_cloning_disabled_ficlone',
+ 'block_cloning_disabled_ficlonerange']
tags = ['functional', 'block_cloning']
[tests/functional/chattr:Linux]
diff --git a/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in b/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in
index 7bf4d05d542..ae4aa627546 100755
--- a/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in
+++ b/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in
@@ -287,6 +287,9 @@ elif sys.platform.startswith('linux'):
'bclone/bclone_samefs_data': ['SKIP', cfr_reason],
'bclone/bclone_samefs_embedded': ['SKIP', cfr_reason],
'bclone/bclone_samefs_hole': ['SKIP', cfr_reason],
+ 'block_cloning/block_cloning_clone_mmap_cached': ['SKIP', cfr_reason],
+ 'block_cloning/block_cloning_clone_mmap_write':
+ ['SKIP', cfr_reason],
'block_cloning/block_cloning_copyfilerange':
['SKIP', cfr_reason],
'block_cloning/block_cloning_copyfilerange_cross_dataset':
diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/.gitignore b/sys/contrib/openzfs/tests/zfs-tests/cmd/.gitignore
index 5f53b687191..0ed0a69eb01 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/cmd/.gitignore
+++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/.gitignore
@@ -2,6 +2,8 @@
/btree_test
/chg_usr_exec
/clonefile
+/clone_mmap_cached
+/clone_mmap_write
/devname2devid
/dir_rd_update
/draid
diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/Makefile.am b/sys/contrib/openzfs/tests/zfs-tests/cmd/Makefile.am
index 1b915ae98ca..23848a82ffb 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/cmd/Makefile.am
+++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/Makefile.am
@@ -3,6 +3,8 @@ scripts_zfs_tests_bindir = $(datadir)/$(PACKAGE)/zfs-tests/bin
scripts_zfs_tests_bin_PROGRAMS = %D%/chg_usr_exec
scripts_zfs_tests_bin_PROGRAMS += %D%/clonefile
+scripts_zfs_tests_bin_PROGRAMS += %D%/clone_mmap_cached
+scripts_zfs_tests_bin_PROGRAMS += %D%/clone_mmap_write
scripts_zfs_tests_bin_PROGRAMS += %D%/cp_files
scripts_zfs_tests_bin_PROGRAMS += %D%/ctime
scripts_zfs_tests_bin_PROGRAMS += %D%/dir_rd_update
diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/clone_mmap_cached.c b/sys/contrib/openzfs/tests/zfs-tests/cmd/clone_mmap_cached.c
new file mode 100644
index 00000000000..c1cdf796cfb
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/clone_mmap_cached.c
@@ -0,0 +1,146 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2024 by Pawel Jakub Dawidek
+ */
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef __FreeBSD__
+#define loff_t off_t
+#endif
+
+ssize_t
+copy_file_range(int, loff_t *, int, loff_t *, size_t, unsigned int)
+ __attribute__((weak));
+
+static void *
+mmap_file(int fd, size_t size)
+{
+ void *p;
+
+ p = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
+ if (p == MAP_FAILED) {
+ (void) fprintf(stderr, "mmap failed: %s\n", strerror(errno));
+ exit(2);
+ }
+
+ return (p);
+}
+
+static void
+usage(const char *progname)
+{
+
+ /*
+ * -i cache input before copy_file_range(2).
+ * -o cache input before copy_file_range(2).
+ */
+ (void) fprintf(stderr, "usage: %s [-io]