zfs: merge OpenZFS master-9305ff2ed

Notable upstream pull request merges:
  #11153 Scalable teardown lock for FreeBSD
  #11651 Don't bomb out when using keylocation=file://
  #11667 zvol: call zil_replaying() during replay
  #11683 abd_get_offset_struct() may allocate new abd
  #11693 Intentionally allow ZFS_READONLY in zfs_write
  #11716 zpool import cachefile improvements
  #11720 FreeBSD: Clean up zfsdev_close to match Linux
  #11730 FreeBSD: bring back possibility to rewind the
         checkpoint from bootloader

Obtained from:	OpenZFS
MFC after:	2 weeks
This commit is contained in:
Martin Matuska 2021-03-14 02:23:51 +01:00
commit 9db44a8e5d
44 changed files with 896 additions and 378 deletions

View File

@ -6,7 +6,7 @@ on:
jobs:
checkstyle:
runs-on: ubuntu-latest
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
with:

View File

@ -298,8 +298,15 @@ sas_handler() {
# Utilize DM device name to gather subordinate block devices
# using sysfs to avoid userspace utilities
DMDEV=$(ls -l --full-time /dev/mapper | grep $DM_NAME |
# If our DEVNAME is something like /dev/dm-177, then we may be
# able to get our DMDEV from it.
DMDEV=$(echo $DEVNAME | sed 's;/dev/;;g')
if [ ! -e /sys/block/$DMDEV/slaves/* ] ; then
# It's not there, try looking in /dev/mapper
DMDEV=$(ls -l --full-time /dev/mapper | grep $DM_NAME |
awk '{gsub("../", " "); print $NF}')
fi
# Use sysfs pointers in /sys/block/dm-X/slaves because using
# userspace tools creates lots of overhead and should be avoided

View File

@ -2623,8 +2623,8 @@ print_class_vdevs(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv,
/*
* Display the status for the given pool.
*/
static void
show_import(nvlist_t *config)
static int
show_import(nvlist_t *config, boolean_t report_error)
{
uint64_t pool_state;
vdev_stat_t *vs;
@ -2656,6 +2656,13 @@ show_import(nvlist_t *config)
reason = zpool_import_status(config, &msgid, &errata);
/*
* If we're importing using a cachefile, then we won't report any
* errors unless we are in the scan phase of the import.
*/
if (reason != ZPOOL_STATUS_OK && !report_error)
return (reason);
(void) printf(gettext(" pool: %s\n"), name);
(void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid);
(void) printf(gettext(" state: %s"), health);
@ -2983,6 +2990,7 @@ show_import(nvlist_t *config)
"be part of this pool, though their\n\texact "
"configuration cannot be determined.\n"));
}
return (0);
}
static boolean_t
@ -3121,6 +3129,121 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts,
return (ret);
}
static int
import_pools(nvlist_t *pools, nvlist_t *props, char *mntopts, int flags,
char *orig_name, char *new_name,
boolean_t do_destroyed, boolean_t pool_specified, boolean_t do_all,
importargs_t *import)
{
nvlist_t *config = NULL;
nvlist_t *found_config = NULL;
uint64_t pool_state;
/*
* At this point we have a list of import candidate configs. Even if
* we were searching by pool name or guid, we still need to
* post-process the list to deal with pool state and possible
* duplicate names.
*/
int err = 0;
nvpair_t *elem = NULL;
boolean_t first = B_TRUE;
while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
verify(nvpair_value_nvlist(elem, &config) == 0);
verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
&pool_state) == 0);
if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
continue;
if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
continue;
verify(nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY,
import->policy) == 0);
if (!pool_specified) {
if (first)
first = B_FALSE;
else if (!do_all)
(void) printf("\n");
if (do_all) {
err |= do_import(config, NULL, mntopts,
props, flags);
} else {
/*
* If we're importing from cachefile, then
* we don't want to report errors until we
* are in the scan phase of the import. If
* we get an error, then we return that error
* to invoke the scan phase.
*/
if (import->cachefile && !import->scan)
err = show_import(config, B_FALSE);
else
(void) show_import(config, B_TRUE);
}
} else if (import->poolname != NULL) {
char *name;
/*
* We are searching for a pool based on name.
*/
verify(nvlist_lookup_string(config,
ZPOOL_CONFIG_POOL_NAME, &name) == 0);
if (strcmp(name, import->poolname) == 0) {
if (found_config != NULL) {
(void) fprintf(stderr, gettext(
"cannot import '%s': more than "
"one matching pool\n"),
import->poolname);
(void) fprintf(stderr, gettext(
"import by numeric ID instead\n"));
err = B_TRUE;
}
found_config = config;
}
} else {
uint64_t guid;
/*
* Search for a pool by guid.
*/
verify(nvlist_lookup_uint64(config,
ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
if (guid == import->guid)
found_config = config;
}
}
/*
* If we were searching for a specific pool, verify that we found a
* pool, and then do the import.
*/
if (pool_specified && err == 0) {
if (found_config == NULL) {
(void) fprintf(stderr, gettext("cannot import '%s': "
"no such pool available\n"), orig_name);
err = B_TRUE;
} else {
err |= do_import(found_config, new_name,
mntopts, props, flags);
}
}
/*
* If we were just looking for pools, report an error if none were
* found.
*/
if (!pool_specified && first)
(void) fprintf(stderr,
gettext("no pools available to import\n"));
return (err);
}
typedef struct target_exists_args {
const char *poolname;
uint64_t poolguid;
@ -3248,51 +3371,54 @@ zpool_do_checkpoint(int argc, char **argv)
/*
* zpool import [-d dir] [-D]
* import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l]
* [-d dir | -c cachefile] [-f] -a
* [-d dir | -c cachefile | -s] [-f] -a
* import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-l]
* [-d dir | -c cachefile] [-f] [-n] [-F] <pool | id> [newpool]
* [-d dir | -c cachefile | -s] [-f] [-n] [-F] <pool | id>
* [newpool]
*
* -c Read pool information from a cachefile instead of searching
* devices.
* -c Read pool information from a cachefile instead of searching
* devices. If importing from a cachefile config fails, then
* fallback to searching for devices only in the directories that
* exist in the cachefile.
*
* -d Scan in a specific directory, other than /dev/. More than
* -d Scan in a specific directory, other than /dev/. More than
* one directory can be specified using multiple '-d' options.
*
* -D Scan for previously destroyed pools or import all or only
* specified destroyed pools.
* -D Scan for previously destroyed pools or import all or only
* specified destroyed pools.
*
* -R Temporarily import the pool, with all mountpoints relative to
* -R Temporarily import the pool, with all mountpoints relative to
* the given root. The pool will remain exported when the machine
* is rebooted.
*
* -V Import even in the presence of faulted vdevs. This is an
* intentionally undocumented option for testing purposes, and
* treats the pool configuration as complete, leaving any bad
* -V Import even in the presence of faulted vdevs. This is an
* intentionally undocumented option for testing purposes, and
* treats the pool configuration as complete, leaving any bad
* vdevs in the FAULTED state. In other words, it does verbatim
* import.
*
* -f Force import, even if it appears that the pool is active.
* -f Force import, even if it appears that the pool is active.
*
* -F Attempt rewind if necessary.
* -F Attempt rewind if necessary.
*
* -n See if rewind would work, but don't actually rewind.
* -n See if rewind would work, but don't actually rewind.
*
* -N Import the pool but don't mount datasets.
* -N Import the pool but don't mount datasets.
*
* -T Specify a starting txg to use for import. This option is
* intentionally undocumented option for testing purposes.
* -T Specify a starting txg to use for import. This option is
* intentionally undocumented option for testing purposes.
*
* -a Import all pools found.
* -a Import all pools found.
*
* -l Load encryption keys while importing.
* -l Load encryption keys while importing.
*
* -o Set property=value and/or temporary mount options (without '=').
* -o Set property=value and/or temporary mount options (without '=').
*
* -s Scan using the default search path, the libblkid cache will
* not be consulted.
* -s Scan using the default search path, the libblkid cache will
* not be consulted.
*
* --rewind-to-checkpoint
* Import the pool and revert back to the checkpoint.
* --rewind-to-checkpoint
* Import the pool and revert back to the checkpoint.
*
* The import command scans for pools to import, and import pools based on pool
* name and GUID. The pool can also be renamed as part of the import process.
@ -3309,15 +3435,11 @@ zpool_do_import(int argc, char **argv)
boolean_t do_all = B_FALSE;
boolean_t do_destroyed = B_FALSE;
char *mntopts = NULL;
nvpair_t *elem;
nvlist_t *config;
uint64_t searchguid = 0;
char *searchname = NULL;
char *propval;
nvlist_t *found_config;
nvlist_t *policy = NULL;
nvlist_t *props = NULL;
boolean_t first;
int flags = ZFS_IMPORT_NORMAL;
uint32_t rewind_policy = ZPOOL_NO_REWIND;
boolean_t dryrun = B_FALSE;
@ -3325,7 +3447,8 @@ zpool_do_import(int argc, char **argv)
boolean_t xtreme_rewind = B_FALSE;
boolean_t do_scan = B_FALSE;
boolean_t pool_exists = B_FALSE;
uint64_t pool_state, txg = -1ULL;
boolean_t pool_specified = B_FALSE;
uint64_t txg = -1ULL;
char *cachefile = NULL;
importargs_t idata = { 0 };
char *endptr;
@ -3447,6 +3570,11 @@ zpool_do_import(int argc, char **argv)
usage(B_FALSE);
}
if (cachefile && do_scan) {
(void) fprintf(stderr, gettext("-c is incompatible with -s\n"));
usage(B_FALSE);
}
if ((flags & ZFS_IMPORT_LOAD_KEYS) && (flags & ZFS_IMPORT_ONLY)) {
(void) fprintf(stderr, gettext("-l is incompatible with -N\n"));
usage(B_FALSE);
@ -3527,7 +3655,7 @@ zpool_do_import(int argc, char **argv)
searchname = argv[0];
searchguid = 0;
}
found_config = NULL;
pool_specified = B_TRUE;
/*
* User specified a name or guid. Ensure it's unique.
@ -3606,98 +3734,33 @@ zpool_do_import(int argc, char **argv)
return (1);
}
err = import_pools(pools, props, mntopts, flags, argv[0],
argc == 1 ? NULL : argv[1], do_destroyed, pool_specified,
do_all, &idata);
/*
* At this point we have a list of import candidate configs. Even if
* we were searching by pool name or guid, we still need to
* post-process the list to deal with pool state and possible
* duplicate names.
* If we're using the cachefile and we failed to import, then
* fallback to scanning the directory for pools that match
* those in the cachefile.
*/
err = 0;
elem = NULL;
first = B_TRUE;
while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
if (err != 0 && cachefile != NULL) {
(void) printf(gettext("cachefile import failed, retrying\n"));
verify(nvpair_value_nvlist(elem, &config) == 0);
/*
* We use the scan flag to gather the directories that exist
* in the cachefile. If we need to fallback to searching for
* the pool config, we will only search devices in these
* directories.
*/
idata.scan = B_TRUE;
nvlist_free(pools);
pools = zpool_search_import(g_zfs, &idata, &libzfs_config_ops);
verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
&pool_state) == 0);
if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
continue;
if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
continue;
verify(nvlist_add_nvlist(config, ZPOOL_LOAD_POLICY,
policy) == 0);
if (argc == 0) {
if (first)
first = B_FALSE;
else if (!do_all)
(void) printf("\n");
if (do_all) {
err |= do_import(config, NULL, mntopts,
props, flags);
} else {
show_import(config);
}
} else if (searchname != NULL) {
char *name;
/*
* We are searching for a pool based on name.
*/
verify(nvlist_lookup_string(config,
ZPOOL_CONFIG_POOL_NAME, &name) == 0);
if (strcmp(name, searchname) == 0) {
if (found_config != NULL) {
(void) fprintf(stderr, gettext(
"cannot import '%s': more than "
"one matching pool\n"), searchname);
(void) fprintf(stderr, gettext(
"import by numeric ID instead\n"));
err = B_TRUE;
}
found_config = config;
}
} else {
uint64_t guid;
/*
* Search for a pool by guid.
*/
verify(nvlist_lookup_uint64(config,
ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
if (guid == searchguid)
found_config = config;
}
err = import_pools(pools, props, mntopts, flags, argv[0],
argc == 1 ? NULL : argv[1], do_destroyed, pool_specified,
do_all, &idata);
}
/*
* If we were searching for a specific pool, verify that we found a
* pool, and then do the import.
*/
if (argc != 0 && err == 0) {
if (found_config == NULL) {
(void) fprintf(stderr, gettext("cannot import '%s': "
"no such pool available\n"), argv[0]);
err = B_TRUE;
} else {
err |= do_import(found_config, argc == 1 ? NULL :
argv[1], mntopts, props, flags);
}
}
/*
* If we were just looking for pools, report an error if none were
* found.
*/
if (argc == 0 && first)
(void) fprintf(stderr,
gettext("no pools available to import\n"));
error:
nvlist_free(props);
nvlist_free(pools);
@ -7785,8 +7848,8 @@ print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs)
* do not print estimated time if hours_left is more than
* 30 days
*/
(void) printf(gettext(" %s copied out of %s at %s/s, "
"%.2f%% done"),
(void) printf(gettext(
"\t%s copied out of %s at %s/s, %.2f%% done"),
examined_buf, total_buf, rate_buf, 100 * fraction_done);
if (hours_left < (30 * 24)) {
(void) printf(gettext(", %lluh%um to go\n"),
@ -7801,8 +7864,8 @@ print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs)
if (prs->prs_mapping_memory > 0) {
char mem_buf[7];
zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf));
(void) printf(gettext(" %s memory used for "
"removed device mappings\n"),
(void) printf(gettext(
"\t%s memory used for removed device mappings\n"),
mem_buf);
}
}

View File

@ -248,6 +248,7 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose)
fflags = DMU_GET_FEATUREFLAGS(drrb->drr_versioninfo);
fflags &= ~(DMU_BACKUP_FEATURE_DEDUP |
DMU_BACKUP_FEATURE_DEDUPPROPS);
/* cppcheck-suppress syntaxError */
DMU_SET_FEATUREFLAGS(drrb->drr_versioninfo, fflags);
int sz = drr->drr_payloadlen;

View File

@ -11,6 +11,7 @@ AC_DEFUN([ZFS_AC_DEBUG_ENABLE], [
DEBUG_CPPFLAGS="-DDEBUG -UNDEBUG"
DEBUG_LDFLAGS=""
DEBUG_ZFS="_with_debug"
WITH_DEBUG="true"
AC_DEFINE(ZFS_DEBUG, 1, [zfs debugging enabled])
KERNEL_DEBUG_CFLAGS="-Werror"
@ -22,6 +23,7 @@ AC_DEFUN([ZFS_AC_DEBUG_DISABLE], [
DEBUG_CPPFLAGS="-UDEBUG -DNDEBUG"
DEBUG_LDFLAGS=""
DEBUG_ZFS="_without_debug"
WITH_DEBUG=""
KERNEL_DEBUG_CFLAGS=""
KERNEL_DEBUG_CPPFLAGS="-UDEBUG -DNDEBUG"
@ -51,6 +53,7 @@ AC_DEFUN([ZFS_AC_DEBUG], [
AC_SUBST(DEBUG_CPPFLAGS)
AC_SUBST(DEBUG_LDFLAGS)
AC_SUBST(DEBUG_ZFS)
AC_SUBST(WITH_DEBUG)
AC_SUBST(KERNEL_DEBUG_CFLAGS)
AC_SUBST(KERNEL_DEBUG_CPPFLAGS)
@ -152,6 +155,39 @@ AC_DEFUN([ZFS_AC_DEBUG_KMEM_TRACKING], [
AC_MSG_RESULT([$enable_debug_kmem_tracking])
])
AC_DEFUN([ZFS_AC_DEBUG_INVARIANTS_DETECT_FREEBSD], [
AS_IF([sysctl -n kern.conftxt | fgrep -qx $'options\tINVARIANTS'],
[enable_invariants="yes"],
[enable_invariants="no"])
])
AC_DEFUN([ZFS_AC_DEBUG_INVARIANTS_DETECT], [
AM_COND_IF([BUILD_FREEBSD],
[ZFS_AC_DEBUG_INVARIANTS_DETECT_FREEBSD],
[enable_invariants="no"])
])
dnl #
dnl # Detected for the running kernel by default, enables INVARIANTS features
dnl # in the FreeBSD kernel module. This feature must be used when building
dnl # for a FreeBSD kernel with "options INVARIANTS" in the KERNCONF and must
dnl # not be used when the INVARIANTS option is absent.
dnl #
AC_DEFUN([ZFS_AC_DEBUG_INVARIANTS], [
AC_MSG_CHECKING([whether FreeBSD kernel INVARIANTS checks are enabled])
AC_ARG_ENABLE([invariants],
[AS_HELP_STRING([--enable-invariants],
[Enable FreeBSD kernel INVARIANTS checks [[default: detect]]])],
[], [ZFS_AC_DEBUG_INVARIANTS_DETECT])
AS_IF([test "x$enable_invariants" = xyes],
[WITH_INVARIANTS="true"],
[WITH_INVARIANTS=""])
AC_SUBST(WITH_INVARIANTS)
AC_MSG_RESULT([$enable_invariants])
])
AC_DEFUN([ZFS_AC_CONFIG_ALWAYS], [
AX_COUNT_CPUS([])
AC_SUBST(CPU_COUNT)

View File

@ -61,6 +61,7 @@ ZFS_AC_DEBUG
ZFS_AC_DEBUGINFO
ZFS_AC_DEBUG_KMEM
ZFS_AC_DEBUG_KMEM_TRACKING
ZFS_AC_DEBUG_INVARIANTS
AC_CONFIG_FILES([
Makefile

View File

@ -4,6 +4,7 @@ KERNEL_H = \
atomic.h \
byteorder.h \
callb.h \
ccompat.h \
ccompile.h \
cmn_err.h \
condvar.h \
@ -18,9 +19,11 @@ KERNEL_H = \
fcntl.h \
file.h \
freebsd_rwlock.h \
idmap.h \
inttypes.h \
isa_defs.h \
kmem_cache.h \
kidmap.h \
kmem.h \
kstat.h \
list_impl.h \

View File

@ -68,65 +68,65 @@ void spl_dumpstack(void);
#define PANIC(fmt, a...) \
spl_panic(__FILE__, __FUNCTION__, __LINE__, fmt, ## a)
#define VERIFY(cond) \
(void) (unlikely(!(cond)) && \
#define VERIFY(cond) \
(void) (unlikely(!(cond)) && \
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"%s", "VERIFY(" #cond ") failed\n"))
#define VERIFY3B(LEFT, OP, RIGHT) do { \
boolean_t _verify3_left = (boolean_t)(LEFT); \
boolean_t _verify3_right = (boolean_t)(RIGHT); \
if (!(_verify3_left OP _verify3_right)) \
#define VERIFY3B(LEFT, OP, RIGHT) do { \
const boolean_t _verify3_left = (boolean_t)(LEFT); \
const boolean_t _verify3_right = (boolean_t)(RIGHT);\
if (unlikely(!(_verify3_left OP _verify3_right))) \
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
"failed (%d " #OP " %d)\n", \
(boolean_t) (_verify3_left), \
(boolean_t) (_verify3_right)); \
"failed (%d " #OP " %d)\n", \
(boolean_t) (_verify3_left), \
(boolean_t) (_verify3_right)); \
} while (0)
#define VERIFY3S(LEFT, OP, RIGHT) do { \
int64_t _verify3_left = (int64_t)(LEFT); \
int64_t _verify3_right = (int64_t)(RIGHT); \
if (!(_verify3_left OP _verify3_right)) \
#define VERIFY3S(LEFT, OP, RIGHT) do { \
const int64_t _verify3_left = (int64_t)(LEFT); \
const int64_t _verify3_right = (int64_t)(RIGHT); \
if (unlikely(!(_verify3_left OP _verify3_right))) \
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
"failed (%lld " #OP " %lld)\n", \
(long long) (_verify3_left), \
(long long) (_verify3_right)); \
"failed (%lld " #OP " %lld)\n", \
(long long) (_verify3_left), \
(long long) (_verify3_right)); \
} while (0)
#define VERIFY3U(LEFT, OP, RIGHT) do { \
uint64_t _verify3_left = (uint64_t)(LEFT); \
uint64_t _verify3_right = (uint64_t)(RIGHT); \
if (!(_verify3_left OP _verify3_right)) \
#define VERIFY3U(LEFT, OP, RIGHT) do { \
const uint64_t _verify3_left = (uint64_t)(LEFT); \
const uint64_t _verify3_right = (uint64_t)(RIGHT); \
if (unlikely(!(_verify3_left OP _verify3_right))) \
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
"failed (%llu " #OP " %llu)\n", \
(unsigned long long) (_verify3_left), \
(unsigned long long) (_verify3_right)); \
"failed (%llu " #OP " %llu)\n", \
(unsigned long long) (_verify3_left), \
(unsigned long long) (_verify3_right)); \
} while (0)
#define VERIFY3P(LEFT, OP, RIGHT) do { \
uintptr_t _verify3_left = (uintptr_t)(LEFT); \
uintptr_t _verify3_right = (uintptr_t)(RIGHT); \
if (!(_verify3_left OP _verify3_right)) \
#define VERIFY3P(LEFT, OP, RIGHT) do { \
const uintptr_t _verify3_left = (uintptr_t)(LEFT); \
const uintptr_t _verify3_right = (uintptr_t)(RIGHT);\
if (unlikely(!(_verify3_left OP _verify3_right))) \
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
"failed (%px " #OP " %px)\n", \
(void *) (_verify3_left), \
(void *) (_verify3_right)); \
"failed (%px " #OP " %px)\n", \
(void *) (_verify3_left), \
(void *) (_verify3_right)); \
} while (0)
#define VERIFY0(RIGHT) do { \
int64_t _verify3_left = (int64_t)(0); \
int64_t _verify3_right = (int64_t)(RIGHT); \
if (!(_verify3_left == _verify3_right)) \
#define VERIFY0(RIGHT) do { \
const int64_t _verify3_left = (int64_t)(0); \
const int64_t _verify3_right = (int64_t)(RIGHT); \
if (unlikely(!(_verify3_left == _verify3_right))) \
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(0 == " #RIGHT ") " \
"failed (0 == %lld)\n", \
(long long) (_verify3_right)); \
"VERIFY3(0 == " #RIGHT ") " \
"failed (0 == %lld)\n", \
(long long) (_verify3_right)); \
} while (0)
#define CTASSERT_GLOBAL(x) CTASSERT(x)
#define CTASSERT_GLOBAL(x) CTASSERT(x)
/*
* Debugging disabled (--disable-debug)
@ -154,11 +154,11 @@ void spl_dumpstack(void);
#define ASSERT0 VERIFY0
#define ASSERT VERIFY
#define IMPLY(A, B) \
((void)(((!(A)) || (B)) || \
((void)(likely((!(A)) || (B)) || \
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"(" #A ") implies (" #B ")")))
#define EQUIV(A, B) \
((void)((!!(A) == !!(B)) || \
((void)(likely(!!(A) == !!(B)) || \
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"(" #A ") is equivalent to (" #B ")")))
/* END CSTYLED */

View File

@ -27,7 +27,7 @@
#ifndef _SYS_FS_ZFS_VFSOPS_H
#define _SYS_FS_ZFS_VFSOPS_H
#if __FreeBSD_version >= 1300109
#if __FreeBSD_version >= 1300125
#define TEARDOWN_RMS
#endif

View File

@ -62,63 +62,63 @@ void spl_dumpstack(void);
#define PANIC(fmt, a...) \
spl_panic(__FILE__, __FUNCTION__, __LINE__, fmt, ## a)
#define VERIFY(cond) \
(void) (unlikely(!(cond)) && \
#define VERIFY(cond) \
(void) (unlikely(!(cond)) && \
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"%s", "VERIFY(" #cond ") failed\n"))
#define VERIFY3B(LEFT, OP, RIGHT) do { \
boolean_t _verify3_left = (boolean_t)(LEFT); \
boolean_t _verify3_right = (boolean_t)(RIGHT); \
if (!(_verify3_left OP _verify3_right)) \
#define VERIFY3B(LEFT, OP, RIGHT) do { \
const boolean_t _verify3_left = (boolean_t)(LEFT); \
const boolean_t _verify3_right = (boolean_t)(RIGHT);\
if (unlikely(!(_verify3_left OP _verify3_right))) \
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
"failed (%d " #OP " %d)\n", \
(boolean_t) (_verify3_left), \
(boolean_t) (_verify3_right)); \
"failed (%d " #OP " %d)\n", \
(boolean_t) (_verify3_left), \
(boolean_t) (_verify3_right)); \
} while (0)
#define VERIFY3S(LEFT, OP, RIGHT) do { \
int64_t _verify3_left = (int64_t)(LEFT); \
int64_t _verify3_right = (int64_t)(RIGHT); \
if (!(_verify3_left OP _verify3_right)) \
#define VERIFY3S(LEFT, OP, RIGHT) do { \
const int64_t _verify3_left = (int64_t)(LEFT); \
const int64_t _verify3_right = (int64_t)(RIGHT); \
if (unlikely(!(_verify3_left OP _verify3_right))) \
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
"failed (%lld " #OP " %lld)\n", \
(long long) (_verify3_left), \
(long long) (_verify3_right)); \
"failed (%lld " #OP " %lld)\n", \
(long long) (_verify3_left), \
(long long) (_verify3_right)); \
} while (0)
#define VERIFY3U(LEFT, OP, RIGHT) do { \
uint64_t _verify3_left = (uint64_t)(LEFT); \
uint64_t _verify3_right = (uint64_t)(RIGHT); \
if (!(_verify3_left OP _verify3_right)) \
#define VERIFY3U(LEFT, OP, RIGHT) do { \
const uint64_t _verify3_left = (uint64_t)(LEFT); \
const uint64_t _verify3_right = (uint64_t)(RIGHT); \
if (unlikely(!(_verify3_left OP _verify3_right))) \
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
"failed (%llu " #OP " %llu)\n", \
(unsigned long long) (_verify3_left), \
(unsigned long long) (_verify3_right)); \
"failed (%llu " #OP " %llu)\n", \
(unsigned long long) (_verify3_left), \
(unsigned long long) (_verify3_right)); \
} while (0)
#define VERIFY3P(LEFT, OP, RIGHT) do { \
uintptr_t _verify3_left = (uintptr_t)(LEFT); \
uintptr_t _verify3_right = (uintptr_t)(RIGHT); \
if (!(_verify3_left OP _verify3_right)) \
#define VERIFY3P(LEFT, OP, RIGHT) do { \
const uintptr_t _verify3_left = (uintptr_t)(LEFT); \
const uintptr_t _verify3_right = (uintptr_t)(RIGHT);\
if (unlikely(!(_verify3_left OP _verify3_right))) \
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(" #LEFT " " #OP " " #RIGHT ") " \
"failed (%px " #OP " %px)\n", \
(void *) (_verify3_left), \
(void *) (_verify3_right)); \
"failed (%px " #OP " %px)\n", \
(void *) (_verify3_left), \
(void *) (_verify3_right)); \
} while (0)
#define VERIFY0(RIGHT) do { \
int64_t _verify3_left = (int64_t)(0); \
int64_t _verify3_right = (int64_t)(RIGHT); \
if (!(_verify3_left == _verify3_right)) \
#define VERIFY0(RIGHT) do { \
const int64_t _verify3_left = (int64_t)(0); \
const int64_t _verify3_right = (int64_t)(RIGHT); \
if (unlikely(!(_verify3_left == _verify3_right))) \
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"VERIFY3(0 == " #RIGHT ") " \
"failed (0 == %lld)\n", \
(long long) (_verify3_right)); \
"VERIFY3(0 == " #RIGHT ") " \
"failed (0 == %lld)\n", \
(long long) (_verify3_right)); \
} while (0)
#define CTASSERT_GLOBAL(x) _CTASSERT(x, __LINE__)
@ -154,11 +154,11 @@ void spl_dumpstack(void);
#define ASSERT0 VERIFY0
#define ASSERT VERIFY
#define IMPLY(A, B) \
((void)(((!(A)) || (B)) || \
((void)(likely((!(A)) || (B)) || \
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"(" #A ") implies (" #B ")")))
#define EQUIV(A, B) \
((void)((!!(A) == !!(B)) || \
((void)(likely(!!(A) == !!(B)) || \
spl_panic(__FILE__, __FUNCTION__, __LINE__, \
"(" #A ") is equivalent to (" #B ")")))
/* END CSTYLED */

View File

@ -138,6 +138,39 @@ struct zfsvfs {
taskqid_t z_drain_task; /* task id for the unlink drain task */
};
#define ZFS_TEARDOWN_INIT(zfsvfs) \
rrm_init(&(zfsvfs)->z_teardown_lock, B_FALSE)
#define ZFS_TEARDOWN_DESTROY(zfsvfs) \
rrm_destroy(&(zfsvfs)->z_teardown_lock)
#define ZFS_TEARDOWN_TRY_ENTER_READ(zfsvfs) \
rw_tryenter(&(zfsvfs)->z_teardown_lock, RW_READER)
#define ZFS_TEARDOWN_ENTER_READ(zfsvfs, tag) \
rrm_enter_read(&(zfsvfs)->z_teardown_lock, tag);
#define ZFS_TEARDOWN_EXIT_READ(zfsvfs, tag) \
rrm_exit(&(zfsvfs)->z_teardown_lock, tag)
#define ZFS_TEARDOWN_ENTER_WRITE(zfsvfs, tag) \
rrm_enter(&(zfsvfs)->z_teardown_lock, RW_WRITER, tag)
#define ZFS_TEARDOWN_EXIT_WRITE(zfsvfs) \
rrm_exit(&(zfsvfs)->z_teardown_lock, tag)
#define ZFS_TEARDOWN_EXIT(zfsvfs, tag) \
rrm_exit(&(zfsvfs)->z_teardown_lock, tag)
#define ZFS_TEARDOWN_READ_HELD(zfsvfs) \
RRM_READ_HELD(&(zfsvfs)->z_teardown_lock)
#define ZFS_TEARDOWN_WRITE_HELD(zfsvfs) \
RRM_WRITE_HELD(&(zfsvfs)->z_teardown_lock)
#define ZFS_TEARDOWN_HELD(zfsvfs) \
RRM_LOCK_HELD(&(zfsvfs)->z_teardown_lock)
#define ZSB_XATTR 0x0001 /* Enable user xattrs */
/*

View File

@ -81,7 +81,7 @@ extern "C" {
do { \
ZFS_TEARDOWN_ENTER_READ(zfsvfs, FTAG); \
if (unlikely((zfsvfs)->z_unmounted)) { \
ZFS_EXIT_READ(zfsvfs, FTAG); \
ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG); \
return (error); \
} \
} while (0)
@ -92,7 +92,7 @@ do { \
#define ZFS_EXIT(zfsvfs) \
do { \
zfs_exit_fs(zfsvfs); \
ZFS_EXIT_READ(zfsvfs, FTAG); \
ZFS_TEARDOWN_EXIT_READ(zfsvfs, FTAG); \
} while (0)
#define ZPL_EXIT(zfsvfs) \

View File

@ -39,6 +39,7 @@ redact_block_get_size(redact_block_phys_t *rbp)
static inline void
redact_block_set_size(redact_block_phys_t *rbp, uint64_t size)
{
/* cppcheck-suppress syntaxError */
BF64_SET_SB((rbp)->rbp_size_count, 48, 16, SPA_MINBLOCKSHIFT, 0, size);
}
@ -51,6 +52,7 @@ redact_block_get_count(redact_block_phys_t *rbp)
static inline void
redact_block_set_count(redact_block_phys_t *rbp, uint64_t count)
{
/* cppcheck-suppress syntaxError */
BF64_SET_SB((rbp)->rbp_size_count, 0, 48, 0, 1, count);
}

View File

@ -525,7 +525,6 @@ typedef struct zfs_useracct {
} zfs_useracct_t;
#define ZFSDEV_MAX_MINOR (1 << 16)
#define ZFS_MIN_MINOR (ZFSDEV_MAX_MINOR + 1)
#define ZPOOL_EXPORT_AFTER_SPLIT 0x1

View File

@ -532,6 +532,8 @@ get_key_material(libzfs_handle_t *hdl, boolean_t do_verify, boolean_t newkey,
break;
case ZFS_KEYLOCATION_URI:
ret = ENOTSUP;
for (handler = uri_handlers; handler->zuh_scheme != NULL;
handler++) {
if (strcmp(handler->zuh_scheme, uri_scheme) != 0)
@ -544,9 +546,11 @@ get_key_material(libzfs_handle_t *hdl, boolean_t do_verify, boolean_t newkey,
break;
}
ret = ENOTSUP;
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"URI scheme is not supported"));
if (ret == ENOTSUP) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"URI scheme is not supported"));
goto error;
}
break;
default:

View File

@ -22,7 +22,7 @@
/*
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020 by Delphix. All rights reserved.
* Copyright (c) 2014, 2021 by Delphix. All rights reserved.
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
* Copyright 2017 RackTop Systems.
* Copyright (c) 2018 Datto Inc.
@ -553,7 +553,28 @@ unmount_one(libzfs_handle_t *hdl, const char *mountpoint, int flags)
error = do_unmount(mountpoint, flags);
if (error != 0) {
return (zfs_error_fmt(hdl, EZFS_UMOUNTFAILED,
int libzfs_err;
switch (error) {
case EBUSY:
libzfs_err = EZFS_BUSY;
break;
case EIO:
libzfs_err = EZFS_IO;
break;
case ENOENT:
libzfs_err = EZFS_NOENT;
break;
case ENOMEM:
libzfs_err = EZFS_NOMEM;
break;
case EPERM:
libzfs_err = EZFS_PERM;
break;
default:
libzfs_err = EZFS_UMOUNTFAILED;
}
return (zfs_error_fmt(hdl, libzfs_err,
dgettext(TEXT_DOMAIN, "cannot unmount '%s'"),
mountpoint));
}

View File

@ -128,8 +128,9 @@ do_mount(zfs_handle_t *zhp, const char *mntpt, char *opts, int flags)
int
do_unmount(const char *mntpt, int flags)
{
return (unmount(mntpt, flags));
if (unmount(mntpt, flags) < 0)
return (errno);
return (0);
}
int

View File

@ -22,7 +22,7 @@
/*
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020 by Delphix. All rights reserved.
* Copyright (c) 2014, 2021 by Delphix. All rights reserved.
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
* Copyright 2017 RackTop Systems.
* Copyright (c) 2018 Datto Inc.
@ -377,7 +377,9 @@ int
do_unmount(const char *mntpt, int flags)
{
if (!libzfs_envvar_is_set("ZFS_MOUNT_HELPER")) {
return (umount2(mntpt, flags));
int rv = umount2(mntpt, flags);
return (rv < 0 ? errno : 0);
}
char force_opt[] = "-f";

View File

@ -1269,7 +1269,8 @@ zpool_find_import_scan(libpc_handle_t *hdl, pthread_mutex_t *lock,
* to import a specific pool.
*/
static nvlist_t *
zpool_find_import_impl(libpc_handle_t *hdl, importargs_t *iarg)
zpool_find_import_impl(libpc_handle_t *hdl, importargs_t *iarg,
pthread_mutex_t *lock, avl_tree_t *cache)
{
nvlist_t *ret = NULL;
pool_list_t pools = { 0 };
@ -1277,34 +1278,11 @@ zpool_find_import_impl(libpc_handle_t *hdl, importargs_t *iarg)
vdev_entry_t *ve, *venext;
config_entry_t *ce, *cenext;
name_entry_t *ne, *nenext;
pthread_mutex_t lock;
avl_tree_t *cache;
rdsk_node_t *slice;
void *cookie;
tpool_t *t;
verify(iarg->poolname == NULL || iarg->guid == 0);
pthread_mutex_init(&lock, NULL);
/*
* Locate pool member vdevs by blkid or by directory scanning.
* On success a newly allocated AVL tree which is populated with an
* entry for each discovered vdev will be returned in the cache.
* It's the caller's responsibility to consume and destroy this tree.
*/
if (iarg->scan || iarg->paths != 0) {
size_t dirs = iarg->paths;
const char * const *dir = (const char * const *)iarg->path;
if (dirs == 0)
dir = zpool_default_search_paths(&dirs);
if (zpool_find_import_scan(hdl, &lock, &cache, dir, dirs) != 0)
return (NULL);
} else {
if (zpool_find_import_blkid(hdl, &lock, &cache) != 0)
return (NULL);
}
/*
* Create a thread pool to parallelize the process of reading and
@ -1384,7 +1362,6 @@ zpool_find_import_impl(libpc_handle_t *hdl, importargs_t *iarg)
}
avl_destroy(cache);
free(cache);
pthread_mutex_destroy(&lock);
ret = get_configs(hdl, &pools, iarg->can_be_active, iarg->policy);
@ -1411,14 +1388,43 @@ zpool_find_import_impl(libpc_handle_t *hdl, importargs_t *iarg)
return (ret);
}
/*
* Given a config, discover the paths for the devices which
* exist in the config.
*/
static int
discover_cached_paths(libpc_handle_t *hdl, nvlist_t *nv,
avl_tree_t *cache, pthread_mutex_t *lock)
{
char *path = NULL;
uint_t children;
nvlist_t **child;
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
&child, &children) == 0) {
for (int c = 0; c < children; c++) {
discover_cached_paths(hdl, child[c], cache, lock);
}
}
/*
* Once we have the path, we need to add the directory to
* our directoy cache.
*/
if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
return (zpool_find_import_scan_dir(hdl, lock, cache,
dirname(path), 0));
}
return (0);
}
/*
* Given a cache file, return the contents as a list of importable pools.
* poolname or guid (but not both) are provided by the caller when trying
* to import a specific pool.
*/
static nvlist_t *
zpool_find_import_cached(libpc_handle_t *hdl, const char *cachefile,
const char *poolname, uint64_t guid)
zpool_find_import_cached(libpc_handle_t *hdl, importargs_t *iarg)
{
char *buf;
int fd;
@ -1430,9 +1436,9 @@ zpool_find_import_cached(libpc_handle_t *hdl, const char *cachefile,
uint64_t this_guid;
boolean_t active;
verify(poolname == NULL || guid == 0);
verify(iarg->poolname == NULL || iarg->guid == 0);
if ((fd = open(cachefile, O_RDONLY)) < 0) {
if ((fd = open(iarg->cachefile, O_RDONLY)) < 0) {
zutil_error_aux(hdl, "%s", strerror(errno));
(void) zutil_error(hdl, EZFS_BADCACHE,
dgettext(TEXT_DOMAIN, "failed to open cache file"));
@ -1488,11 +1494,11 @@ zpool_find_import_cached(libpc_handle_t *hdl, const char *cachefile,
src = fnvpair_value_nvlist(elem);
name = fnvlist_lookup_string(src, ZPOOL_CONFIG_POOL_NAME);
if (poolname != NULL && strcmp(poolname, name) != 0)
if (iarg->poolname != NULL && strcmp(iarg->poolname, name) != 0)
continue;
this_guid = fnvlist_lookup_uint64(src, ZPOOL_CONFIG_POOL_GUID);
if (guid != 0 && guid != this_guid)
if (iarg->guid != 0 && iarg->guid != this_guid)
continue;
if (zutil_pool_active(hdl, name, this_guid, &active) != 0) {
@ -1504,8 +1510,68 @@ zpool_find_import_cached(libpc_handle_t *hdl, const char *cachefile,
if (active)
continue;
if (iarg->scan) {
uint64_t saved_guid = iarg->guid;
const char *saved_poolname = iarg->poolname;
pthread_mutex_t lock;
/*
* Create the device cache that will hold the
* devices we will scan based on the cachefile.
* This will get destroyed and freed by
* zpool_find_import_impl.
*/
avl_tree_t *cache = zutil_alloc(hdl,
sizeof (avl_tree_t));
avl_create(cache, slice_cache_compare,
sizeof (rdsk_node_t),
offsetof(rdsk_node_t, rn_node));
nvlist_t *nvroot = fnvlist_lookup_nvlist(src,
ZPOOL_CONFIG_VDEV_TREE);
/*
* We only want to find the pool with this_guid.
* We will reset these values back later.
*/
iarg->guid = this_guid;
iarg->poolname = NULL;
/*
* We need to build up a cache of devices that exists
* in the paths pointed to by the cachefile. This allows
* us to preserve the device namespace that was
* originally specified by the user but also lets us
* scan devices in those directories in case they had
* been renamed.
*/
pthread_mutex_init(&lock, NULL);
discover_cached_paths(hdl, nvroot, cache, &lock);
nvlist_t *nv = zpool_find_import_impl(hdl, iarg,
&lock, cache);
pthread_mutex_destroy(&lock);
/*
* zpool_find_import_impl will return back
* a list of pools that it found based on the
* device cache. There should only be one pool
* since we're looking for a specific guid.
* We will use that pool to build up the final
* pool nvlist which is returned back to the
* caller.
*/
nvpair_t *pair = nvlist_next_nvpair(nv, NULL);
fnvlist_add_nvlist(pools, nvpair_name(pair),
fnvpair_value_nvlist(pair));
VERIFY3P(nvlist_next_nvpair(nv, pair), ==, NULL);
iarg->guid = saved_guid;
iarg->poolname = saved_poolname;
continue;
}
if (nvlist_add_string(src, ZPOOL_CONFIG_CACHEFILE,
cachefile) != 0) {
iarg->cachefile) != 0) {
(void) zutil_no_memory(hdl);
nvlist_free(raw);
nvlist_free(pools);
@ -1527,11 +1593,51 @@ zpool_find_import_cached(libpc_handle_t *hdl, const char *cachefile,
}
nvlist_free(dst);
}
nvlist_free(raw);
return (pools);
}
static nvlist_t *
zpool_find_import(libpc_handle_t *hdl, importargs_t *iarg)
{
pthread_mutex_t lock;
avl_tree_t *cache;
nvlist_t *pools = NULL;
verify(iarg->poolname == NULL || iarg->guid == 0);
pthread_mutex_init(&lock, NULL);
/*
* Locate pool member vdevs by blkid or by directory scanning.
* On success a newly allocated AVL tree which is populated with an
* entry for each discovered vdev will be returned in the cache.
* It's the caller's responsibility to consume and destroy this tree.
*/
if (iarg->scan || iarg->paths != 0) {
size_t dirs = iarg->paths;
const char * const *dir = (const char * const *)iarg->path;
if (dirs == 0)
dir = zpool_default_search_paths(&dirs);
if (zpool_find_import_scan(hdl, &lock, &cache,
dir, dirs) != 0) {
pthread_mutex_destroy(&lock);
return (NULL);
}
} else {
if (zpool_find_import_blkid(hdl, &lock, &cache) != 0) {
pthread_mutex_destroy(&lock);
return (NULL);
}
}
pools = zpool_find_import_impl(hdl, iarg, &lock, cache);
pthread_mutex_destroy(&lock);
return (pools);
}
nvlist_t *
zpool_search_import(void *hdl, importargs_t *import,
const pool_config_ops_t *pco)
@ -1546,10 +1652,9 @@ zpool_search_import(void *hdl, importargs_t *import,
verify(import->poolname == NULL || import->guid == 0);
if (import->cachefile != NULL)
pools = zpool_find_import_cached(&handle, import->cachefile,
import->poolname, import->guid);
pools = zpool_find_import_cached(&handle, import);
else
pools = zpool_find_import_impl(&handle, import);
pools = zpool_find_import(&handle, import);
if ((pools == NULL || nvlist_empty(pools)) &&
handle.lpc_open_access_error && geteuid() != 0) {

View File

@ -261,6 +261,16 @@ causes the property to be inherited by all descendant datasets, as through
was run on any descendant datasets that have this property set on the
sending system.
.Pp
If the send stream was sent with
.Fl c
then overriding the
.Sy compression
property will have no affect on received data but the
.Sy compression
property will be set. To have the data recompressed on receive remove the
.Fl c
flag from the send stream.
.Pp
Any editable property can be set at receive time. Set-once properties bound
to the received data, such as
.Sy normalization

View File

@ -189,7 +189,12 @@ feature is enabled on the sending system but the
option is not supplied in conjunction with
.Fl c ,
then the data will be decompressed before sending so it can be split into
smaller block sizes.
smaller block sizes. Streams sent with
.Fl c
will not have their data recompressed on the receiver side using
.Fl o compress=value.
The data will stay compressed as it was from the sender. The new compression
property will be set for future data.
.It Fl w, -raw
For encrypted datasets, send data exactly as it exists on disk. This allows
backups to be taken even if encryption keys are not currently loaded. The

View File

@ -17,6 +17,10 @@ check:
modules_uninstall modules_uninstall-Linux modules_uninstall-FreeBSD \
cppcheck cppcheck-Linux cppcheck-FreeBSD
# For FreeBSD, use debug options from ./configure if not overridden.
export WITH_DEBUG ?= @WITH_DEBUG@
export WITH_INVARIANTS ?= @WITH_INVARIANTS@
# Filter out options that FreeBSD make doesn't understand
getflags = ( \
set -- \
@ -42,6 +46,7 @@ FMAKEFLAGS = -C @abs_srcdir@ -f Makefile.bsd $(shell $(getflags))
ifneq (@abs_srcdir@,@abs_builddir@)
FMAKEFLAGS += MAKEOBJDIR=@abs_builddir@
endif
FMAKE = env -u MAKEFLAGS make $(FMAKEFLAGS)
modules-Linux:

View File

@ -182,23 +182,21 @@ zfsdev_ioctl(struct cdev *dev, ulong_t zcmd, caddr_t arg, int flag,
static void
zfsdev_close(void *data)
{
zfsdev_state_t *zs, *zsp = data;
zfsdev_state_t *zs = data;
ASSERT(zs != NULL);
mutex_enter(&zfsdev_state_lock);
for (zs = zfsdev_state_list; zs != NULL; zs = zs->zs_next) {
if (zs == zsp)
break;
}
if (zs == NULL || zs->zs_minor <= 0) {
mutex_exit(&zfsdev_state_lock);
return;
}
ASSERT(zs->zs_minor != 0);
zs->zs_minor = -1;
zfs_onexit_destroy(zs->zs_onexit);
zfs_zevent_destroy(zs->zs_zevent);
mutex_exit(&zfsdev_state_lock);
zs->zs_onexit = NULL;
zs->zs_zevent = NULL;
mutex_exit(&zfsdev_state_lock);
}
static int

View File

@ -209,7 +209,6 @@ zfs_dd_lookup(znode_t *dzp, znode_t **zpp)
#ifdef ZFS_DEBUG
if (zfsvfs->z_replay == B_FALSE)
ASSERT_VOP_LOCKED(ZTOV(dzp), __func__);
ASSERT(ZFS_TEARDOWN_READ_HELD(zfsvfs));
#endif
if (dzp->z_unlinked)
return (ENOENT);
@ -234,7 +233,6 @@ zfs_dirlook(znode_t *dzp, const char *name, znode_t **zpp)
#ifdef ZFS_DEBUG
if (zfsvfs->z_replay == B_FALSE)
ASSERT_VOP_LOCKED(ZTOV(dzp), __func__);
ASSERT(ZFS_TEARDOWN_READ_HELD(zfsvfs));
#endif
if (dzp->z_unlinked)
return (SET_ERROR(ENOENT));

View File

@ -1163,6 +1163,9 @@ zvol_ensure_zilog(zvol_state_t *zv)
zv->zv_zilog = zil_open(zv->zv_objset,
zvol_get_data);
zv->zv_flags |= ZVOL_WRITTEN_TO;
/* replay / destroy done in zvol_create_minor_impl() */
VERIFY0((zv->zv_zilog->zl_header->zh_flags &
ZIL_REPLAY_NEEDED));
}
rw_downgrade(&zv->zv_suspend_lock);
}
@ -1387,12 +1390,16 @@ zvol_create_minor_impl(const char *name)
zv->zv_volsize = volsize;
zv->zv_objset = os;
ASSERT3P(zv->zv_zilog, ==, NULL);
zv->zv_zilog = zil_open(os, zvol_get_data);
if (spa_writeable(dmu_objset_spa(os))) {
if (zil_replay_disable)
zil_destroy(dmu_objset_zil(os), B_FALSE);
zil_destroy(zv->zv_zilog, B_FALSE);
else
zil_replay(os, zv, zvol_replay_vector);
}
zil_close(zv->zv_zilog);
zv->zv_zilog = NULL;
ASSERT3P(zv->zv_kstat.dk_kstats, ==, NULL);
dataset_kstats_create(&zv->zv_kstat, zv->zv_objset);

View File

@ -2214,13 +2214,11 @@ zfs_zaccess_dataset_check(znode_t *zp, uint32_t v4_mode)
}
/*
* Only check for READONLY on non-directories.
* Intentionally allow ZFS_READONLY through here.
* See zfs_zaccess_common().
*/
if ((v4_mode & WRITE_MASK_DATA) &&
((!S_ISDIR(ZTOI(zp)->i_mode) &&
(zp->z_pflags & (ZFS_READONLY | ZFS_IMMUTABLE))) ||
(S_ISDIR(ZTOI(zp)->i_mode) &&
(zp->z_pflags & ZFS_IMMUTABLE)))) {
(zp->z_pflags & ZFS_IMMUTABLE)) {
return (SET_ERROR(EPERM));
}
@ -2434,6 +2432,24 @@ zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode,
return (0);
}
/*
* Note: ZFS_READONLY represents the "DOS R/O" attribute.
* When that flag is set, we should behave as if write access
* were not granted by anything in the ACL. In particular:
* We _must_ allow writes after opening the file r/w, then
* setting the DOS R/O attribute, and writing some more.
* (Similar to how you can write after fchmod(fd, 0444).)
*
* Therefore ZFS_READONLY is ignored in the dataset check
* above, and checked here as if part of the ACL check.
* Also note: DOS R/O is ignored for directories.
*/
if ((v4_mode & WRITE_MASK_DATA) &&
S_ISDIR(ZTOI(zp)->i_mode) &&
(zp->z_pflags & ZFS_READONLY)) {
return (SET_ERROR(EPERM));
}
return (zfs_zaccess_aces_check(zp, working_mode, B_FALSE, cr));
}

View File

@ -1412,6 +1412,7 @@ zio_crypt_init_uios_zil(boolean_t encrypt, uint8_t *plainbuf,
nr_src = 1;
nr_dst = 0;
}
bzero(dst, datalen);
/* find the start and end record of the log block */
zilc = (zil_chain_t *)src;

View File

@ -56,12 +56,32 @@ struct zvol_state_os {
taskq_t *zvol_taskq;
static struct ida zvol_ida;
typedef struct zv_request {
typedef struct zv_request_stack {
zvol_state_t *zv;
struct bio *bio;
taskq_ent_t ent;
} zv_request_t;
typedef struct zv_request_task {
zv_request_t zvr;
taskq_ent_t ent;
} zv_request_task_t;
static zv_request_task_t *
zv_request_task_create(zv_request_t zvr)
{
zv_request_task_t *task;
task = kmem_alloc(sizeof (zv_request_task_t), KM_SLEEP);
taskq_init_ent(&task->ent);
task->zvr = zvr;
return (task);
}
static void
zv_request_task_free(zv_request_task_t *task)
{
kmem_free(task, sizeof (*task));
}
/*
* Given a path, return TRUE if path is a ZVOL.
*/
@ -80,9 +100,8 @@ zvol_is_zvol_impl(const char *path)
}
static void
zvol_write(void *arg)
zvol_write(zv_request_t *zvr)
{
zv_request_t *zvr = arg;
struct bio *bio = zvr->bio;
int error = 0;
zfs_uio_t uio;
@ -102,7 +121,6 @@ zvol_write(void *arg)
if (uio.uio_resid == 0) {
rw_exit(&zv->zv_suspend_lock);
BIO_END_IO(bio, 0);
kmem_free(zvr, sizeof (zv_request_t));
return;
}
@ -162,13 +180,19 @@ zvol_write(void *arg)
blk_generic_end_io_acct(q, disk, WRITE, bio, start_time);
BIO_END_IO(bio, -error);
kmem_free(zvr, sizeof (zv_request_t));
}
static void
zvol_discard(void *arg)
zvol_write_task(void *arg)
{
zv_request_task_t *task = arg;
zvol_write(&task->zvr);
zv_request_task_free(task);
}
static void
zvol_discard(zv_request_t *zvr)
{
zv_request_t *zvr = arg;
struct bio *bio = zvr->bio;
zvol_state_t *zv = zvr->zv;
uint64_t start = BIO_BI_SECTOR(bio) << 9;
@ -238,13 +262,19 @@ zvol_discard(void *arg)
blk_generic_end_io_acct(q, disk, WRITE, bio, start_time);
BIO_END_IO(bio, -error);
kmem_free(zvr, sizeof (zv_request_t));
}
static void
zvol_read(void *arg)
zvol_discard_task(void *arg)
{
zv_request_task_t *task = arg;
zvol_discard(&task->zvr);
zv_request_task_free(task);
}
static void
zvol_read(zv_request_t *zvr)
{
zv_request_t *zvr = arg;
struct bio *bio = zvr->bio;
int error = 0;
zfs_uio_t uio;
@ -295,7 +325,14 @@ zvol_read(void *arg)
blk_generic_end_io_acct(q, disk, READ, bio, start_time);
BIO_END_IO(bio, -error);
kmem_free(zvr, sizeof (zv_request_t));
}
static void
zvol_read_task(void *arg)
{
zv_request_task_t *task = arg;
zvol_read(&task->zvr);
zv_request_task_free(task);
}
#ifdef HAVE_SUBMIT_BIO_IN_BLOCK_DEVICE_OPERATIONS
@ -318,7 +355,6 @@ zvol_request(struct request_queue *q, struct bio *bio)
uint64_t offset = BIO_BI_SECTOR(bio) << 9;
uint64_t size = BIO_BI_SIZE(bio);
int rw = bio_data_dir(bio);
zv_request_t *zvr;
if (bio_has_data(bio) && offset + size > zv->zv_volsize) {
printk(KERN_INFO
@ -331,6 +367,12 @@ zvol_request(struct request_queue *q, struct bio *bio)
goto out;
}
zv_request_t zvr = {
.zv = zv,
.bio = bio,
};
zv_request_task_t *task;
if (rw == WRITE) {
if (unlikely(zv->zv_flags & ZVOL_RDONLY)) {
BIO_END_IO(bio, -SET_ERROR(EROFS));
@ -357,15 +399,13 @@ zvol_request(struct request_queue *q, struct bio *bio)
zv->zv_zilog = zil_open(zv->zv_objset,
zvol_get_data);
zv->zv_flags |= ZVOL_WRITTEN_TO;
/* replay / destroy done in zvol_create_minor */
VERIFY0((zv->zv_zilog->zl_header->zh_flags &
ZIL_REPLAY_NEEDED));
}
rw_downgrade(&zv->zv_suspend_lock);
}
zvr = kmem_alloc(sizeof (zv_request_t), KM_SLEEP);
zvr->zv = zv;
zvr->bio = bio;
taskq_init_ent(&zvr->ent);
/*
* We don't want this thread to be blocked waiting for i/o to
* complete, so we instead wait from a taskq callback. The
@ -398,17 +438,19 @@ zvol_request(struct request_queue *q, struct bio *bio)
*/
if (bio_is_discard(bio) || bio_is_secure_erase(bio)) {
if (zvol_request_sync) {
zvol_discard(zvr);
zvol_discard(&zvr);
} else {
task = zv_request_task_create(zvr);
taskq_dispatch_ent(zvol_taskq,
zvol_discard, zvr, 0, &zvr->ent);
zvol_discard_task, task, 0, &task->ent);
}
} else {
if (zvol_request_sync) {
zvol_write(zvr);
zvol_write(&zvr);
} else {
task = zv_request_task_create(zvr);
taskq_dispatch_ent(zvol_taskq,
zvol_write, zvr, 0, &zvr->ent);
zvol_write_task, task, 0, &task->ent);
}
}
} else {
@ -422,19 +464,15 @@ zvol_request(struct request_queue *q, struct bio *bio)
goto out;
}
zvr = kmem_alloc(sizeof (zv_request_t), KM_SLEEP);
zvr->zv = zv;
zvr->bio = bio;
taskq_init_ent(&zvr->ent);
rw_enter(&zv->zv_suspend_lock, RW_READER);
/* See comment in WRITE case above. */
if (zvol_request_sync) {
zvol_read(zvr);
zvol_read(&zvr);
} else {
task = zv_request_task_create(zvr);
taskq_dispatch_ent(zvol_taskq,
zvol_read, zvr, 0, &zvr->ent);
zvol_read_task, task, 0, &task->ent);
}
}
@ -947,12 +985,16 @@ zvol_os_create_minor(const char *name)
blk_queue_flag_set(QUEUE_FLAG_SCSI_PASSTHROUGH, zv->zv_zso->zvo_queue);
#endif
ASSERT3P(zv->zv_zilog, ==, NULL);
zv->zv_zilog = zil_open(os, zvol_get_data);
if (spa_writeable(dmu_objset_spa(os))) {
if (zil_replay_disable)
zil_destroy(dmu_objset_zil(os), B_FALSE);
zil_destroy(zv->zv_zilog, B_FALSE);
else
zil_replay(os, zv, zvol_replay_vector);
}
zil_close(zv->zv_zilog);
zv->zv_zilog = NULL;
ASSERT3P(zv->zv_kstat.dk_kstats, ==, NULL);
dataset_kstats_create(&zv->zv_kstat, zv->zv_objset);

View File

@ -417,7 +417,7 @@ zfs_prop_init(void)
ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
"on | off | lzjb | gzip | gzip-[1-9] | zle | lz4 | "
"zstd | zstd-[1-19] | "
"zstd-fast-[1-10,20,30,40,50,60,70,80,90,100,500,1000]",
"zstd-fast | zstd-fast-[1-10,20,30,40,50,60,70,80,90,100,500,1000]",
"COMPRESS", compress_table);
zprop_register_index(ZFS_PROP_SNAPDIR, "snapdir", ZFS_SNAPDIR_HIDDEN,
PROP_INHERIT, ZFS_TYPE_FILESYSTEM,

View File

@ -555,8 +555,12 @@ abd_get_offset_impl(abd_t *abd, abd_t *sabd, size_t off, size_t size)
abd_t *
abd_get_offset_struct(abd_t *abd, abd_t *sabd, size_t off, size_t size)
{
abd_t *result;
abd_init_struct(abd);
return (abd_get_offset_impl(abd, sabd, off, size));
result = abd_get_offset_impl(abd, sabd, off, size);
if (result != abd)
abd_fini_struct(abd);
return (result);
}
abd_t *

View File

@ -2923,10 +2923,10 @@ ZFS_MODULE_PARAM(zfs, zfs_, recover, INT, ZMOD_RW,
ZFS_MODULE_PARAM(zfs, zfs_, free_leak_on_eio, INT, ZMOD_RW,
"Set to ignore IO errors during free and permanently leak the space");
ZFS_MODULE_PARAM(zfs, zfs_, deadman_checktime_ms, ULONG, ZMOD_RW,
ZFS_MODULE_PARAM(zfs_deadman, zfs_deadman_, checktime_ms, ULONG, ZMOD_RW,
"Dead I/O check interval in milliseconds");
ZFS_MODULE_PARAM(zfs, zfs_, deadman_enabled, INT, ZMOD_RW,
ZFS_MODULE_PARAM(zfs_deadman, zfs_deadman_, enabled, INT, ZMOD_RW,
"Enable deadman timer");
ZFS_MODULE_PARAM(zfs_spa, spa_, asize_inflation, INT, ZMOD_RW,

View File

@ -350,9 +350,11 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
}
/*
* If immutable or not appending then return EPERM
* If immutable or not appending then return EPERM.
* Intentionally allow ZFS_READONLY through here.
* See zfs_zaccess_common()
*/
if ((zp->z_pflags & (ZFS_IMMUTABLE | ZFS_READONLY)) ||
if ((zp->z_pflags & ZFS_IMMUTABLE) ||
((zp->z_pflags & ZFS_APPENDONLY) && !(ioflag & O_APPEND) &&
(zfs_uio_offset(uio) < zp->z_size))) {
ZFS_EXIT(zfsvfs);

View File

@ -473,7 +473,19 @@ zvol_replay_truncate(void *arg1, void *arg2, boolean_t byteswap)
offset = lr->lr_offset;
length = lr->lr_length;
return (dmu_free_long_range(zv->zv_objset, ZVOL_OBJ, offset, length));
dmu_tx_t *tx = dmu_tx_create(zv->zv_objset);
dmu_tx_mark_netfree(tx);
int error = dmu_tx_assign(tx, TXG_WAIT);
if (error != 0) {
dmu_tx_abort(tx);
} else {
zil_replaying(zv->zv_zilog, tx);
dmu_tx_commit(tx);
error = dmu_free_long_range(zv->zv_objset, ZVOL_OBJ, offset,
length);
}
return (error);
}
/*
@ -513,6 +525,7 @@ zvol_replay_write(void *arg1, void *arg2, boolean_t byteswap)
dmu_tx_abort(tx);
} else {
dmu_write(os, ZVOL_OBJ, offset, length, data, tx);
zil_replaying(zv->zv_zilog, tx);
dmu_tx_commit(tx);
}

View File

@ -398,6 +398,7 @@ tests = ['zpool_import_001_pos', 'zpool_import_002_pos',
'import_cachefile_device_replaced',
'import_cachefile_mirror_attached',
'import_cachefile_mirror_detached',
'import_cachefile_paths_changed',
'import_cachefile_shared_device',
'import_devices_missing',
'import_paths_changed',

View File

@ -33,6 +33,7 @@ export SYSTEM_FILES_COMMON='arp
du
echo
egrep
env
expr
false
file
@ -117,7 +118,6 @@ export SYSTEM_FILES_FREEBSD='chflags
compress
diskinfo
dumpon
env
fsck
getextattr
gpart

View File

@ -41,7 +41,7 @@
# PATH may have been modified by sudo's secure_path behavior.
#
if [ -n "$STF_PATH" ]; then
PATH="$STF_PATH"
export PATH="$STF_PATH"
fi
#
@ -2766,10 +2766,6 @@ function add_user #<group_name> <user_name> <basedir>
;;
esac
echo "export PATH=\"$STF_PATH\"" >>$basedir/$user/.profile
echo "export PATH=\"$STF_PATH\"" >>$basedir/$user/.bash_profile
echo "export PATH=\"$STF_PATH\"" >>$basedir/$user/.login
return 0
}
@ -3393,8 +3389,17 @@ function user_run
typeset user=$1
shift
log_note "user:$user $@"
eval su - \$user -c \"$@\" > $TEST_BASE_DIR/out 2>$TEST_BASE_DIR/err
log_note "user: $user"
log_note "cmd: $*"
typeset out=$TEST_BASE_DIR/out
typeset err=$TEST_BASE_DIR/err
sudo -Eu $user env PATH="$PATH" ksh <<<"$*" >$out 2>$err
typeset res=$?
log_note "out: $(<$out)"
log_note "err: $(<$err)"
return $res
}
#

View File

@ -27,10 +27,10 @@ COMPRESSED_ARC_ENABLED compressed_arc_enabled zfs_compressed_arc_enabled
CONDENSE_INDIRECT_COMMIT_ENTRY_DELAY_MS condense.indirect_commit_entry_delay_ms zfs_condense_indirect_commit_entry_delay_ms
CONDENSE_MIN_MAPPING_BYTES condense.min_mapping_bytes zfs_condense_min_mapping_bytes
DBUF_CACHE_MAX_BYTES dbuf_cache.max_bytes dbuf_cache_max_bytes
DEADMAN_CHECKTIME_MS deadman_checktime_ms zfs_deadman_checktime_ms
DEADMAN_FAILMODE deadman_failmode zfs_deadman_failmode
DEADMAN_SYNCTIME_MS deadman_synctime_ms zfs_deadman_synctime_ms
DEADMAN_ZIOTIME_MS deadman_ziotime_ms zfs_deadman_ziotime_ms
DEADMAN_CHECKTIME_MS deadman.checktime_ms zfs_deadman_checktime_ms
DEADMAN_FAILMODE deadman.failmode zfs_deadman_failmode
DEADMAN_SYNCTIME_MS deadman.synctime_ms zfs_deadman_synctime_ms
DEADMAN_ZIOTIME_MS deadman.ziotime_ms zfs_deadman_ziotime_ms
DISABLE_IVSET_GUID_CHECK disable_ivset_guid_check zfs_disable_ivset_guid_check
INITIALIZE_CHUNK_SIZE initialize_chunk_size zfs_initialize_chunk_size
INITIALIZE_VALUE initialize_value zfs_initialize_value

View File

@ -47,31 +47,32 @@ function cleanup
{
unset ZFS_ABORT
if [[ -d $corepath ]]; then
rm -rf $corepath
if is_freebsd && [ -n "$old_corefile" ]; then
sysctl kern.corefile=$old_corefile
fi
if poolexists $pool; then
log_must zpool destroy -f $pool
fi
# Clean up the pool created if we failed to abort.
poolexists $pool && destroy_pool $pool
rm -rf $corepath $vdev1 $vdev2 $vdev3
}
log_assert "With ZFS_ABORT set, all zpool commands can abort and generate a core file."
log_onexit cleanup
#preparation work for testing
corepath=$TESTDIR/core
corefile=$corepath/zpool.core
if [[ -d $corepath ]]; then
rm -rf $corepath
log_must rm -rf $corepath
fi
mkdir $corepath
log_must mkdir $corepath
pool=pool.$$
vdev1=$TESTDIR/file1
vdev2=$TESTDIR/file2
vdev3=$TESTDIR/file3
for vdev in $vdev1 $vdev2 $vdev3; do
mkfile $MINVDEVSIZE $vdev
log_must mkfile $MINVDEVSIZE $vdev
done
set -A cmds "create $pool mirror $vdev1 $vdev2" "list $pool" "iostat $pool" \
@ -86,27 +87,25 @@ set -A badparams "" "create" "destroy" "add" "remove" "list *" "iostat" "status"
"import" "export" "upgrade" "history -?" "get" "set"
if is_linux; then
ulimit -c unlimited
echo "$corepath/core.zpool" >/proc/sys/kernel/core_pattern
echo $corefile >/proc/sys/kernel/core_pattern
echo 0 >/proc/sys/kernel/core_uses_pid
export ASAN_OPTIONS="abort_on_error=1:disable_coredump=0"
elif is_freebsd; then
ulimit -c unlimited
log_must sysctl kern.corefile=$corepath/core.zpool
export ASAN_OPTIONS="abort_on_error=1:disable_coredump=0"
else
coreadm -p ${corepath}/core.%f
old_corefile=$(sysctl -n kern.corefile)
log_must sysctl kern.corefile=$corefile
fi
ulimit -c unlimited
export ASAN_OPTIONS="abort_on_error=1:disable_coredump=0"
export ZFS_ABORT=yes
for subcmd in "${cmds[@]}" "${badparams[@]}"; do
corefile=${corepath}/core.zpool
zpool $subcmd >/dev/null 2>&1
if [[ ! -e $corefile ]]; then
log_fail "zpool $subcmd cannot generate core file with ZFS_ABORT set."
log_fail "zpool $subcmd cannot generate core file with ZFS_ABORT set."
fi
rm -f $corefile
done
unset ZFS_ABORT
log_pass "With ZFS_ABORT set, zpool command can abort and generate core file as expected."

View File

@ -44,9 +44,17 @@
function cleanup
{
unset ZFS_ABORT
if is_freebsd && [ -n "$old_corefile" ]; then
sysctl kern.corefile=$old_corefile
fi
rm -rf $corepath
# Don't leave the pool frozen.
destroy_pool $TESTPOOL
default_mirror_setup $DISKS
}
verify_runnable "both"
@ -54,7 +62,14 @@ verify_runnable "both"
log_assert "Debugging features of zpool should succeed."
log_onexit cleanup
log_must zpool -? > /dev/null 2>&1
corepath=$TESTDIR/core
corefile=$corepath/zpool.core
if [[ -d $corepath ]]; then
log_must rm -rf $corepath
fi
log_must mkdir $corepath
log_must eval "zpool -? >/dev/null 2>&1"
if is_global_zone ; then
log_must zpool freeze $TESTPOOL
@ -65,26 +80,22 @@ fi
log_mustnot zpool freeze fakepool
# Remove corefile possibly left by previous failing run of this test.
[[ -f core ]] && log_must rm -f core
if is_linux; then
ulimit -c unlimited
echo "core" >/proc/sys/kernel/core_pattern
echo $corefile >/proc/sys/kernel/core_pattern
echo 0 >/proc/sys/kernel/core_uses_pid
export ASAN_OPTIONS="abort_on_error=1:disable_coredump=0"
elif is_freebsd; then
ulimit -c unlimited
old_corefile=$(sysctl -n kern.corefile)
log_must sysctl kern.corefile=core
export ASAN_OPTIONS="abort_on_error=1:disable_coredump=0"
log_must sysctl kern.corefile=$corefile
fi
ulimit -c unlimited
export ASAN_OPTIONS="abort_on_error=1:disable_coredump=0"
export ZFS_ABORT=yes
zpool >/dev/null 2>&1
ZFS_ABORT=1; export ZFS_ABORT
zpool > /dev/null 2>&1
unset ZFS_ABORT
[[ -f core ]] || log_fail "zpool did not dump core by request."
[[ -f core ]] && log_must rm -f core
[[ -f $corefile ]] || log_fail "zpool did not dump core by request."
log_pass "Debugging features of zpool succeed."

View File

@ -9,6 +9,7 @@ dist_pkgdata_SCRIPTS = \
import_cachefile_device_replaced.ksh \
import_cachefile_mirror_attached.ksh \
import_cachefile_mirror_detached.ksh \
import_cachefile_paths_changed.ksh \
import_cachefile_shared_device.ksh \
import_devices_missing.ksh \
import_paths_changed.ksh \

View File

@ -0,0 +1,117 @@
#!/bin/ksh -p
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
#
# Copyright (c) 2021 by Delphix. All rights reserved.
#
. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
#
# DESCRIPTION:
# A pool should be importable from a cachefile even if device paths
# have changed.
#
# STRATEGY:
# 1. Create a pool using a cachefile
# 2. Backup cachefile
# 3. Export the pool.
# 4. Change the paths of some of the devices.
# 5. Verify that we can import the pool using the cachefile.
#
verify_runnable "global"
log_onexit cleanup
function test_new_paths
{
typeset poolcreate="$1"
typeset pathstochange="$2"
log_note "$0: pool '$poolcreate', changing paths of $pathstochange."
log_must zpool create -o cachefile=$CPATH $TESTPOOL1 $poolcreate
log_must cp $CPATH $CPATHBKP
log_must zpool export $TESTPOOL1
for dev in $pathstochange; do
log_must mv $dev "${dev}_new"
done
log_must zpool import -c $CPATHBKP $TESTPOOL1
log_must check_pool_healthy $TESTPOOL1
# Cleanup
log_must zpool destroy $TESTPOOL1
log_must rm -f $CPATH $CPATHBKP
for dev in $pathstochange; do
log_must mv "${dev}_new" $dev
done
log_note ""
}
function test_duplicate_pools
{
typeset poolcreate="$1"
typeset pathstocopy="$2"
log_note "$0: pool '$poolcreate', creating duplicate pool using $pathstocopy."
log_must zpool create -o cachefile=$CPATH $TESTPOOL1 $poolcreate
log_must zpool export $TESTPOOL1
for dev in $pathstocopy; do
log_must cp $dev "${dev}_orig"
done
log_must zpool create -f -o cachefile=$CPATH $TESTPOOL1 $poolcreate
log_must cp $CPATH $CPATHBKP
log_must zpool export $TESTPOOL1
for dev in $pathstocopy; do
log_must mv $dev "${dev}_new"
done
log_must zpool import -c $CPATHBKP
log_must zpool import -c $CPATHBKP $TESTPOOL1
log_must check_pool_healthy $TESTPOOL1
# Cleanup
log_must zpool destroy $TESTPOOL1
log_must rm -f $CPATH $CPATHBKP
for dev in $pathstocopy; do
log_must rm "${dev}_orig"
log_must mv "${dev}_new" $dev
done
log_note ""
}
test_new_paths "$VDEV0 $VDEV1" "$VDEV0 $VDEV1"
test_new_paths "mirror $VDEV0 $VDEV1" "$VDEV0 $VDEV1"
test_new_paths "$VDEV0 log $VDEV1" "$VDEV0 $VDEV1"
test_new_paths "raidz $VDEV0 $VDEV1 $VDEV2" "$VDEV0 $VDEV1 $VDEV2"
test_new_paths "draid $VDEV0 $VDEV1 $VDEV2" "$VDEV0 $VDEV1 $VDEV2"
test_duplicate_pools "$VDEV0 $VDEV1" "$VDEV0 $VDEV1"
test_duplicate_pools "mirror $VDEV0 $VDEV1" "$VDEV0 $VDEV1"
test_duplicate_pools "$VDEV0 log $VDEV1" "$VDEV0 $VDEV1"
test_duplicate_pools "raidz $VDEV0 $VDEV1 $VDEV2" "$VDEV0 $VDEV1 $VDEV2"
test_duplicate_pools "draid $VDEV0 $VDEV1 $VDEV2" "$VDEV0 $VDEV1 $VDEV2"
log_pass "zpool import with cachefile succeeded after changing device paths."

View File

@ -66,7 +66,7 @@ log_must zpool create $MPOOL mirror $VDEV1 $VDEV2
# 2. Start the ZED and verify it handles missed events.
log_must zed_start
log_must file_wait $ZED_DEBUG_LOG
log_must file_wait_event $ZED_DEBUG_LOG 'sysevent\.fs\.zfs\.config_sync' 150
log_must cp $ZED_DEBUG_LOG $TMP_EVENTS_ZED
awk -v event="sysevent.fs.zfs.pool_create" \
@ -92,12 +92,11 @@ done
# 5. Start the ZED and verify it only handled the new missed events.
log_must zed_start
log_must file_wait $ZED_DEBUG_LOG 35
log_must file_wait_event $ZED_DEBUG_LOG 'sysevent\.fs\.zfs\.resilver_finish' 150
log_must cp $ZED_DEBUG_LOG $TMP_EVENTS_ZED
log_mustnot grep -q "sysevent.fs.zfs.pool_create" $TMP_EVENTS_ZED
log_mustnot file_wait_event $ZED_DEBUG_LOG 'sysevent\.fs\.zfs\.pool_create' 30
log_must grep -q "sysevent.fs.zfs.vdev_online" $TMP_EVENTS_ZED
log_must grep -q "sysevent.fs.zfs.resilver_start" $TMP_EVENTS_ZED
log_must grep -q "sysevent.fs.zfs.resilver_finish" $TMP_EVENTS_ZED
log_pass "Verify ZED handles missed events on when starting"

View File

@ -43,34 +43,40 @@
# 4. Check that we're unable to write an xattr as a non-root user
#
function cleanup {
log_must rm $TESTDIR/myfile.$$
function cleanup
{
rm -f $testfile $tempfile
}
log_assert "read/write xattr on a file with no permissions fails"
log_onexit cleanup
log_must touch $TESTDIR/myfile.$$
create_xattr $TESTDIR/myfile.$$ passwd /etc/passwd
typeset testfile=$TESTDIR/testfile.$$
typeset tempfile=/tmp/tempfile.$$
log_must chmod 000 $TESTDIR/myfile.$$
log_must touch $testfile
create_xattr $testfile passwd /etc/passwd
log_must chmod 000 $testfile
if is_illumos; then
log_mustnot su $ZFS_USER -c "runat $TESTDIR/myfile.$$ cat passwd"
log_mustnot su $ZFS_USER -c "runat $TESTDIR/myfile.$$ cp /etc/passwd ."
log_mustnot su $ZFS_USER -c "runat $testfile cat passwd"
log_mustnot su $ZFS_USER -c "runat $testfile cp /etc/passwd ."
else
user_run $ZFS_USER eval \
"get_xattr passwd $TESTDIR/myfile.$$ >/tmp/passwd.$$"
log_mustnot diff /etc/passwd /tmp/passwd.$$
log_must rm /tmp/passwd.$$
log_mustnot user_run $ZFS_USER "
. $STF_SUITE/include/libtest.shlib
get_xattr passwd $testfile >$tempfile
"
log_mustnot diff -q /etc/passwd $tempfile
log_must rm $tempfile
user_run $ZFS_USER eval \
"set_xattr_stdin passwd $TESTDIR/myfile.$$ </etc/group"
log_must chmod 644 $TESTDIR/myfile.$$
get_xattr passwd $TESTDIR/myfile.$$ >/tmp/passwd.$$
log_must diff /etc/passwd /tmp/passwd.$$
log_must rm /tmp/passwd.$$
log_mustnot user_run $ZFS_USER "
. $STF_SUITE/include/libtest.shlib
set_xattr_stdin passwd $testfile </etc/group
"
log_must chmod 644 $testfile
get_xattr passwd $testfile >$tempfile
log_must diff -q /etc/passwd $tempfile
log_must rm $tempfile
fi
log_pass "read/write xattr on a file with no permissions fails"

View File

@ -734,7 +734,7 @@
/* #undef ZFS_IS_GPL_COMPATIBLE */
/* Define the project alias string. */
#define ZFS_META_ALIAS "zfs-2.0.0-FreeBSD_gbedbc13da"
#define ZFS_META_ALIAS "zfs-2.0.0-FreeBSD_g9305ff2ed"
/* Define the project author. */
#define ZFS_META_AUTHOR "OpenZFS"
@ -764,7 +764,7 @@
#define ZFS_META_NAME "zfs"
/* Define the project release. */
#define ZFS_META_RELEASE "FreeBSD_gbedbc13da"
#define ZFS_META_RELEASE "FreeBSD_g9305ff2ed"
/* Define the project version. */
#define ZFS_META_VERSION "2.0.0"