mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-07 00:50:50 +00:00
zfs: merge openzfs/zfs@a0b2a93c4
Notable upstream pull request merges: #1566066670ba9f
fix(mount): do not truncate shares not zfs mount #157193bddc4dae
spa: Fix FreeBSD sysctl handlers (already merged) #157195a703d136
spa: Let spa_taskq_param_get()'s addition of a newline be optional #157216138af86b
Stop wasting time on malloc in snprintf_zstd_header #157231f5bf9600
Make zdb -R a little more sane. #1572620dd16d9f
Make zdb -R scale less poorly #15737d9885b377
fix: Uber block label not always found for aux vdevs #157372df2a58dc
Extend aux label to add path information #15737b64be1624
Add path handling for aux vdevs in `label_path` #15747a1771d243
Fix "out of memory" error #157521a11ad9d2
Fix a potential use-after-free in zfs_setsecattr() #15772f45dd90f3
Fix cloning into mmaped and cached file #157811494e8fba
Autotrim High Load Average Fix Obtained from: OpenZFS OpenZFS commit:a0b2a93c41
This commit is contained in:
commit
78ae60b447
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; \
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
* You should have received a copy of the GNU General Public License along
|
||||
* with the SPL. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Solaris Porting Layer (SPL) Credential Implementation.
|
||||
* Solaris Porting Layer (SPL) Condition Variables Implementation.
|
||||
*/
|
||||
|
||||
#include <sys/condvar.h>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zidmap_t *mnt_ns)
|
|||
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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}
|
||||
|
||||
|
|
|
@ -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} \
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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':
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
/btree_test
|
||||
/chg_usr_exec
|
||||
/clonefile
|
||||
/clone_mmap_cached
|
||||
/clone_mmap_write
|
||||
/devname2devid
|
||||
/dir_rd_update
|
||||
/draid
|
||||
|
|
|
@ -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
|
||||
|
|
146
sys/contrib/openzfs/tests/zfs-tests/cmd/clone_mmap_cached.c
Normal file
146
sys/contrib/openzfs/tests/zfs-tests/cmd/clone_mmap_cached.c
Normal file
|
@ -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 <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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] <input> <output>\n", progname);
|
||||
exit(3);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int dfd, sfd;
|
||||
size_t dsize, ssize;
|
||||
void *dmem, *smem, *ptr;
|
||||
off_t doff, soff;
|
||||
struct stat sb;
|
||||
bool cache_input, cache_output;
|
||||
const char *progname;
|
||||
int c;
|
||||
|
||||
progname = argv[0];
|
||||
cache_input = cache_output = false;
|
||||
|
||||
while ((c = getopt(argc, argv, "io")) != -1) {
|
||||
switch (c) {
|
||||
case 'i':
|
||||
cache_input = true;
|
||||
break;
|
||||
case 'o':
|
||||
cache_output = true;
|
||||
break;
|
||||
default:
|
||||
usage(progname);
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc != 2) {
|
||||
usage(progname);
|
||||
}
|
||||
|
||||
sfd = open(argv[0], O_RDONLY);
|
||||
if (fstat(sfd, &sb) == -1) {
|
||||
(void) fprintf(stderr, "fstat failed: %s\n", strerror(errno));
|
||||
exit(2);
|
||||
}
|
||||
ssize = sb.st_size;
|
||||
smem = mmap_file(sfd, ssize);
|
||||
|
||||
dfd = open(argv[1], O_RDWR);
|
||||
if (fstat(dfd, &sb) == -1) {
|
||||
(void) fprintf(stderr, "fstat failed: %s\n", strerror(errno));
|
||||
exit(2);
|
||||
}
|
||||
dsize = sb.st_size;
|
||||
dmem = mmap_file(dfd, dsize);
|
||||
|
||||
/*
|
||||
* Hopefully it won't be compiled out.
|
||||
*/
|
||||
if (cache_input) {
|
||||
ptr = malloc(ssize);
|
||||
assert(ptr != NULL);
|
||||
memcpy(ptr, smem, ssize);
|
||||
free(ptr);
|
||||
}
|
||||
if (cache_output) {
|
||||
ptr = malloc(ssize);
|
||||
assert(ptr != NULL);
|
||||
memcpy(ptr, dmem, dsize);
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
soff = doff = 0;
|
||||
if (copy_file_range(sfd, &soff, dfd, &doff, ssize, 0) < 0) {
|
||||
(void) fprintf(stderr, "copy_file_range failed: %s\n",
|
||||
strerror(errno));
|
||||
exit(2);
|
||||
}
|
||||
|
||||
exit(memcmp(smem, dmem, ssize) == 0 ? 0 : 1);
|
||||
}
|
123
sys/contrib/openzfs/tests/zfs-tests/cmd/clone_mmap_write.c
Normal file
123
sys/contrib/openzfs/tests/zfs-tests/cmd/clone_mmap_write.c
Normal file
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* This program clones the file, mmap it, and writes from the map into
|
||||
* file. This scenario triggers a panic on Linux in dbuf_redirty(),
|
||||
* which is fixed under PR#15656. On FreeBSD, the same test causes data
|
||||
* corruption, which is fixed by PR#15665.
|
||||
*
|
||||
* It would be good to test for this scenario in ZTS. This program and
|
||||
* issue was initially produced by @robn.
|
||||
*/
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#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 int
|
||||
open_file(const char *source)
|
||||
{
|
||||
int fd;
|
||||
if ((fd = open(source, O_RDWR | O_APPEND)) < 0) {
|
||||
(void) fprintf(stderr, "Error opening %s\n", source);
|
||||
exit(1);
|
||||
}
|
||||
sync();
|
||||
return (fd);
|
||||
}
|
||||
|
||||
static int
|
||||
clone_file(int sfd, long long size, const char *dest)
|
||||
{
|
||||
int dfd;
|
||||
|
||||
if ((dfd = open(dest, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0) {
|
||||
(void) fprintf(stderr, "Error opening %s\n", dest);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (copy_file_range(sfd, 0, dfd, 0, size, 0) < 0) {
|
||||
(void) fprintf(stderr, "copy_file_range failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return (dfd);
|
||||
}
|
||||
|
||||
static void *
|
||||
map_file(int fd, long long size)
|
||||
{
|
||||
void *p = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (p == MAP_FAILED) {
|
||||
(void) fprintf(stderr, "mmap failed\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return (p);
|
||||
}
|
||||
|
||||
static void
|
||||
map_write(void *p, int fd)
|
||||
{
|
||||
if (pwrite(fd, p, 1024*128, 0) < 0) {
|
||||
(void) fprintf(stderr, "write failed\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int sfd, dfd;
|
||||
void *p;
|
||||
struct stat sb;
|
||||
if (argc != 3) {
|
||||
(void) printf("usage: %s <input source file> "
|
||||
"<clone destination file>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
sfd = open_file(argv[1]);
|
||||
if (fstat(sfd, &sb) == -1) {
|
||||
(void) fprintf(stderr, "fstat failed\n");
|
||||
exit(1);
|
||||
}
|
||||
dfd = clone_file(sfd, sb.st_size, argv[2]);
|
||||
p = map_file(dfd, sb.st_size);
|
||||
map_write(p, dfd);
|
||||
return (0);
|
||||
}
|
|
@ -162,7 +162,7 @@ main(int argc, char **argv)
|
|||
{
|
||||
cf_mode_t mode = CF_MODE_NONE;
|
||||
|
||||
char c;
|
||||
int c;
|
||||
while ((c = getopt(argc, argv, "crfdq")) != -1) {
|
||||
switch (c) {
|
||||
case 'c':
|
||||
|
|
|
@ -362,12 +362,20 @@ main(void)
|
|||
return (1);
|
||||
}
|
||||
|
||||
if (t1 == t2) {
|
||||
(void) fprintf(stderr, "%s: t1(%ld) == t2(%ld)\n",
|
||||
|
||||
/*
|
||||
* Ideally, time change would be exactly two seconds, but allow
|
||||
* a little slack in case of scheduling delays or similar.
|
||||
*/
|
||||
long delta = (long)t2 - (long)t1;
|
||||
if (delta < 2 || delta > 4) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: BAD time change: t1(%ld), t2(%ld)\n",
|
||||
timetest_table[i].name, (long)t1, (long)t2);
|
||||
return (1);
|
||||
} else {
|
||||
(void) fprintf(stderr, "%s: t1(%ld) != t2(%ld)\n",
|
||||
(void) fprintf(stderr,
|
||||
"%s: good time change: t1(%ld), t2(%ld)\n",
|
||||
timetest_table[i].name, (long)t1, (long)t2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -185,6 +185,8 @@ export ZFSTEST_FILES='badsend
|
|||
btree_test
|
||||
chg_usr_exec
|
||||
clonefile
|
||||
clone_mmap_cached
|
||||
clone_mmap_write
|
||||
devname2devid
|
||||
dir_rd_update
|
||||
draid
|
||||
|
|
|
@ -461,6 +461,8 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
|
|||
functional/bclone/setup.ksh \
|
||||
functional/block_cloning/cleanup.ksh \
|
||||
functional/block_cloning/setup.ksh \
|
||||
functional/block_cloning/block_cloning_clone_mmap_cached.ksh \
|
||||
functional/block_cloning/block_cloning_clone_mmap_write.ksh \
|
||||
functional/block_cloning/block_cloning_copyfilerange_cross_dataset.ksh \
|
||||
functional/block_cloning/block_cloning_copyfilerange_fallback.ksh \
|
||||
functional/block_cloning/block_cloning_copyfilerange_fallback_same_txg.ksh \
|
||||
|
@ -912,6 +914,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
|
|||
functional/cli_root/zfs_share/zfs_share_012_pos.ksh \
|
||||
functional/cli_root/zfs_share/zfs_share_013_pos.ksh \
|
||||
functional/cli_root/zfs_share/zfs_share_concurrent_shares.ksh \
|
||||
functional/cli_root/zfs_share/zfs_share_after_mount.ksh \
|
||||
functional/cli_root/zfs_snapshot/cleanup.ksh \
|
||||
functional/cli_root/zfs_snapshot/setup.ksh \
|
||||
functional/cli_root/zfs_snapshot/zfs_snapshot_001_neg.ksh \
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
#!/bin/ksh -p
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# When the destination file is mmaped and is already cached we need to
|
||||
# update mmaped pages after successful clone.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create a pool.
|
||||
# 2. Create a two test files with random content.
|
||||
# 3. mmap the files, read them and clone from one to the other using
|
||||
# clone_mmap_cached.
|
||||
# 4. clone_mmap_cached also verifies if the content of the destination
|
||||
# file was updated while reading it from mmaped memory.
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
|
||||
log_unsupported "copy_file_range not available before Linux 4.5"
|
||||
fi
|
||||
|
||||
VDIR=$TEST_BASE_DIR/disk-bclone
|
||||
VDEV="$VDIR/a"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
datasetexists $TESTPOOL && destroy_pool $TESTPOOL
|
||||
rm -rf $VDIR
|
||||
}
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
log_assert "Test for clone into mmaped and cached file"
|
||||
|
||||
log_must rm -rf $VDIR
|
||||
log_must mkdir -p $VDIR
|
||||
log_must truncate -s 1G $VDEV
|
||||
|
||||
log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $VDEV
|
||||
log_must zfs create $TESTPOOL/$TESTFS
|
||||
|
||||
for opts in "--" "-i" "-o" "-io"
|
||||
do
|
||||
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/src bs=1M count=1
|
||||
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/dst bs=1M count=1
|
||||
|
||||
# Clear cache.
|
||||
log_must zpool export $TESTPOOL
|
||||
log_must zpool import -d $VDIR $TESTPOOL
|
||||
|
||||
log_must clone_mmap_cached $opts /$TESTPOOL/$TESTFS/src /$TESTPOOL/$TESTFS/dst
|
||||
|
||||
sync_pool $TESTPOOL
|
||||
log_must sync
|
||||
|
||||
log_must have_same_content /$TESTPOOL/$TESTFS/src /$TESTPOOL/$TESTFS/dst
|
||||
blocks=$(get_same_blocks $TESTPOOL/$TESTFS src $TESTPOOL/$TESTFS dst)
|
||||
# FreeBSD's seq(1) leaves a trailing space, remove it with sed(1).
|
||||
log_must [ "$blocks" = "$(seq -s " " 0 7 | sed 's/ $//')" ]
|
||||
done
|
||||
|
||||
log_pass "Clone properly updates mmapped and cached pages"
|
|
@ -0,0 +1,79 @@
|
|||
#!/bin/ksh -p
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# A PANIC is triggered in dbuf_redirty() if we clone a file, mmap it
|
||||
# and write from the map into the file. PR#15656 fixes this scenario.
|
||||
# This scenario also causes data corruption on FreeBSD, which is fixed
|
||||
# by PR#15665.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create a pool
|
||||
# 2. Create a test file
|
||||
# 3. Clone, mmap and write to the file using clone_mmap_write
|
||||
# 5. Synchronize cached writes
|
||||
# 6. Verfiy data is correctly written to the disk
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
|
||||
log_unsupported "copy_file_range not available before Linux 4.5"
|
||||
fi
|
||||
|
||||
VDIR=$TEST_BASE_DIR/disk-bclone
|
||||
VDEV="$VDIR/a"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
datasetexists $TESTPOOL && destroy_pool $TESTPOOL
|
||||
rm -rf $VDIR
|
||||
}
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
log_assert "Test for clone, mmap and write scenario"
|
||||
|
||||
log_must rm -rf $VDIR
|
||||
log_must mkdir -p $VDIR
|
||||
log_must truncate -s 1G $VDEV
|
||||
|
||||
log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $VDEV
|
||||
log_must zfs create $TESTPOOL/$TESTFS
|
||||
|
||||
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/file bs=1M count=512
|
||||
log_must clone_mmap_write /$TESTPOOL/$TESTFS/file /$TESTPOOL/$TESTFS/clone
|
||||
|
||||
sync_pool $TESTPOOL
|
||||
log_must sync
|
||||
|
||||
log_must have_same_content /$TESTPOOL/$TESTFS/file /$TESTPOOL/$TESTFS/clone
|
||||
blocks=$(get_same_blocks $TESTPOOL/$TESTFS file $TESTPOOL/$TESTFS clone)
|
||||
# FreeBSD's seq(1) leaves a trailing space, remove it with sed(1).
|
||||
log_must [ "$blocks" = "$(seq -s " " 1 4095 | sed 's/ $//')" ]
|
||||
|
||||
log_pass "Clone, mmap and write does not cause data corruption or " \
|
||||
"trigger panic"
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
verify_runnable "global"
|
||||
|
||||
if [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
|
||||
if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
|
||||
log_unsupported "copy_file_range not available before Linux 4.5"
|
||||
fi
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
verify_runnable "global"
|
||||
|
||||
if [[ $(linux_version) -lt $(linux_version "5.3") ]]; then
|
||||
if is_linux && [[ $(linux_version) -lt $(linux_version "5.3") ]]; then
|
||||
log_unsupported "copy_file_range can't copy cross-filesystem before Linux 5.3"
|
||||
fi
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
verify_runnable "global"
|
||||
|
||||
if [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
|
||||
if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
|
||||
log_unsupported "copy_file_range not available before Linux 4.5"
|
||||
fi
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
verify_runnable "global"
|
||||
|
||||
if [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
|
||||
if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
|
||||
log_unsupported "copy_file_range not available before Linux 4.5"
|
||||
fi
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
verify_runnable "global"
|
||||
|
||||
if [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
|
||||
if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
|
||||
log_unsupported "copy_file_range not available before Linux 4.5"
|
||||
fi
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
verify_runnable "global"
|
||||
|
||||
if [[ $(linux_version) -lt $(linux_version "5.3") ]]; then
|
||||
if is_linux && [[ $(linux_version) -lt $(linux_version "5.3") ]]; then
|
||||
log_unsupported "copy_file_range can't copy cross-filesystem before Linux 5.3"
|
||||
fi
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
verify_runnable "global"
|
||||
|
||||
if [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
|
||||
if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
|
||||
log_unsupported "copy_file_range not available before Linux 4.5"
|
||||
fi
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
verify_runnable "global"
|
||||
|
||||
if [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
|
||||
if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
|
||||
log_unsupported "copy_file_range not available before Linux 4.5"
|
||||
fi
|
||||
|
||||
|
@ -77,13 +77,14 @@ log_must zfs create -o recordsize=32K $TESTPOOL/$TESTFS
|
|||
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/file1 bs=32K count=1022 \
|
||||
conv=fsync
|
||||
sync_pool $TESTPOOL
|
||||
log_must clonefile -c /$TESTPOOL/$TESTFS/file1 /$TESTPOOL/$TESTFS/file2
|
||||
log_must clonefile -f /$TESTPOOL/$TESTFS/file1 /$TESTPOOL/$TESTFS/file2
|
||||
log_must sync
|
||||
|
||||
sync_pool $TESTPOOL
|
||||
log_must have_same_content /$TESTPOOL/$TESTFS/file1 /$TESTPOOL/$TESTFS/file2
|
||||
typeset blocks=$(get_same_blocks $TESTPOOL/$TESTFS file1 $TESTPOOL/$TESTFS file2)
|
||||
log_must [ "$blocks" = "$(seq -s " " 0 1021)" ]
|
||||
# FreeBSD's seq(1) leaves a trailing space, remove it with sed(1).
|
||||
log_must [ "$blocks" = "$(seq -s " " 0 1021 | sed 's/ $//')" ]
|
||||
|
||||
log_pass "LWB buffer overflow is not triggered with multiple VDEVs ZIL"
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
|
||||
verify_runnable "global"
|
||||
|
||||
if [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
|
||||
if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
|
||||
log_unsupported "copy_file_range not available before Linux 4.5"
|
||||
fi
|
||||
|
||||
|
@ -90,8 +90,8 @@ log_must zpool freeze $TESTPOOL
|
|||
#
|
||||
# 4. TX_CLONE_RANGE: Clone the file
|
||||
#
|
||||
log_must clonefile -c /$TESTPOOL/$TESTFS/file1 /$TESTPOOL/$TESTFS/clone1
|
||||
log_must clonefile -c /$TESTPOOL/$TESTFS/file2 /$TESTPOOL/$TESTFS/clone2
|
||||
log_must clonefile -f /$TESTPOOL/$TESTFS/file1 /$TESTPOOL/$TESTFS/clone1
|
||||
log_must clonefile -f /$TESTPOOL/$TESTFS/file2 /$TESTPOOL/$TESTFS/clone2
|
||||
|
||||
#
|
||||
# 5. Unmount filesystem and export the pool
|
||||
|
@ -126,6 +126,7 @@ log_must [ "$blocks" = "0 1 2 3" ]
|
|||
|
||||
typeset blocks=$(get_same_blocks $TESTPOOL/$TESTFS file2 \
|
||||
$TESTPOOL/$TESTFS clone2)
|
||||
log_must [ "$blocks" = "$(seq -s " " 0 2047)" ]
|
||||
# FreeBSD's seq(1) leaves a trailing space, remove it with sed(1).
|
||||
log_must [ "$blocks" = "$(seq -s " " 0 2047 | sed 's/ $//')" ]
|
||||
|
||||
log_pass $claim
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
|
||||
verify_runnable "global"
|
||||
|
||||
if [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
|
||||
if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
|
||||
log_unsupported "copy_file_range not available before Linux 4.5"
|
||||
fi
|
||||
|
||||
|
@ -92,8 +92,8 @@ log_must zpool freeze $TESTPOOL
|
|||
#
|
||||
# 4. TX_CLONE_RANGE: Clone the file
|
||||
#
|
||||
log_must clonefile -c /$TESTPOOL/$TESTFS/file1 /$TESTPOOL/$TESTFS/clone1
|
||||
log_must clonefile -c /$TESTPOOL/$TESTFS/file2 /$TESTPOOL/$TESTFS/clone2
|
||||
log_must clonefile -f /$TESTPOOL/$TESTFS/file1 /$TESTPOOL/$TESTFS/clone1
|
||||
log_must clonefile -f /$TESTPOOL/$TESTFS/file2 /$TESTPOOL/$TESTFS/clone2
|
||||
|
||||
#
|
||||
# 5. Unmount filesystem and export the pool
|
||||
|
@ -128,6 +128,7 @@ log_must [ "$blocks" = "0 1 2 3" ]
|
|||
|
||||
typeset blocks=$(get_same_blocks $TESTPOOL/$TESTFS file2 \
|
||||
$TESTPOOL/$TESTFS clone2 $PASSPHRASE)
|
||||
log_must [ "$blocks" = "$(seq -s " " 0 2047)" ]
|
||||
# FreeBSD's seq(1) leaves a trailing space, remove it with sed(1).
|
||||
log_must [ "$blocks" = "$(seq -s " " 0 2047 | sed 's/ $//')" ]
|
||||
|
||||
log_pass $claim
|
||||
|
|
|
@ -30,6 +30,9 @@
|
|||
if ! command -v clonefile > /dev/null ; then
|
||||
log_unsupported "clonefile program required to test block cloning"
|
||||
fi
|
||||
if ! command -v clone_mmap_cached > /dev/null ; then
|
||||
log_unsupported "clone_mmap_cached program required to test block cloning"
|
||||
fi
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
#!/bin/ksh -p
|
||||
#
|
||||
# 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) 2023 by Proxmox. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
# DESCRIPTION:
|
||||
# Verify that nfs shares persist after zfs mount -a
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Verify that the filesystem is not shared.
|
||||
# 2. Enable the 'sharenfs' property
|
||||
# 3. Verify filesystem is shared
|
||||
# 4. Invoke 'zfs mount -a'
|
||||
# 5. Verify filesystem is still shared
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
log_must zfs set sharenfs=off $TESTPOOL/$TESTFS
|
||||
is_shared $TESTPOOL/$TESTFS && \
|
||||
log_must unshare_fs $TESTPOOL/$TESTFS
|
||||
log_must zfs share -a
|
||||
}
|
||||
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
cleanup
|
||||
|
||||
log_must zfs set sharenfs="on" $TESTPOOL/$TESTFS
|
||||
log_must is_shared $TESTPOOL/$TESTFS
|
||||
log_must is_exported $TESTPOOL/$TESTFS
|
||||
|
||||
log_must zfs mount -a
|
||||
log_must is_shared $TESTPOOL/$TESTFS
|
||||
log_must is_exported $TESTPOOL/$TESTFS
|
||||
|
||||
log_pass "Verify that nfs shares persist after zfs mount -a"
|
|
@ -1137,7 +1137,7 @@
|
|||
/* #undef ZFS_IS_GPL_COMPATIBLE */
|
||||
|
||||
/* Define the project alias string. */
|
||||
#define ZFS_META_ALIAS "zfs-2.2.99-288-FreeBSD_ga382e2119"
|
||||
#define ZFS_META_ALIAS "zfs-2.2.99-310-FreeBSD_ga0b2a93c4"
|
||||
|
||||
/* Define the project author. */
|
||||
#define ZFS_META_AUTHOR "OpenZFS"
|
||||
|
@ -1167,7 +1167,7 @@
|
|||
#define ZFS_META_NAME "zfs"
|
||||
|
||||
/* Define the project release. */
|
||||
#define ZFS_META_RELEASE "288-FreeBSD_ga382e2119"
|
||||
#define ZFS_META_RELEASE "310_FreeBSD-ga0b2a93c4"
|
||||
|
||||
/* Define the project version. */
|
||||
#define ZFS_META_VERSION "2.2.99"
|
||||
|
|
|
@ -1 +1 @@
|
|||
#define ZFS_META_GITREV "zfs-2.2.99-288-ga382e2119"
|
||||
#define ZFS_META_GITREV "zfs-2.2.99-310-ga0b2a93c4"
|
||||
|
|
Loading…
Reference in a new issue