Notable upstream pull request merges:
 #15940 41ae864b6 Replace P2ALIGN with P2ALIGN_TYPED and delete P2ALIGN
 #16128 5137c132a zpool import output is not formated properly
 #16138 efbef9e6c FreeBSD: Add zfs_link_create() error handling
 #16146 04bae5ec9 Disable high priority ZIO threads on FreeBSD and Linux
 #16151 cc3869153 zfs_ioc_send: use a dedicated taskq thread for send
 #16151 adda768e3 spa: remove spa_taskq_dispatch_sync()
 #16151 515c4dd21 spa: flatten spa_taskq_dispatch_ent()
 #16151 0a543db37 spa_taskq_dispatch_ent: simplify arguments
 #16153 975a13259 Add support for parallel pool exports
 #16153 89acef992 Simplified the scope of the namespace lock
 #16159 136c05321 ZAP: Fix leaf references on zap_expand_leaf() errors
 #16162 af5dbed31 Fix scn_queue races on very old pools
 #16165 3400127a7 Fix ZIL clone records for legacy holes
 #16167 414acbd37 Unbreak FreeBSD cross-build on MacOS broken in 051460b8b
 #16172 eced2e2f1 libzfs: Fix mounting datasets under thread limit pressure
 #16178 b64afa41d Better control the thread pool size when mounting datasets
 #16181 fa99d9cd9 zfs_dbgmsg_print: make FreeBSD and Linux consistent
 #16191 e675852bc dbuf: separate refcount calls for dbuf and dbuf_user
 #16198 a043b60f1 Correct level handling in zstream recompress
 #16204 34906f8bb zap: reuse zap_leaf_t on dbuf reuse after shrink
 #16206 d0aa9dbcc Use memset to zero stack allocations containing unions
 #16207 8865dfbca Fix assertion in Persistent L2ARC
 #16208 08648cf0d Allow block cloning to be interrupted by a signal
 #16210 e2357561b FreeBSD: Add const qualifier to members of struct
        opensolaris_utsname
 #16214 800d59d57 Some improvements to metaslabs eviction
 #16216 02c5aa9b0 Destroy ARC buffer in case of fill error
 #16225 01c8efdd5 Simplify issig()

Obtained from:	OpenZFS
OpenZFS commit:	e2357561b9
This commit is contained in:
Martin Matuska 2024-05-31 09:31:58 +02:00
commit aca928a50a
89 changed files with 1696 additions and 612 deletions

View File

@ -11,6 +11,7 @@ PACKAGE= zfs
SRCS = \
assert.c \
backtrace.c \
list.c \
mkdirp.c \
os/freebsd/zone.c \

View File

@ -85,6 +85,7 @@
#include <sys/brt_impl.h>
#include <zfs_comutil.h>
#include <sys/zstd/zstd.h>
#include <sys/backtrace.h>
#include <libnvpair.h>
#include <libzutil.h>
@ -120,6 +121,9 @@ static int flagbits[256];
static uint64_t max_inflight_bytes = 256 * 1024 * 1024; /* 256MB */
static int leaked_objects = 0;
static range_tree_t *mos_refd_objs;
static spa_t *spa;
static objset_t *os;
static boolean_t kernel_init_done;
static void snprintf_blkptr_compact(char *, size_t, const blkptr_t *,
boolean_t);
@ -131,6 +135,7 @@ static int dump_bpobj_cb(void *arg, const blkptr_t *bp, boolean_t free,
static void zdb_print_blkptr(const blkptr_t *bp, int flags);
static void zdb_exit(int reason);
typedef struct sublivelist_verify_block_refcnt {
/* block pointer entry in livelist being verified */
@ -818,17 +823,40 @@ usage(void)
(void) fprintf(stderr, "Specify an option more than once (e.g. -bb) "
"to make only that option verbose\n");
(void) fprintf(stderr, "Default is to dump everything non-verbosely\n");
exit(1);
zdb_exit(1);
}
static void
dump_debug_buffer(void)
{
if (dump_opt['G']) {
(void) printf("\n");
(void) fflush(stdout);
zfs_dbgmsg_print("zdb");
}
ssize_t ret __attribute__((unused));
if (!dump_opt['G'])
return;
/*
* We use write() instead of printf() so that this function
* is safe to call from a signal handler.
*/
ret = write(STDERR_FILENO, "\n", 1);
zfs_dbgmsg_print(STDERR_FILENO, "zdb");
}
static void sig_handler(int signo)
{
struct sigaction action;
libspl_backtrace(STDERR_FILENO);
dump_debug_buffer();
/*
* Restore default action and re-raise signal so SIGSEGV and
* SIGABRT can trigger a core dump.
*/
action.sa_handler = SIG_DFL;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
(void) sigaction(signo, &action, NULL);
raise(signo);
}
/*
@ -849,7 +877,7 @@ fatal(const char *fmt, ...)
dump_debug_buffer();
exit(1);
zdb_exit(1);
}
static void
@ -2276,7 +2304,7 @@ snprintf_zstd_header(spa_t *spa, char *blkbuf, size_t buflen,
buf = malloc(SPA_MAXBLOCKSIZE);
if (buf == NULL) {
(void) fprintf(stderr, "out of memory\n");
exit(1);
zdb_exit(1);
}
decode_embedded_bp_compressed(bp, buf);
memcpy(&zstd_hdr, buf, sizeof (zstd_hdr));
@ -3231,6 +3259,23 @@ fuid_table_destroy(void)
}
}
static void
zdb_exit(int reason)
{
if (os != NULL) {
close_objset(os, FTAG);
} else if (spa != NULL) {
spa_close(spa, FTAG);
}
fuid_table_destroy();
if (kernel_init_done)
kernel_fini();
exit(reason);
}
/*
* print uid or gid information.
* For normal POSIX id just the id is printed in decimal format.
@ -4161,32 +4206,32 @@ dump_cachefile(const char *cachefile)
if ((fd = open64(cachefile, O_RDONLY)) < 0) {
(void) printf("cannot open '%s': %s\n", cachefile,
strerror(errno));
exit(1);
zdb_exit(1);
}
if (fstat64(fd, &statbuf) != 0) {
(void) printf("failed to stat '%s': %s\n", cachefile,
strerror(errno));
exit(1);
zdb_exit(1);
}
if ((buf = malloc(statbuf.st_size)) == NULL) {
(void) fprintf(stderr, "failed to allocate %llu bytes\n",
(u_longlong_t)statbuf.st_size);
exit(1);
zdb_exit(1);
}
if (read(fd, buf, statbuf.st_size) != statbuf.st_size) {
(void) fprintf(stderr, "failed to read %llu bytes\n",
(u_longlong_t)statbuf.st_size);
exit(1);
zdb_exit(1);
}
(void) close(fd);
if (nvlist_unpack(buf, statbuf.st_size, &config, 0) != 0) {
(void) fprintf(stderr, "failed to unpack nvlist\n");
exit(1);
zdb_exit(1);
}
free(buf);
@ -5102,14 +5147,14 @@ dump_label(const char *dev)
if ((fd = open64(path, O_RDONLY)) < 0) {
(void) printf("cannot open '%s': %s\n", path, strerror(errno));
exit(1);
zdb_exit(1);
}
if (fstat64_blk(fd, &statbuf) != 0) {
(void) printf("failed to stat '%s': %s\n", path,
strerror(errno));
(void) close(fd);
exit(1);
zdb_exit(1);
}
if (S_ISBLK(statbuf.st_mode) && zfs_dev_flush(fd) != 0)
@ -5122,7 +5167,7 @@ dump_label(const char *dev)
sizeof (cksum_record_t), offsetof(cksum_record_t, link));
psize = statbuf.st_size;
psize = P2ALIGN(psize, (uint64_t)sizeof (vdev_label_t));
psize = P2ALIGN_TYPED(psize, sizeof (vdev_label_t), uint64_t);
ashift = SPA_MINBLOCKSHIFT;
/*
@ -8221,7 +8266,7 @@ dump_zpool(spa_t *spa)
if (rc != 0) {
dump_debug_buffer();
exit(rc);
zdb_exit(rc);
}
}
@ -8825,18 +8870,18 @@ zdb_embedded_block(char *thing)
words + 12, words + 13, words + 14, words + 15);
if (err != 16) {
(void) fprintf(stderr, "invalid input format\n");
exit(1);
zdb_exit(1);
}
ASSERT3U(BPE_GET_LSIZE(&bp), <=, SPA_MAXBLOCKSIZE);
buf = malloc(SPA_MAXBLOCKSIZE);
if (buf == NULL) {
(void) fprintf(stderr, "out of memory\n");
exit(1);
zdb_exit(1);
}
err = decode_embedded_bp(&bp, buf, BPE_GET_LSIZE(&bp));
if (err != 0) {
(void) fprintf(stderr, "decode failed: %u\n", err);
exit(1);
zdb_exit(1);
}
zdb_dump_block_raw(buf, BPE_GET_LSIZE(&bp), 0);
free(buf);
@ -8863,8 +8908,6 @@ int
main(int argc, char **argv)
{
int c;
spa_t *spa = NULL;
objset_t *os = NULL;
int dump_all = 1;
int verbose = 0;
int error = 0;
@ -8880,9 +8923,27 @@ main(int argc, char **argv)
char *spa_config_path_env, *objset_str;
boolean_t target_is_spa = B_TRUE, dataset_lookup = B_FALSE;
nvlist_t *cfg = NULL;
struct sigaction action;
dprintf_setup(&argc, argv);
/*
* Set up signal handlers, so if we crash due to bad on-disk data we
* can get more info. Unlike ztest, we don't bail out if we can't set
* up signal handlers, because zdb is very useful without them.
*/
action.sa_handler = sig_handler;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
if (sigaction(SIGSEGV, &action, NULL) < 0) {
(void) fprintf(stderr, "zdb: cannot catch SIGSEGV: %s\n",
strerror(errno));
}
if (sigaction(SIGABRT, &action, NULL) < 0) {
(void) fprintf(stderr, "zdb: cannot catch SIGABRT: %s\n",
strerror(errno));
}
/*
* If there is an environment variable SPA_CONFIG_PATH it overrides
* default spa_config_path setting. If -U flag is specified it will
@ -9093,6 +9154,7 @@ main(int argc, char **argv)
spa_mode_readable_spacemaps = B_TRUE;
kernel_init(SPA_MODE_READ);
kernel_init_done = B_TRUE;
if (dump_all)
verbose = MAX(verbose, 1);
@ -9116,19 +9178,23 @@ main(int argc, char **argv)
if (argc != 1)
usage();
zdb_embedded_block(argv[0]);
return (0);
error = 0;
goto fini;
}
if (argc < 1) {
if (!dump_opt['e'] && dump_opt['C']) {
dump_cachefile(spa_config_path);
return (0);
error = 0;
goto fini;
}
usage();
}
if (dump_opt['l'])
return (dump_label(argv[0]));
if (dump_opt['l']) {
error = dump_label(argv[0]);
goto fini;
}
if (dump_opt['X'] || dump_opt['F'])
rewind = ZPOOL_DO_REWIND |
@ -9183,7 +9249,8 @@ main(int argc, char **argv)
} else if (objset_str && !zdb_numeric(objset_str + 1) &&
dump_opt['N']) {
printf("Supply a numeric objset ID with -N\n");
exit(1);
error = 1;
goto fini;
}
} else {
target_pool = target;
@ -9240,7 +9307,8 @@ main(int argc, char **argv)
if (argc != 2)
usage();
dump_opt['v'] = verbose + 3;
return (dump_path(argv[0], argv[1], NULL));
error = dump_path(argv[0], argv[1], NULL);
goto fini;
}
if (dump_opt['r']) {
@ -9328,7 +9396,7 @@ main(int argc, char **argv)
fatal("can't dump '%s': %s", target,
strerror(error));
}
return (error);
goto fini;
} else {
target_pool = strdup(target);
if (strpbrk(target, "/@") != NULL)
@ -9458,9 +9526,10 @@ main(int argc, char **argv)
free(checkpoint_target);
}
fini:
if (os != NULL) {
close_objset(os, FTAG);
} else {
} else if (spa != NULL) {
spa_close(spa, FTAG);
}
@ -9468,7 +9537,8 @@ main(int argc, char **argv)
dump_debug_buffer();
kernel_fini();
if (kernel_init_done)
kernel_fini();
return (error);
}

View File

@ -702,7 +702,7 @@ zfs_enable_ds(void *arg)
{
unavailpool_t *pool = (unavailpool_t *)arg;
(void) zpool_enable_datasets(pool->uap_zhp, NULL, 0);
(void) zpool_enable_datasets(pool->uap_zhp, NULL, 0, 512);
zpool_close(pool->uap_zhp);
free(pool);
}

View File

@ -9,6 +9,7 @@ dist_zedexec_SCRIPTS = \
%D%/all-debug.sh \
%D%/all-syslog.sh \
%D%/data-notify.sh \
%D%/deadman-slot_off.sh \
%D%/generic-notify.sh \
%D%/pool_import-led.sh \
%D%/resilver_finish-notify.sh \
@ -29,6 +30,7 @@ SUBSTFILES += $(nodist_zedexec_SCRIPTS)
zedconfdefaults = \
all-syslog.sh \
data-notify.sh \
deadman-slot_off.sh \
history_event-zfs-list-cacher.sh \
pool_import-led.sh \
resilver_finish-notify.sh \

View File

@ -0,0 +1,71 @@
#!/bin/sh
# shellcheck disable=SC3014,SC2154,SC2086,SC2034
#
# Turn off disk's enclosure slot if an I/O is hung triggering the deadman.
#
# It's possible for outstanding I/O to a misbehaving SCSI disk to neither
# promptly complete or return an error. This can occur due to retry and
# recovery actions taken by the SCSI layer, driver, or disk. When it occurs
# the pool will be unresponsive even though there may be sufficient redundancy
# configured to proceeded without this single disk.
#
# When a hung I/O is detected by the kmods it will be posted as a deadman
# event. By default an I/O is considered to be hung after 5 minutes. This
# value can be changed with the zfs_deadman_ziotime_ms module parameter.
# If ZED_POWER_OFF_ENCLOSURE_SLOT_ON_DEADMAN is set the disk's enclosure
# slot will be powered off causing the outstanding I/O to fail. The ZED
# will then handle this like a normal disk failure and FAULT the vdev.
#
# We assume the user will be responsible for turning the slot back on
# after replacing the disk.
#
# Note that this script requires that your enclosure be supported by the
# Linux SCSI Enclosure services (SES) driver. The script will do nothing
# if you have no enclosure, or if your enclosure isn't supported.
#
# Exit codes:
# 0: slot successfully powered off
# 1: enclosure not available
# 2: ZED_POWER_OFF_ENCLOSURE_SLOT_ON_DEADMAN disabled
# 3: System not configured to wait on deadman
# 4: The enclosure sysfs path passed from ZFS does not exist
# 5: Enclosure slot didn't actually turn off after we told it to
[ -f "${ZED_ZEDLET_DIR}/zed.rc" ] && . "${ZED_ZEDLET_DIR}/zed.rc"
. "${ZED_ZEDLET_DIR}/zed-functions.sh"
if [ ! -d /sys/class/enclosure ] ; then
# No JBOD enclosure or NVMe slots
exit 1
fi
if [ "${ZED_POWER_OFF_ENCLOSURE_SLOT_ON_DEADMAN}" != "1" ] ; then
exit 2
fi
if [ "$ZEVENT_POOL_FAILMODE" != "wait" ] ; then
exit 3
fi
if [ ! -f "$ZEVENT_VDEV_ENC_SYSFS_PATH/power_status" ] ; then
exit 4
fi
# Turn off the slot and wait for sysfs to report that the slot is off.
# It can take ~400ms on some enclosures and multiple retries may be needed.
for i in $(seq 1 20) ; do
echo "off" | tee "$ZEVENT_VDEV_ENC_SYSFS_PATH/power_status"
for j in $(seq 1 5) ; do
if [ "$(cat $ZEVENT_VDEV_ENC_SYSFS_PATH/power_status)" == "off" ] ; then
break 2
fi
sleep 0.1
done
done
if [ "$(cat $ZEVENT_VDEV_ENC_SYSFS_PATH/power_status)" != "off" ] ; then
exit 5
fi
zed_log_msg "powered down slot $ZEVENT_VDEV_ENC_SYSFS_PATH for $ZEVENT_VDEV_PATH"

View File

@ -148,6 +148,13 @@ ZED_SYSLOG_SUBCLASS_EXCLUDE="history_event"
# supports slot power control via sysfs.
#ZED_POWER_OFF_ENCLOSURE_SLOT_ON_FAULT=1
##
# Power off the drive's slot in the enclosure if there is a hung I/O which
# exceeds the deadman timeout. This can help prevent a single misbehaving
# drive from rendering a redundant pool unavailable. This assumes your drive
# enclosure fully supports slot power control via sysfs.
#ZED_POWER_OFF_ENCLOSURE_SLOT_ON_DEADMAN=1
##
# Ntfy topic
# This defines which topic will receive the ntfy notification.

View File

@ -7192,6 +7192,8 @@ share_mount(int op, int argc, char **argv)
int c, ret = 0;
char *options = NULL;
int flags = 0;
const uint_t mount_nthr = 512;
uint_t nthr;
/* check options */
while ((c = getopt(argc, argv, op == OP_MOUNT ? ":aRlvo:Of" : "al"))
@ -7310,9 +7312,9 @@ share_mount(int op, int argc, char **argv)
* be serialized so that we can prompt the user for their keys
* in a consistent manner.
*/
nthr = op == OP_MOUNT && !(flags & MS_CRYPT) ? mount_nthr : 1;
zfs_foreach_mountpoint(g_zfs, cb.cb_handles, cb.cb_used,
share_mount_one_cb, &share_mount_state,
op == OP_MOUNT && !(flags & MS_CRYPT));
share_mount_one_cb, &share_mount_state, nthr);
zfs_commit_shares(NULL);
ret = share_mount_state.sm_status;

View File

@ -80,6 +80,8 @@
libzfs_handle_t *g_zfs;
static int mount_tp_nthr = 512; /* tpool threads for multi-threaded mounting */
static int zpool_do_create(int, char **);
static int zpool_do_destroy(int, char **);
@ -2030,10 +2032,19 @@ zpool_do_destroy(int argc, char **argv)
}
typedef struct export_cbdata {
tpool_t *tpool;
pthread_mutex_t mnttab_lock;
boolean_t force;
boolean_t hardforce;
int retval;
} export_cbdata_t;
typedef struct {
char *aea_poolname;
export_cbdata_t *aea_cbdata;
} async_export_args_t;
/*
* Export one pool
*/
@ -2042,11 +2053,20 @@ zpool_export_one(zpool_handle_t *zhp, void *data)
{
export_cbdata_t *cb = data;
if (zpool_disable_datasets(zhp, cb->force) != 0)
return (1);
/*
* zpool_disable_datasets() is not thread-safe for mnttab access.
* So we serialize access here for 'zpool export -a' parallel case.
*/
if (cb->tpool != NULL)
pthread_mutex_lock(&cb->mnttab_lock);
/* The history must be logged as part of the export */
log_history = B_FALSE;
int retval = zpool_disable_datasets(zhp, cb->force);
if (cb->tpool != NULL)
pthread_mutex_unlock(&cb->mnttab_lock);
if (retval)
return (1);
if (cb->hardforce) {
if (zpool_export_force(zhp, history_str) != 0)
@ -2058,6 +2078,48 @@ zpool_export_one(zpool_handle_t *zhp, void *data)
return (0);
}
/*
* Asynchronous export request
*/
static void
zpool_export_task(void *arg)
{
async_export_args_t *aea = arg;
zpool_handle_t *zhp = zpool_open(g_zfs, aea->aea_poolname);
if (zhp != NULL) {
int ret = zpool_export_one(zhp, aea->aea_cbdata);
if (ret != 0)
aea->aea_cbdata->retval = ret;
zpool_close(zhp);
} else {
aea->aea_cbdata->retval = 1;
}
free(aea->aea_poolname);
free(aea);
}
/*
* Process an export request in parallel
*/
static int
zpool_export_one_async(zpool_handle_t *zhp, void *data)
{
tpool_t *tpool = ((export_cbdata_t *)data)->tpool;
async_export_args_t *aea = safe_malloc(sizeof (async_export_args_t));
/* save pool name since zhp will go out of scope */
aea->aea_poolname = strdup(zpool_get_name(zhp));
aea->aea_cbdata = data;
/* ship off actual export to another thread */
if (tpool_dispatch(tpool, zpool_export_task, (void *)aea) != 0)
return (errno); /* unlikely */
else
return (0);
}
/*
* zpool export [-f] <pool> ...
*
@ -2098,17 +2160,33 @@ zpool_do_export(int argc, char **argv)
cb.force = force;
cb.hardforce = hardforce;
cb.tpool = NULL;
cb.retval = 0;
argc -= optind;
argv += optind;
/* The history will be logged as part of the export itself */
log_history = B_FALSE;
if (do_all) {
if (argc != 0) {
(void) fprintf(stderr, gettext("too many arguments\n"));
usage(B_FALSE);
}
return (for_each_pool(argc, argv, B_TRUE, NULL,
ZFS_TYPE_POOL, B_FALSE, zpool_export_one, &cb));
cb.tpool = tpool_create(1, 5 * sysconf(_SC_NPROCESSORS_ONLN),
0, NULL);
pthread_mutex_init(&cb.mnttab_lock, NULL);
/* Asynchronously call zpool_export_one using thread pool */
ret = for_each_pool(argc, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
B_FALSE, zpool_export_one_async, &cb);
tpool_wait(cb.tpool);
tpool_destroy(cb.tpool);
(void) pthread_mutex_destroy(&cb.mnttab_lock);
return (ret | cb.retval);
}
/* check arguments */
@ -2938,6 +3016,7 @@ show_import(nvlist_t *config, boolean_t report_error)
const char *health;
uint_t vsc;
const char *comment;
const char *indent;
status_cbdata_t cb = { 0 };
verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
@ -2962,82 +3041,84 @@ show_import(nvlist_t *config, boolean_t report_error)
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);
if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0) {
indent = " ";
} else {
comment = NULL;
indent = "";
}
(void) printf(gettext("%s pool: %s\n"), indent, name);
(void) printf(gettext("%s id: %llu\n"), indent, (u_longlong_t)guid);
(void) printf(gettext("%s state: %s"), indent, health);
if (pool_state == POOL_STATE_DESTROYED)
(void) printf(gettext(" (DESTROYED)"));
(void) printf("\n");
if (reason != ZPOOL_STATUS_OK) {
(void) printf("%s", indent);
printf_color(ANSI_BOLD, gettext("status: "));
}
switch (reason) {
case ZPOOL_STATUS_MISSING_DEV_R:
case ZPOOL_STATUS_MISSING_DEV_NR:
case ZPOOL_STATUS_BAD_GUID_SUM:
printf_color(ANSI_BOLD, gettext("status: "));
printf_color(ANSI_YELLOW, gettext("One or more devices are "
"missing from the system.\n"));
break;
case ZPOOL_STATUS_CORRUPT_LABEL_R:
case ZPOOL_STATUS_CORRUPT_LABEL_NR:
printf_color(ANSI_BOLD, gettext("status: "));
printf_color(ANSI_YELLOW, gettext("One or more devices contains"
" corrupted data.\n"));
printf_color(ANSI_YELLOW, gettext("One or more devices "
"contains corrupted data.\n"));
break;
case ZPOOL_STATUS_CORRUPT_DATA:
(void) printf(
gettext(" status: The pool data is corrupted.\n"));
printf_color(ANSI_YELLOW, gettext("The pool data is "
"corrupted.\n"));
break;
case ZPOOL_STATUS_OFFLINE_DEV:
printf_color(ANSI_BOLD, gettext("status: "));
printf_color(ANSI_YELLOW, gettext("One or more devices "
"are offlined.\n"));
break;
case ZPOOL_STATUS_CORRUPT_POOL:
printf_color(ANSI_BOLD, gettext("status: "));
printf_color(ANSI_YELLOW, gettext("The pool metadata is "
"corrupted.\n"));
break;
case ZPOOL_STATUS_VERSION_OLDER:
printf_color(ANSI_BOLD, gettext("status: "));
printf_color(ANSI_YELLOW, gettext("The pool is formatted using "
"a legacy on-disk version.\n"));
break;
case ZPOOL_STATUS_VERSION_NEWER:
printf_color(ANSI_BOLD, gettext("status: "));
printf_color(ANSI_YELLOW, gettext("The pool is formatted using "
"an incompatible version.\n"));
break;
case ZPOOL_STATUS_FEAT_DISABLED:
printf_color(ANSI_BOLD, gettext("status: "));
printf_color(ANSI_YELLOW, gettext("Some supported "
"features are not enabled on the pool.\n\t"
"(Note that they may be intentionally disabled "
"if the\n\t'compatibility' property is set.)\n"));
"features are not enabled on the pool.\n"
"\t%s(Note that they may be intentionally disabled if the\n"
"\t%s'compatibility' property is set.)\n"), indent, indent);
break;
case ZPOOL_STATUS_COMPATIBILITY_ERR:
printf_color(ANSI_BOLD, gettext("status: "));
printf_color(ANSI_YELLOW, gettext("Error reading or parsing "
"the file(s) indicated by the 'compatibility'\n"
"property.\n"));
"\t%sproperty.\n"), indent);
break;
case ZPOOL_STATUS_INCOMPATIBLE_FEAT:
printf_color(ANSI_BOLD, gettext("status: "));
printf_color(ANSI_YELLOW, gettext("One or more features "
"are enabled on the pool despite not being\n"
"requested by the 'compatibility' property.\n"));
"\t%srequested by the 'compatibility' property.\n"),
indent);
break;
case ZPOOL_STATUS_UNSUP_FEAT_READ:
printf_color(ANSI_BOLD, gettext("status: "));
printf_color(ANSI_YELLOW, gettext("The pool uses the following "
"feature(s) not supported on this system:\n"));
color_start(ANSI_YELLOW);
@ -3046,66 +3127,60 @@ show_import(nvlist_t *config, boolean_t report_error)
break;
case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
printf_color(ANSI_BOLD, gettext("status: "));
printf_color(ANSI_YELLOW, gettext("The pool can only be "
"accessed in read-only mode on this system. It\n\tcannot be"
" accessed in read-write mode because it uses the "
"following\n\tfeature(s) not supported on this system:\n"));
"accessed in read-only mode on this system. It\n"
"\t%scannot be accessed in read-write mode because it uses "
"the following\n"
"\t%sfeature(s) not supported on this system:\n"),
indent, indent);
color_start(ANSI_YELLOW);
zpool_print_unsup_feat(config);
color_end();
break;
case ZPOOL_STATUS_HOSTID_ACTIVE:
printf_color(ANSI_BOLD, gettext("status: "));
printf_color(ANSI_YELLOW, gettext("The pool is currently "
"imported by another system.\n"));
break;
case ZPOOL_STATUS_HOSTID_REQUIRED:
printf_color(ANSI_BOLD, gettext("status: "));
printf_color(ANSI_YELLOW, gettext("The pool has the "
"multihost property on. It cannot\n\tbe safely imported "
"when the system hostid is not set.\n"));
"multihost property on. It cannot\n"
"\t%sbe safely imported when the system hostid is not "
"set.\n"), indent);
break;
case ZPOOL_STATUS_HOSTID_MISMATCH:
printf_color(ANSI_BOLD, gettext("status: "));
printf_color(ANSI_YELLOW, gettext("The pool was last accessed "
"by another system.\n"));
break;
case ZPOOL_STATUS_FAULTED_DEV_R:
case ZPOOL_STATUS_FAULTED_DEV_NR:
printf_color(ANSI_BOLD, gettext("status: "));
printf_color(ANSI_YELLOW, gettext("One or more devices are "
"faulted.\n"));
break;
case ZPOOL_STATUS_BAD_LOG:
printf_color(ANSI_BOLD, gettext("status: "));
printf_color(ANSI_YELLOW, gettext("An intent log record cannot "
"be read.\n"));
break;
case ZPOOL_STATUS_RESILVERING:
case ZPOOL_STATUS_REBUILDING:
printf_color(ANSI_BOLD, gettext("status: "));
printf_color(ANSI_YELLOW, gettext("One or more devices were "
"being resilvered.\n"));
break;
case ZPOOL_STATUS_ERRATA:
printf_color(ANSI_BOLD, gettext("status: "));
printf_color(ANSI_YELLOW, gettext("Errata #%d detected.\n"),
errata);
break;
case ZPOOL_STATUS_NON_NATIVE_ASHIFT:
printf_color(ANSI_BOLD, gettext("status: "));
printf_color(ANSI_YELLOW, gettext("One or more devices are "
"configured to use a non-native block size.\n"
"\tExpect reduced performance.\n"));
"\t%sExpect reduced performance.\n"), indent);
break;
default:
@ -3118,114 +3193,121 @@ show_import(nvlist_t *config, boolean_t report_error)
/*
* Print out an action according to the overall state of the pool.
*/
if (vs->vs_state != VDEV_STATE_HEALTHY ||
reason != ZPOOL_STATUS_ERRATA || errata != ZPOOL_ERRATA_NONE) {
(void) printf("%s", indent);
(void) printf(gettext("action: "));
}
if (vs->vs_state == VDEV_STATE_HEALTHY) {
if (reason == ZPOOL_STATUS_VERSION_OLDER ||
reason == ZPOOL_STATUS_FEAT_DISABLED) {
(void) printf(gettext(" action: The pool can be "
"imported using its name or numeric identifier, "
"though\n\tsome features will not be available "
"without an explicit 'zpool upgrade'.\n"));
(void) printf(gettext("The pool can be imported using "
"its name or numeric identifier, though\n"
"\t%ssome features will not be available without "
"an explicit 'zpool upgrade'.\n"), indent);
} else if (reason == ZPOOL_STATUS_COMPATIBILITY_ERR) {
(void) printf(gettext(" action: The pool can be "
"imported using its name or numeric\n\tidentifier, "
"though the file(s) indicated by its "
"'compatibility'\n\tproperty cannot be parsed at "
"this time.\n"));
(void) printf(gettext("The pool can be imported using "
"its name or numeric\n"
"\t%sidentifier, though the file(s) indicated by "
"its 'compatibility'\n"
"\t%sproperty cannot be parsed at this time.\n"),
indent, indent);
} else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) {
(void) printf(gettext(" action: The pool can be "
"imported using its name or numeric "
"identifier and\n\tthe '-f' flag.\n"));
(void) printf(gettext("The pool can be imported using "
"its name or numeric identifier and\n"
"\t%sthe '-f' flag.\n"), indent);
} else if (reason == ZPOOL_STATUS_ERRATA) {
switch (errata) {
case ZPOOL_ERRATA_NONE:
break;
case ZPOOL_ERRATA_ZOL_2094_SCRUB:
(void) printf(gettext(" action: The pool can "
"be imported using its name or numeric "
"identifier,\n\thowever there is a compat"
"ibility issue which should be corrected"
"\n\tby running 'zpool scrub'\n"));
(void) printf(gettext("The pool can be "
"imported using its name or numeric "
"identifier,\n"
"\t%showever there is a compatibility "
"issue which should be corrected\n"
"\t%sby running 'zpool scrub'\n"),
indent, indent);
break;
case ZPOOL_ERRATA_ZOL_2094_ASYNC_DESTROY:
(void) printf(gettext(" action: The pool can"
"not be imported with this version of ZFS "
"due to\n\tan active asynchronous destroy. "
"Revert to an earlier version\n\tand "
"allow the destroy to complete before "
"updating.\n"));
(void) printf(gettext("The pool cannot be "
"imported with this version of ZFS due to\n"
"\t%san active asynchronous destroy. "
"Revert to an earlier version\n"
"\t%sand allow the destroy to complete "
"before updating.\n"), indent, indent);
break;
case ZPOOL_ERRATA_ZOL_6845_ENCRYPTION:
(void) printf(gettext(" action: Existing "
"encrypted datasets contain an on-disk "
"incompatibility, which\n\tneeds to be "
"corrected. Backup these datasets to new "
"encrypted datasets\n\tand destroy the "
"old ones.\n"));
(void) printf(gettext("Existing encrypted "
"datasets contain an on-disk "
"incompatibility, which\n"
"\t%sneeds to be corrected. Backup these "
"datasets to new encrypted datasets\n"
"\t%sand destroy the old ones.\n"),
indent, indent);
break;
case ZPOOL_ERRATA_ZOL_8308_ENCRYPTION:
(void) printf(gettext(" action: Existing "
"encrypted snapshots and bookmarks contain "
"an on-disk\n\tincompatibility. This may "
"cause on-disk corruption if they are used"
"\n\twith 'zfs recv'. To correct the "
"issue, enable the bookmark_v2 feature.\n\t"
"No additional action is needed if there "
"are no encrypted snapshots or\n\t"
"bookmarks. If preserving the encrypted "
"snapshots and bookmarks is\n\trequired, "
"use a non-raw send to backup and restore "
"them. Alternately,\n\tthey may be removed"
" to resolve the incompatibility.\n"));
(void) printf(gettext("Existing encrypted "
"snapshots and bookmarks contain an "
"on-disk\n"
"\t%sincompatibility. This may cause "
"on-disk corruption if they are used\n"
"\t%swith 'zfs recv'. To correct the "
"issue, enable the bookmark_v2 feature.\n"
"\t%sNo additional action is needed if "
"there are no encrypted snapshots or\n"
"\t%sbookmarks. If preserving the "
"encrypted snapshots and bookmarks is\n"
"\t%srequired, use a non-raw send to "
"backup and restore them. Alternately,\n"
"\t%sthey may be removed to resolve the "
"incompatibility.\n"), indent, indent,
indent, indent, indent, indent);
break;
default:
/*
* All errata must contain an action message.
*/
assert(0);
assert(errata == ZPOOL_ERRATA_NONE);
}
} else {
(void) printf(gettext(" action: The pool can be "
"imported using its name or numeric "
"identifier.\n"));
(void) printf(gettext("The pool can be imported using "
"its name or numeric identifier.\n"));
}
} else if (vs->vs_state == VDEV_STATE_DEGRADED) {
(void) printf(gettext(" action: The pool can be imported "
"despite missing or damaged devices. The\n\tfault "
"tolerance of the pool may be compromised if imported.\n"));
(void) printf(gettext("The pool can be imported despite "
"missing or damaged devices. The\n"
"\t%sfault tolerance of the pool may be compromised if "
"imported.\n"), indent);
} else {
switch (reason) {
case ZPOOL_STATUS_VERSION_NEWER:
(void) printf(gettext(" action: The pool cannot be "
"imported. Access the pool on a system running "
"newer\n\tsoftware, or recreate the pool from "
"backup.\n"));
(void) printf(gettext("The pool cannot be imported. "
"Access the pool on a system running newer\n"
"\t%ssoftware, or recreate the pool from "
"backup.\n"), indent);
break;
case ZPOOL_STATUS_UNSUP_FEAT_READ:
printf_color(ANSI_BOLD, gettext("action: "));
printf_color(ANSI_YELLOW, gettext("The pool cannot be "
"imported. Access the pool on a system that "
"supports\n\tthe required feature(s), or recreate "
"the pool from backup.\n"));
(void) printf(gettext("The pool cannot be imported. "
"Access the pool on a system that supports\n"
"\t%sthe required feature(s), or recreate the pool "
"from backup.\n"), indent);
break;
case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
printf_color(ANSI_BOLD, gettext("action: "));
printf_color(ANSI_YELLOW, gettext("The pool cannot be "
"imported in read-write mode. Import the pool "
"with\n"
"\t\"-o readonly=on\", access the pool on a system "
"that supports the\n\trequired feature(s), or "
"recreate the pool from backup.\n"));
(void) printf(gettext("The pool cannot be imported in "
"read-write mode. Import the pool with\n"
"\t%s'-o readonly=on', access the pool on a system "
"that supports the\n"
"\t%srequired feature(s), or recreate the pool "
"from backup.\n"), indent, indent);
break;
case ZPOOL_STATUS_MISSING_DEV_R:
case ZPOOL_STATUS_MISSING_DEV_NR:
case ZPOOL_STATUS_BAD_GUID_SUM:
(void) printf(gettext(" action: The pool cannot be "
"imported. Attach the missing\n\tdevices and try "
"again.\n"));
(void) printf(gettext("The pool cannot be imported. "
"Attach the missing\n"
"\t%sdevices and try again.\n"), indent);
break;
case ZPOOL_STATUS_HOSTID_ACTIVE:
VERIFY0(nvlist_lookup_nvlist(config,
@ -3239,47 +3321,49 @@ show_import(nvlist_t *config, boolean_t report_error)
hostid = fnvlist_lookup_uint64(nvinfo,
ZPOOL_CONFIG_MMP_HOSTID);
(void) printf(gettext(" action: The pool must be "
"exported from %s (hostid=%"PRIx64")\n\tbefore it "
"can be safely imported.\n"), hostname, hostid);
(void) printf(gettext("The pool must be exported from "
"%s (hostid=%"PRIx64")\n"
"\t%sbefore it can be safely imported.\n"),
hostname, hostid, indent);
break;
case ZPOOL_STATUS_HOSTID_REQUIRED:
(void) printf(gettext(" action: Set a unique system "
"hostid with the zgenhostid(8) command.\n"));
(void) printf(gettext("Set a unique system hostid with "
"the zgenhostid(8) command.\n"));
break;
default:
(void) printf(gettext(" action: The pool cannot be "
"imported due to damaged devices or data.\n"));
(void) printf(gettext("The pool cannot be imported due "
"to damaged devices or data.\n"));
}
}
/* Print the comment attached to the pool. */
if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
if (comment != NULL)
(void) printf(gettext("comment: %s\n"), comment);
/*
* If the state is "closed" or "can't open", and the aux state
* is "corrupt data":
*/
if (((vs->vs_state == VDEV_STATE_CLOSED) ||
(vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
(vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
if ((vs->vs_state == VDEV_STATE_CLOSED ||
vs->vs_state == VDEV_STATE_CANT_OPEN) &&
vs->vs_aux == VDEV_AUX_CORRUPT_DATA) {
if (pool_state == POOL_STATE_DESTROYED)
(void) printf(gettext("\tThe pool was destroyed, "
"but can be imported using the '-Df' flags.\n"));
(void) printf(gettext("\t%sThe pool was destroyed, "
"but can be imported using the '-Df' flags.\n"),
indent);
else if (pool_state != POOL_STATE_EXPORTED)
(void) printf(gettext("\tThe pool may be active on "
"another system, but can be imported using\n\t"
"the '-f' flag.\n"));
(void) printf(gettext("\t%sThe pool may be active on "
"another system, but can be imported using\n"
"\t%sthe '-f' flag.\n"), indent, indent);
}
if (msgid != NULL) {
(void) printf(gettext(
" see: https://openzfs.github.io/openzfs-docs/msg/%s\n"),
msgid);
(void) printf(gettext("%s see: "
"https://openzfs.github.io/openzfs-docs/msg/%s\n"),
indent, msgid);
}
(void) printf(gettext(" config:\n\n"));
(void) printf(gettext("%sconfig:\n\n"), indent);
cb.cb_namewidth = max_width(NULL, nvroot, 0, strlen(name),
VDEV_NAME_TYPE_ID);
@ -3293,9 +3377,10 @@ show_import(nvlist_t *config, boolean_t report_error)
print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_CLASS_LOGS);
if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
(void) printf(gettext("\n\tAdditional devices are known to "
"be part of this pool, though their\n\texact "
"configuration cannot be determined.\n"));
(void) printf(gettext("\n\t%sAdditional devices are known to "
"be part of this pool, though their\n"
"\t%sexact configuration cannot be determined.\n"),
indent, indent);
}
return (0);
}
@ -3342,7 +3427,7 @@ zfs_force_import_required(nvlist_t *config)
*/
static int
do_import(nvlist_t *config, const char *newname, const char *mntopts,
nvlist_t *props, int flags)
nvlist_t *props, int flags, uint_t mntthreads)
{
int ret = 0;
int ms_status = 0;
@ -3442,7 +3527,7 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts,
if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
!(flags & ZFS_IMPORT_ONLY)) {
ms_status = zpool_enable_datasets(zhp, mntopts, 0);
ms_status = zpool_enable_datasets(zhp, mntopts, 0, mntthreads);
if (ms_status == EZFS_SHAREFAILED) {
(void) fprintf(stderr, gettext("Import was "
"successful, but unable to share some datasets\n"));
@ -3461,6 +3546,7 @@ typedef struct import_parameters {
const char *ip_mntopts;
nvlist_t *ip_props;
int ip_flags;
uint_t ip_mntthreads;
int *ip_err;
} import_parameters_t;
@ -3469,7 +3555,7 @@ do_import_task(void *arg)
{
import_parameters_t *ip = arg;
*ip->ip_err |= do_import(ip->ip_config, NULL, ip->ip_mntopts,
ip->ip_props, ip->ip_flags);
ip->ip_props, ip->ip_flags, ip->ip_mntthreads);
free(ip);
}
@ -3483,6 +3569,7 @@ import_pools(nvlist_t *pools, nvlist_t *props, char *mntopts, int flags,
uint64_t pool_state;
boolean_t pool_specified = (import->poolname != NULL ||
import->guid != 0);
uint_t npools = 0;
tpool_t *tp = NULL;
@ -3500,6 +3587,10 @@ import_pools(nvlist_t *pools, nvlist_t *props, char *mntopts, int flags,
int err = 0;
nvpair_t *elem = NULL;
boolean_t first = B_TRUE;
if (!pool_specified && import->do_all) {
while ((elem = nvlist_next_nvpair(pools, elem)) != NULL)
npools++;
}
while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
verify(nvpair_value_nvlist(elem, &config) == 0);
@ -3530,6 +3621,7 @@ import_pools(nvlist_t *pools, nvlist_t *props, char *mntopts, int flags,
ip->ip_mntopts = mntopts;
ip->ip_props = props;
ip->ip_flags = flags;
ip->ip_mntthreads = mount_tp_nthr / npools;
ip->ip_err = &err;
(void) tpool_dispatch(tp, do_import_task,
@ -3597,7 +3689,7 @@ import_pools(nvlist_t *pools, nvlist_t *props, char *mntopts, int flags,
err = B_TRUE;
} else {
err |= do_import(found_config, new_name,
mntopts, props, flags);
mntopts, props, flags, mount_tp_nthr);
}
}
@ -7141,7 +7233,8 @@ zpool_do_split(int argc, char **argv)
}
if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL) {
ms_status = zpool_enable_datasets(zhp, mntopts, 0);
ms_status = zpool_enable_datasets(zhp, mntopts, 0,
mount_tp_nthr);
if (ms_status == EZFS_SHAREFAILED) {
(void) fprintf(stderr, gettext("Split was successful, "
"datasets are mounted but sharing of some datasets "

View File

@ -77,7 +77,7 @@ zstream_do_recompress(int argc, char *argv[])
while ((c = getopt(argc, argv, "l:")) != -1) {
switch (c) {
case 'l':
if (sscanf(optarg, "%d", &level) != 0) {
if (sscanf(optarg, "%d", &level) != 1) {
fprintf(stderr,
"failed to parse level '%s'\n",
optarg);

View File

@ -186,7 +186,7 @@ static void
zfs_redup_stream(int infd, int outfd, boolean_t verbose)
{
int bufsz = SPA_MAXBLOCKSIZE;
dmu_replay_record_t thedrr = { 0 };
dmu_replay_record_t thedrr;
dmu_replay_record_t *drr = &thedrr;
redup_table_t rdt;
zio_cksum_t stream_cksum;
@ -194,6 +194,8 @@ zfs_redup_stream(int infd, int outfd, boolean_t verbose)
uint64_t num_records = 0;
uint64_t num_write_byref_records = 0;
memset(&thedrr, 0, sizeof (dmu_replay_record_t));
#ifdef _ILP32
uint64_t max_rde_size = SMALLEST_POSSIBLE_MAX_RDT_MB << 20;
#else

View File

@ -136,9 +136,7 @@
#include <libzutil.h>
#include <sys/crypto/icp.h>
#include <sys/zfs_impl.h>
#if (__GLIBC__ && !__UCLIBC__)
#include <execinfo.h> /* for backtrace() */
#endif
#include <sys/backtrace.h>
static int ztest_fd_data = -1;
static int ztest_fd_rand = -1;
@ -617,22 +615,15 @@ dump_debug_buffer(void)
* We use write() instead of printf() so that this function
* is safe to call from a signal handler.
*/
ret = write(STDOUT_FILENO, "\n", 1);
zfs_dbgmsg_print("ztest");
ret = write(STDERR_FILENO, "\n", 1);
zfs_dbgmsg_print(STDERR_FILENO, "ztest");
}
#define BACKTRACE_SZ 100
static void sig_handler(int signo)
{
struct sigaction action;
#if (__GLIBC__ && !__UCLIBC__) /* backtrace() is a GNU extension */
int nptrs;
void *buffer[BACKTRACE_SZ];
nptrs = backtrace(buffer, BACKTRACE_SZ);
backtrace_symbols_fd(buffer, nptrs, STDERR_FILENO);
#endif
libspl_backtrace(STDERR_FILENO);
dump_debug_buffer();
/*
@ -2529,7 +2520,7 @@ ztest_get_data(void *arg, uint64_t arg2, lr_write_t *lr, char *buf,
ASSERT3P(zio, !=, NULL);
size = doi.doi_data_block_size;
if (ISP2(size)) {
offset = P2ALIGN(offset, size);
offset = P2ALIGN_TYPED(offset, size, uint64_t);
} else {
ASSERT3U(offset, <, size);
offset = 0;
@ -3978,7 +3969,8 @@ raidz_scratch_verify(void)
raidvd = vdev_lookup_top(spa, vre->vre_vdev_id);
offset = RRSS_GET_OFFSET(&spa->spa_uberblock);
state = RRSS_GET_STATE(&spa->spa_uberblock);
write_size = P2ALIGN(VDEV_BOOT_SIZE, 1 << raidvd->vdev_ashift);
write_size = P2ALIGN_TYPED(VDEV_BOOT_SIZE, 1 << raidvd->vdev_ashift,
uint64_t);
logical_size = write_size * raidvd->vdev_children;
switch (state) {
@ -5016,7 +5008,8 @@ ztest_dmu_object_next_chunk(ztest_ds_t *zd, uint64_t id)
*/
mutex_enter(&os->os_obj_lock);
object = ztest_random(os->os_obj_next_chunk);
os->os_obj_next_chunk = P2ALIGN(object, dnodes_per_chunk);
os->os_obj_next_chunk = P2ALIGN_TYPED(object, dnodes_per_chunk,
uint64_t);
mutex_exit(&os->os_obj_lock);
}
@ -6638,7 +6631,8 @@ ztest_fault_inject(ztest_ds_t *zd, uint64_t id)
* the end of the disk (vdev_psize) is aligned to
* sizeof (vdev_label_t).
*/
uint64_t psize = P2ALIGN(fsize, sizeof (vdev_label_t));
uint64_t psize = P2ALIGN_TYPED(fsize, sizeof (vdev_label_t),
uint64_t);
if ((leaf & 1) == 1 &&
offset + sizeof (bad) > psize - VDEV_LABEL_END_SIZE)
continue;
@ -6962,8 +6956,8 @@ ztest_fletcher_incr(ztest_ds_t *zd, uint64_t id)
size_t inc = 64 * ztest_random(size / 67);
/* sometimes add few bytes to test non-simd */
if (ztest_random(100) < 10)
inc += P2ALIGN(ztest_random(64),
sizeof (uint32_t));
inc += P2ALIGN_TYPED(ztest_random(64),
sizeof (uint32_t), uint64_t);
if (inc > (size - pos))
inc = size - pos;

View File

@ -0,0 +1,40 @@
dnl #
dnl # check if kernel provides definitions for given types
dnl #
dnl _ZFS_AC_KERNEL_SRC_TYPE(type)
AC_DEFUN([_ZFS_AC_KERNEL_SRC_TYPE], [
ZFS_LINUX_TEST_SRC([type_$1], [
#include <linux/types.h>
],[
const $1 __attribute__((unused)) x = ($1) 0;
])
])
dnl _ZFS_AC_KERNEL_TYPE(type)
AC_DEFUN([_ZFS_AC_KERNEL_TYPE], [
AC_MSG_CHECKING([whether kernel defines $1])
ZFS_LINUX_TEST_RESULT([type_$1], [
AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_KERNEL_]m4_quote(m4_translit([$1], [a-z], [A-Z])),
1, [kernel defines $1])
], [
AC_MSG_RESULT([no])
])
])
dnl ZFS_AC_KERNEL_TYPES([types...])
AC_DEFUN([ZFS_AC_KERNEL_TYPES], [
AC_DEFUN([ZFS_AC_KERNEL_SRC_TYPES], [
m4_foreach_w([type], [$1], [
_ZFS_AC_KERNEL_SRC_TYPE(type)
])
])
AC_DEFUN([ZFS_AC_KERNEL_TYPES], [
m4_foreach_w([type], [$1], [
_ZFS_AC_KERNEL_TYPE(type)
])
])
])
ZFS_AC_KERNEL_TYPES([intptr_t])

View File

@ -37,6 +37,7 @@ dnl # only once the compilation can be done in parallel significantly
dnl # speeding up the process.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
ZFS_AC_KERNEL_SRC_TYPES
ZFS_AC_KERNEL_SRC_OBJTOOL
ZFS_AC_KERNEL_SRC_GLOBAL_PAGE_STATE
ZFS_AC_KERNEL_SRC_ACCESS_OK_TYPE
@ -187,6 +188,7 @@ dnl #
dnl # Check results of kernel interface tests.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
ZFS_AC_KERNEL_TYPES
ZFS_AC_KERNEL_ACCESS_OK_TYPE
ZFS_AC_KERNEL_GLOBAL_PAGE_STATE
ZFS_AC_KERNEL_OBJTOOL

View File

@ -512,32 +512,33 @@ AC_DEFUN([ZFS_AC_DEFAULT_PACKAGE], [
[with_vendor=$withval],
[with_vendor=check])
AS_IF([test "x$with_vendor" = "xcheck"],[
if test -f /etc/toss-release ; then
VENDOR=toss ;
elif test -f /etc/fedora-release ; then
VENDOR=fedora ;
elif test -f /etc/redhat-release ; then
VENDOR=redhat ;
elif test -f /etc/gentoo-release ; then
VENDOR=gentoo ;
if test -f /etc/alpine-release ; then
VENDOR=alpine ;
elif test -f /etc/arch-release ; then
VENDOR=arch ;
elif test -f /etc/fedora-release ; then
VENDOR=fedora ;
elif test -f /bin/freebsd-version ; then
VENDOR=freebsd ;
elif test -f /etc/gentoo-release ; then
VENDOR=gentoo ;
elif test -f /etc/lunar.release ; then
VENDOR=lunar ;
elif test -f /etc/openEuler-release ; then
VENDOR=openeuler ;
elif test -f /etc/SuSE-release ; then
VENDOR=sles ;
elif test -f /etc/slackware-version ; then
VENDOR=slackware ;
elif test -f /etc/lunar.release ; then
VENDOR=lunar ;
elif test -f /etc/toss-release ; then
VENDOR=toss ;
elif test -f /etc/lsb-release ; then
VENDOR=ubuntu ;
# put debian and redhat last as derivatives may have also their file
elif test -f /etc/debian_version ; then
VENDOR=debian ;
elif test -f /etc/alpine-release ; then
VENDOR=alpine ;
elif test -f /bin/freebsd-version ; then
VENDOR=freebsd ;
elif test -f /etc/openEuler-release ; then
VENDOR=openeuler ;
elif test -f /etc/redhat-release ; then
VENDOR=redhat ;
else
VENDOR= ;
fi],
@ -550,20 +551,15 @@ AC_DEFUN([ZFS_AC_DEFAULT_PACKAGE], [
AC_MSG_CHECKING([default package type])
case "$VENDOR" in
toss) DEFAULT_PACKAGE=rpm ;;
redhat) DEFAULT_PACKAGE=rpm ;;
fedora) DEFAULT_PACKAGE=rpm ;;
gentoo) DEFAULT_PACKAGE=tgz ;;
alpine) DEFAULT_PACKAGE=tgz ;;
arch) DEFAULT_PACKAGE=tgz ;;
sles) DEFAULT_PACKAGE=rpm ;;
slackware) DEFAULT_PACKAGE=tgz ;;
lunar) DEFAULT_PACKAGE=tgz ;;
ubuntu) DEFAULT_PACKAGE=deb ;;
debian) DEFAULT_PACKAGE=deb ;;
freebsd) DEFAULT_PACKAGE=pkg ;;
openeuler) DEFAULT_PACKAGE=rpm ;;
*) DEFAULT_PACKAGE=rpm ;;
alpine|arch|gentoo|lunar|slackware)
DEFAULT_PACKAGE=tgz ;;
debian|ubuntu)
DEFAULT_PACKAGE=deb ;;
freebsd)
DEFAULT_PACKAGE=pkg ;;
*)
# fedora|openeuler|redhat|sles|toss
DEFAULT_PACKAGE=rpm ;;
esac
AC_MSG_RESULT([$DEFAULT_PACKAGE])
AC_SUBST(DEFAULT_PACKAGE)
@ -578,7 +574,7 @@ AC_DEFUN([ZFS_AC_DEFAULT_PACKAGE], [
AC_MSG_CHECKING([default shell])
case "$VENDOR" in
gentoo|alpine) DEFAULT_INIT_SHELL=/sbin/openrc-run
alpine|gentoo) DEFAULT_INIT_SHELL=/sbin/openrc-run
IS_SYSV_RC=false ;;
*) DEFAULT_INIT_SHELL=/bin/sh
IS_SYSV_RC=true ;;
@ -598,17 +594,19 @@ AC_DEFUN([ZFS_AC_DEFAULT_PACKAGE], [
AC_MSG_CHECKING([default init config directory])
case "$VENDOR" in
alpine) initconfdir=/etc/conf.d ;;
gentoo) initconfdir=/etc/conf.d ;;
toss) initconfdir=/etc/sysconfig ;;
redhat) initconfdir=/etc/sysconfig ;;
fedora) initconfdir=/etc/sysconfig ;;
sles) initconfdir=/etc/sysconfig ;;
openeuler) initconfdir=/etc/sysconfig ;;
ubuntu) initconfdir=/etc/default ;;
debian) initconfdir=/etc/default ;;
freebsd) initconfdir=$sysconfdir/rc.conf.d;;
*) initconfdir=/etc/default ;;
alpine|gentoo)
initconfdir=/etc/conf.d
;;
fedora|openeuler|redhat|sles|toss)
initconfdir=/etc/sysconfig
;;
freebsd)
initconfdir=$sysconfdir/rc.conf.d
;;
*)
# debian|ubuntu
initconfdir=/etc/default
;;
esac
AC_MSG_RESULT([$initconfdir])
AC_SUBST(initconfdir)
@ -625,11 +623,15 @@ AC_DEFUN([ZFS_AC_DEFAULT_PACKAGE], [
AC_MSG_CHECKING([default bash completion directory])
case "$VENDOR" in
ubuntu) bashcompletiondir=/usr/share/bash-completion/completions ;;
debian) bashcompletiondir=/usr/share/bash-completion/completions ;;
freebsd) bashcompletiondir=$sysconfdir/bash_completion.d;;
gentoo) bashcompletiondir=/usr/share/bash-completion/completions ;;
*) bashcompletiondir=/etc/bash_completion.d ;;
alpine|debian|gentoo|ubuntu)
bashcompletiondir=/usr/share/bash-completion/completions
;;
freebsd)
bashcompletiondir=$sysconfdir/bash_completion.d
;;
*)
bashcompletiondir=/etc/bash_completion.d
;;
esac
AC_MSG_RESULT([$bashcompletiondir])
AC_SUBST(bashcompletiondir)

View File

@ -716,7 +716,7 @@ typedef struct get_all_cb {
} get_all_cb_t;
_LIBZFS_H void zfs_foreach_mountpoint(libzfs_handle_t *, zfs_handle_t **,
size_t, zfs_iter_f, void *, boolean_t);
size_t, zfs_iter_f, void *, uint_t);
_LIBZFS_H void libzfs_add_handle(get_all_cb_t *, zfs_handle_t *);
/*
@ -1004,7 +1004,8 @@ _LIBZFS_H int zfs_smb_acl_rename(libzfs_handle_t *, char *, char *, char *,
* Enable and disable datasets within a pool by mounting/unmounting and
* sharing/unsharing them.
*/
_LIBZFS_H int zpool_enable_datasets(zpool_handle_t *, const char *, int);
_LIBZFS_H int zpool_enable_datasets(zpool_handle_t *, const char *, int,
uint_t);
_LIBZFS_H int zpool_disable_datasets(zpool_handle_t *, boolean_t);
_LIBZFS_H void zpool_disable_datasets_os(zpool_handle_t *, boolean_t);
_LIBZFS_H void zpool_disable_volume_os(const char *);

View File

@ -138,7 +138,8 @@ typedef int enum_t;
#define readdir64 readdir
#define dirent64 dirent
#endif
#define P2ALIGN(x, align) ((x) & -(align))
// Deprecated. Use P2ALIGN_TYPED instead.
// #define P2ALIGN(x, align) ((x) & -(align))
#define P2CROSS(x, y, align) (((x) ^ (y)) > (align) - 1)
#define P2ROUNDUP(x, align) ((((x) - 1) | ((align) - 1)) + 1)
#define P2PHASE(x, align) ((x) & ((align) - 1))

View File

@ -45,11 +45,11 @@
#define F_SEEK_HOLE FIOSEEKHOLE
struct opensolaris_utsname {
char *sysname;
char *nodename;
char *release;
char version[32];
char *machine;
const char *sysname;
const char *nodename;
const char *release;
char version[32];
const char *machine;
};
#define task_io_account_read(n)

View File

@ -39,20 +39,14 @@
#include <sys/signalvar.h>
#include <sys/debug.h>
#define FORREAL 0
#define JUSTLOOKING 1
static __inline int
issig(int why)
issig(void)
{
struct thread *td = curthread;
struct proc *p;
int sig;
ASSERT(why == FORREAL || why == JUSTLOOKING);
if (SIGPENDING(td)) {
if (why == JUSTLOOKING)
return (1);
p = td->td_proc;
PROC_LOCK(p);
mtx_lock(&p->p_sigacts->ps_mtx);

View File

@ -191,7 +191,8 @@ extern unsigned char bcd_to_byte[256];
* eg, P2ALIGN(0x1234, 0x100) == 0x1200 (0x12*align)
* eg, P2ALIGN(0x5600, 0x100) == 0x5600 (0x56*align)
*/
#define P2ALIGN(x, align) ((x) & -(align))
// Deprecated. Use P2ALIGN_TYPED instead.
// #define P2ALIGN(x, align) ((x) & -(align))
/*
* return x % (mod) align

View File

@ -30,9 +30,6 @@
#include <linux/sched/signal.h>
#endif
#define FORREAL 0 /* Usual side-effects */
#define JUSTLOOKING 1 /* Don't stop the process */
extern int issig(int why);
extern int issig(void);
#endif /* SPL_SIGNAL_H */

View File

@ -159,7 +159,8 @@ makedev(unsigned int major, unsigned int minor)
/*
* Compatibility macros/typedefs needed for Solaris -> Linux port
*/
#define P2ALIGN(x, align) ((x) & -(align))
// Deprecated. Use P2ALIGN_TYPED instead.
// #define P2ALIGN(x, align) ((x) & -(align))
#define P2CROSS(x, y, align) (((x) ^ (y)) > (align) - 1)
#define P2ROUNDUP(x, align) ((((x) - 1) | ((align) - 1)) + 1)
#define P2PHASE(x, align) ((x) & ((align) - 1))

View File

@ -38,7 +38,9 @@ typedef unsigned long ulong_t;
typedef unsigned long long u_longlong_t;
typedef long long longlong_t;
#ifndef HAVE_KERNEL_INTPTR_T
typedef long intptr_t;
#endif
typedef unsigned long long rlim64_t;
typedef struct task_struct kthread_t;

View File

@ -243,6 +243,7 @@ struct spa {
dsl_pool_t *spa_dsl_pool;
boolean_t spa_is_initializing; /* true while opening pool */
boolean_t spa_is_exporting; /* true while exporting pool */
kthread_t *spa_export_thread; /* valid during pool export */
kthread_t *spa_load_thread; /* loading, no namespace lock */
metaslab_class_t *spa_normal_class; /* normal data class */
metaslab_class_t *spa_log_class; /* intent log data class */
@ -478,10 +479,8 @@ struct spa {
extern char *spa_config_path;
extern const char *zfs_deadman_failmode;
extern uint_t spa_slop_shift;
extern void spa_taskq_dispatch_ent(spa_t *spa, zio_type_t t, zio_taskq_type_t q,
task_func_t *func, void *arg, uint_t flags, taskq_ent_t *ent, zio_t *zio);
extern void spa_taskq_dispatch_sync(spa_t *, zio_type_t t, zio_taskq_type_t q,
task_func_t *func, void *arg, uint_t flags);
extern void spa_taskq_dispatch(spa_t *spa, zio_type_t t, zio_taskq_type_t q,
task_func_t *func, zio_t *zio, boolean_t cutinline);
extern void spa_load_spares(spa_t *spa);
extern void spa_load_l2cache(spa_t *spa);
extern sysevent_t *spa_event_create(spa_t *spa, vdev_t *vd, nvlist_t *hist_nvl,

View File

@ -249,8 +249,7 @@ extern struct proc p0;
extern kthread_t *zk_thread_create(const char *name, void (*func)(void *),
void *arg, size_t stksize, int state);
#define issig(why) (FALSE)
#define ISSIG(thr, why) (FALSE)
#define issig() (FALSE)
#define KPREEMPT_SYNC (-1)

View File

@ -104,7 +104,7 @@ extern void zfs_dbgmsg_fini(void);
#ifndef _KERNEL
extern int dprintf_find_string(const char *string);
extern void zfs_dbgmsg_print(const char *tag);
extern void zfs_dbgmsg_print(int fd, const char *tag);
#endif
#ifdef __cplusplus

View File

@ -1175,8 +1175,8 @@ efi_use_whole_disk(int fd)
* (for performance reasons). The alignment should match the
* alignment used by the "zpool_label_disk" function.
*/
limit = P2ALIGN(efi_label->efi_last_lba - nblocks - EFI_MIN_RESV_SIZE,
PARTITION_END_ALIGNMENT);
limit = P2ALIGN_TYPED(efi_label->efi_last_lba - nblocks -
EFI_MIN_RESV_SIZE, PARTITION_END_ALIGNMENT, diskaddr_t);
if (data_start + data_size != limit || resv_start != limit)
sync_needed = B_TRUE;

View File

@ -79,6 +79,7 @@
<elf-symbol name='fnvpair_value_uint64' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='fnvpair_value_uint8' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_assertf' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_backtrace' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_set_assert_ok' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='nv_alloc_fini' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='nv_alloc_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@ -1156,6 +1157,11 @@
<parameter type-id='80f4b756'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='strchr' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='80f4b756'/>
<parameter type-id='95e97e5e'/>
<return type-id='26a90f95'/>
</function-decl>
<function-decl name='strcspn' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='80f4b756'/>
<parameter type-id='80f4b756'/>
@ -2041,9 +2047,77 @@
</function-type>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/assert.c' language='LANG_C99'>
<array-type-def dimensions='1' type-id='a84c031d' size-in-bits='320' id='36c46961'>
<subrange length='40' type-id='7359adad' id='8f80b239'/>
</array-type-def>
<union-decl name='pthread_mutex_t' size-in-bits='320' naming-typedef-id='7a6844eb' visibility='default' id='70681f9b'>
<data-member access='public'>
<var-decl name='__data' type-id='4c734837' visibility='default'/>
</data-member>
<data-member access='public'>
<var-decl name='__size' type-id='36c46961' visibility='default'/>
</data-member>
<data-member access='public'>
<var-decl name='__align' type-id='bd54fe1a' visibility='default'/>
</data-member>
</union-decl>
<typedef-decl name='pthread_mutex_t' type-id='70681f9b' id='7a6844eb'/>
<class-decl name='__pthread_mutex_s' size-in-bits='320' is-struct='yes' visibility='default' id='4c734837'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='__lock' type-id='95e97e5e' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='32'>
<var-decl name='__count' type-id='f0981eeb' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='__owner' type-id='95e97e5e' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='96'>
<var-decl name='__nusers' type-id='f0981eeb' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
<var-decl name='__kind' type-id='95e97e5e' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='160'>
<var-decl name='__spins' type-id='a2185560' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='176'>
<var-decl name='__elision' type-id='a2185560' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='192'>
<var-decl name='__list' type-id='518fb49c' visibility='default'/>
</data-member>
</class-decl>
<class-decl name='__pthread_internal_list' size-in-bits='128' is-struct='yes' visibility='default' id='0e01899c'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='__prev' type-id='4d98cd5a' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='__next' type-id='4d98cd5a' visibility='default'/>
</data-member>
</class-decl>
<typedef-decl name='__pthread_list_t' type-id='0e01899c' id='518fb49c'/>
<typedef-decl name='__pid_t' type-id='95e97e5e' id='3629bad8'/>
<pointer-type-def type-id='0e01899c' size-in-bits='64' id='4d98cd5a'/>
<pointer-type-def type-id='7a6844eb' size-in-bits='64' id='18c91f9e'/>
<function-decl name='libspl_backtrace' mangled-name='libspl_backtrace' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_backtrace'>
<parameter type-id='95e97e5e'/>
<return type-id='48b5725f'/>
</function-decl>
<function-decl name='pthread_mutex_lock' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='18c91f9e'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='pthread_mutex_unlock' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='18c91f9e'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='abort' visibility='default' binding='global' size-in-bits='64'>
<return type-id='48b5725f'/>
</function-decl>
<function-decl name='getpid' visibility='default' binding='global' size-in-bits='64'>
<return type-id='3629bad8'/>
</function-decl>
<function-decl name='__vfprintf_chk' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='e75a27e9'/>
<parameter type-id='95e97e5e'/>
@ -2051,11 +2125,43 @@
<parameter type-id='b7f2d5e6'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='gettid' visibility='default' binding='global' size-in-bits='64'>
<return type-id='3629bad8'/>
</function-decl>
<function-decl name='prctl' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='95e97e5e'/>
<parameter is-variadic='yes'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='libspl_set_assert_ok' mangled-name='libspl_set_assert_ok' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_set_assert_ok'>
<parameter type-id='c19b74c3' name='val'/>
<return type-id='48b5725f'/>
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/backtrace.c' language='LANG_C99'>
<typedef-decl name='__ssize_t' type-id='bd54fe1a' id='41060289'/>
<typedef-decl name='ssize_t' type-id='41060289' id='79a0948f'/>
<qualified-type-def type-id='eaa32e2f' const='yes' id='83be723c'/>
<pointer-type-def type-id='83be723c' size-in-bits='64' id='7acd98a2'/>
<pointer-type-def type-id='eaa32e2f' size-in-bits='64' id='63e171df'/>
<function-decl name='backtrace' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='63e171df'/>
<parameter type-id='95e97e5e'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='backtrace_symbols_fd' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='7acd98a2'/>
<parameter type-id='95e97e5e'/>
<parameter type-id='95e97e5e'/>
<return type-id='48b5725f'/>
</function-decl>
<function-decl name='write' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='95e97e5e'/>
<parameter type-id='eaa32e2f'/>
<parameter type-id='b59d7dce'/>
<return type-id='79a0948f'/>
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='module/nvpair/fnvpair.c' language='LANG_C99'>
<function-decl name='fnvlist_alloc' mangled-name='fnvlist_alloc' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='fnvlist_alloc'>
<return type-id='5ce45b60'/>
@ -2536,11 +2642,6 @@
<parameter type-id='b59d7dce'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='strchr' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='80f4b756'/>
<parameter type-id='95e97e5e'/>
<return type-id='26a90f95'/>
</function-decl>
<function-decl name='strlen' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='80f4b756'/>
<return type-id='b59d7dce'/>

View File

@ -7,7 +7,8 @@ noinst_LTLIBRARIES += libspl_assert.la libspl.la
CPPCHECKTARGETS += libspl_assert.la libspl.la
libspl_assert_la_SOURCES = \
%D%/assert.c
%D%/assert.c \
%D%/backtrace.c
libspl_la_SOURCES = \
%D%/libspl_impl.h \
@ -45,3 +46,7 @@ libspl_la_LIBADD = \
libspl_la_LIBADD += $(LIBATOMIC_LIBS) $(LIBCLOCK_GETTIME)
libspl_assert_la_LIBADD = $(BACKTRACE_LIBS) $(LIBUNWIND_LIBS)
if BUILD_FREEBSD
libspl_assert_la_LIBADD += -lpthread
endif

View File

@ -28,6 +28,7 @@
#include <assert.h>
#include <pthread.h>
#include <sys/backtrace.h>
#if defined(__linux__)
#include <errno.h>
@ -51,53 +52,17 @@
pthread_getname_np(pthread_self(), buf, len);
#endif
#if defined(HAVE_LIBUNWIND)
#define UNW_LOCAL_ONLY
#include <libunwind.h>
static inline void
libspl_dump_backtrace(void)
#if defined(__APPLE__)
static inline uint64_t
libspl_gettid(void)
{
unw_context_t uc;
unw_cursor_t cp;
unw_word_t ip, off;
char funcname[128];
#ifdef HAVE_LIBUNWIND_ELF
char objname[128];
unw_word_t objoff;
#endif
uint64_t tid;
fprintf(stderr, "Call trace:\n");
unw_getcontext(&uc);
unw_init_local(&cp, &uc);
while (unw_step(&cp) > 0) {
unw_get_reg(&cp, UNW_REG_IP, &ip);
unw_get_proc_name(&cp, funcname, sizeof (funcname), &off);
#ifdef HAVE_LIBUNWIND_ELF
unw_get_elf_filename(&cp, objname, sizeof (objname), &objoff);
fprintf(stderr, " [0x%08lx] %s+0x%2lx (in %s +0x%2lx)\n",
ip, funcname, off, objname, objoff);
#else
fprintf(stderr, " [0x%08lx] %s+0x%2lx\n", ip, funcname, off);
#endif
}
}
#elif defined(HAVE_BACKTRACE)
#include <execinfo.h>
if (pthread_threadid_np(NULL, &tid) != 0)
tid = 0;
static inline void
libspl_dump_backtrace(void)
{
void *btptrs[100];
size_t nptrs = backtrace(btptrs, 100);
char **bt = backtrace_symbols(btptrs, nptrs);
fprintf(stderr, "Call trace:\n");
for (size_t i = 0; i < nptrs; i++)
fprintf(stderr, " %s\n", bt[i]);
free(bt);
return (tid);
}
#else
#define libspl_dump_backtrace()
#endif
#if defined(__APPLE__)
@ -151,7 +116,7 @@ libspl_assertf(const char *file, const char *func, int line,
getpid(), libspl_getprogname(),
libspl_gettid(), tname);
libspl_dump_backtrace();
libspl_backtrace(STDERR_FILENO);
#if !__has_feature(attribute_analyzer_noreturn) && !defined(__COVERITY__)
if (libspl_assert_ok) {

View File

@ -0,0 +1,119 @@
/*
* 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, Rob Norris <robn@despairlabs.com>
* Copyright (c) 2024, Klara Inc.
*/
#include <sys/backtrace.h>
#include <sys/types.h>
#include <unistd.h>
/*
* libspl_backtrace() must be safe to call from inside a signal hander. This
* mostly means it must not allocate, and so we can't use things like printf.
*/
#if defined(HAVE_LIBUNWIND)
#define UNW_LOCAL_ONLY
#include <libunwind.h>
static size_t
libspl_u64_to_hex_str(uint64_t v, size_t digits, char *buf, size_t buflen)
{
static const char hexdigits[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
size_t pos = 0;
boolean_t want = (digits == 0);
for (int i = 15; i >= 0; i--) {
const uint64_t d = v >> (i * 4) & 0xf;
if (!want && (d != 0 || digits > i))
want = B_TRUE;
if (want) {
buf[pos++] = hexdigits[d];
if (pos == buflen)
break;
}
}
return (pos);
}
void
libspl_backtrace(int fd)
{
ssize_t ret __attribute__((unused));
unw_context_t uc;
unw_cursor_t cp;
unw_word_t loc;
char buf[128];
size_t n;
ret = write(fd, "Call trace:\n", 12);
unw_getcontext(&uc);
unw_init_local(&cp, &uc);
while (unw_step(&cp) > 0) {
unw_get_reg(&cp, UNW_REG_IP, &loc);
ret = write(fd, " [0x", 5);
n = libspl_u64_to_hex_str(loc, 10, buf, sizeof (buf));
ret = write(fd, buf, n);
ret = write(fd, "] ", 2);
unw_get_proc_name(&cp, buf, sizeof (buf), &loc);
for (n = 0; n < sizeof (buf) && buf[n] != '\0'; n++) {}
ret = write(fd, buf, n);
ret = write(fd, "+0x", 3);
n = libspl_u64_to_hex_str(loc, 2, buf, sizeof (buf));
ret = write(fd, buf, n);
#ifdef HAVE_LIBUNWIND_ELF
ret = write(fd, " (in ", 5);
unw_get_elf_filename(&cp, buf, sizeof (buf), &loc);
for (n = 0; n < sizeof (buf) && buf[n] != '\0'; n++) {}
ret = write(fd, buf, n);
ret = write(fd, " +0x", 4);
n = libspl_u64_to_hex_str(loc, 2, buf, sizeof (buf));
ret = write(fd, buf, n);
ret = write(fd, ")", 1);
#endif
ret = write(fd, "\n", 1);
}
}
#elif defined(HAVE_BACKTRACE)
#include <execinfo.h>
void
libspl_backtrace(int fd)
{
ssize_t ret __attribute__((unused));
void *btptrs[64];
size_t nptrs = backtrace(btptrs, 64);
ret = write(fd, "Call trace:\n", 12);
backtrace_symbols_fd(btptrs, nptrs, fd);
}
#else
#include <sys/debug.h>
void
libspl_backtrace(int fd __maybe_unused)
{
}
#endif

View File

@ -27,6 +27,7 @@ libspl_sys_HEADERS = \
%D%/sys/acl.h \
%D%/sys/acl_impl.h \
%D%/sys/asm_linkage.h \
%D%/sys/backtrace.h \
%D%/sys/callb.h \
%D%/sys/cmn_err.h \
%D%/sys/cred.h \

View File

@ -52,7 +52,8 @@
/*
* Compatibility macros/typedefs needed for Solaris -> Linux port
*/
#define P2ALIGN(x, align) ((x) & -(align))
// Deprecated. Use P2ALIGN_TYPED instead.
// #define P2ALIGN(x, align) ((x) & -(align))
#define P2CROSS(x, y, align) (((x) ^ (y)) > (align) - 1)
#define P2ROUNDUP(x, align) ((((x) - 1) | ((align) - 1)) + 1)
#define P2BOUNDARY(off, len, align) \

View File

@ -0,0 +1,32 @@
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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, Rob Norris <robn@despairlabs.com>
* Copyright (c) 2024, Klara Inc.
*/
#ifndef _LIBSPL_SYS_BACKTRACE_H
#define _LIBSPL_SYS_BACKTRACE_H
void libspl_backtrace(int fd);
#endif

View File

@ -423,6 +423,26 @@ tpool_dispatch(tpool_t *tpool, void (*func)(void *), void *arg)
pthread_mutex_lock(&tpool->tp_mutex);
if (!(tpool->tp_flags & TP_SUSPEND)) {
if (tpool->tp_idle > 0)
(void) pthread_cond_signal(&tpool->tp_workcv);
else if (tpool->tp_current >= tpool->tp_maximum) {
/* At worker limit. Leave task on queue */
} else {
if (create_worker(tpool) == 0) {
/* Started a new worker thread */
tpool->tp_current++;
} else if (tpool->tp_current > 0) {
/* Leave task on queue */
} else {
/* Cannot start a single worker! */
pthread_mutex_unlock(&tpool->tp_mutex);
free(job);
return (-1);
}
}
}
if (tpool->tp_head == NULL)
tpool->tp_head = job;
else
@ -430,14 +450,6 @@ tpool_dispatch(tpool_t *tpool, void (*func)(void *), void *arg)
tpool->tp_tail = job;
tpool->tp_njobs++;
if (!(tpool->tp_flags & TP_SUSPEND)) {
if (tpool->tp_idle > 0)
(void) pthread_cond_signal(&tpool->tp_workcv);
else if (tpool->tp_current < tpool->tp_maximum &&
create_worker(tpool) == 0)
tpool->tp_current++;
}
pthread_mutex_unlock(&tpool->tp_mutex);
return (0);
}

View File

@ -149,6 +149,7 @@
<elf-symbol name='getmntany' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='getzoneid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_assertf' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_backtrace' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_set_assert_ok' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='list_create' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='list_destroy' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@ -242,6 +243,22 @@
<elf-symbol name='uu_zalloc' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
</elf-function-symbols>
<abi-instr address-size='64' path='lib/libspl/assert.c' language='LANG_C99'>
<typedef-decl name='__pid_t' type-id='95e97e5e' id='3629bad8'/>
<function-decl name='libspl_backtrace' mangled-name='libspl_backtrace' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_backtrace'>
<parameter type-id='95e97e5e'/>
<return type-id='48b5725f'/>
</function-decl>
<function-decl name='getpid' visibility='default' binding='global' size-in-bits='64'>
<return type-id='3629bad8'/>
</function-decl>
<function-decl name='gettid' visibility='default' binding='global' size-in-bits='64'>
<return type-id='3629bad8'/>
</function-decl>
<function-decl name='prctl' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='95e97e5e'/>
<parameter is-variadic='yes'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='libspl_set_assert_ok' mangled-name='libspl_set_assert_ok' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_set_assert_ok'>
<parameter type-id='c19b74c3' name='val'/>
<return type-id='48b5725f'/>
@ -576,6 +593,27 @@
</function-decl>
<type-decl name='unsigned short int' size-in-bits='16' id='8efea9e5'/>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/backtrace.c' language='LANG_C99'>
<qualified-type-def type-id='eaa32e2f' const='yes' id='83be723c'/>
<pointer-type-def type-id='83be723c' size-in-bits='64' id='7acd98a2'/>
<function-decl name='backtrace' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='63e171df'/>
<parameter type-id='95e97e5e'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='backtrace_symbols_fd' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='7acd98a2'/>
<parameter type-id='95e97e5e'/>
<parameter type-id='95e97e5e'/>
<return type-id='48b5725f'/>
</function-decl>
<function-decl name='write' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='95e97e5e'/>
<parameter type-id='eaa32e2f'/>
<parameter type-id='b59d7dce'/>
<return type-id='79a0948f'/>
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/getexecname.c' language='LANG_C99'>
<function-decl name='getexecname' mangled-name='getexecname' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getexecname'>
<return type-id='80f4b756'/>
@ -596,14 +634,11 @@
<var-decl name='prev' type-id='b03eadb4' visibility='default'/>
</data-member>
</class-decl>
<class-decl name='list' size-in-bits='256' is-struct='yes' visibility='default' id='e824dae9'>
<class-decl name='list' size-in-bits='192' is-struct='yes' visibility='default' id='e824dae9'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='list_size' type-id='b59d7dce' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='list_offset' type-id='b59d7dce' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='list_head' type-id='b0b5e45e' visibility='default'/>
</data-member>
</class-decl>
@ -800,9 +835,16 @@
<type-decl name='unsigned long int' size-in-bits='64' id='7359adad'/>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/os/linux/getmntany.c' language='LANG_C99'>
<array-type-def dimensions='1' type-id='38b51b3c' size-in-bits='832' id='02b72c00'>
<subrange length='13' type-id='7359adad' id='487fded1'/>
</array-type-def>
<array-type-def dimensions='1' type-id='03085adc' size-in-bits='192' id='083f8d58'>
<subrange length='3' type-id='7359adad' id='56f209d2'/>
</array-type-def>
<class-decl name='__locale_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='23de8b96'/>
<array-type-def dimensions='1' type-id='80f4b756' size-in-bits='832' id='39e6f84a'>
<subrange length='13' type-id='7359adad' id='487fded1'/>
</array-type-def>
<class-decl name='mnttab' size-in-bits='256' is-struct='yes' visibility='default' id='1b055409'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='mnt_special' type-id='26a90f95' visibility='default'/>
@ -912,6 +954,25 @@
<typedef-decl name='__blksize_t' type-id='bd54fe1a' id='d3f10a7f'/>
<typedef-decl name='__blkcnt64_t' type-id='bd54fe1a' id='4e711bf1'/>
<typedef-decl name='__syscall_slong_t' type-id='bd54fe1a' id='03085adc'/>
<class-decl name='__locale_struct' size-in-bits='1856' is-struct='yes' visibility='default' id='90cc1ce3'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='__locales' type-id='02b72c00' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='832'>
<var-decl name='__ctype_b' type-id='31347b7a' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='896'>
<var-decl name='__ctype_tolower' type-id='6d60f45d' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='960'>
<var-decl name='__ctype_toupper' type-id='6d60f45d' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1024'>
<var-decl name='__names' type-id='39e6f84a' visibility='default'/>
</data-member>
</class-decl>
<typedef-decl name='__locale_t' type-id='f01e1813' id='b7ac9b5f'/>
<typedef-decl name='locale_t' type-id='b7ac9b5f' id='973a4f8d'/>
<class-decl name='timespec' size-in-bits='128' is-struct='yes' visibility='default' id='a9c79a1f'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='tv_sec' type-id='65eda9c0' visibility='default'/>
@ -920,12 +981,23 @@
<var-decl name='tv_nsec' type-id='03085adc' visibility='default'/>
</data-member>
</class-decl>
<pointer-type-def type-id='23de8b96' size-in-bits='64' id='38b51b3c'/>
<pointer-type-def type-id='90cc1ce3' size-in-bits='64' id='f01e1813'/>
<qualified-type-def type-id='95e97e5e' const='yes' id='2448a865'/>
<pointer-type-def type-id='2448a865' size-in-bits='64' id='6d60f45d'/>
<qualified-type-def type-id='8efea9e5' const='yes' id='3beb2af4'/>
<pointer-type-def type-id='3beb2af4' size-in-bits='64' id='31347b7a'/>
<pointer-type-def type-id='0c544dc0' size-in-bits='64' id='394fc496'/>
<pointer-type-def type-id='56fe4a37' size-in-bits='64' id='b6b61d2f'/>
<qualified-type-def type-id='b6b61d2f' restrict='yes' id='3cad23cd'/>
<pointer-type-def type-id='1b055409' size-in-bits='64' id='9d424d31'/>
<pointer-type-def type-id='0bbec9cd' size-in-bits='64' id='62f7a03d'/>
<qualified-type-def type-id='62f7a03d' restrict='yes' id='f1cadedf'/>
<class-decl name='__locale_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='23de8b96'/>
<function-decl name='uselocale' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='973a4f8d'/>
<return type-id='973a4f8d'/>
</function-decl>
<function-decl name='getmntent_r' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='e75a27e9'/>
<parameter type-id='3cad23cd'/>
@ -937,8 +1009,9 @@
<parameter type-id='822cd80b'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='strerror' visibility='default' binding='global' size-in-bits='64'>
<function-decl name='strerror_l' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='95e97e5e'/>
<parameter type-id='973a4f8d'/>
<return type-id='26a90f95'/>
</function-decl>
<function-decl name='__fprintf_chk' visibility='default' binding='global' size-in-bits='64'>

View File

@ -191,6 +191,7 @@
<elf-symbol name='is_mpath_whole_disk' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libpc_error_description' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_assertf' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_backtrace' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_set_assert_ok' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libzfs_add_handle' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libzfs_envvar_is_set' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@ -777,6 +778,18 @@
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/assert.c' language='LANG_C99'>
<function-decl name='libspl_backtrace' mangled-name='libspl_backtrace' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_backtrace'>
<parameter type-id='95e97e5e'/>
<return type-id='48b5725f'/>
</function-decl>
<function-decl name='gettid' visibility='default' binding='global' size-in-bits='64'>
<return type-id='3629bad8'/>
</function-decl>
<function-decl name='prctl' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='95e97e5e'/>
<parameter is-variadic='yes'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='libspl_set_assert_ok' mangled-name='libspl_set_assert_ok' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_set_assert_ok'>
<parameter type-id='c19b74c3' name='val'/>
<return type-id='48b5725f'/>
@ -1092,6 +1105,19 @@
<return type-id='48b5725f'/>
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/backtrace.c' language='LANG_C99'>
<function-decl name='backtrace' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='63e171df'/>
<parameter type-id='95e97e5e'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='backtrace_symbols_fd' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='7acd98a2'/>
<parameter type-id='95e97e5e'/>
<parameter type-id='95e97e5e'/>
<return type-id='48b5725f'/>
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/getexecname.c' language='LANG_C99'>
<function-decl name='getexecname' mangled-name='getexecname' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getexecname'>
<return type-id='80f4b756'/>
@ -5532,13 +5558,14 @@
<parameter type-id='b59d7dce' name='num_handles'/>
<parameter type-id='d8e49ab9' name='func'/>
<parameter type-id='eaa32e2f' name='data'/>
<parameter type-id='c19b74c3' name='parallel'/>
<parameter type-id='3502e3ff' name='nthr'/>
<return type-id='48b5725f'/>
</function-decl>
<function-decl name='zpool_enable_datasets' mangled-name='zpool_enable_datasets' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_enable_datasets'>
<parameter type-id='4c81de99' name='zhp'/>
<parameter type-id='80f4b756' name='mntopts'/>
<parameter type-id='95e97e5e' name='flags'/>
<parameter type-id='3502e3ff' name='nthr'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='zpool_disable_datasets' mangled-name='zpool_disable_datasets' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_disable_datasets'>
@ -6251,6 +6278,11 @@
<parameter type-id='8c85230f'/>
<return type-id='26a90f95'/>
</function-decl>
<function-decl name='ctime_r' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='d6e2847c'/>
<parameter type-id='266fe297'/>
<return type-id='26a90f95'/>
</function-decl>
<function-decl name='__realpath_chk' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='9d26089a'/>
<parameter type-id='266fe297'/>
@ -6362,7 +6394,7 @@
<function-decl name='zpool_add' mangled-name='zpool_add' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_add'>
<parameter type-id='4c81de99' name='zhp'/>
<parameter type-id='5ce45b60' name='nvroot'/>
<parameter type-id='c19b74c3' name='ashift_check'/>
<parameter type-id='c19b74c3' name='check_ashift'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='zpool_export' mangled-name='zpool_export' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_export'>
@ -8671,7 +8703,7 @@
<array-type-def dimensions='1' type-id='a84c031d' size-in-bits='256' id='16dc656a'>
<subrange length='32' type-id='7359adad' id='ae5bde82'/>
</array-type-def>
<class-decl name='importargs' size-in-bits='448' is-struct='yes' visibility='default' id='7ac83801'>
<class-decl name='importargs' size-in-bits='512' is-struct='yes' visibility='default' id='7ac83801'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='path' type-id='9b23c9ad' visibility='default'/>
</data-member>
@ -8696,6 +8728,12 @@
<data-member access='public' layout-offset-in-bits='384'>
<var-decl name='policy' type-id='5ce45b60' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='448'>
<var-decl name='do_destroyed' type-id='c19b74c3' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='480'>
<var-decl name='do_all' type-id='c19b74c3' visibility='default'/>
</data-member>
</class-decl>
<typedef-decl name='importargs_t' type-id='7ac83801' id='7a842a6b'/>
<class-decl name='libpc_handle' size-in-bits='8448' is-struct='yes' visibility='default' id='7c8737f0'>

View File

@ -83,8 +83,6 @@
#include <sys/systeminfo.h>
#define MAXISALEN 257 /* based on sysinfo(2) man page */
static int mount_tp_nthr = 512; /* tpool threads for multi-threaded mounting */
static void zfs_mount_task(void *);
static const proto_table_t proto_table[SA_PROTOCOL_COUNT] = {
@ -1098,7 +1096,10 @@ zfs_dispatch_mount(libzfs_handle_t *hdl, zfs_handle_t **handles,
mnt_param->mnt_func = func;
mnt_param->mnt_data = data;
(void) tpool_dispatch(tp, zfs_mount_task, (void*)mnt_param);
if (tpool_dispatch(tp, zfs_mount_task, (void*)mnt_param)) {
/* Could not dispatch to thread pool; execute directly */
zfs_mount_task((void*)mnt_param);
}
}
/*
@ -1202,19 +1203,20 @@ zfs_mount_task(void *arg)
*
* Callbacks are issued in one of two ways:
*
* 1. Sequentially: If the parallel argument is B_FALSE or the ZFS_SERIAL_MOUNT
* 1. Sequentially: If the nthr argument is <= 1 or the ZFS_SERIAL_MOUNT
* environment variable is set, then we issue callbacks sequentially.
*
* 2. In parallel: If the parallel argument is B_TRUE and the ZFS_SERIAL_MOUNT
* 2. In parallel: If the nthr argument is > 1 and the ZFS_SERIAL_MOUNT
* environment variable is not set, then we use a tpool to dispatch threads
* to mount filesystems in parallel. This function dispatches tasks to mount
* the filesystems at the top-level mountpoints, and these tasks in turn
* are responsible for recursively mounting filesystems in their children
* mountpoints.
* mountpoints. The value of the nthr argument will be the number of worker
* threads for the thread pool.
*/
void
zfs_foreach_mountpoint(libzfs_handle_t *hdl, zfs_handle_t **handles,
size_t num_handles, zfs_iter_f func, void *data, boolean_t parallel)
size_t num_handles, zfs_iter_f func, void *data, uint_t nthr)
{
zoneid_t zoneid = getzoneid();
@ -1223,7 +1225,7 @@ zfs_foreach_mountpoint(libzfs_handle_t *hdl, zfs_handle_t **handles,
* variable that can be used as a convenience to do a/b comparison
* of serial vs. parallel mounting.
*/
boolean_t serial_mount = !parallel ||
boolean_t serial_mount = nthr <= 1 ||
(getenv("ZFS_SERIAL_MOUNT") != NULL);
/*
@ -1243,7 +1245,7 @@ zfs_foreach_mountpoint(libzfs_handle_t *hdl, zfs_handle_t **handles,
* Issue the callback function for each dataset using a parallel
* algorithm that uses a thread pool to manage threads.
*/
tpool_t *tp = tpool_create(1, mount_tp_nthr, 0, NULL);
tpool_t *tp = tpool_create(1, nthr, 0, NULL);
/*
* There may be multiple "top level" mountpoints outside of the pool's
@ -1270,10 +1272,12 @@ zfs_foreach_mountpoint(libzfs_handle_t *hdl, zfs_handle_t **handles,
/*
* Mount and share all datasets within the given pool. This assumes that no
* datasets within the pool are currently mounted.
* datasets within the pool are currently mounted. nthr will be number of
* worker threads to use while mounting datasets.
*/
int
zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags)
zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags,
uint_t nthr)
{
get_all_cb_t cb = { 0 };
mount_state_t ms = { 0 };
@ -1299,7 +1303,7 @@ zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags)
ms.ms_mntopts = mntopts;
ms.ms_mntflags = flags;
zfs_foreach_mountpoint(zhp->zpool_hdl, cb.cb_handles, cb.cb_used,
zfs_mount_one, &ms, B_TRUE);
zfs_mount_one, &ms, nthr);
if (ms.ms_mntstatus != 0)
ret = EZFS_MOUNTFAILED;
@ -1310,7 +1314,7 @@ zpool_enable_datasets(zpool_handle_t *zhp, const char *mntopts, int flags)
*/
ms.ms_mntstatus = 0;
zfs_foreach_mountpoint(zhp->zpool_hdl, cb.cb_handles, cb.cb_used,
zfs_share_one, &ms, B_FALSE);
zfs_share_one, &ms, 1);
if (ms.ms_mntstatus != 0)
ret = EZFS_SHAREFAILED;
else

View File

@ -2170,7 +2170,8 @@ zfs_send_saved(zfs_handle_t *zhp, sendflags_t *flags, int outfd,
static int
send_conclusion_record(int fd, zio_cksum_t *zc)
{
dmu_replay_record_t drr = { 0 };
dmu_replay_record_t drr;
memset(&drr, 0, sizeof (dmu_replay_record_t));
drr.drr_type = DRR_END;
if (zc != NULL)
drr.drr_u.drr_end.drr_checksum = *zc;
@ -2272,7 +2273,8 @@ send_prelim_records(zfs_handle_t *zhp, const char *from, int fd,
}
if (!dryrun) {
dmu_replay_record_t drr = { 0 };
dmu_replay_record_t drr;
memset(&drr, 0, sizeof (dmu_replay_record_t));
/* write first begin record */
drr.drr_type = DRR_BEGIN;
drr.drr_u.drr_begin.drr_magic = DMU_BACKUP_MAGIC;

View File

@ -268,7 +268,8 @@ zpool_label_disk(libzfs_handle_t *hdl, zpool_handle_t *zhp, const char *name)
if (start_block == MAXOFFSET_T)
start_block = NEW_START_BLOCK;
slice_size -= start_block;
slice_size = P2ALIGN(slice_size, PARTITION_END_ALIGNMENT);
slice_size = P2ALIGN_TYPED(slice_size, PARTITION_END_ALIGNMENT,
uint64_t);
vtoc->efi_parts[0].p_start = start_block;
vtoc->efi_parts[0].p_size = slice_size;

View File

@ -132,6 +132,7 @@
<elf-symbol name='getmntany' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='getzoneid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_assertf' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_backtrace' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libspl_set_assert_ok' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libzfs_core_fini' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
<elf-symbol name='libzfs_core_init' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
@ -231,10 +232,18 @@
<var-decl name='reg_save_area' type-id='eaa32e2f' visibility='default'/>
</data-member>
</class-decl>
<typedef-decl name='__pid_t' type-id='95e97e5e' id='3629bad8'/>
<pointer-type-def type-id='d5027220' size-in-bits='64' id='b7f2d5e6'/>
<function-decl name='libspl_backtrace' mangled-name='libspl_backtrace' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_backtrace'>
<parameter type-id='95e97e5e'/>
<return type-id='48b5725f'/>
</function-decl>
<function-decl name='abort' visibility='default' binding='global' size-in-bits='64'>
<return type-id='48b5725f'/>
</function-decl>
<function-decl name='getpid' visibility='default' binding='global' size-in-bits='64'>
<return type-id='3629bad8'/>
</function-decl>
<function-decl name='__vfprintf_chk' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='e75a27e9'/>
<parameter type-id='95e97e5e'/>
@ -242,6 +251,14 @@
<parameter type-id='b7f2d5e6'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='gettid' visibility='default' binding='global' size-in-bits='64'>
<return type-id='3629bad8'/>
</function-decl>
<function-decl name='prctl' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='95e97e5e'/>
<parameter is-variadic='yes'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='libspl_set_assert_ok' mangled-name='libspl_set_assert_ok' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='libspl_set_assert_ok'>
<parameter type-id='c19b74c3' name='val'/>
<return type-id='48b5725f'/>
@ -574,6 +591,27 @@
<type-decl name='unsigned long int' size-in-bits='64' id='7359adad'/>
<type-decl name='unsigned short int' size-in-bits='16' id='8efea9e5'/>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/backtrace.c' language='LANG_C99'>
<qualified-type-def type-id='eaa32e2f' const='yes' id='83be723c'/>
<pointer-type-def type-id='83be723c' size-in-bits='64' id='7acd98a2'/>
<function-decl name='backtrace' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='63e171df'/>
<parameter type-id='95e97e5e'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='backtrace_symbols_fd' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='7acd98a2'/>
<parameter type-id='95e97e5e'/>
<parameter type-id='95e97e5e'/>
<return type-id='48b5725f'/>
</function-decl>
<function-decl name='write' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='95e97e5e'/>
<parameter type-id='eaa32e2f'/>
<parameter type-id='b59d7dce'/>
<return type-id='79a0948f'/>
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/getexecname.c' language='LANG_C99'>
<function-decl name='getexecname' mangled-name='getexecname' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='getexecname'>
<return type-id='80f4b756'/>
@ -594,14 +632,11 @@
<var-decl name='prev' type-id='b03eadb4' visibility='default'/>
</data-member>
</class-decl>
<class-decl name='list' size-in-bits='256' is-struct='yes' visibility='default' id='e824dae9'>
<class-decl name='list' size-in-bits='192' is-struct='yes' visibility='default' id='e824dae9'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='list_size' type-id='b59d7dce' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='list_offset' type-id='b59d7dce' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='128'>
<data-member access='public' layout-offset-in-bits='64'>
<var-decl name='list_head' type-id='b0b5e45e' visibility='default'/>
</data-member>
</class-decl>
@ -770,6 +805,13 @@
</function-decl>
</abi-instr>
<abi-instr address-size='64' path='lib/libspl/os/linux/getmntany.c' language='LANG_C99'>
<array-type-def dimensions='1' type-id='38b51b3c' size-in-bits='832' id='02b72c00'>
<subrange length='13' type-id='7359adad' id='487fded1'/>
</array-type-def>
<class-decl name='__locale_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='23de8b96'/>
<array-type-def dimensions='1' type-id='80f4b756' size-in-bits='832' id='39e6f84a'>
<subrange length='13' type-id='7359adad' id='487fded1'/>
</array-type-def>
<class-decl name='mnttab' size-in-bits='256' is-struct='yes' visibility='default' id='1b055409'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='mnt_special' type-id='26a90f95' visibility='default'/>
@ -873,12 +915,42 @@
</class-decl>
<typedef-decl name='__ino64_t' type-id='7359adad' id='71288a47'/>
<typedef-decl name='__blkcnt64_t' type-id='bd54fe1a' id='4e711bf1'/>
<class-decl name='__locale_struct' size-in-bits='1856' is-struct='yes' visibility='default' id='90cc1ce3'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='__locales' type-id='02b72c00' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='832'>
<var-decl name='__ctype_b' type-id='31347b7a' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='896'>
<var-decl name='__ctype_tolower' type-id='6d60f45d' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='960'>
<var-decl name='__ctype_toupper' type-id='6d60f45d' visibility='default'/>
</data-member>
<data-member access='public' layout-offset-in-bits='1024'>
<var-decl name='__names' type-id='39e6f84a' visibility='default'/>
</data-member>
</class-decl>
<typedef-decl name='__locale_t' type-id='f01e1813' id='b7ac9b5f'/>
<typedef-decl name='locale_t' type-id='b7ac9b5f' id='973a4f8d'/>
<pointer-type-def type-id='23de8b96' size-in-bits='64' id='38b51b3c'/>
<pointer-type-def type-id='90cc1ce3' size-in-bits='64' id='f01e1813'/>
<qualified-type-def type-id='95e97e5e' const='yes' id='2448a865'/>
<pointer-type-def type-id='2448a865' size-in-bits='64' id='6d60f45d'/>
<qualified-type-def type-id='8efea9e5' const='yes' id='3beb2af4'/>
<pointer-type-def type-id='3beb2af4' size-in-bits='64' id='31347b7a'/>
<pointer-type-def type-id='0c544dc0' size-in-bits='64' id='394fc496'/>
<pointer-type-def type-id='56fe4a37' size-in-bits='64' id='b6b61d2f'/>
<qualified-type-def type-id='b6b61d2f' restrict='yes' id='3cad23cd'/>
<pointer-type-def type-id='1b055409' size-in-bits='64' id='9d424d31'/>
<pointer-type-def type-id='0bbec9cd' size-in-bits='64' id='62f7a03d'/>
<qualified-type-def type-id='62f7a03d' restrict='yes' id='f1cadedf'/>
<class-decl name='__locale_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='23de8b96'/>
<function-decl name='uselocale' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='973a4f8d'/>
<return type-id='973a4f8d'/>
</function-decl>
<function-decl name='getmntent_r' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='e75a27e9'/>
<parameter type-id='3cad23cd'/>
@ -895,8 +967,9 @@
<parameter type-id='80f4b756'/>
<return type-id='95e97e5e'/>
</function-decl>
<function-decl name='strerror' visibility='default' binding='global' size-in-bits='64'>
<function-decl name='strerror_l' visibility='default' binding='global' size-in-bits='64'>
<parameter type-id='95e97e5e'/>
<parameter type-id='973a4f8d'/>
<return type-id='26a90f95'/>
</function-decl>
<function-decl name='__fprintf_chk' visibility='default' binding='global' size-in-bits='64'>
@ -1119,7 +1192,7 @@
<enumerator name='LZC_SEND_FLAG_RAW' value='8'/>
<enumerator name='LZC_SEND_FLAG_SAVED' value='16'/>
</enum-decl>
<class-decl name='ddt_key' size-in-bits='320' is-struct='yes' visibility='default' id='e0a4a1cb'>
<class-decl name='ddt_key_t' size-in-bits='320' is-struct='yes' naming-typedef-id='67f6d2cf' visibility='default' id='5fae1718'>
<data-member access='public' layout-offset-in-bits='0'>
<var-decl name='ddk_cksum' type-id='39730d0b' visibility='default'/>
</data-member>
@ -1127,7 +1200,7 @@
<var-decl name='ddk_prop' type-id='9c313c2d' visibility='default'/>
</data-member>
</class-decl>
<typedef-decl name='ddt_key_t' type-id='e0a4a1cb' id='67f6d2cf'/>
<typedef-decl name='ddt_key_t' type-id='5fae1718' id='67f6d2cf'/>
<enum-decl name='dmu_object_type' id='04b3b0b9'>
<underlying-type type-id='9cac1fee'/>
<enumerator name='DMU_OT_NONE' value='0'/>

View File

@ -906,6 +906,13 @@ Historically used for controlling what reporting was available under
.Pa /proc/spl/kstat/zfs .
No effect.
.
.It Sy zfs_deadman_checktime_ms Ns = Ns Sy 60000 Ns ms Po 1 min Pc Pq u64
Check time in milliseconds.
This defines the frequency at which we check for hung I/O requests
and potentially invoke the
.Sy zfs_deadman_failmode
behavior.
.
.It Sy zfs_deadman_enabled Ns = Ns Sy 1 Ns | Ns 0 Pq int
When a pool sync operation takes longer than
.Sy zfs_deadman_synctime_ms ,
@ -921,6 +928,10 @@ By default, the deadman is enabled and set to
which results in "hung" I/O operations only being logged.
The deadman is automatically disabled when a pool gets suspended.
.
.It Sy zfs_deadman_events_per_second Ns = Ns Sy 1 Ns /s Pq int
Rate limit deadman zevents (which report hung I/O operations) to this many per
second.
.
.It Sy zfs_deadman_failmode Ns = Ns Sy wait Pq charp
Controls the failure behavior when the deadman detects a "hung" I/O operation.
Valid values are:
@ -938,13 +949,6 @@ This can be used to facilitate automatic fail-over
to a properly configured fail-over partner.
.El
.
.It Sy zfs_deadman_checktime_ms Ns = Ns Sy 60000 Ns ms Po 1 min Pc Pq u64
Check time in milliseconds.
This defines the frequency at which we check for hung I/O requests
and potentially invoke the
.Sy zfs_deadman_failmode
behavior.
.
.It Sy zfs_deadman_synctime_ms Ns = Ns Sy 600000 Ns ms Po 10 min Pc Pq u64
Interval in milliseconds after which the deadman is triggered and also
the interval after which a pool sync operation is considered to be "hung".
@ -1002,8 +1006,7 @@ will result in objects waiting when there is not actually contention on the
same object.
.
.It Sy zfs_slow_io_events_per_second Ns = Ns Sy 20 Ns /s Pq int
Rate limit delay and deadman zevents (which report slow I/O operations) to this
many per
Rate limit delay zevents (which report slow I/O operations) to this many per
second.
.
.It Sy zfs_unflushed_max_mem_amt Ns = Ns Sy 1073741824 Ns B Po 1 GiB Pc Pq u64
@ -2367,7 +2370,7 @@ This is an advanced debugging parameter.
Don't change this unless you understand what it does.
Set values only apply to pools imported/created after that.
.
.It Sy zio_taskq_write Ns = Ns Sy sync fixed,1,5 scale fixed,1,5 Pq charp
.It Sy zio_taskq_write Ns = Ns Sy sync null scale null Pq charp
Set the queue and thread configuration for the IO write queues.
This is an advanced debugging parameter.
Don't change this unless you understand what it does.

View File

@ -832,12 +832,14 @@ aes_encrypt_atomic(crypto_mechanism_t *mechanism,
crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext,
crypto_spi_ctx_template_t template)
{
aes_ctx_t aes_ctx = {{{{0}}}};
aes_ctx_t aes_ctx;
off_t saved_offset;
size_t saved_length;
size_t length_needed;
int ret;
memset(&aes_ctx, 0, sizeof (aes_ctx_t));
ASSERT(ciphertext != NULL);
/*
@ -956,12 +958,14 @@ aes_decrypt_atomic(crypto_mechanism_t *mechanism,
crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext,
crypto_spi_ctx_template_t template)
{
aes_ctx_t aes_ctx = {{{{0}}}};
aes_ctx_t aes_ctx;
off_t saved_offset;
size_t saved_length;
size_t length_needed;
int ret;
memset(&aes_ctx, 0, sizeof (aes_ctx_t));
ASSERT(plaintext != NULL);
/*

View File

@ -37,6 +37,9 @@
#include <sys/zfs_context.h>
static struct opensolaris_utsname hw_utsname = {
.sysname = ostype,
.nodename = prison0.pr_hostname,
.release = osrelease,
.machine = MACHINE
};
@ -49,10 +52,6 @@ utsname(void)
static void
opensolaris_utsname_init(void *arg)
{
hw_utsname.sysname = ostype;
hw_utsname.nodename = prison0.pr_hostname;
hw_utsname.release = osrelease;
snprintf(hw_utsname.version, sizeof (hw_utsname.version),
"%d", osreldate);
}

View File

@ -457,7 +457,7 @@ vdev_geom_read_config(struct g_consumer *cp, nvlist_t **configp)
ZFS_LOG(1, "Reading config from %s...", pp->name);
psize = pp->mediasize;
psize = P2ALIGN(psize, (uint64_t)sizeof (vdev_label_t));
psize = P2ALIGN_TYPED(psize, sizeof (vdev_label_t), uint64_t);
size = sizeof (*vdev_lists[0]) + pp->sectorsize -
((sizeof (*vdev_lists[0]) - 1) % pp->sectorsize) - 1;

View File

@ -232,15 +232,30 @@ __dprintf(boolean_t dprint, const char *file, const char *func,
#else
void
zfs_dbgmsg_print(const char *tag)
zfs_dbgmsg_print(int fd, const char *tag)
{
zfs_dbgmsg_t *zdm;
ssize_t ret __attribute__((unused));
/*
* We use write() in this function instead of printf()
* so it is safe to call from a signal handler.
*/
ret = write(fd, "ZFS_DBGMSG(", 11);
ret = write(fd, tag, strlen(tag));
ret = write(fd, ") START:\n", 9);
(void) printf("ZFS_DBGMSG(%s):\n", tag);
mutex_enter(&zfs_dbgmsgs_lock);
for (zdm = list_head(&zfs_dbgmsgs); zdm;
for (zfs_dbgmsg_t *zdm = list_head(&zfs_dbgmsgs); zdm != NULL;
zdm = list_next(&zfs_dbgmsgs, zdm))
(void) printf("%s\n", zdm->zdm_msg);
ret = write(fd, zdm->zdm_msg, strlen(zdm->zdm_msg));
ret = write(fd, "\n", 1);
}
ret = write(fd, "ZFS_DBGMSG(", 11);
ret = write(fd, tag, strlen(tag));
ret = write(fd, ") END\n", 6);
mutex_exit(&zfs_dbgmsgs_lock);
}
#endif /* _KERNEL */

View File

@ -543,6 +543,7 @@ zfs_rmnode(znode_t *zp)
dataset_kstats_update_nunlinked_kstat(&zfsvfs->z_kstat, 1);
zfs_znode_delete(zp, tx);
zfs_znode_free(zp);
dmu_tx_commit(tx);

View File

@ -1175,10 +1175,25 @@ zfs_create(znode_t *dzp, const char *name, vattr_t *vap, int excl, int mode,
return (error);
}
zfs_mknode(dzp, vap, tx, cr, 0, &zp, &acl_ids);
error = zfs_link_create(dzp, name, zp, tx, ZNEW);
if (error != 0) {
/*
* Since, we failed to add the directory entry for it,
* delete the newly created dnode.
*/
zfs_znode_delete(zp, tx);
VOP_UNLOCK1(ZTOV(zp));
zrele(zp);
zfs_acl_ids_free(&acl_ids);
dmu_tx_commit(tx);
getnewvnode_drop_reserve();
goto out;
}
if (fuid_dirtied)
zfs_fuid_sync(zfsvfs, tx);
(void) zfs_link_create(dzp, name, zp, tx, ZNEW);
txtype = zfs_log_create_txtype(Z_FILE, vsecp, vap);
zfs_log_create(zilog, tx, txtype, dzp, zp, name,
vsecp, acl_ids.z_fuidp, vap);
@ -1526,13 +1541,19 @@ zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp,
*/
zfs_mknode(dzp, vap, tx, cr, 0, &zp, &acl_ids);
if (fuid_dirtied)
zfs_fuid_sync(zfsvfs, tx);
/*
* Now put new name in parent dir.
*/
(void) zfs_link_create(dzp, dirname, zp, tx, ZNEW);
error = zfs_link_create(dzp, dirname, zp, tx, ZNEW);
if (error != 0) {
zfs_znode_delete(zp, tx);
VOP_UNLOCK1(ZTOV(zp));
zrele(zp);
goto out;
}
if (fuid_dirtied)
zfs_fuid_sync(zfsvfs, tx);
*zpp = zp;
@ -1540,6 +1561,7 @@ zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp,
zfs_log_create(zilog, tx, txtype, dzp, zp, dirname, NULL,
acl_ids.z_fuidp, vap);
out:
zfs_acl_ids_free(&acl_ids);
dmu_tx_commit(tx);
@ -1550,7 +1572,7 @@ zfs_mkdir(znode_t *dzp, const char *dirname, vattr_t *vap, znode_t **zpp,
zil_commit(zilog, 0);
zfs_exit(zfsvfs, FTAG);
return (0);
return (error);
}
#if __FreeBSD_version < 1300124
@ -3586,10 +3608,14 @@ zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap,
/*
* Insert the new object into the directory.
*/
(void) zfs_link_create(dzp, name, zp, tx, ZNEW);
zfs_log_symlink(zilog, tx, txtype, dzp, zp, name, link);
*zpp = zp;
error = zfs_link_create(dzp, name, zp, tx, ZNEW);
if (error != 0) {
zfs_znode_delete(zp, tx);
VOP_UNLOCK1(ZTOV(zp));
zrele(zp);
} else {
zfs_log_symlink(zilog, tx, txtype, dzp, zp, name, link);
}
zfs_acl_ids_free(&acl_ids);
@ -3597,8 +3623,12 @@ zfs_symlink(znode_t *dzp, const char *name, vattr_t *vap,
getnewvnode_drop_reserve();
if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
zil_commit(zilog, 0);
if (error == 0) {
*zpp = zp;
if (zfsvfs->z_os->os_sync == ZFS_SYNC_ALWAYS)
zil_commit(zilog, 0);
}
zfs_exit(zfsvfs, FTAG);
return (error);

View File

@ -1234,7 +1234,6 @@ zfs_znode_delete(znode_t *zp, dmu_tx_t *tx)
VERIFY0(dmu_object_free(os, obj, tx));
zfs_znode_dmu_fini(zp);
ZFS_OBJ_HOLD_EXIT(zfsvfs, obj);
zfs_znode_free(zp);
}
void

View File

@ -234,7 +234,7 @@ procfs_list_install(const char *module,
modulestr = kmem_asprintf("%s/%s", module, submodule);
else
modulestr = kmem_asprintf("%s", module);
mutex_init(&procfs_list->pl_lock, NULL, MUTEX_DEFAULT, NULL);
mutex_init(&procfs_list->pl_lock, NULL, MUTEX_NOLOCKDEP, NULL);
list_create(&procfs_list->pl_list,
procfs_list_node_off + sizeof (procfs_list_node_t),
procfs_list_node_off + offsetof(procfs_list_node_t, pln_link));

View File

@ -158,7 +158,7 @@ task_alloc(taskq_t *tq, uint_t flags, unsigned long *irqflags)
* throttling the task dispatch rate.
*/
spin_unlock_irqrestore(&tq->tq_lock, *irqflags);
schedule_timeout(HZ / 100);
schedule_timeout_interruptible(HZ / 100);
spin_lock_irqsave_nested(&tq->tq_lock, *irqflags,
tq->tq_lock_class);
if (count < 100) {

View File

@ -152,26 +152,16 @@ spl_kthread_create(int (*func)(void *), void *data, const char namefmt[], ...)
EXPORT_SYMBOL(spl_kthread_create);
/*
* The "why" argument indicates the allowable side-effects of the call:
*
* FORREAL: Extract the next pending signal from p_sig into p_cursig;
* stop the process if a stop has been requested or if a traced signal
* is pending.
*
* JUSTLOOKING: Don't stop the process, just indicate whether or not
* a signal might be pending (FORREAL is needed to tell for sure).
* Extract the next pending signal from p_sig into p_cursig; stop the process
* if a stop has been requested or if a traced signal is pending.
*/
int
issig(int why)
issig(void)
{
ASSERT(why == FORREAL || why == JUSTLOOKING);
if (!signal_pending(current))
return (0);
if (why != FORREAL)
return (1);
struct task_struct *task = current;
spl_kernel_siginfo_t __info;
sigset_t set;

View File

@ -397,7 +397,7 @@ vdev_disk_open(vdev_t *v, uint64_t *psize, uint64_t *max_psize,
if (v->vdev_removed)
break;
schedule_timeout(MSEC_TO_TICK(10));
schedule_timeout_interruptible(MSEC_TO_TICK(10));
} else if (unlikely(BDH_PTR_ERR(bdh) == -ERESTARTSYS)) {
timeout = MSEC2NSEC(zfs_vdev_open_timeout_ms * 10);
continue;

View File

@ -221,29 +221,29 @@ __dprintf(boolean_t dprint, const char *file, const char *func,
#else
void
zfs_dbgmsg_print(const char *tag)
zfs_dbgmsg_print(int fd, const char *tag)
{
ssize_t ret __attribute__((unused));
mutex_enter(&zfs_dbgmsgs.pl_lock);
/*
* We use write() in this function instead of printf()
* so it is safe to call from a signal handler.
*/
ret = write(STDOUT_FILENO, "ZFS_DBGMSG(", 11);
ret = write(STDOUT_FILENO, tag, strlen(tag));
ret = write(STDOUT_FILENO, ") START:\n", 9);
ret = write(fd, "ZFS_DBGMSG(", 11);
ret = write(fd, tag, strlen(tag));
ret = write(fd, ") START:\n", 9);
mutex_enter(&zfs_dbgmsgs.pl_lock);
for (zfs_dbgmsg_t *zdm = list_head(&zfs_dbgmsgs.pl_list); zdm != NULL;
zdm = list_next(&zfs_dbgmsgs.pl_list, zdm)) {
ret = write(STDOUT_FILENO, zdm->zdm_msg,
strlen(zdm->zdm_msg));
ret = write(STDOUT_FILENO, "\n", 1);
ret = write(fd, zdm->zdm_msg, strlen(zdm->zdm_msg));
ret = write(fd, "\n", 1);
}
ret = write(STDOUT_FILENO, "ZFS_DBGMSG(", 11);
ret = write(STDOUT_FILENO, tag, strlen(tag));
ret = write(STDOUT_FILENO, ") END\n", 6);
ret = write(fd, "ZFS_DBGMSG(", 11);
ret = write(fd, tag, strlen(tag));
ret = write(fd, ") END\n", 6);
mutex_exit(&zfs_dbgmsgs.pl_lock);
}

View File

@ -384,7 +384,7 @@ zvol_discard(zv_request_t *zvr)
*/
if (!io_is_secure_erase(bio, rq)) {
start = P2ROUNDUP(start, zv->zv_volblocksize);
end = P2ALIGN(end, zv->zv_volblocksize);
end = P2ALIGN_TYPED(end, zv->zv_volblocksize, uint64_t);
size = end - start;
}
@ -798,7 +798,8 @@ zvol_open(struct block_device *bdev, fmode_t flag)
if ((gethrtime() - start) > timeout)
return (SET_ERROR(-ERESTARTSYS));
schedule_timeout(MSEC_TO_TICK(10));
schedule_timeout_interruptible(
MSEC_TO_TICK(10));
goto retry;
#endif
} else {

View File

@ -471,7 +471,8 @@ fletcher_4_native(const void *buf, uint64_t size,
const void *ctx_template, zio_cksum_t *zcp)
{
(void) ctx_template;
const uint64_t p2size = P2ALIGN(size, FLETCHER_MIN_SIMD_SIZE);
const uint64_t p2size = P2ALIGN_TYPED(size, FLETCHER_MIN_SIMD_SIZE,
uint64_t);
ASSERT(IS_P2ALIGNED(size, sizeof (uint32_t)));
@ -519,7 +520,8 @@ fletcher_4_byteswap(const void *buf, uint64_t size,
const void *ctx_template, zio_cksum_t *zcp)
{
(void) ctx_template;
const uint64_t p2size = P2ALIGN(size, FLETCHER_MIN_SIMD_SIZE);
const uint64_t p2size = P2ALIGN_TYPED(size, FLETCHER_MIN_SIMD_SIZE,
uint64_t);
ASSERT(IS_P2ALIGNED(size, sizeof (uint32_t)));
@ -878,7 +880,7 @@ abd_fletcher_4_iter(void *data, size_t size, void *private)
fletcher_4_ctx_t *ctx = cdp->acd_ctx;
fletcher_4_ops_t *ops = (fletcher_4_ops_t *)cdp->acd_private;
boolean_t native = cdp->acd_byteorder == ZIO_CHECKSUM_NATIVE;
uint64_t asize = P2ALIGN(size, FLETCHER_MIN_SIMD_SIZE);
uint64_t asize = P2ALIGN_TYPED(size, FLETCHER_MIN_SIMD_SIZE, uint64_t);
ASSERT(IS_P2ALIGNED(size, sizeof (uint32_t)));

View File

@ -8143,11 +8143,11 @@ l2arc_dev_get_next(void)
ASSERT3P(next, !=, NULL);
} while (vdev_is_dead(next->l2ad_vdev) || next->l2ad_rebuild ||
next->l2ad_trim_all);
next->l2ad_trim_all || next->l2ad_spa->spa_is_exporting);
/* if we were unable to find any usable vdevs, return NULL */
if (vdev_is_dead(next->l2ad_vdev) || next->l2ad_rebuild ||
next->l2ad_trim_all)
next->l2ad_trim_all || next->l2ad_spa->spa_is_exporting)
next = NULL;
l2arc_dev_last = next;
@ -8886,7 +8886,7 @@ l2arc_evict(l2arc_dev_t *dev, uint64_t distance, boolean_t all)
* assertions may be violated without functional consequences
* as the device is about to be removed.
*/
ASSERT3U(dev->l2ad_hand + distance, <, dev->l2ad_end);
ASSERT3U(dev->l2ad_hand + distance, <=, dev->l2ad_end);
if (!dev->l2ad_first)
ASSERT3U(dev->l2ad_hand, <=, dev->l2ad_evict);
}

View File

@ -218,7 +218,7 @@ zfs_btree_create_custom(zfs_btree_t *tree,
zfs_btree_find_in_buf : bt_find_in_buf;
tree->bt_elem_size = size;
tree->bt_leaf_size = lsize;
tree->bt_leaf_cap = P2ALIGN(esize / size, 2);
tree->bt_leaf_cap = P2ALIGN_TYPED(esize / size, 2, size_t);
tree->bt_height = -1;
tree->bt_bulk = NULL;
}

View File

@ -292,8 +292,8 @@ dbuf_cons(void *vdb, void *unused, int kmflag)
dmu_buf_impl_t *db = vdb;
memset(db, 0, sizeof (dmu_buf_impl_t));
mutex_init(&db->db_mtx, NULL, MUTEX_DEFAULT, NULL);
rw_init(&db->db_rwlock, NULL, RW_DEFAULT, NULL);
mutex_init(&db->db_mtx, NULL, MUTEX_NOLOCKDEP, NULL);
rw_init(&db->db_rwlock, NULL, RW_NOLOCKDEP, NULL);
cv_init(&db->db_changed, NULL, CV_DEFAULT, NULL);
multilist_link_init(&db->db_cache_link);
zfs_refcount_create(&db->db_holds);
@ -578,7 +578,7 @@ dbuf_evict_user(dmu_buf_impl_t *db)
*/
uint64_t size = dbu->dbu_size;
(void) zfs_refcount_remove_many(
&dbuf_caches[db->db_caching_status].size, size, db);
&dbuf_caches[db->db_caching_status].size, size, dbu);
if (db->db_caching_status == DB_DBUF_CACHE)
DBUF_STAT_DECR(cache_levels_bytes[db->db_level], size);
}
@ -784,12 +784,15 @@ dbuf_evict_one(void)
if (db != NULL) {
multilist_sublist_remove(mls, db);
multilist_sublist_unlock(mls);
uint64_t size = db->db.db_size + dmu_buf_user_size(&db->db);
uint64_t size = db->db.db_size;
uint64_t usize = dmu_buf_user_size(&db->db);
(void) zfs_refcount_remove_many(
&dbuf_caches[DB_DBUF_CACHE].size, size, db);
(void) zfs_refcount_remove_many(
&dbuf_caches[DB_DBUF_CACHE].size, usize, db->db_user);
DBUF_STAT_BUMPDOWN(cache_levels[db->db_level]);
DBUF_STAT_BUMPDOWN(cache_count);
DBUF_STAT_DECR(cache_levels_bytes[db->db_level], size);
DBUF_STAT_DECR(cache_levels_bytes[db->db_level], size + usize);
ASSERT3U(db->db_caching_status, ==, DB_DBUF_CACHE);
db->db_caching_status = DB_NO_CACHE;
dbuf_destroy(db);
@ -958,7 +961,7 @@ dbuf_init(void)
0, dbuf_cons, dbuf_dest, NULL, NULL, NULL, 0);
for (int i = 0; i < hmsize; i++)
mutex_init(&h->hash_mutexes[i], NULL, MUTEX_DEFAULT, NULL);
mutex_init(&h->hash_mutexes[i], NULL, MUTEX_NOLOCKDEP, NULL);
dbuf_stats_init(h);
@ -2850,6 +2853,7 @@ dmu_buf_fill_done(dmu_buf_t *dbuf, dmu_tx_t *tx, boolean_t failed)
failed = B_FALSE;
} else if (failed) {
VERIFY(!dbuf_undirty(db, tx));
arc_buf_destroy(db->db_buf, db);
db->db_buf = NULL;
dbuf_clear_data(db);
DTRACE_SET_STATE(db, "fill failed");
@ -3794,16 +3798,21 @@ dbuf_hold_impl(dnode_t *dn, uint8_t level, uint64_t blkid,
multilist_remove(&dbuf_caches[db->db_caching_status].cache, db);
uint64_t size = db->db.db_size + dmu_buf_user_size(&db->db);
uint64_t size = db->db.db_size;
uint64_t usize = dmu_buf_user_size(&db->db);
(void) zfs_refcount_remove_many(
&dbuf_caches[db->db_caching_status].size, size, db);
(void) zfs_refcount_remove_many(
&dbuf_caches[db->db_caching_status].size, usize,
db->db_user);
if (db->db_caching_status == DB_DBUF_METADATA_CACHE) {
DBUF_STAT_BUMPDOWN(metadata_cache_count);
} else {
DBUF_STAT_BUMPDOWN(cache_levels[db->db_level]);
DBUF_STAT_BUMPDOWN(cache_count);
DBUF_STAT_DECR(cache_levels_bytes[db->db_level], size);
DBUF_STAT_DECR(cache_levels_bytes[db->db_level],
size + usize);
}
db->db_caching_status = DB_NO_CACHE;
}
@ -4022,10 +4031,12 @@ dbuf_rele_and_unlock(dmu_buf_impl_t *db, const void *tag, boolean_t evicting)
db->db_caching_status = dcs;
multilist_insert(&dbuf_caches[dcs].cache, db);
uint64_t db_size = db->db.db_size +
dmu_buf_user_size(&db->db);
size = zfs_refcount_add_many(
uint64_t db_size = db->db.db_size;
uint64_t dbu_size = dmu_buf_user_size(&db->db);
(void) zfs_refcount_add_many(
&dbuf_caches[dcs].size, db_size, db);
size = zfs_refcount_add_many(
&dbuf_caches[dcs].size, dbu_size, db->db_user);
uint8_t db_level = db->db_level;
mutex_exit(&db->db_mtx);
@ -4038,7 +4049,7 @@ dbuf_rele_and_unlock(dmu_buf_impl_t *db, const void *tag, boolean_t evicting)
DBUF_STAT_MAX(cache_size_bytes_max, size);
DBUF_STAT_BUMP(cache_levels[db_level]);
DBUF_STAT_INCR(cache_levels_bytes[db_level],
db_size);
db_size + dbu_size);
}
if (dcs == DB_DBUF_CACHE && !evicting)

View File

@ -537,7 +537,8 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length,
if (dn->dn_datablkshift) {
int blkshift = dn->dn_datablkshift;
nblks = (P2ROUNDUP(offset + length, 1ULL << blkshift) -
P2ALIGN(offset, 1ULL << blkshift)) >> blkshift;
P2ALIGN_TYPED(offset, 1ULL << blkshift, uint64_t))
>> blkshift;
} else {
if (offset + length > dn->dn_datablksz) {
zfs_panic_recover("zfs: accessing past end of object "
@ -854,7 +855,7 @@ get_next_chunk(dnode_t *dn, uint64_t *start, uint64_t minimum, uint64_t *l1blks)
}
/* set start to the beginning of this L1 indirect */
*start = P2ALIGN(*start, iblkrange);
*start = P2ALIGN_TYPED(*start, iblkrange, uint64_t);
}
if (*start < minimum)
*start = minimum;

View File

@ -116,7 +116,7 @@ diff_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
dmu_diffarg_t *da = arg;
int err = 0;
if (issig(JUSTLOOKING) && issig(FORREAL))
if (issig())
return (SET_ERROR(EINTR));
if (zb->zb_level == ZB_DNODE_LEVEL ||

View File

@ -160,7 +160,7 @@ dmu_object_alloc_impl(objset_t *os, dmu_object_type_t ot, int blocksize,
* is not suitably aligned.
*/
os->os_obj_next_chunk =
P2ALIGN(object, dnodes_per_chunk) +
P2ALIGN_TYPED(object, dnodes_per_chunk, uint64_t) +
dnodes_per_chunk;
(void) atomic_swap_64(cpuobj, object);
mutex_exit(&os->os_obj_lock);

View File

@ -2437,7 +2437,7 @@ dmu_objset_space_upgrade(objset_t *os)
if (err != 0)
return (err);
if (issig(JUSTLOOKING) && issig(FORREAL))
if (issig())
return (SET_ERROR(EINTR));
objerr = dmu_bonus_hold(os, obj, FTAG, &db);

View File

@ -3389,7 +3389,7 @@ dmu_recv_stream(dmu_recv_cookie_t *drc, offset_t *voffp)
* stream, then we free drc->drc_rrd and exit.
*/
while (rwa->err == 0) {
if (issig(JUSTLOOKING) && issig(FORREAL)) {
if (issig()) {
err = SET_ERROR(EINTR);
break;
}

View File

@ -912,7 +912,7 @@ perform_redaction(objset_t *os, redaction_list_t *rl,
object = prev_obj;
}
while (err == 0 && object <= rec->end_object) {
if (issig(JUSTLOOKING) && issig(FORREAL)) {
if (issig()) {
err = EINTR;
break;
}

View File

@ -2552,7 +2552,7 @@ dmu_send_impl(struct dmu_send_params *dspp)
while (err == 0 && !range->eos_marker) {
err = do_dump(&dsc, range);
range = get_next_range(&srt_arg->q, range);
if (issig(JUSTLOOKING) && issig(FORREAL))
if (issig())
err = SET_ERROR(EINTR);
}

View File

@ -627,8 +627,8 @@ metaslab_class_expandable_space(metaslab_class_t *mc)
* metaslabs. We report the expandable space in terms
* of the metaslab size since that's the unit of expansion.
*/
space += P2ALIGN(tvd->vdev_max_asize - tvd->vdev_asize,
1ULL << tvd->vdev_ms_shift);
space += P2ALIGN_TYPED(tvd->vdev_max_asize - tvd->vdev_asize,
1ULL << tvd->vdev_ms_shift, uint64_t);
}
spa_config_exit(mc->mc_spa, SCL_VDEV, FTAG);
return (space);
@ -638,6 +638,7 @@ void
metaslab_class_evict_old(metaslab_class_t *mc, uint64_t txg)
{
multilist_t *ml = &mc->mc_metaslab_txg_list;
hrtime_t now = gethrtime();
for (int i = 0; i < multilist_get_num_sublists(ml); i++) {
multilist_sublist_t *mls = multilist_sublist_lock_idx(ml, i);
metaslab_t *msp = multilist_sublist_head(mls);
@ -661,8 +662,10 @@ metaslab_class_evict_old(metaslab_class_t *mc, uint64_t txg)
multilist_sublist_unlock(mls);
if (txg >
msp->ms_selected_txg + metaslab_unload_delay &&
gethrtime() > msp->ms_selected_time +
(uint64_t)MSEC2NSEC(metaslab_unload_delay_ms)) {
now > msp->ms_selected_time +
MSEC2NSEC(metaslab_unload_delay_ms) &&
(msp->ms_allocator == -1 ||
!metaslab_preload_enabled)) {
metaslab_evict(msp, txg);
} else {
/*

View File

@ -34,6 +34,7 @@
* Copyright (c) 2017, Intel Corporation.
* Copyright (c) 2021, Colm Buckley <colm@tuatha.org>
* Copyright (c) 2023 Hewlett Packard Enterprise Development LP.
* Copyright (c) 2024, Klara Inc.
*/
/*
@ -170,14 +171,19 @@ static const char *const zio_taskq_types[ZIO_TASKQ_TYPES] = {
* that scales with the number of CPUs.
*
* The different taskq priorities are to handle the different contexts (issue
* and interrupt) and then to reserve threads for ZIO_PRIORITY_NOW I/Os that
* need to be handled with minimum delay.
* and interrupt) and then to reserve threads for high priority I/Os that
* need to be handled with minimum delay. Illumos taskq has unfair TQ_FRONT
* implementation, so separate high priority threads are used there.
*/
static zio_taskq_info_t zio_taskqs[ZIO_TYPES][ZIO_TASKQ_TYPES] = {
/* ISSUE ISSUE_HIGH INTR INTR_HIGH */
{ ZTI_ONE, ZTI_NULL, ZTI_ONE, ZTI_NULL }, /* NULL */
{ ZTI_N(8), ZTI_NULL, ZTI_SCALE, ZTI_NULL }, /* READ */
#ifdef illumos
{ ZTI_SYNC, ZTI_N(5), ZTI_SCALE, ZTI_N(5) }, /* WRITE */
#else
{ ZTI_SYNC, ZTI_NULL, ZTI_SCALE, ZTI_NULL }, /* WRITE */
#endif
{ ZTI_SCALE, ZTI_NULL, ZTI_ONE, ZTI_NULL }, /* FREE */
{ ZTI_ONE, ZTI_NULL, ZTI_ONE, ZTI_NULL }, /* CLAIM */
{ ZTI_ONE, ZTI_NULL, ZTI_ONE, ZTI_NULL }, /* FLUSH */
@ -1217,7 +1223,7 @@ spa_taskqs_fini(spa_t *spa, zio_type_t t, zio_taskq_type_t q)
*
* Example (the defaults for READ and WRITE)
* zio_taskq_read='fixed,1,8 null scale null'
* zio_taskq_write='sync fixed,1,5 scale fixed,1,5'
* zio_taskq_write='sync null scale null'
*
* Each sets the entire row at a time.
*
@ -1484,9 +1490,9 @@ spa_taskq_write_param(ZFS_MODULE_PARAM_ARGS)
* Note that a type may have multiple discrete taskqs to avoid lock contention
* on the taskq itself.
*/
static taskq_t *
spa_taskq_dispatch_select(spa_t *spa, zio_type_t t, zio_taskq_type_t q,
zio_t *zio)
void
spa_taskq_dispatch(spa_t *spa, zio_type_t t, zio_taskq_type_t q,
task_func_t *func, zio_t *zio, boolean_t cutinline)
{
spa_taskqs_t *tqs = &spa->spa_zio_taskq[t][q];
taskq_t *tq;
@ -1494,37 +1500,25 @@ spa_taskq_dispatch_select(spa_t *spa, zio_type_t t, zio_taskq_type_t q,
ASSERT3P(tqs->stqs_taskq, !=, NULL);
ASSERT3U(tqs->stqs_count, !=, 0);
/*
* NB: We are assuming that the zio can only be dispatched
* to a single taskq at a time. It would be a grievous error
* to dispatch the zio to another taskq at the same time.
*/
ASSERT(zio);
ASSERT(taskq_empty_ent(&zio->io_tqent));
if (tqs->stqs_count == 1) {
tq = tqs->stqs_taskq[0];
} else if ((t == ZIO_TYPE_WRITE) && (q == ZIO_TASKQ_ISSUE) &&
(zio != NULL) && ZIO_HAS_ALLOCATOR(zio)) {
ZIO_HAS_ALLOCATOR(zio)) {
tq = tqs->stqs_taskq[zio->io_allocator % tqs->stqs_count];
} else {
tq = tqs->stqs_taskq[((uint64_t)gethrtime()) % tqs->stqs_count];
}
return (tq);
}
void
spa_taskq_dispatch_ent(spa_t *spa, zio_type_t t, zio_taskq_type_t q,
task_func_t *func, void *arg, uint_t flags, taskq_ent_t *ent,
zio_t *zio)
{
taskq_t *tq = spa_taskq_dispatch_select(spa, t, q, zio);
taskq_dispatch_ent(tq, func, arg, flags, ent);
}
/*
* Same as spa_taskq_dispatch_ent() but block on the task until completion.
*/
void
spa_taskq_dispatch_sync(spa_t *spa, zio_type_t t, zio_taskq_type_t q,
task_func_t *func, void *arg, uint_t flags)
{
taskq_t *tq = spa_taskq_dispatch_select(spa, t, q, NULL);
taskqid_t id = taskq_dispatch(tq, func, arg, flags);
if (id)
taskq_wait_id(tq, id);
taskq_dispatch_ent(tq, func, zio, cutinline ? TQ_FRONT : 0,
&zio->io_tqent);
}
static void
@ -1986,7 +1980,8 @@ spa_destroy_aux_threads(spa_t *spa)
static void
spa_unload(spa_t *spa)
{
ASSERT(MUTEX_HELD(&spa_namespace_lock));
ASSERT(MUTEX_HELD(&spa_namespace_lock) ||
spa->spa_export_thread == curthread);
ASSERT(spa_state(spa) != POOL_STATE_UNINITIALIZED);
spa_import_progress_remove(spa_guid(spa));
@ -6950,7 +6945,7 @@ static int
spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig,
boolean_t force, boolean_t hardforce)
{
int error;
int error = 0;
spa_t *spa;
hrtime_t export_start = gethrtime();
@ -6974,8 +6969,8 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig,
spa->spa_is_exporting = B_TRUE;
/*
* Put a hold on the pool, drop the namespace lock, stop async tasks,
* reacquire the namespace lock, and see if we can export.
* Put a hold on the pool, drop the namespace lock, stop async tasks
* and see if we can export.
*/
spa_open_ref(spa, FTAG);
mutex_exit(&spa_namespace_lock);
@ -6985,10 +6980,14 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig,
taskq_wait(spa->spa_zvol_taskq);
}
mutex_enter(&spa_namespace_lock);
spa->spa_export_thread = curthread;
spa_close(spa, FTAG);
if (spa->spa_state == POOL_STATE_UNINITIALIZED)
if (spa->spa_state == POOL_STATE_UNINITIALIZED) {
mutex_exit(&spa_namespace_lock);
goto export_spa;
}
/*
* The pool will be in core if it's openable, in which case we can
* modify its state. Objsets may be open only because they're dirty,
@ -7009,6 +7008,14 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig,
goto fail;
}
mutex_exit(&spa_namespace_lock);
/*
* At this point we no longer hold the spa_namespace_lock and
* there were no references on the spa. Future spa_lookups will
* notice the spa->spa_export_thread and wait until we signal
* that we are finshed.
*/
if (spa->spa_sync_on) {
vdev_t *rvd = spa->spa_root_vdev;
/*
@ -7020,6 +7027,7 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig,
if (!force && new_state == POOL_STATE_EXPORTED &&
spa_has_active_shared_spare(spa)) {
error = SET_ERROR(EXDEV);
mutex_enter(&spa_namespace_lock);
goto fail;
}
@ -7084,6 +7092,13 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig,
if (oldconfig && spa->spa_config)
*oldconfig = fnvlist_dup(spa->spa_config);
if (new_state == POOL_STATE_EXPORTED)
zio_handle_export_delay(spa, gethrtime() - export_start);
/*
* Take the namespace lock for the actual spa_t removal
*/
mutex_enter(&spa_namespace_lock);
if (new_state != POOL_STATE_UNINITIALIZED) {
if (!hardforce)
spa_write_cachefile(spa, B_TRUE, B_TRUE, B_FALSE);
@ -7095,17 +7110,25 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig,
* we make sure to reset the exporting flag.
*/
spa->spa_is_exporting = B_FALSE;
spa->spa_export_thread = NULL;
}
if (new_state == POOL_STATE_EXPORTED)
zio_handle_export_delay(spa, gethrtime() - export_start);
/*
* Wake up any waiters in spa_lookup()
*/
cv_broadcast(&spa_namespace_cv);
mutex_exit(&spa_namespace_lock);
return (0);
fail:
spa->spa_is_exporting = B_FALSE;
spa->spa_export_thread = NULL;
spa_async_resume(spa);
/*
* Wake up any waiters in spa_lookup()
*/
cv_broadcast(&spa_namespace_cv);
mutex_exit(&spa_namespace_lock);
return (error);
}
@ -10145,6 +10168,9 @@ spa_sync(spa_t *spa, uint64_t txg)
metaslab_class_evict_old(spa->spa_normal_class, txg);
metaslab_class_evict_old(spa->spa_log_class, txg);
/* spa_embedded_log_class has only one metaslab per vdev. */
metaslab_class_evict_old(spa->spa_special_class, txg);
metaslab_class_evict_old(spa->spa_dedup_class, txg);
spa_sync_close_syncing_log_sm(spa);

View File

@ -27,7 +27,7 @@
* Copyright (c) 2017 Datto Inc.
* Copyright (c) 2017, Intel Corporation.
* Copyright (c) 2019, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
* Copyright (c) 2023, Klara Inc.
* Copyright (c) 2023, 2024, Klara Inc.
*/
#include <sys/zfs_context.h>
@ -82,8 +82,8 @@
* - Check if spa_refcount is zero
* - Rename a spa_t
* - add/remove/attach/detach devices
* - Held for the duration of create/destroy/export
* - Held at the start and end of import
* - Held for the duration of create/destroy
* - Held at the start and end of import and export
*
* It does not need to handle recursion. A create or destroy may
* reference objects (files or zvols) in other pools, but by
@ -636,8 +636,14 @@ spa_lookup(const char *name)
if (spa == NULL)
return (NULL);
if (spa->spa_load_thread != NULL &&
spa->spa_load_thread != curthread) {
/*
* Avoid racing with import/export, which don't hold the namespace
* lock for their entire duration.
*/
if ((spa->spa_load_thread != NULL &&
spa->spa_load_thread != curthread) ||
(spa->spa_export_thread != NULL &&
spa->spa_export_thread != curthread)) {
cv_wait(&spa_namespace_cv, &spa_namespace_lock);
goto retry;
}
@ -950,14 +956,15 @@ spa_open_ref(spa_t *spa, const void *tag)
/*
* Remove a reference to the given spa_t. Must have at least one reference, or
* have the namespace lock held.
* have the namespace lock held or be part of a pool import/export.
*/
void
spa_close(spa_t *spa, const void *tag)
{
ASSERT(zfs_refcount_count(&spa->spa_refcount) > spa->spa_minref ||
MUTEX_HELD(&spa_namespace_lock) ||
spa->spa_load_thread == curthread);
spa->spa_load_thread == curthread ||
spa->spa_export_thread == curthread);
(void) zfs_refcount_remove(&spa->spa_refcount, tag);
}
@ -977,13 +984,15 @@ spa_async_close(spa_t *spa, const void *tag)
/*
* Check to see if the spa refcount is zero. Must be called with
* spa_namespace_lock held. We really compare against spa_minref, which is the
* number of references acquired when opening a pool
* spa_namespace_lock held or be the spa export thread. We really
* compare against spa_minref, which is the number of references
* acquired when opening a pool
*/
boolean_t
spa_refcount_zero(spa_t *spa)
{
ASSERT(MUTEX_HELD(&spa_namespace_lock));
ASSERT(MUTEX_HELD(&spa_namespace_lock) ||
spa->spa_export_thread == curthread);
return (zfs_refcount_count(&spa->spa_refcount) == spa->spa_minref);
}
@ -1231,6 +1240,8 @@ spa_vdev_enter(spa_t *spa)
mutex_enter(&spa->spa_vdev_top_lock);
mutex_enter(&spa_namespace_lock);
ASSERT0(spa->spa_export_thread);
vdev_autotrim_stop_all(spa);
return (spa_vdev_config_enter(spa));
@ -1248,6 +1259,8 @@ spa_vdev_detach_enter(spa_t *spa, uint64_t guid)
mutex_enter(&spa->spa_vdev_top_lock);
mutex_enter(&spa_namespace_lock);
ASSERT0(spa->spa_export_thread);
vdev_autotrim_stop_all(spa);
if (guid != 0) {

View File

@ -112,6 +112,11 @@ int zfs_vdev_dtl_sm_blksz = (1 << 12);
*/
static unsigned int zfs_slow_io_events_per_second = 20;
/*
* Rate limit deadman "hung IO" events to this many per second.
*/
static unsigned int zfs_deadman_events_per_second = 1;
/*
* Rate limit checksum events after this many checksum errors per second.
*/
@ -348,7 +353,8 @@ vdev_get_min_asize(vdev_t *vd)
* to the nearest metaslab.
*/
if (vd == vd->vdev_top)
return (P2ALIGN(vd->vdev_asize, 1ULL << vd->vdev_ms_shift));
return (P2ALIGN_TYPED(vd->vdev_asize, 1ULL << vd->vdev_ms_shift,
uint64_t));
return (pvd->vdev_ops->vdev_op_min_asize(pvd));
}
@ -665,7 +671,7 @@ vdev_alloc_common(spa_t *spa, uint_t id, uint64_t guid, vdev_ops_t *ops)
*/
zfs_ratelimit_init(&vd->vdev_delay_rl, &zfs_slow_io_events_per_second,
1);
zfs_ratelimit_init(&vd->vdev_deadman_rl, &zfs_slow_io_events_per_second,
zfs_ratelimit_init(&vd->vdev_deadman_rl, &zfs_deadman_events_per_second,
1);
zfs_ratelimit_init(&vd->vdev_checksum_rl,
&zfs_checksum_events_per_second, 1);
@ -2115,8 +2121,8 @@ vdev_open(vdev_t *vd)
}
}
osize = P2ALIGN(osize, (uint64_t)sizeof (vdev_label_t));
max_osize = P2ALIGN(max_osize, (uint64_t)sizeof (vdev_label_t));
osize = P2ALIGN_TYPED(osize, sizeof (vdev_label_t), uint64_t);
max_osize = P2ALIGN_TYPED(max_osize, sizeof (vdev_label_t), uint64_t);
if (vd->vdev_children == 0) {
if (osize < SPA_MINDEVSIZE) {
@ -4764,9 +4770,9 @@ vdev_get_stats_ex(vdev_t *vd, vdev_stat_t *vs, vdev_stat_ex_t *vsx)
* can expand.
*/
if (vd->vdev_aux == NULL && tvd != NULL) {
vs->vs_esize = P2ALIGN(
vs->vs_esize = P2ALIGN_TYPED(
vd->vdev_max_asize - vd->vdev_asize,
1ULL << tvd->vdev_ms_shift);
1ULL << tvd->vdev_ms_shift, uint64_t);
}
vs->vs_configured_ashift = vd->vdev_top != NULL
@ -6475,6 +6481,9 @@ ZFS_MODULE_PARAM(zfs_vdev, zfs_vdev_, ms_count_limit, UINT, ZMOD_RW,
ZFS_MODULE_PARAM(zfs, zfs_, slow_io_events_per_second, UINT, ZMOD_RW,
"Rate limit slow IO (delay) events to this many per second");
ZFS_MODULE_PARAM(zfs, zfs_, deadman_events_per_second, UINT, ZMOD_RW,
"Rate limit hung IO (deadman) events to this many per second");
/* BEGIN CSTYLED */
ZFS_MODULE_PARAM(zfs, zfs_, checksum_events_per_second, UINT, ZMOD_RW,
"Rate limit checksum events to this many checksum errors per second "

View File

@ -682,7 +682,8 @@ vdev_initialize_stop_wait(spa_t *spa, list_t *vd_list)
(void) spa;
vdev_t *vd;
ASSERT(MUTEX_HELD(&spa_namespace_lock));
ASSERT(MUTEX_HELD(&spa_namespace_lock) ||
spa->spa_export_thread == curthread);
while ((vd = list_remove_head(vd_list)) != NULL) {
mutex_enter(&vd->vdev_initialize_lock);
@ -724,7 +725,8 @@ vdev_initialize_stop(vdev_t *vd, vdev_initializing_state_t tgt_state,
if (vd_list == NULL) {
vdev_initialize_stop_wait_impl(vd);
} else {
ASSERT(MUTEX_HELD(&spa_namespace_lock));
ASSERT(MUTEX_HELD(&spa_namespace_lock) ||
vd->vdev_spa->spa_export_thread == curthread);
list_insert_tail(vd_list, vd);
}
}
@ -756,7 +758,8 @@ vdev_initialize_stop_all(vdev_t *vd, vdev_initializing_state_t tgt_state)
spa_t *spa = vd->vdev_spa;
list_t vd_list;
ASSERT(MUTEX_HELD(&spa_namespace_lock));
ASSERT(MUTEX_HELD(&spa_namespace_lock) ||
spa->spa_export_thread == curthread);
list_create(&vd_list, sizeof (vdev_t),
offsetof(vdev_t, vdev_initialize_node));

View File

@ -4039,7 +4039,8 @@ raidz_reflow_scratch_sync(void *arg, dmu_tx_t *tx)
spa_config_enter(spa, SCL_STATE, FTAG, RW_READER);
vdev_t *raidvd = vdev_lookup_top(spa, vre->vre_vdev_id);
int ashift = raidvd->vdev_ashift;
uint64_t write_size = P2ALIGN(VDEV_BOOT_SIZE, 1 << ashift);
uint64_t write_size = P2ALIGN_TYPED(VDEV_BOOT_SIZE, 1 << ashift,
uint64_t);
uint64_t logical_size = write_size * raidvd->vdev_children;
uint64_t read_size =
P2ROUNDUP(DIV_ROUND_UP(logical_size, (raidvd->vdev_children - 1)),

View File

@ -1087,7 +1087,8 @@ vdev_rebuild_stop_wait(vdev_t *vd)
{
spa_t *spa = vd->vdev_spa;
ASSERT(MUTEX_HELD(&spa_namespace_lock));
ASSERT(MUTEX_HELD(&spa_namespace_lock) ||
spa->spa_export_thread == curthread);
if (vd == spa->spa_root_vdev) {
for (uint64_t i = 0; i < vd->vdev_children; i++)

View File

@ -1040,7 +1040,8 @@ vdev_trim_stop_wait(spa_t *spa, list_t *vd_list)
(void) spa;
vdev_t *vd;
ASSERT(MUTEX_HELD(&spa_namespace_lock));
ASSERT(MUTEX_HELD(&spa_namespace_lock) ||
spa->spa_export_thread == curthread);
while ((vd = list_remove_head(vd_list)) != NULL) {
mutex_enter(&vd->vdev_trim_lock);
@ -1079,7 +1080,8 @@ vdev_trim_stop(vdev_t *vd, vdev_trim_state_t tgt_state, list_t *vd_list)
if (vd_list == NULL) {
vdev_trim_stop_wait_impl(vd);
} else {
ASSERT(MUTEX_HELD(&spa_namespace_lock));
ASSERT(MUTEX_HELD(&spa_namespace_lock) ||
vd->vdev_spa->spa_export_thread == curthread);
list_insert_tail(vd_list, vd);
}
}
@ -1115,7 +1117,8 @@ vdev_trim_stop_all(vdev_t *vd, vdev_trim_state_t tgt_state)
list_t vd_list;
vdev_t *vd_l2cache;
ASSERT(MUTEX_HELD(&spa_namespace_lock));
ASSERT(MUTEX_HELD(&spa_namespace_lock) ||
spa->spa_export_thread == curthread);
list_create(&vd_list, sizeof (vdev_t),
offsetof(vdev_t, vdev_trim_node));

View File

@ -425,20 +425,36 @@ zap_leaf_evict_sync(void *dbu)
static zap_leaf_t *
zap_create_leaf(zap_t *zap, dmu_tx_t *tx)
{
zap_leaf_t *l = kmem_zalloc(sizeof (zap_leaf_t), KM_SLEEP);
ASSERT(RW_WRITE_HELD(&zap->zap_rwlock));
rw_init(&l->l_rwlock, NULL, RW_NOLOCKDEP, NULL);
rw_enter(&l->l_rwlock, RW_WRITER);
l->l_blkid = zap_allocate_blocks(zap, 1);
l->l_dbuf = NULL;
uint64_t blkid = zap_allocate_blocks(zap, 1);
dmu_buf_t *db = NULL;
VERIFY0(dmu_buf_hold_by_dnode(zap->zap_dnode,
l->l_blkid << FZAP_BLOCK_SHIFT(zap), NULL, &l->l_dbuf,
blkid << FZAP_BLOCK_SHIFT(zap), NULL, &db,
DMU_READ_NO_PREFETCH));
dmu_buf_init_user(&l->l_dbu, zap_leaf_evict_sync, NULL, &l->l_dbuf);
VERIFY3P(NULL, ==, dmu_buf_set_user(l->l_dbuf, &l->l_dbu));
/*
* Create the leaf structure and stash it on the dbuf. If zap was
* recent shrunk or truncated, the dbuf might have been sitting in the
* cache waiting to be evicted, and so still have the old leaf attached
* to it. If so, just reuse it.
*/
zap_leaf_t *l = dmu_buf_get_user(db);
if (l == NULL) {
l = kmem_zalloc(sizeof (zap_leaf_t), KM_SLEEP);
l->l_blkid = blkid;
l->l_dbuf = db;
rw_init(&l->l_rwlock, NULL, RW_NOLOCKDEP, NULL);
dmu_buf_init_user(&l->l_dbu, zap_leaf_evict_sync, NULL,
&l->l_dbuf);
dmu_buf_set_user(l->l_dbuf, &l->l_dbu);
} else {
ASSERT3U(l->l_blkid, ==, blkid);
ASSERT3P(l->l_dbuf, ==, db);
}
rw_enter(&l->l_rwlock, RW_WRITER);
dmu_buf_will_dirty(l->l_dbuf, tx);
zap_leaf_init(l, zap->zap_normflags != 0);
@ -711,6 +727,7 @@ zap_expand_leaf(zap_name_t *zn, zap_leaf_t *l,
uint64_t object = zap->zap_object;
zap_put_leaf(l);
*lp = l = NULL;
zap_unlockdir(zap, tag);
err = zap_lockdir(os, object, tx, RW_WRITER,
FALSE, FALSE, tag, &zn->zn_zap);
@ -920,21 +937,17 @@ fzap_add_cd(zap_name_t *zn,
} else if (err == EAGAIN) {
err = zap_expand_leaf(zn, l, tag, tx, &l);
zap = zn->zn_zap; /* zap_expand_leaf() may change zap */
if (err == 0) {
if (err == 0)
goto retry;
} else if (err == ENOSPC) {
/*
* If we failed to expand the leaf, then bailout
* as there is no point trying
* zap_put_leaf_maybe_grow_ptrtbl().
*/
return (err);
}
}
out:
if (zap != NULL)
zap_put_leaf_maybe_grow_ptrtbl(zn, l, tag, tx);
if (l != NULL) {
if (err == ENOSPC)
zap_put_leaf(l);
else
zap_put_leaf_maybe_grow_ptrtbl(zn, l, tag, tx);
}
return (err);
}
@ -991,8 +1004,12 @@ fzap_update(zap_name_t *zn,
goto retry;
}
if (zap != NULL)
zap_put_leaf_maybe_grow_ptrtbl(zn, l, tag, tx);
if (l != NULL) {
if (err == ENOSPC)
zap_put_leaf(l);
else
zap_put_leaf_maybe_grow_ptrtbl(zn, l, tag, tx);
}
return (err);
}

View File

@ -780,8 +780,7 @@ zcp_lua_counthook(lua_State *state, lua_Debug *ar)
* Check if we were canceled while waiting for the
* txg to sync or from our open context thread
*/
if (ri->zri_canceled ||
(!ri->zri_sync && issig(JUSTLOOKING) && issig(FORREAL))) {
if (ri->zri_canceled || (!ri->zri_sync && issig())) {
ri->zri_canceled = B_TRUE;
(void) lua_pushstring(state, "Channel program was canceled.");
(void) lua_error(state);

View File

@ -38,7 +38,7 @@
* Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
* Copyright (c) 2019 Datto Inc.
* Copyright (c) 2019, 2020 by Christian Schwarz. All rights reserved.
* Copyright (c) 2019, 2021, Klara Inc.
* Copyright (c) 2019, 2021, 2024, Klara Inc.
* Copyright (c) 2019, Allan Jude
* Copyright 2024 Oxide Computer Company
*/
@ -2336,7 +2336,7 @@ zfs_ioc_snapshot_list_next(zfs_cmd_t *zc)
}
while (error == 0) {
if (issig(JUSTLOOKING) && issig(FORREAL)) {
if (issig()) {
error = SET_ERROR(EINTR);
break;
}
@ -5514,6 +5514,14 @@ zfs_ioc_recv_new(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
return (error);
}
/*
* When stack space is limited, we write replication stream data to the target
* on a separate taskq thread, to make sure there's enough stack space.
*/
#ifndef HAVE_LARGE_STACKS
#define USE_SEND_TASKQ 1
#endif
typedef struct dump_bytes_io {
zfs_file_t *dbi_fp;
caddr_t dbi_buf;
@ -5534,31 +5542,65 @@ dump_bytes_cb(void *arg)
dbi->dbi_err = zfs_file_write(fp, buf, dbi->dbi_len, NULL);
}
typedef struct dump_bytes_arg {
zfs_file_t *dba_fp;
#ifdef USE_SEND_TASKQ
taskq_t *dba_tq;
taskq_ent_t dba_tqent;
#endif
} dump_bytes_arg_t;
static int
dump_bytes(objset_t *os, void *buf, int len, void *arg)
{
dump_bytes_arg_t *dba = (dump_bytes_arg_t *)arg;
dump_bytes_io_t dbi;
dbi.dbi_fp = arg;
dbi.dbi_fp = dba->dba_fp;
dbi.dbi_buf = buf;
dbi.dbi_len = len;
#if defined(HAVE_LARGE_STACKS)
dump_bytes_cb(&dbi);
#ifdef USE_SEND_TASKQ
taskq_dispatch_ent(dba->dba_tq, dump_bytes_cb, &dbi, TQ_SLEEP,
&dba->dba_tqent);
taskq_wait(dba->dba_tq);
#else
/*
* The vn_rdwr() call is performed in a taskq to ensure that there is
* always enough stack space to write safely to the target filesystem.
* The ZIO_TYPE_FREE threads are used because there can be a lot of
* them and they are used in vdev_file.c for a similar purpose.
*/
spa_taskq_dispatch_sync(dmu_objset_spa(os), ZIO_TYPE_FREE,
ZIO_TASKQ_ISSUE, dump_bytes_cb, &dbi, TQ_SLEEP);
#endif /* HAVE_LARGE_STACKS */
dump_bytes_cb(&dbi);
#endif
return (dbi.dbi_err);
}
static int
dump_bytes_init(dump_bytes_arg_t *dba, int fd, dmu_send_outparams_t *out)
{
zfs_file_t *fp = zfs_file_get(fd);
if (fp == NULL)
return (SET_ERROR(EBADF));
dba->dba_fp = fp;
#ifdef USE_SEND_TASKQ
dba->dba_tq = taskq_create("z_send", 1, defclsyspri, 0, 0, 0);
taskq_init_ent(&dba->dba_tqent);
#endif
memset(out, 0, sizeof (dmu_send_outparams_t));
out->dso_outfunc = dump_bytes;
out->dso_arg = dba;
out->dso_dryrun = B_FALSE;
return (0);
}
static void
dump_bytes_fini(dump_bytes_arg_t *dba)
{
zfs_file_put(dba->dba_fp);
#ifdef USE_SEND_TASKQ
taskq_destroy(dba->dba_tq);
#endif
}
/*
* inputs:
* zc_name name of snapshot to send
@ -5643,21 +5685,18 @@ zfs_ioc_send(zfs_cmd_t *zc)
dsl_dataset_rele(tosnap, FTAG);
dsl_pool_rele(dp, FTAG);
} else {
zfs_file_t *fp;
dmu_send_outparams_t out = {0};
dump_bytes_arg_t dba;
dmu_send_outparams_t out;
error = dump_bytes_init(&dba, zc->zc_cookie, &out);
if (error)
return (error);
if ((fp = zfs_file_get(zc->zc_cookie)) == NULL)
return (SET_ERROR(EBADF));
off = zfs_file_off(fp);
out.dso_outfunc = dump_bytes;
out.dso_arg = fp;
out.dso_dryrun = B_FALSE;
off = zfs_file_off(dba.dba_fp);
error = dmu_send_obj(zc->zc_name, zc->zc_sendobj,
zc->zc_fromobj, embedok, large_block_ok, compressok,
rawok, savedok, zc->zc_cookie, &off, &out);
zfs_file_put(fp);
dump_bytes_fini(&dba);
}
return (error);
}
@ -6604,7 +6643,6 @@ zfs_ioc_send_new(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl)
offset_t off;
const char *fromname = NULL;
int fd;
zfs_file_t *fp;
boolean_t largeblockok;
boolean_t embedok;
boolean_t compressok;
@ -6629,20 +6667,19 @@ zfs_ioc_send_new(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl)
(void) nvlist_lookup_string(innvl, "redactbook", &redactbook);
if ((fp = zfs_file_get(fd)) == NULL)
return (SET_ERROR(EBADF));
dump_bytes_arg_t dba;
dmu_send_outparams_t out;
error = dump_bytes_init(&dba, fd, &out);
if (error)
return (error);
off = zfs_file_off(fp);
dmu_send_outparams_t out = {0};
out.dso_outfunc = dump_bytes;
out.dso_arg = fp;
out.dso_dryrun = B_FALSE;
off = zfs_file_off(dba.dba_fp);
error = dmu_send(snapname, fromname, embedok, largeblockok,
compressok, rawok, savedok, resumeobj, resumeoff,
redactbook, fd, &off, &out);
zfs_file_put(fp);
dump_bytes_fini(&dba);
return (error);
}

View File

@ -895,7 +895,7 @@ zfs_log_clone_range(zilog_t *zilog, dmu_tx_t *tx, int txtype, znode_t *zp,
itx_t *itx;
lr_clone_range_t *lr;
uint64_t partlen, max_log_data;
size_t i, partnbps;
size_t partnbps;
if (zil_replaying(zilog, tx) || zp->z_unlinked)
return;
@ -904,10 +904,8 @@ zfs_log_clone_range(zilog_t *zilog, dmu_tx_t *tx, int txtype, znode_t *zp,
while (nbps > 0) {
partnbps = MIN(nbps, max_log_data / sizeof (bps[0]));
partlen = 0;
for (i = 0; i < partnbps; i++) {
partlen += BP_GET_LSIZE(&bps[i]);
}
partlen = partnbps * blksz;
ASSERT3U(partlen, <, len + blksz);
partlen = MIN(partlen, len);
itx = zil_itx_create(txtype,

View File

@ -1412,6 +1412,11 @@ zfs_clone_range(znode_t *inzp, uint64_t *inoffp, znode_t *outzp,
outoff += size;
len -= size;
done += size;
if (issig()) {
error = SET_ERROR(EINTR);
break;
}
}
vmem_free(bps, sizeof (bps[0]) * maxblocks);

View File

@ -2023,7 +2023,6 @@ zio_taskq_dispatch(zio_t *zio, zio_taskq_type_t q, boolean_t cutinline)
{
spa_t *spa = zio->io_spa;
zio_type_t t = zio->io_type;
int flags = (cutinline ? TQ_FRONT : 0);
/*
* If we're a config writer or a probe, the normal issue and
@ -2041,23 +2040,18 @@ zio_taskq_dispatch(zio_t *zio, zio_taskq_type_t q, boolean_t cutinline)
/*
* If this is a high priority I/O, then use the high priority taskq if
* available.
* available or cut the line otherwise.
*/
if ((zio->io_priority == ZIO_PRIORITY_NOW ||
zio->io_priority == ZIO_PRIORITY_SYNC_WRITE) &&
spa->spa_zio_taskq[t][q + 1].stqs_count != 0)
q++;
if (zio->io_priority == ZIO_PRIORITY_SYNC_WRITE) {
if (spa->spa_zio_taskq[t][q + 1].stqs_count != 0)
q++;
else
cutinline = B_TRUE;
}
ASSERT3U(q, <, ZIO_TASKQ_TYPES);
/*
* NB: We are assuming that the zio can only be dispatched
* to a single taskq at a time. It would be a grievous error
* to dispatch the zio to another taskq at the same time.
*/
ASSERT(taskq_empty_ent(&zio->io_tqent));
spa_taskq_dispatch_ent(spa, t, q, zio_execute, zio, flags,
&zio->io_tqent, zio);
spa_taskq_dispatch(spa, t, q, zio_execute, zio, cutinline);
}
static boolean_t
@ -5005,10 +4999,9 @@ zio_done(zio_t *zio)
* Reexecution is potentially a huge amount of work.
* Hand it off to the otherwise-unused claim taskq.
*/
ASSERT(taskq_empty_ent(&zio->io_tqent));
spa_taskq_dispatch_ent(zio->io_spa,
spa_taskq_dispatch(zio->io_spa,
ZIO_TYPE_CLAIM, ZIO_TASKQ_ISSUE,
zio_reexecute, zio, 0, &zio->io_tqent, NULL);
zio_reexecute, zio, B_FALSE);
}
return (NULL);
}

View File

@ -430,7 +430,8 @@ tags = ['functional', 'cli_root', 'zpool_events']
[tests/functional/cli_root/zpool_export]
tests = ['zpool_export_001_pos', 'zpool_export_002_pos',
'zpool_export_003_neg', 'zpool_export_004_pos']
'zpool_export_003_neg', 'zpool_export_004_pos',
'zpool_export_parallel_pos', 'zpool_export_parallel_admin']
tags = ['functional', 'cli_root', 'zpool_export']
[tests/functional/cli_root/zpool_get]

View File

@ -182,7 +182,6 @@ if sys.platform.startswith('freebsd'):
'cli_root/zfs_unshare/zfs_unshare_008_pos': ['SKIP', na_reason],
'cp_files/cp_files_002_pos': ['SKIP', na_reason],
'link_count/link_count_001': ['SKIP', na_reason],
'casenorm/mixed_create_failure': ['FAIL', 13215],
'mmap/mmap_sync_001_pos': ['SKIP', na_reason],
'rsend/send_raw_ashift': ['SKIP', 14961],
})

View File

@ -521,13 +521,15 @@ test_send_new(const char *snapshot, int fd)
static void
test_recv_new(const char *dataset, int fd)
{
dmu_replay_record_t drr = { 0 };
dmu_replay_record_t drr;
nvlist_t *required = fnvlist_alloc();
nvlist_t *optional = fnvlist_alloc();
nvlist_t *props = fnvlist_alloc();
char snapshot[MAXNAMELEN + 32];
ssize_t count;
memset(&drr, 0, sizeof (dmu_replay_record_t));
int cleanup_fd = open(ZFS_DEV, O_RDWR);
if (cleanup_fd == -1) {
(void) fprintf(stderr, "open(%s) failed: %s\n", ZFS_DEV,

View File

@ -29,6 +29,7 @@ CONDENSE_INDIRECT_OBSOLETE_PCT condense.indirect_obsolete_pct zfs_condense_indir
CONDENSE_MIN_MAPPING_BYTES condense.min_mapping_bytes zfs_condense_min_mapping_bytes
DBUF_CACHE_SHIFT dbuf.cache_shift dbuf_cache_shift
DEADMAN_CHECKTIME_MS deadman.checktime_ms zfs_deadman_checktime_ms
DEADMAN_EVENTS_PER_SECOND deadman_events_per_second zfs_deadman_events_per_second
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

View File

@ -1084,6 +1084,8 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zpool_export/zpool_export_002_pos.ksh \
functional/cli_root/zpool_export/zpool_export_003_neg.ksh \
functional/cli_root/zpool_export/zpool_export_004_pos.ksh \
functional/cli_root/zpool_export/zpool_export_parallel_admin.ksh \
functional/cli_root/zpool_export/zpool_export_parallel_pos.ksh \
functional/cli_root/zpool_get/cleanup.ksh \
functional/cli_root/zpool_get/setup.ksh \
functional/cli_root/zpool_get/vdev_get_001_pos.ksh \

View File

@ -0,0 +1,72 @@
#!/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 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#
# Copyright (c) 2024 Klara, Inc.
#
. $STF_SUITE/include/libtest.shlib
#
# DESCRIPTION:
# Verify that admin commands cannot race a pool export
#
# STRATEGY:
# 1. Create a pool
# 2. Import the pool with an injected delay in the background
# 3. Execute some admin commands against the pool
#
verify_runnable "global"
DEVICE_DIR=$TEST_BASE_DIR/dev_export-test
function cleanup
{
zinject -c all
poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
[[ -d $DEVICE_DIR ]] && log_must rm -rf $DEVICE_DIR
}
log_assert "admin commands cannot race a pool export"
log_onexit cleanup
[[ ! -d $DEVICE_DIR ]] && log_must mkdir -p $DEVICE_DIR
log_must truncate -s $MINVDEVSIZE ${DEVICE_DIR}/disk0 ${DEVICE_DIR}/disk1
log_must zpool create -f $TESTPOOL1 mirror ${DEVICE_DIR}/disk0 ${DEVICE_DIR}/disk1
log_must zinject -P export -s 10 $TESTPOOL1
log_must zpool export $TESTPOOL1 &
zpool set comment=hello $TESTPOOL1
zpool reguid $TESTPOOL1 &
zpool split $TESTPOOL1 &
log_pass "admin commands cannot race a pool export"

View File

@ -0,0 +1,129 @@
#!/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 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#
# Copyright (c) 2024 Klara, Inc.
#
. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.cfg
. $STF_SUITE/tests/functional/cli_root/zpool_import/zpool_import.kshlib
# test uses 8 vdevs
MAX_NUM=8
DEVICE_DIR=$TEST_BASE_DIR/dev_import-test
#
# DESCRIPTION:
# Verify that pool exports can occur in parallel
#
# STRATEGY:
# 1. Create 8 pools
# 2. Inject an export delay using zinject
# 3. Export half of the pools synchronously to baseline sequential cost
# 4. Export the other half asynchronously to demonstrate parallel savings
# 6. Import 4 pools
# 7. Test zpool export -a
#
verify_runnable "global"
#
# override the minimum sized vdevs
#
POOLNAME="test_pool"
function cleanup
{
zinject -c all
for i in {0..$(($MAX_NUM - 1))}; do
poolexists $POOLNAME-$i && destroy_pool $POOLNAME-$i
done
[[ -d $DEVICE_DIR ]] && log_must rm -rf $DEVICE_DIR
}
log_assert "Pool exports can occur in parallel"
log_onexit cleanup
[[ ! -d $DEVICE_DIR ]] && log_must mkdir -p $DEVICE_DIR
#
# Create some pools with export delay injectors
#
for i in {0..$(($MAX_NUM - 1))}; do
log_must truncate -s $MINVDEVSIZE ${DEVICE_DIR}/disk$i
log_must zpool create $POOLNAME-$i $DEVICE_DIR/disk$i
log_must zinject -P export -s 8 $POOLNAME-$i
done
#
# Export half of the pools synchronously
#
SECONDS=0
for i in {0..3}; do
log_must zpool export $POOLNAME-$i
done
sequential_time=$SECONDS
log_note "sequentially exported 4 pools in $sequential_time seconds"
#
# Export half of the pools in parallel
#
SECONDS=0
for i in {4..7}; do
log_must zpool export $POOLNAME-$i &
done
wait
parallel_time=$SECONDS
log_note "asyncronously exported 4 pools in $parallel_time seconds"
log_must test $parallel_time -lt $(($sequential_time / 3))
#
# import 4 pools with export delay injectors
#
for i in {4..7}; do
log_must zpool import -d $DEVICE_DIR/disk$i $POOLNAME-$i
log_must zinject -P export -s 8 $POOLNAME-$i
done
#
# now test zpool export -a
#
SECONDS=0
log_must zpool export -a
parallel_time=$SECONDS
log_note "asyncronously exported 4 pools, using '-a', in $parallel_time seconds"
log_must test $parallel_time -lt $(($sequential_time / 3))
log_pass "Pool exports occur in parallel"

View File

@ -28,7 +28,7 @@
# Verify spa deadman events are rate limited
#
# STRATEGY:
# 1. Reduce the zfs_slow_io_events_per_second to 1.
# 1. Reduce the zfs_deadman_events_per_second to 1.
# 2. Reduce the zfs_deadman_ziotime_ms to 1ms.
# 3. Write data to a pool and read it back.
# 4. Verify deadman events have been produced at a reasonable rate.
@ -44,15 +44,15 @@ function cleanup
zinject -c all
default_cleanup_noexit
set_tunable64 SLOW_IO_EVENTS_PER_SECOND $OLD_SLOW_IO_EVENTS
set_tunable64 DEADMAN_EVENTS_PER_SECOND $OLD_DEADMAN_EVENTS
set_tunable64 DEADMAN_ZIOTIME_MS $ZIOTIME_DEFAULT
}
log_assert "Verify spa deadman events are rate limited"
log_onexit cleanup
OLD_SLOW_IO_EVENTS=$(get_tunable SLOW_IO_EVENTS_PER_SECOND)
log_must set_tunable64 SLOW_IO_EVENTS_PER_SECOND 1
OLD_DEADMAN_EVENTS=$(get_tunable DEADMAN_EVENTS_PER_SECOND)
log_must set_tunable64 DEADMAN_EVENTS_PER_SECOND 1
log_must set_tunable64 DEADMAN_ZIOTIME_MS 1
# Create a new pool in order to use the updated deadman settings.

View File

@ -87,6 +87,9 @@
#define HAVE_AVX512VL 1
#endif
/* backtrace() is available */
/* #undef HAVE_BACKTRACE */
/* bdevname() is available */
/* #undef HAVE_BDEVNAME */
@ -598,6 +601,9 @@
/* Define if compiler supports -Winfinite-recursion */
/* #undef HAVE_KERNEL_INFINITE_RECURSION */
/* kernel defines intptr_t */
/* #undef HAVE_KERNEL_INTPTR_T */
/* kernel has kernel_neon_* functions */
/* #undef HAVE_KERNEL_NEON */
@ -1188,7 +1194,7 @@
/* #undef ZFS_IS_GPL_COMPATIBLE */
/* Define the project alias string. */
#define ZFS_META_ALIAS "zfs-2.2.99-474-FreeBSD_g8f1b7a6fa"
#define ZFS_META_ALIAS "zfs-2.2.99-517-FreeBSD_ge2357561b"
/* Define the project author. */
#define ZFS_META_AUTHOR "OpenZFS"
@ -1218,7 +1224,7 @@
#define ZFS_META_NAME "zfs"
/* Define the project release. */
#define ZFS_META_RELEASE "474-FreeBSD_g8f1b7a6fa"
#define ZFS_META_RELEASE "517-FreeBSD_ge2357561b"
/* Define the project version. */
#define ZFS_META_VERSION "2.2.99"

View File

@ -1 +1 @@
#define ZFS_META_GITREV "zfs-2.2.99-474-g8f1b7a6fa"
#define ZFS_META_GITREV "zfs-2.2.99-517-ge2357561b"