mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 19:34:43 +01:00
zfs: merge openzfs/zfs@814f9afba (zfs-2.4-release) into stable/15
OpenZFS 2.4.0 rc3 Notable upstream pull request merges: #17750964dfc317FreeBSD: Correct _PC_MIN_HOLE_SIZE #17793b9d1e28a7ddt prune: Add SCL_ZIO deadlock workaround #177991585a10a8Make mount/share errors non-fatal for zfs create/clone #17801073b34b3eFix display of default xattr to show 'sa' #17803e09c86cb1zvol: verify IO type is supported #17807 -multiple zpool iostat: fix regressions in "all pools" mode after #17786 #17826b9356f06eExplicit set ashift for non-leaf vdevs #17830f0bff230fSuppress some ashift warnings #17833c1f55bff8Fix the type of the raidz_outlier_check_interval_ms parameter #17836799bda73eFix return value for setting zvol threading #17834f0c76f8a7libzpool/cmn_err: remove suppression, add stop option, cleanup #178431956417b5mmap_seek: print error code and text on failure #178477987d4debUpdate device removal documentation #178516f6e1c90aFreeBSD: zfs_getpages: Don't zero freshly allocated pages Obtained from: OpenZFS OpenZFS commit:814f9afba7OpenZFS tag: zfs-2.4.0-rc3
This commit is contained in:
commit
ce7e1f86a1
60 files changed
+1135
-708
No files matched your search
@@ -14,7 +14,7 @@ Please check our issue tracker before opening a new feature request.
|
||||
Filling out the following template will help other contributors better understand your proposed feature.
|
||||
-->
|
||||
|
||||
### Describe the feature would like to see added to OpenZFS
|
||||
### Describe the feature you would like to see added to OpenZFS
|
||||
|
||||
<!--
|
||||
Provide a clear and concise description of the feature.
|
||||
|
||||
@@ -121,7 +121,14 @@ case "$OS" in
|
||||
KSRC="$FREEBSD_SNAP/../amd64/$FreeBSD/src.txz"
|
||||
;;
|
||||
freebsd15-0c)
|
||||
FreeBSD="15.0-ALPHA3"
|
||||
FreeBSD="15.0-ALPHA4"
|
||||
OSNAME="FreeBSD $FreeBSD"
|
||||
OSv="freebsd14.0"
|
||||
URLxz="$FREEBSD_SNAP/$FreeBSD/amd64/Latest/FreeBSD-$FreeBSD-amd64-BASIC-CI-ufs.raw.xz"
|
||||
KSRC="$FREEBSD_SNAP/../amd64/$FreeBSD/src.txz"
|
||||
;;
|
||||
freebsd16-0c)
|
||||
FreeBSD="16.0-CURRENT"
|
||||
OSNAME="FreeBSD $FreeBSD"
|
||||
OSv="freebsd14.0"
|
||||
URLxz="$FREEBSD_SNAP/$FreeBSD/amd64/Latest/FreeBSD-$FreeBSD-amd64-BASIC-CI-ufs.raw.xz"
|
||||
@@ -287,7 +294,7 @@ else
|
||||
while pidof /usr/bin/qemu-system-x86_64 >/dev/null; do
|
||||
ssh 2>/dev/null root@vm0 "uname -a" && break
|
||||
done
|
||||
ssh root@vm0 "pkg install -y bash ca_root_nss git qemu-guest-agent python3 py311-cloud-init"
|
||||
ssh root@vm0 "env IGNORE_OSVERSION=yes pkg install -y bash ca_root_nss git qemu-guest-agent python3 py311-cloud-init"
|
||||
ssh root@vm0 "chsh -s $BASH root"
|
||||
ssh root@vm0 'sysrc qemu_guest_agent_enable="YES"'
|
||||
ssh root@vm0 'sysrc cloudinit_enable="YES"'
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ jobs:
|
||||
# FreeBSD variants of 2025-06:
|
||||
# FreeBSD Release: freebsd13-5r, freebsd14-2r, freebsd14-3r
|
||||
# FreeBSD Stable: freebsd13-5s, freebsd14-3s
|
||||
# FreeBSD Current: freebsd15-0c
|
||||
# FreeBSD Current: freebsd15-0c, freebsd16-0c
|
||||
os: ${{ fromJson(needs.test-config.outputs.test_os) }}
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
|
||||
@@ -2,7 +2,7 @@ Meta: 1
|
||||
Name: zfs
|
||||
Branch: 1.0
|
||||
Version: 2.4.0
|
||||
Release: rc2
|
||||
Release: rc3
|
||||
Release-Tags: relext
|
||||
License: CDDL
|
||||
Author: OpenZFS
|
||||
|
||||
@@ -106,11 +106,15 @@ extern boolean_t spa_mode_readable_spacemaps;
|
||||
extern uint_t zfs_reconstruct_indirect_combinations_max;
|
||||
extern uint_t zfs_btree_verify_intensity;
|
||||
|
||||
enum {
|
||||
ARG_ALLOCATED = 256,
|
||||
ARG_BLOCK_BIN_MODE,
|
||||
ARG_BLOCK_CLASSES,
|
||||
};
|
||||
|
||||
static const char cmdname[] = "zdb";
|
||||
uint8_t dump_opt[512];
|
||||
|
||||
#define ALLOCATED_OPT 256
|
||||
|
||||
typedef void object_viewer_t(objset_t *, uint64_t, void *data, size_t size);
|
||||
|
||||
static uint64_t *zopt_metaslab = NULL;
|
||||
@@ -131,6 +135,20 @@ static objset_t *os;
|
||||
static boolean_t kernel_init_done;
|
||||
static boolean_t corruption_found = B_FALSE;
|
||||
|
||||
static enum {
|
||||
BIN_AUTO = 0,
|
||||
BIN_PSIZE,
|
||||
BIN_LSIZE,
|
||||
BIN_ASIZE,
|
||||
} block_bin_mode = BIN_AUTO;
|
||||
|
||||
static enum {
|
||||
CLASS_NORMAL = 1 << 1,
|
||||
CLASS_SPECIAL = 1 << 2,
|
||||
CLASS_DEDUP = 1 << 3,
|
||||
CLASS_OTHER = 1 << 4,
|
||||
} block_classes = 0;
|
||||
|
||||
static void snprintf_blkptr_compact(char *, size_t, const blkptr_t *,
|
||||
boolean_t);
|
||||
static void mos_obj_refd(uint64_t);
|
||||
@@ -749,6 +767,12 @@ usage(void)
|
||||
(void) fprintf(stderr, " Options to control amount of output:\n");
|
||||
(void) fprintf(stderr, " -b --block-stats "
|
||||
"block statistics\n");
|
||||
(void) fprintf(stderr, " --bin=(lsize|psize|asize) "
|
||||
"bin blocks based on this size in all three columns\n");
|
||||
(void) fprintf(stderr,
|
||||
" --class=(normal|special|dedup|other)[,...]\n"
|
||||
" only consider blocks from "
|
||||
"these allocation classes\n");
|
||||
(void) fprintf(stderr, " -B --backup "
|
||||
"backup stream\n");
|
||||
(void) fprintf(stderr, " -c --checksum "
|
||||
@@ -1694,7 +1718,7 @@ dump_metaslab(metaslab_t *msp)
|
||||
(u_longlong_t)msp->ms_id, (u_longlong_t)msp->ms_start,
|
||||
(u_longlong_t)space_map_object(sm), freebuf);
|
||||
|
||||
if (dump_opt[ALLOCATED_OPT] ||
|
||||
if (dump_opt[ARG_ALLOCATED] ||
|
||||
(dump_opt['m'] > 2 && !dump_opt['L'])) {
|
||||
mutex_enter(&msp->ms_lock);
|
||||
VERIFY0(metaslab_load(msp));
|
||||
@@ -1705,7 +1729,7 @@ dump_metaslab(metaslab_t *msp)
|
||||
dump_metaslab_stats(msp);
|
||||
}
|
||||
|
||||
if (dump_opt[ALLOCATED_OPT]) {
|
||||
if (dump_opt[ARG_ALLOCATED]) {
|
||||
uint64_t off = msp->ms_start;
|
||||
zfs_range_tree_walk(msp->ms_allocatable, dump_allocated,
|
||||
&off);
|
||||
@@ -1726,7 +1750,7 @@ dump_metaslab(metaslab_t *msp)
|
||||
SPACE_MAP_HISTOGRAM_SIZE, sm->sm_shift);
|
||||
}
|
||||
|
||||
if (dump_opt[ALLOCATED_OPT] ||
|
||||
if (dump_opt[ARG_ALLOCATED] ||
|
||||
(dump_opt['m'] > 2 && !dump_opt['L'])) {
|
||||
metaslab_unload(msp);
|
||||
mutex_exit(&msp->ms_lock);
|
||||
@@ -5814,6 +5838,34 @@ dump_size_histograms(zdb_cb_t *zcb)
|
||||
|
||||
|
||||
(void) printf("\nBlock Size Histogram\n");
|
||||
switch (block_bin_mode) {
|
||||
case BIN_PSIZE:
|
||||
printf("(note: all categories are binned by %s)\n", "psize");
|
||||
break;
|
||||
case BIN_LSIZE:
|
||||
printf("(note: all categories are binned by %s)\n", "lsize");
|
||||
break;
|
||||
case BIN_ASIZE:
|
||||
printf("(note: all categories are binned by %s)\n", "asize");
|
||||
break;
|
||||
default:
|
||||
printf("(note: all categories are binned separately)\n");
|
||||
break;
|
||||
}
|
||||
if (block_classes != 0) {
|
||||
char buf[256] = "";
|
||||
if (block_classes & CLASS_NORMAL)
|
||||
strlcat(buf, "\"normal\", ", sizeof (buf));
|
||||
if (block_classes & CLASS_SPECIAL)
|
||||
strlcat(buf, "\"special\", ", sizeof (buf));
|
||||
if (block_classes & CLASS_DEDUP)
|
||||
strlcat(buf, "\"dedup\", ", sizeof (buf));
|
||||
if (block_classes & CLASS_OTHER)
|
||||
strlcat(buf, "\"other\", ", sizeof (buf));
|
||||
buf[strlen(buf)-2] = '\0';
|
||||
printf("(note: only blocks in these classes are counted: %s)\n",
|
||||
buf);
|
||||
}
|
||||
/*
|
||||
* Print the first line titles
|
||||
*/
|
||||
@@ -6162,29 +6214,85 @@ skipped:
|
||||
[BPE_GET_PSIZE(bp)]++;
|
||||
return;
|
||||
}
|
||||
|
||||
if (block_classes != 0) {
|
||||
spa_config_enter(zcb->zcb_spa, SCL_CONFIG, FTAG, RW_READER);
|
||||
|
||||
uint64_t vdev = DVA_GET_VDEV(&bp->blk_dva[0]);
|
||||
uint64_t offset = DVA_GET_OFFSET(&bp->blk_dva[0]);
|
||||
vdev_t *vd = vdev_lookup_top(zcb->zcb_spa, vdev);
|
||||
ASSERT(vd != NULL);
|
||||
metaslab_t *ms = vd->vdev_ms[offset >> vd->vdev_ms_shift];
|
||||
ASSERT(ms != NULL);
|
||||
metaslab_group_t *mg = ms->ms_group;
|
||||
ASSERT(mg != NULL);
|
||||
metaslab_class_t *mc = mg->mg_class;
|
||||
ASSERT(mc != NULL);
|
||||
|
||||
spa_config_exit(zcb->zcb_spa, SCL_CONFIG, FTAG);
|
||||
|
||||
int class;
|
||||
if (mc == spa_normal_class(zcb->zcb_spa)) {
|
||||
class = CLASS_NORMAL;
|
||||
} else if (mc == spa_special_class(zcb->zcb_spa)) {
|
||||
class = CLASS_SPECIAL;
|
||||
} else if (mc == spa_dedup_class(zcb->zcb_spa)) {
|
||||
class = CLASS_DEDUP;
|
||||
} else {
|
||||
class = CLASS_OTHER;
|
||||
}
|
||||
|
||||
if (!(block_classes & class)) {
|
||||
goto hist_skipped;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The binning histogram bins by powers of two up to
|
||||
* SPA_MAXBLOCKSIZE rather than creating bins for
|
||||
* every possible blocksize found in the pool.
|
||||
*/
|
||||
int bin = highbit64(BP_GET_PSIZE(bp)) - 1;
|
||||
int bin;
|
||||
|
||||
/*
|
||||
* Binning strategy: each bin includes blocks up to and including
|
||||
* the given size (excluding blocks that fit into the previous bin).
|
||||
* This way, the "4K" bin includes blocks within the (2K; 4K] range.
|
||||
*/
|
||||
#define BIN(size) (highbit64((size) - 1))
|
||||
|
||||
switch (block_bin_mode) {
|
||||
case BIN_PSIZE: bin = BIN(BP_GET_PSIZE(bp)); break;
|
||||
case BIN_LSIZE: bin = BIN(BP_GET_LSIZE(bp)); break;
|
||||
case BIN_ASIZE: bin = BIN(BP_GET_ASIZE(bp)); break;
|
||||
case BIN_AUTO: break;
|
||||
default: PANIC("bad block_bin_mode"); abort();
|
||||
}
|
||||
|
||||
if (block_bin_mode == BIN_AUTO)
|
||||
bin = BIN(BP_GET_PSIZE(bp));
|
||||
|
||||
zcb->zcb_psize_count[bin]++;
|
||||
zcb->zcb_psize_len[bin] += BP_GET_PSIZE(bp);
|
||||
zcb->zcb_psize_total += BP_GET_PSIZE(bp);
|
||||
|
||||
bin = highbit64(BP_GET_LSIZE(bp)) - 1;
|
||||
if (block_bin_mode == BIN_AUTO)
|
||||
bin = BIN(BP_GET_LSIZE(bp));
|
||||
|
||||
zcb->zcb_lsize_count[bin]++;
|
||||
zcb->zcb_lsize_len[bin] += BP_GET_LSIZE(bp);
|
||||
zcb->zcb_lsize_total += BP_GET_LSIZE(bp);
|
||||
|
||||
bin = highbit64(BP_GET_ASIZE(bp)) - 1;
|
||||
if (block_bin_mode == BIN_AUTO)
|
||||
bin = BIN(BP_GET_ASIZE(bp));
|
||||
|
||||
zcb->zcb_asize_count[bin]++;
|
||||
zcb->zcb_asize_len[bin] += BP_GET_ASIZE(bp);
|
||||
zcb->zcb_asize_total += BP_GET_ASIZE(bp);
|
||||
|
||||
#undef BIN
|
||||
|
||||
hist_skipped:
|
||||
if (!do_claim)
|
||||
return;
|
||||
|
||||
@@ -9426,7 +9534,11 @@ main(int argc, char **argv)
|
||||
{"livelist", no_argument, NULL, 'y'},
|
||||
{"zstd-headers", no_argument, NULL, 'Z'},
|
||||
{"allocated-map", no_argument, NULL,
|
||||
ALLOCATED_OPT},
|
||||
ARG_ALLOCATED},
|
||||
{"bin", required_argument, NULL,
|
||||
ARG_BLOCK_BIN_MODE},
|
||||
{"class", required_argument, NULL,
|
||||
ARG_BLOCK_CLASSES},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@@ -9457,7 +9569,7 @@ main(int argc, char **argv)
|
||||
case 'u':
|
||||
case 'y':
|
||||
case 'Z':
|
||||
case ALLOCATED_OPT:
|
||||
case ARG_ALLOCATED:
|
||||
dump_opt[c]++;
|
||||
dump_all = 0;
|
||||
break;
|
||||
@@ -9540,6 +9652,59 @@ main(int argc, char **argv)
|
||||
case 'x':
|
||||
vn_dumpdir = optarg;
|
||||
break;
|
||||
case ARG_BLOCK_BIN_MODE:
|
||||
if (strcmp(optarg, "lsize") == 0) {
|
||||
block_bin_mode = BIN_LSIZE;
|
||||
} else if (strcmp(optarg, "psize") == 0) {
|
||||
block_bin_mode = BIN_PSIZE;
|
||||
} else if (strcmp(optarg, "asize") == 0) {
|
||||
block_bin_mode = BIN_ASIZE;
|
||||
} else {
|
||||
(void) fprintf(stderr,
|
||||
"--bin=\"%s\" must be one of \"lsize\", "
|
||||
"\"psize\" or \"asize\"\n", optarg);
|
||||
usage();
|
||||
}
|
||||
break;
|
||||
|
||||
case ARG_BLOCK_CLASSES: {
|
||||
char *buf = strdup(optarg), *tok = buf, *next,
|
||||
*save = NULL;
|
||||
|
||||
while ((next = strtok_r(tok, ",", &save)) != NULL) {
|
||||
tok = NULL;
|
||||
|
||||
if (strcmp(next, "normal") == 0) {
|
||||
block_classes |= CLASS_NORMAL;
|
||||
} else if (strcmp(next, "special") == 0) {
|
||||
block_classes |= CLASS_SPECIAL;
|
||||
} else if (strcmp(next, "dedup") == 0) {
|
||||
block_classes |= CLASS_DEDUP;
|
||||
} else if (strcmp(next, "other") == 0) {
|
||||
block_classes |= CLASS_OTHER;
|
||||
} else {
|
||||
(void) fprintf(stderr,
|
||||
"--class=\"%s\" must be a "
|
||||
"comma-separated list of either "
|
||||
"\"normal\", \"special\", "
|
||||
"\"asize\" or \"other\"; "
|
||||
"got \"%s\"\n",
|
||||
optarg, next);
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
if (block_classes == 0) {
|
||||
(void) fprintf(stderr,
|
||||
"--class= must be a comma-separated "
|
||||
"list of either \"normal\", \"special\", "
|
||||
"\"asize\" or \"other\"; got empty\n");
|
||||
usage();
|
||||
}
|
||||
|
||||
free(buf);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
@@ -9582,6 +9747,9 @@ main(int argc, char **argv)
|
||||
*/
|
||||
spa_mode_readable_spacemaps = B_TRUE;
|
||||
|
||||
libspl_set_assert_ok((dump_opt['A'] == 1) || (dump_opt['A'] > 2));
|
||||
zfs_recover = (dump_opt['A'] > 1);
|
||||
|
||||
if (dump_all)
|
||||
verbose = MAX(verbose, 1);
|
||||
|
||||
@@ -9592,9 +9760,6 @@ main(int argc, char **argv)
|
||||
dump_opt[c] += verbose;
|
||||
}
|
||||
|
||||
libspl_set_assert_ok((dump_opt['A'] == 1) || (dump_opt['A'] > 2));
|
||||
zfs_recover = (dump_opt['A'] > 1);
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if (argc < 2 && dump_opt['R'])
|
||||
|
||||
@@ -914,7 +914,11 @@ zfs_do_clone(int argc, char **argv)
|
||||
log_history = B_FALSE;
|
||||
}
|
||||
|
||||
ret = zfs_mount_and_share(g_zfs, argv[1], ZFS_TYPE_DATASET);
|
||||
/*
|
||||
* Dataset cloned successfully, mount/share failures are
|
||||
* non-fatal.
|
||||
*/
|
||||
(void) zfs_mount_and_share(g_zfs, argv[1], ZFS_TYPE_DATASET);
|
||||
}
|
||||
|
||||
zfs_close(zhp);
|
||||
@@ -1333,7 +1337,9 @@ zfs_do_create(int argc, char **argv)
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = zfs_mount_and_share(g_zfs, argv[0], ZFS_TYPE_DATASET);
|
||||
/* Dataset created successfully, mount/share failures are non-fatal */
|
||||
ret = 0;
|
||||
(void) zfs_mount_and_share(g_zfs, argv[0], ZFS_TYPE_DATASET);
|
||||
error:
|
||||
nvlist_free(props);
|
||||
return (ret);
|
||||
|
||||
@@ -107,6 +107,8 @@
|
||||
* zinject
|
||||
* zinject <-a | -u pool>
|
||||
* zinject -c <id|all>
|
||||
* zinject -E <delay> [-a] [-m] [-f freq] [-l level] [-r range]
|
||||
* [-T iotype] [-t type object | -b bookmark pool]
|
||||
* zinject [-q] <-t type> [-f freq] [-u] [-a] [-m] [-e errno] [-l level]
|
||||
* [-r range] <object>
|
||||
* zinject [-f freq] [-a] [-m] [-u] -b objset:object:level:start:end pool
|
||||
@@ -132,14 +134,18 @@
|
||||
* The '-f' flag controls the frequency of errors injected, expressed as a
|
||||
* real number percentage between 0.0001 and 100. The default is 100.
|
||||
*
|
||||
* The this form is responsible for actually injecting the handler into the
|
||||
* The <object> form is responsible for actually injecting the handler into the
|
||||
* framework. It takes the arguments described above, translates them to the
|
||||
* internal tuple using libzpool, and then issues an ioctl() to register the
|
||||
* handler.
|
||||
*
|
||||
* The final form can target a specific bookmark, regardless of whether a
|
||||
* The '-b' option can target a specific bookmark, regardless of whether a
|
||||
* human-readable interface has been designed. It allows developers to specify
|
||||
* a particular block by number.
|
||||
*
|
||||
* The '-E' option injects pipeline ready stage delays for the given object or
|
||||
* bookmark. The delay is specified in milliseconds, and it supports I/O type
|
||||
* and range filters.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
@@ -346,6 +352,13 @@ usage(void)
|
||||
"\t\tsuch that the operation takes a minimum of supplied seconds\n"
|
||||
"\t\tto complete.\n"
|
||||
"\n"
|
||||
"\tzinject -E <delay> [-a] [-m] [-f freq] [-l level] [-r range]\n"
|
||||
"\t\t[-T iotype] [-t type object | -b bookmark pool]\n"
|
||||
"\n"
|
||||
"\t\tInject pipeline ready stage delays for the given object path\n"
|
||||
"\t\t(data or dnode) or raw bookmark. The delay is specified in\n"
|
||||
"\t\tmilliseconds.\n"
|
||||
"\n"
|
||||
"\tzinject -I [-s <seconds> | -g <txgs>] pool\n"
|
||||
"\t\tCause the pool to stop writing blocks yet not\n"
|
||||
"\t\treport errors for a duration. Simulates buggy hardware\n"
|
||||
@@ -724,12 +737,15 @@ register_handler(const char *pool, int flags, zinject_record_t *record,
|
||||
if (quiet) {
|
||||
(void) printf("%llu\n", (u_longlong_t)zc.zc_guid);
|
||||
} else {
|
||||
boolean_t show_object = B_FALSE;
|
||||
boolean_t show_iotype = B_FALSE;
|
||||
(void) printf("Added handler %llu with the following "
|
||||
"properties:\n", (u_longlong_t)zc.zc_guid);
|
||||
(void) printf(" pool: %s\n", pool);
|
||||
if (record->zi_guid) {
|
||||
(void) printf(" vdev: %llx\n",
|
||||
(u_longlong_t)record->zi_guid);
|
||||
show_iotype = B_TRUE;
|
||||
} else if (record->zi_func[0] != '\0') {
|
||||
(void) printf(" panic function: %s\n",
|
||||
record->zi_func);
|
||||
@@ -742,7 +758,18 @@ register_handler(const char *pool, int flags, zinject_record_t *record,
|
||||
} else if (record->zi_timer > 0) {
|
||||
(void) printf(" timer: %lld ms\n",
|
||||
(u_longlong_t)NSEC2MSEC(record->zi_timer));
|
||||
if (record->zi_cmd == ZINJECT_DELAY_READY) {
|
||||
show_object = B_TRUE;
|
||||
show_iotype = B_TRUE;
|
||||
}
|
||||
} else {
|
||||
show_object = B_TRUE;
|
||||
}
|
||||
if (show_iotype) {
|
||||
(void) printf("iotype: %s\n",
|
||||
iotype_to_str(record->zi_iotype));
|
||||
}
|
||||
if (show_object) {
|
||||
(void) printf("objset: %llu\n",
|
||||
(u_longlong_t)record->zi_objset);
|
||||
(void) printf("object: %llu\n",
|
||||
@@ -910,6 +937,7 @@ main(int argc, char **argv)
|
||||
int ret;
|
||||
int flags = 0;
|
||||
uint32_t dvas = 0;
|
||||
hrtime_t ready_delay = -1;
|
||||
|
||||
if ((g_zfs = libzfs_init()) == NULL) {
|
||||
(void) fprintf(stderr, "%s\n", libzfs_error_init(errno));
|
||||
@@ -940,7 +968,7 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
while ((c = getopt(argc, argv,
|
||||
":aA:b:C:d:D:f:Fg:qhIc:t:T:l:mr:s:e:uL:p:P:")) != -1) {
|
||||
":aA:b:C:d:D:E:f:Fg:qhIc:t:T:l:mr:s:e:uL:p:P:")) != -1) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
flags |= ZINJECT_FLUSH_ARC;
|
||||
@@ -1113,6 +1141,18 @@ main(int argc, char **argv)
|
||||
case 'u':
|
||||
flags |= ZINJECT_UNLOAD_SPA;
|
||||
break;
|
||||
case 'E':
|
||||
ready_delay = MSEC2NSEC(strtol(optarg, &end, 10));
|
||||
if (ready_delay <= 0 || *end != '\0') {
|
||||
(void) fprintf(stderr, "invalid delay '%s': "
|
||||
"must be a positive duration\n", optarg);
|
||||
usage();
|
||||
libzfs_fini(g_zfs);
|
||||
return (1);
|
||||
}
|
||||
record.zi_cmd = ZINJECT_DELAY_READY;
|
||||
record.zi_timer = ready_delay;
|
||||
break;
|
||||
case 'L':
|
||||
if ((label = name_to_type(optarg)) == TYPE_INVAL &&
|
||||
!LABEL_TYPE(type)) {
|
||||
@@ -1150,7 +1190,7 @@ main(int argc, char **argv)
|
||||
*/
|
||||
if (raw != NULL || range != NULL || type != TYPE_INVAL ||
|
||||
level != 0 || record.zi_cmd != ZINJECT_UNINITIALIZED ||
|
||||
record.zi_freq > 0 || dvas != 0) {
|
||||
record.zi_freq > 0 || dvas != 0 || ready_delay >= 0) {
|
||||
(void) fprintf(stderr, "cancel (-c) incompatible with "
|
||||
"any other options\n");
|
||||
usage();
|
||||
@@ -1186,7 +1226,7 @@ main(int argc, char **argv)
|
||||
*/
|
||||
if (raw != NULL || range != NULL || type != TYPE_INVAL ||
|
||||
level != 0 || record.zi_cmd != ZINJECT_UNINITIALIZED ||
|
||||
dvas != 0) {
|
||||
dvas != 0 || ready_delay >= 0) {
|
||||
(void) fprintf(stderr, "device (-d) incompatible with "
|
||||
"data error injection\n");
|
||||
usage();
|
||||
@@ -1276,13 +1316,23 @@ main(int argc, char **argv)
|
||||
return (1);
|
||||
}
|
||||
|
||||
record.zi_cmd = ZINJECT_DATA_FAULT;
|
||||
if (record.zi_cmd == ZINJECT_UNINITIALIZED) {
|
||||
record.zi_cmd = ZINJECT_DATA_FAULT;
|
||||
if (!error)
|
||||
error = EIO;
|
||||
} else if (error != 0) {
|
||||
(void) fprintf(stderr, "error type -e incompatible "
|
||||
"with delay injection\n");
|
||||
libzfs_fini(g_zfs);
|
||||
return (1);
|
||||
} else {
|
||||
record.zi_iotype = io_type;
|
||||
}
|
||||
|
||||
if (translate_raw(raw, &record) != 0) {
|
||||
libzfs_fini(g_zfs);
|
||||
return (1);
|
||||
}
|
||||
if (!error)
|
||||
error = EIO;
|
||||
} else if (record.zi_cmd == ZINJECT_PANIC) {
|
||||
if (raw != NULL || range != NULL || type != TYPE_INVAL ||
|
||||
level != 0 || device != NULL || record.zi_freq > 0 ||
|
||||
@@ -1410,6 +1460,13 @@ main(int argc, char **argv)
|
||||
record.zi_dvas = dvas;
|
||||
}
|
||||
|
||||
if (record.zi_cmd != ZINJECT_UNINITIALIZED && error != 0) {
|
||||
(void) fprintf(stderr, "error type -e incompatible "
|
||||
"with delay injection\n");
|
||||
libzfs_fini(g_zfs);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (error == EACCES) {
|
||||
if (type != TYPE_DATA) {
|
||||
(void) fprintf(stderr, "decryption errors "
|
||||
@@ -1425,8 +1482,12 @@ main(int argc, char **argv)
|
||||
* not found.
|
||||
*/
|
||||
error = ECKSUM;
|
||||
} else {
|
||||
} else if (record.zi_cmd == ZINJECT_UNINITIALIZED) {
|
||||
record.zi_cmd = ZINJECT_DATA_FAULT;
|
||||
if (!error)
|
||||
error = EIO;
|
||||
} else {
|
||||
record.zi_iotype = io_type;
|
||||
}
|
||||
|
||||
if (translate_record(type, argv[0], range, level, &record, pool,
|
||||
@@ -1434,8 +1495,6 @@ main(int argc, char **argv)
|
||||
libzfs_fini(g_zfs);
|
||||
return (1);
|
||||
}
|
||||
if (!error)
|
||||
error = EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -103,6 +103,7 @@ add_pool(zpool_handle_t *zhp, zpool_list_t *zlp)
|
||||
new->zn_last_refresh = zlp->zl_last_refresh;
|
||||
uu_avl_insert(zlp->zl_avl, new, idx);
|
||||
} else {
|
||||
zpool_refresh_stats_from_handle(node->zn_handle, zhp);
|
||||
node->zn_last_refresh = zlp->zl_last_refresh;
|
||||
zpool_close(zhp);
|
||||
free(new);
|
||||
@@ -203,31 +204,23 @@ pool_list_refresh(zpool_list_t *zlp)
|
||||
return (navail);
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for any new pools and add them to the list. zpool_iter()
|
||||
* will call zpool_refresh_stats() as part of its work, so this has
|
||||
* the side effect of updating all active handles.
|
||||
*/
|
||||
/* Search for any new pools and add them to the list. */
|
||||
(void) zpool_iter(g_zfs, add_pool_cb, zlp);
|
||||
|
||||
/*
|
||||
* Walk the list for any that weren't refreshed, and update and remove
|
||||
* them. It's not enough to just skip available ones, as zpool_iter()
|
||||
* won't update them, so they'll still appear active in our list.
|
||||
*/
|
||||
/* Walk the list of existing pools, and update or remove them. */
|
||||
zpool_node_t *node, *next;
|
||||
for (node = uu_avl_first(zlp->zl_avl); node != NULL; node = next) {
|
||||
next = uu_avl_next(zlp->zl_avl, node);
|
||||
|
||||
/*
|
||||
* Skip any that were refreshed and are online; they're already
|
||||
* handled.
|
||||
* Skip any that were refreshed and are online; they were added
|
||||
* by zpool_iter() and are already up to date.
|
||||
*/
|
||||
if (node->zn_last_refresh == zlp->zl_last_refresh &&
|
||||
zpool_get_state(node->zn_handle) != POOL_STATE_UNAVAIL)
|
||||
continue;
|
||||
|
||||
/* Do the refresh ourselves, just in case. */
|
||||
/* Refresh and remove if necessary. */
|
||||
boolean_t missing;
|
||||
zpool_refresh_stats(node->zn_handle, &missing);
|
||||
if (missing) {
|
||||
|
||||
@@ -6677,6 +6677,7 @@ zpool_do_iostat(int argc, char **argv)
|
||||
if (skip) {
|
||||
(void) fflush(stdout);
|
||||
(void) fsleep(interval);
|
||||
last_npools = npools;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -270,14 +270,13 @@ is_spare(nvlist_t *config, const char *path)
|
||||
* draid* Virtual dRAID spare
|
||||
*/
|
||||
static nvlist_t *
|
||||
make_leaf_vdev(nvlist_t *props, const char *arg, boolean_t is_primary)
|
||||
make_leaf_vdev(const char *arg, boolean_t is_primary, uint64_t ashift)
|
||||
{
|
||||
char path[MAXPATHLEN];
|
||||
struct stat64 statbuf;
|
||||
nvlist_t *vdev = NULL;
|
||||
const char *type = NULL;
|
||||
boolean_t wholedisk = B_FALSE;
|
||||
uint64_t ashift = 0;
|
||||
int err;
|
||||
|
||||
/*
|
||||
@@ -381,31 +380,6 @@ make_leaf_vdev(nvlist_t *props, const char *arg, boolean_t is_primary)
|
||||
verify(nvlist_add_uint64(vdev, ZPOOL_CONFIG_WHOLE_DISK,
|
||||
(uint64_t)wholedisk) == 0);
|
||||
|
||||
/*
|
||||
* Override defaults if custom properties are provided.
|
||||
*/
|
||||
if (props != NULL) {
|
||||
const char *value = NULL;
|
||||
|
||||
if (nvlist_lookup_string(props,
|
||||
zpool_prop_to_name(ZPOOL_PROP_ASHIFT), &value) == 0) {
|
||||
if (zfs_nicestrtonum(NULL, value, &ashift) != 0) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("ashift must be a number.\n"));
|
||||
return (NULL);
|
||||
}
|
||||
if (ashift != 0 &&
|
||||
(ashift < ASHIFT_MIN || ashift > ASHIFT_MAX)) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("invalid 'ashift=%" PRIu64 "' "
|
||||
"property: only values between %" PRId32 " "
|
||||
"and %" PRId32 " are allowed.\n"),
|
||||
ashift, ASHIFT_MIN, ASHIFT_MAX);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the device is known to incorrectly report its physical sector
|
||||
* size explicitly provide the known correct value.
|
||||
@@ -1513,6 +1487,29 @@ construct_spec(nvlist_t *props, int argc, char **argv)
|
||||
const char *type, *fulltype;
|
||||
boolean_t is_log, is_special, is_dedup, is_spare;
|
||||
boolean_t seen_logs;
|
||||
uint64_t ashift = 0;
|
||||
|
||||
if (props != NULL) {
|
||||
const char *value = NULL;
|
||||
|
||||
if (nvlist_lookup_string(props,
|
||||
zpool_prop_to_name(ZPOOL_PROP_ASHIFT), &value) == 0) {
|
||||
if (zfs_nicestrtonum(NULL, value, &ashift) != 0) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("ashift must be a number.\n"));
|
||||
return (NULL);
|
||||
}
|
||||
if (ashift != 0 &&
|
||||
(ashift < ASHIFT_MIN || ashift > ASHIFT_MAX)) {
|
||||
(void) fprintf(stderr,
|
||||
gettext("invalid 'ashift=%" PRIu64 "' "
|
||||
"property: only values between %" PRId32 " "
|
||||
"and %" PRId32 " are allowed.\n"),
|
||||
ashift, ASHIFT_MIN, ASHIFT_MAX);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
top = NULL;
|
||||
toplevels = 0;
|
||||
@@ -1618,9 +1615,9 @@ construct_spec(nvlist_t *props, int argc, char **argv)
|
||||
children * sizeof (nvlist_t *));
|
||||
if (child == NULL)
|
||||
zpool_no_memory();
|
||||
if ((nv = make_leaf_vdev(props, argv[c],
|
||||
if ((nv = make_leaf_vdev(argv[c],
|
||||
!(is_log || is_special || is_dedup ||
|
||||
is_spare))) == NULL) {
|
||||
is_spare), ashift)) == NULL) {
|
||||
for (c = 0; c < children - 1; c++)
|
||||
nvlist_free(child[c]);
|
||||
free(child);
|
||||
@@ -1684,6 +1681,10 @@ construct_spec(nvlist_t *props, int argc, char **argv)
|
||||
ZPOOL_CONFIG_ALLOCATION_BIAS,
|
||||
VDEV_ALLOC_BIAS_DEDUP) == 0);
|
||||
}
|
||||
if (ashift > 0) {
|
||||
fnvlist_add_uint64(nv,
|
||||
ZPOOL_CONFIG_ASHIFT, ashift);
|
||||
}
|
||||
if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) {
|
||||
verify(nvlist_add_uint64(nv,
|
||||
ZPOOL_CONFIG_NPARITY,
|
||||
@@ -1711,8 +1712,9 @@ construct_spec(nvlist_t *props, int argc, char **argv)
|
||||
* We have a device. Pass off to make_leaf_vdev() to
|
||||
* construct the appropriate nvlist describing the vdev.
|
||||
*/
|
||||
if ((nv = make_leaf_vdev(props, argv[0], !(is_log ||
|
||||
is_special || is_dedup || is_spare))) == NULL)
|
||||
if ((nv = make_leaf_vdev(argv[0], !(is_log ||
|
||||
is_special || is_dedup || is_spare),
|
||||
ashift)) == NULL)
|
||||
goto spec_out;
|
||||
|
||||
verify(nvlist_add_uint64(nv,
|
||||
|
||||
@@ -119,15 +119,49 @@ AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_REVALIDATE_DISK], [
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # 6.18 API change
|
||||
dnl # block_device_operation->getgeo takes struct gendisk* as first arg
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK], [
|
||||
ZFS_LINUX_TEST_SRC([block_device_operations_getgeo_gendisk], [
|
||||
#include <linux/blkdev.h>
|
||||
|
||||
static int blk_getgeo(struct gendisk *disk, struct hd_geometry *geo)
|
||||
{
|
||||
(void) disk, (void) geo;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static const struct block_device_operations
|
||||
bops __attribute__ ((unused)) = {
|
||||
.getgeo = blk_getgeo,
|
||||
};
|
||||
], [], [])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK], [
|
||||
AC_MSG_CHECKING([whether bops->getgeo() takes gendisk as first arg])
|
||||
ZFS_LINUX_TEST_RESULT([block_device_operations_getgeo_gendisk], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE([HAVE_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK], [1],
|
||||
[Define if getgeo() in block_device_operations takes struct gendisk * as its first arg])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS], [
|
||||
ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS
|
||||
ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID
|
||||
ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_RELEASE_1ARG
|
||||
ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_REVALIDATE_DISK
|
||||
ZFS_AC_KERNEL_SRC_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS], [
|
||||
ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_CHECK_EVENTS
|
||||
ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_RELEASE_VOID
|
||||
ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_REVALIDATE_DISK
|
||||
ZFS_AC_KERNEL_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK
|
||||
])
|
||||
@@ -0,0 +1,24 @@
|
||||
dnl #
|
||||
dnl # 6.18 API change
|
||||
dnl # - generic_drop_inode() renamed to inode_generic_drop()
|
||||
dnl # - generic_delete_inode() renamed to inode_just_drop()
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_INODE_GENERIC_DROP], [
|
||||
ZFS_LINUX_TEST_SRC([inode_generic_drop], [
|
||||
#include <linux/fs.h>
|
||||
],[
|
||||
struct inode *ip = NULL;
|
||||
inode_generic_drop(ip);
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_INODE_GENERIC_DROP], [
|
||||
AC_MSG_CHECKING([whether inode_generic_drop() exists])
|
||||
ZFS_LINUX_TEST_RESULT([inode_generic_drop], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_INODE_GENERIC_DROP, 1,
|
||||
[inode_generic_drop() exists])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
@@ -0,0 +1,31 @@
|
||||
dnl #
|
||||
dnl # 6.18 API change
|
||||
dnl # ns->ops->type was moved to ns->ns.ns_type (struct ns_common)
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_NS_COMMON_TYPE], [
|
||||
ZFS_LINUX_TEST_SRC([ns_common_type], [
|
||||
#include <linux/user_namespace.h>
|
||||
],[
|
||||
struct user_namespace ns;
|
||||
ns.ns.ns_type = 0;
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_NS_COMMON_TYPE], [
|
||||
AC_MSG_CHECKING([whether ns_type is accessible through ns_common])
|
||||
ZFS_LINUX_TEST_RESULT([ns_common_type], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE([HAVE_NS_COMMON_TYPE], 1,
|
||||
[Define if ns_type is accessible through ns_common])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_NAMESPACE], [
|
||||
ZFS_AC_KERNEL_SRC_NS_COMMON_TYPE
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_NAMESPACE], [
|
||||
ZFS_AC_KERNEL_NS_COMMON_TYPE
|
||||
])
|
||||
@@ -1,79 +0,0 @@
|
||||
dnl #
|
||||
dnl # 2.6.38 API change
|
||||
dnl # ns_capable() was introduced
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_NS_CAPABLE], [
|
||||
ZFS_LINUX_TEST_SRC([ns_capable], [
|
||||
#include <linux/capability.h>
|
||||
],[
|
||||
ns_capable((struct user_namespace *)NULL, CAP_SYS_ADMIN);
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_NS_CAPABLE], [
|
||||
AC_MSG_CHECKING([whether ns_capable exists])
|
||||
ZFS_LINUX_TEST_RESULT([ns_capable], [
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
ZFS_LINUX_TEST_ERROR([ns_capable()])
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # 2.6.39 API change
|
||||
dnl # struct user_namespace was added to struct cred_t as cred->user_ns member
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_CRED_USER_NS], [
|
||||
ZFS_LINUX_TEST_SRC([cred_user_ns], [
|
||||
#include <linux/cred.h>
|
||||
],[
|
||||
struct cred cr;
|
||||
cr.user_ns = (struct user_namespace *)NULL;
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_CRED_USER_NS], [
|
||||
AC_MSG_CHECKING([whether cred_t->user_ns exists])
|
||||
ZFS_LINUX_TEST_RESULT([cred_user_ns], [
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
ZFS_LINUX_TEST_ERROR([cred_t->user_ns()])
|
||||
])
|
||||
])
|
||||
|
||||
dnl #
|
||||
dnl # 3.4 API change
|
||||
dnl # kuid_has_mapping() and kgid_has_mapping() were added to distinguish
|
||||
dnl # between internal kernel uids/gids and user namespace uids/gids.
|
||||
dnl #
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_KUID_HAS_MAPPING], [
|
||||
ZFS_LINUX_TEST_SRC([kuid_has_mapping], [
|
||||
#include <linux/uidgid.h>
|
||||
],[
|
||||
kuid_has_mapping((struct user_namespace *)NULL, KUIDT_INIT(0));
|
||||
kgid_has_mapping((struct user_namespace *)NULL, KGIDT_INIT(0));
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_KUID_HAS_MAPPING], [
|
||||
AC_MSG_CHECKING([whether kuid_has_mapping/kgid_has_mapping exist])
|
||||
ZFS_LINUX_TEST_RESULT([kuid_has_mapping], [
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
ZFS_LINUX_TEST_ERROR([kuid_has_mapping()])
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_USERNS_CAPABILITIES], [
|
||||
ZFS_AC_KERNEL_SRC_NS_CAPABLE
|
||||
ZFS_AC_KERNEL_SRC_HAS_CAPABILITY
|
||||
ZFS_AC_KERNEL_SRC_CRED_USER_NS
|
||||
ZFS_AC_KERNEL_SRC_KUID_HAS_MAPPING
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_USERNS_CAPABILITIES], [
|
||||
ZFS_AC_KERNEL_NS_CAPABLE
|
||||
ZFS_AC_KERNEL_HAS_CAPABILITY
|
||||
ZFS_AC_KERNEL_CRED_USER_NS
|
||||
ZFS_AC_KERNEL_KUID_HAS_MAPPING
|
||||
])
|
||||
@@ -0,0 +1,58 @@
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_WRITEPAGE_T], [
|
||||
dnl #
|
||||
dnl # 6.3 API change
|
||||
dnl # The writepage_t function type now has its first argument as
|
||||
dnl # struct folio* instead of struct page*
|
||||
dnl #
|
||||
ZFS_LINUX_TEST_SRC([writepage_t_folio], [
|
||||
#include <linux/writeback.h>
|
||||
static int putpage(struct folio *folio,
|
||||
struct writeback_control *wbc, void *data)
|
||||
{ return 0; }
|
||||
writepage_t func = putpage;
|
||||
],[])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_WRITEPAGE_T], [
|
||||
AC_MSG_CHECKING([whether int (*writepage_t)() takes struct folio*])
|
||||
ZFS_LINUX_TEST_RESULT([writepage_t_folio], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_WRITEPAGE_T_FOLIO, 1,
|
||||
[int (*writepage_t)() takes struct folio*])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_WRITE_CACHE_PAGES], [
|
||||
dnl #
|
||||
dnl # 6.18 API change
|
||||
dnl # write_cache_pages() has been removed.
|
||||
dnl #
|
||||
ZFS_LINUX_TEST_SRC([write_cache_pages], [
|
||||
#include <linux/writeback.h>
|
||||
], [
|
||||
(void) write_cache_pages(NULL, NULL, NULL, NULL);
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_WRITE_CACHE_PAGES], [
|
||||
AC_MSG_CHECKING([whether write_cache_pages() is available])
|
||||
ZFS_LINUX_TEST_RESULT([write_cache_pages], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_WRITE_CACHE_PAGES, 1,
|
||||
[write_cache_pages() is available])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_WRITEBACK], [
|
||||
ZFS_AC_KERNEL_SRC_WRITEPAGE_T
|
||||
ZFS_AC_KERNEL_SRC_WRITE_CACHE_PAGES
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_WRITEBACK], [
|
||||
ZFS_AC_KERNEL_WRITEPAGE_T
|
||||
ZFS_AC_KERNEL_WRITE_CACHE_PAGES
|
||||
])
|
||||
@@ -1,26 +0,0 @@
|
||||
AC_DEFUN([ZFS_AC_KERNEL_SRC_WRITEPAGE_T], [
|
||||
dnl #
|
||||
dnl # 6.3 API change
|
||||
dnl # The writepage_t function type now has its first argument as
|
||||
dnl # struct folio* instead of struct page*
|
||||
dnl #
|
||||
ZFS_LINUX_TEST_SRC([writepage_t_folio], [
|
||||
#include <linux/writeback.h>
|
||||
static int putpage(struct folio *folio,
|
||||
struct writeback_control *wbc, void *data)
|
||||
{ return 0; }
|
||||
writepage_t func = putpage;
|
||||
],[])
|
||||
])
|
||||
|
||||
AC_DEFUN([ZFS_AC_KERNEL_WRITEPAGE_T], [
|
||||
AC_MSG_CHECKING([whether int (*writepage_t)() takes struct folio*])
|
||||
ZFS_LINUX_TEST_RESULT([writepage_t_folio], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_WRITEPAGE_T_FOLIO, 1,
|
||||
[int (*writepage_t)() takes struct folio*])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
])
|
||||
|
||||
@@ -121,7 +121,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
|
||||
ZFS_AC_KERNEL_SRC_IDMAP_MNT_API
|
||||
ZFS_AC_KERNEL_SRC_IDMAP_NO_USERNS
|
||||
ZFS_AC_KERNEL_SRC_IATTR_VFSID
|
||||
ZFS_AC_KERNEL_SRC_WRITEPAGE_T
|
||||
ZFS_AC_KERNEL_SRC_WRITEBACK
|
||||
ZFS_AC_KERNEL_SRC_RECLAIMED
|
||||
ZFS_AC_KERNEL_SRC_REGISTER_SYSCTL_TABLE
|
||||
ZFS_AC_KERNEL_SRC_REGISTER_SYSCTL_SZ
|
||||
@@ -136,6 +136,8 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
|
||||
ZFS_AC_KERNEL_SRC_TIMER
|
||||
ZFS_AC_KERNEL_SRC_SUPER_BLOCK_S_WB_ERR
|
||||
ZFS_AC_KERNEL_SRC_SOPS_FREE_INODE
|
||||
ZFS_AC_KERNEL_SRC_NAMESPACE
|
||||
ZFS_AC_KERNEL_SRC_INODE_GENERIC_DROP
|
||||
case "$host_cpu" in
|
||||
powerpc*)
|
||||
ZFS_AC_KERNEL_SRC_CPU_HAS_FEATURE
|
||||
@@ -240,7 +242,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
|
||||
ZFS_AC_KERNEL_IDMAP_MNT_API
|
||||
ZFS_AC_KERNEL_IDMAP_NO_USERNS
|
||||
ZFS_AC_KERNEL_IATTR_VFSID
|
||||
ZFS_AC_KERNEL_WRITEPAGE_T
|
||||
ZFS_AC_KERNEL_WRITEBACK
|
||||
ZFS_AC_KERNEL_RECLAIMED
|
||||
ZFS_AC_KERNEL_REGISTER_SYSCTL_TABLE
|
||||
ZFS_AC_KERNEL_REGISTER_SYSCTL_SZ
|
||||
@@ -256,6 +258,8 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
|
||||
ZFS_AC_KERNEL_TIMER
|
||||
ZFS_AC_KERNEL_SUPER_BLOCK_S_WB_ERR
|
||||
ZFS_AC_KERNEL_SOPS_FREE_INODE
|
||||
ZFS_AC_KERNEL_NAMESPACE
|
||||
ZFS_AC_KERNEL_INODE_GENERIC_DROP
|
||||
case "$host_cpu" in
|
||||
powerpc*)
|
||||
ZFS_AC_KERNEL_CPU_HAS_FEATURE
|
||||
|
||||
@@ -8,7 +8,7 @@ This contrib contains community compatibility patches to get Intel QAT working o
|
||||
These patches are based on the following Intel QAT version:
|
||||
[1.7.l.4.10.0-00014](https://01.org/sites/default/files/downloads/qat1.7.l.4.10.0-00014.tar.gz)
|
||||
|
||||
When using QAT with above kernels versions, the following patches needs to be applied using:
|
||||
When using QAT with the above kernel versions, the following patches need to be applied using:
|
||||
patch -p1 < _$PATCH_
|
||||
_Where $PATCH refers to the path of the patch in question_
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
DESCRIPTION
|
||||
These script were written with the primary intention of being portable and
|
||||
These scripts were written with the primary intention of being portable and
|
||||
usable on as many systems as possible.
|
||||
|
||||
This is, in practice, usually not possible. But the intention is there.
|
||||
|
||||
@@ -479,6 +479,8 @@ _LIBZFS_H zpool_status_t zpool_import_status(nvlist_t *, const char **,
|
||||
_LIBZFS_H nvlist_t *zpool_get_config(zpool_handle_t *, nvlist_t **);
|
||||
_LIBZFS_H nvlist_t *zpool_get_features(zpool_handle_t *);
|
||||
_LIBZFS_H int zpool_refresh_stats(zpool_handle_t *, boolean_t *);
|
||||
_LIBZFS_H void zpool_refresh_stats_from_handle(zpool_handle_t *,
|
||||
zpool_handle_t *);
|
||||
_LIBZFS_H int zpool_get_errlog(zpool_handle_t *, nvlist_t **);
|
||||
_LIBZFS_H void zpool_add_propname(zpool_handle_t *, const char *);
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
/*
|
||||
* Copyright (C) 2011 Lawrence Livermore National Security, LLC.
|
||||
* Copyright (C) 2015 Jörg Thalheim.
|
||||
* Copyright (c) 2025, Rob Norris <robn@despairlabs.com>
|
||||
*/
|
||||
|
||||
#ifndef _ZFS_VFS_H
|
||||
@@ -262,4 +263,10 @@ zpl_is_32bit_api(void)
|
||||
#define zpl_generic_fillattr(user_ns, ip, sp) generic_fillattr(ip, sp)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_INODE_GENERIC_DROP
|
||||
/* 6.18 API change. These were renamed, alias the old names to the new. */
|
||||
#define generic_delete_inode(ip) inode_just_drop(ip)
|
||||
#define generic_drop_inode(ip) inode_generic_drop(ip)
|
||||
#endif
|
||||
|
||||
#endif /* _ZFS_VFS_H */
|
||||
@@ -1030,7 +1030,7 @@ extern void spa_import_progress_set_notes_nolog(spa_t *spa,
|
||||
extern int spa_config_tryenter(spa_t *spa, int locks, const void *tag,
|
||||
krw_t rw);
|
||||
extern void spa_config_enter(spa_t *spa, int locks, const void *tag, krw_t rw);
|
||||
extern void spa_config_enter_mmp(spa_t *spa, int locks, const void *tag,
|
||||
extern void spa_config_enter_priority(spa_t *spa, int locks, const void *tag,
|
||||
krw_t rw);
|
||||
extern void spa_config_exit(spa_t *spa, int locks, const void *tag);
|
||||
extern int spa_config_held(spa_t *spa, int locks, krw_t rw);
|
||||
|
||||
@@ -455,6 +455,7 @@ typedef enum zinject_type {
|
||||
ZINJECT_DECRYPT_FAULT,
|
||||
ZINJECT_DELAY_IMPORT,
|
||||
ZINJECT_DELAY_EXPORT,
|
||||
ZINJECT_DELAY_READY,
|
||||
} zinject_type_t;
|
||||
|
||||
typedef enum zinject_iotype {
|
||||
|
||||
@@ -718,6 +718,7 @@ extern void zio_handle_ignored_writes(zio_t *zio);
|
||||
extern hrtime_t zio_handle_io_delay(zio_t *zio);
|
||||
extern void zio_handle_import_delay(spa_t *spa, hrtime_t elapsed);
|
||||
extern void zio_handle_export_delay(spa_t *spa, hrtime_t elapsed);
|
||||
extern hrtime_t zio_handle_ready_delay(zio_t *zio);
|
||||
|
||||
/*
|
||||
* Checksum ereport functions
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#ifndef _LIBSPL_SYS_UIO_H
|
||||
#define _LIBSPL_SYS_UIO_H
|
||||
|
||||
#include <sys/sysmacros.h>
|
||||
#include <sys/types.h>
|
||||
#include_next <sys/uio.h>
|
||||
|
||||
|
||||
@@ -616,6 +616,7 @@
|
||||
<array-type-def dimensions='1' type-id='de572c22' size-in-bits='1472' id='6d3c2f42'>
|
||||
<subrange length='23' type-id='7359adad' id='fdd0f594'/>
|
||||
</array-type-def>
|
||||
<type-decl name='long long int' size-in-bits='64' id='1eb56b1e'/>
|
||||
<array-type-def dimensions='1' type-id='3a47d82b' size-in-bits='256' id='a133ec23'>
|
||||
<subrange length='4' type-id='7359adad' id='16fe7105'/>
|
||||
</array-type-def>
|
||||
@@ -1020,13 +1021,6 @@
|
||||
<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>
|
||||
<array-type-def dimensions='1' type-id='d315442e' size-in-bits='16' id='811205dc'>
|
||||
<subrange length='1' type-id='7359adad' id='52f813b4'/>
|
||||
</array-type-def>
|
||||
<array-type-def dimensions='1' type-id='d3130597' size-in-bits='768' id='f63f23b9'>
|
||||
<subrange length='12' type-id='7359adad' id='84827bdc'/>
|
||||
</array-type-def>
|
||||
<type-decl name='long long int' size-in-bits='64' id='1eb56b1e'/>
|
||||
<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'/>
|
||||
@@ -1061,93 +1055,6 @@
|
||||
<var-decl name='mnt_minor' type-id='3502e3ff' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='__u16' type-id='8efea9e5' id='d315442e'/>
|
||||
<typedef-decl name='__s32' type-id='95e97e5e' id='3158a266'/>
|
||||
<typedef-decl name='__u32' type-id='f0981eeb' id='3f1a6b60'/>
|
||||
<typedef-decl name='__s64' type-id='1eb56b1e' id='49659421'/>
|
||||
<typedef-decl name='__u64' type-id='3a47d82b' id='d3130597'/>
|
||||
<class-decl name='statx_timestamp' size-in-bits='128' is-struct='yes' visibility='default' id='94101016'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='tv_sec' type-id='49659421' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='tv_nsec' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='96'>
|
||||
<var-decl name='__reserved' type-id='3158a266' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<class-decl name='statx' size-in-bits='2048' is-struct='yes' visibility='default' id='720b04c5'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='stx_mask' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='32'>
|
||||
<var-decl name='stx_blksize' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='stx_attributes' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='stx_nlink' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='160'>
|
||||
<var-decl name='stx_uid' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='192'>
|
||||
<var-decl name='stx_gid' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='224'>
|
||||
<var-decl name='stx_mode' type-id='d315442e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='240'>
|
||||
<var-decl name='__spare0' type-id='811205dc' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='256'>
|
||||
<var-decl name='stx_ino' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='320'>
|
||||
<var-decl name='stx_size' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='384'>
|
||||
<var-decl name='stx_blocks' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='448'>
|
||||
<var-decl name='stx_attributes_mask' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='512'>
|
||||
<var-decl name='stx_atime' type-id='94101016' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='640'>
|
||||
<var-decl name='stx_btime' type-id='94101016' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='768'>
|
||||
<var-decl name='stx_ctime' type-id='94101016' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='896'>
|
||||
<var-decl name='stx_mtime' type-id='94101016' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1024'>
|
||||
<var-decl name='stx_rdev_major' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1056'>
|
||||
<var-decl name='stx_rdev_minor' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1088'>
|
||||
<var-decl name='stx_dev_major' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1120'>
|
||||
<var-decl name='stx_dev_minor' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1152'>
|
||||
<var-decl name='stx_mnt_id' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1216'>
|
||||
<var-decl name='__spare2' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1280'>
|
||||
<var-decl name='__spare3' type-id='f63f23b9' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<class-decl name='mntent' size-in-bits='320' is-struct='yes' visibility='default' id='56fe4a37'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='mnt_fsname' type-id='26a90f95' visibility='default'/>
|
||||
@@ -1237,8 +1144,6 @@
|
||||
<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'/>
|
||||
<pointer-type-def type-id='720b04c5' size-in-bits='64' id='936b8e35'/>
|
||||
<qualified-type-def type-id='936b8e35' restrict='yes' id='31d265b7'/>
|
||||
<function-decl name='getmntent_r' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<parameter type-id='3cad23cd'/>
|
||||
@@ -1254,14 +1159,6 @@
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='statx' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='f0981eeb'/>
|
||||
<parameter type-id='31d265b7'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='__fprintf_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
|
||||
@@ -571,6 +571,7 @@
|
||||
<elf-symbol name='zpool_props_refresh' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zpool_read_label' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zpool_refresh_stats' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zpool_refresh_stats_from_handle' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zpool_reguid' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zpool_reopen_one' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zpool_scan' type='func-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
@@ -641,7 +642,7 @@
|
||||
<elf-symbol name='sa_protocol_names' size='16' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='spa_feature_table' size='2632' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zfeature_checks_disable' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zfs_deleg_perm_tab' size='528' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zfs_deleg_perm_tab' size='544' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zfs_history_event_names' size='328' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zfs_max_dataset_nesting' size='4' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
<elf-symbol name='zfs_userquota_prop_prefixes' size='96' type='object-type' binding='global-binding' visibility='default-visibility' is-defined='yes'/>
|
||||
@@ -1458,103 +1459,8 @@
|
||||
</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='d315442e' size-in-bits='16' id='811205dc'>
|
||||
<subrange length='1' type-id='7359adad' id='52f813b4'/>
|
||||
</array-type-def>
|
||||
<array-type-def dimensions='1' type-id='d3130597' size-in-bits='768' id='f63f23b9'>
|
||||
<subrange length='12' type-id='7359adad' id='84827bdc'/>
|
||||
</array-type-def>
|
||||
<typedef-decl name='__u16' type-id='8efea9e5' id='d315442e'/>
|
||||
<typedef-decl name='__s32' type-id='95e97e5e' id='3158a266'/>
|
||||
<typedef-decl name='__u32' type-id='f0981eeb' id='3f1a6b60'/>
|
||||
<typedef-decl name='__s64' type-id='1eb56b1e' id='49659421'/>
|
||||
<typedef-decl name='__u64' type-id='3a47d82b' id='d3130597'/>
|
||||
<class-decl name='statx_timestamp' size-in-bits='128' is-struct='yes' visibility='default' id='94101016'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='tv_sec' type-id='49659421' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='tv_nsec' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='96'>
|
||||
<var-decl name='__reserved' type-id='3158a266' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<class-decl name='statx' size-in-bits='2048' is-struct='yes' visibility='default' id='720b04c5'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='stx_mask' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='32'>
|
||||
<var-decl name='stx_blksize' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='stx_attributes' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='stx_nlink' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='160'>
|
||||
<var-decl name='stx_uid' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='192'>
|
||||
<var-decl name='stx_gid' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='224'>
|
||||
<var-decl name='stx_mode' type-id='d315442e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='240'>
|
||||
<var-decl name='__spare0' type-id='811205dc' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='256'>
|
||||
<var-decl name='stx_ino' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='320'>
|
||||
<var-decl name='stx_size' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='384'>
|
||||
<var-decl name='stx_blocks' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='448'>
|
||||
<var-decl name='stx_attributes_mask' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='512'>
|
||||
<var-decl name='stx_atime' type-id='94101016' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='640'>
|
||||
<var-decl name='stx_btime' type-id='94101016' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='768'>
|
||||
<var-decl name='stx_ctime' type-id='94101016' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='896'>
|
||||
<var-decl name='stx_mtime' type-id='94101016' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1024'>
|
||||
<var-decl name='stx_rdev_major' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1056'>
|
||||
<var-decl name='stx_rdev_minor' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1088'>
|
||||
<var-decl name='stx_dev_major' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1120'>
|
||||
<var-decl name='stx_dev_minor' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1152'>
|
||||
<var-decl name='stx_mnt_id' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1216'>
|
||||
<var-decl name='__spare2' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1280'>
|
||||
<var-decl name='__spare3' type-id='f63f23b9' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<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='720b04c5' size-in-bits='64' id='936b8e35'/>
|
||||
<qualified-type-def type-id='936b8e35' restrict='yes' id='31d265b7'/>
|
||||
<function-decl name='getmntent_r' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<parameter type-id='3cad23cd'/>
|
||||
@@ -1566,14 +1472,6 @@
|
||||
<parameter type-id='822cd80b'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='statx' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='f0981eeb'/>
|
||||
<parameter type-id='31d265b7'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='lib/libspl/timestamp.c' language='LANG_C99'>
|
||||
<typedef-decl name='nl_item' type-id='95e97e5e' id='03b79a94'/>
|
||||
@@ -3194,6 +3092,10 @@
|
||||
<parameter type-id='dace003f'/>
|
||||
<return type-id='80f4b756'/>
|
||||
</function-decl>
|
||||
<function-decl name='fnvlist_dup' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='22cce67b'/>
|
||||
<return type-id='5ce45b60'/>
|
||||
</function-decl>
|
||||
<function-decl name='fnvpair_value_nvlist' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='3fa542f0'/>
|
||||
<return type-id='5ce45b60'/>
|
||||
@@ -3238,6 +3140,11 @@
|
||||
<parameter type-id='37e3bd22' name='missing'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='zpool_refresh_stats_from_handle' mangled-name='zpool_refresh_stats_from_handle' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_refresh_stats_from_handle'>
|
||||
<parameter type-id='4c81de99' name='dzhp'/>
|
||||
<parameter type-id='4c81de99' name='szhp'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='zpool_skip_pool' mangled-name='zpool_skip_pool' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='zpool_skip_pool'>
|
||||
<parameter type-id='80f4b756' name='poolname'/>
|
||||
<return type-id='c19b74c3'/>
|
||||
@@ -9398,10 +9305,6 @@
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='fnvlist_dup' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='22cce67b'/>
|
||||
<return type-id='5ce45b60'/>
|
||||
</function-decl>
|
||||
<function-decl name='spl_pagesize' mangled-name='spl_pagesize' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='spl_pagesize'>
|
||||
<return type-id='b59d7dce'/>
|
||||
</function-decl>
|
||||
@@ -9774,8 +9677,8 @@
|
||||
</function-decl>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='module/zcommon/zfs_deleg.c' language='LANG_C99'>
|
||||
<array-type-def dimensions='1' type-id='fa1870fd' size-in-bits='4224' id='55e705e7'>
|
||||
<subrange length='33' type-id='7359adad' id='6a5934df'/>
|
||||
<array-type-def dimensions='1' type-id='fa1870fd' size-in-bits='4352' id='55f84f08'>
|
||||
<subrange length='34' type-id='7359adad' id='6a6a7e00'/>
|
||||
</array-type-def>
|
||||
<array-type-def dimensions='1' type-id='fa1870fd' size-in-bits='infinite' id='7c00e69d'>
|
||||
<subrange length='infinite' id='031f2035'/>
|
||||
@@ -9805,30 +9708,31 @@
|
||||
<enumerator name='ZFS_DELEG_NOTE_PROMOTE' value='5'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_RENAME' value='6'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_SEND' value='7'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_RECEIVE' value='8'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_ALLOW' value='9'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_USERPROP' value='10'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_MOUNT' value='11'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_SHARE' value='12'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_USERQUOTA' value='13'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_GROUPQUOTA' value='14'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_USERUSED' value='15'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_GROUPUSED' value='16'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_USEROBJQUOTA' value='17'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_GROUPOBJQUOTA' value='18'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_USEROBJUSED' value='19'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_GROUPOBJUSED' value='20'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_HOLD' value='21'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_RELEASE' value='22'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_DIFF' value='23'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_BOOKMARK' value='24'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_LOAD_KEY' value='25'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_CHANGE_KEY' value='26'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_PROJECTUSED' value='27'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_PROJECTQUOTA' value='28'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_PROJECTOBJUSED' value='29'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_PROJECTOBJQUOTA' value='30'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_NONE' value='31'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_SEND_RAW' value='8'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_RECEIVE' value='9'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_ALLOW' value='10'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_USERPROP' value='11'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_MOUNT' value='12'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_SHARE' value='13'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_USERQUOTA' value='14'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_GROUPQUOTA' value='15'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_USERUSED' value='16'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_GROUPUSED' value='17'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_USEROBJQUOTA' value='18'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_GROUPOBJQUOTA' value='19'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_USEROBJUSED' value='20'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_GROUPOBJUSED' value='21'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_HOLD' value='22'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_RELEASE' value='23'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_DIFF' value='24'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_BOOKMARK' value='25'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_LOAD_KEY' value='26'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_CHANGE_KEY' value='27'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_PROJECTUSED' value='28'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_PROJECTQUOTA' value='29'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_PROJECTOBJUSED' value='30'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_PROJECTOBJQUOTA' value='31'/>
|
||||
<enumerator name='ZFS_DELEG_NOTE_NONE' value='32'/>
|
||||
</enum-decl>
|
||||
<typedef-decl name='zfs_deleg_note_t' type-id='729d4547' id='4613c173'/>
|
||||
<class-decl name='zfs_deleg_perm_tab' size-in-bits='128' is-struct='yes' visibility='default' id='5aa05c1f'>
|
||||
|
||||
@@ -307,6 +307,23 @@ zpool_refresh_stats(zpool_handle_t *zhp, boolean_t *missing)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies the pool config and state from szhp to dzhp. szhp and dzhp must
|
||||
* represent the same pool. Used by pool_list_refresh() to avoid another
|
||||
* round-trip into the kernel to get stats already collected earlier in the
|
||||
* function.
|
||||
*/
|
||||
void
|
||||
zpool_refresh_stats_from_handle(zpool_handle_t *dzhp, zpool_handle_t *szhp)
|
||||
{
|
||||
VERIFY0(strcmp(dzhp->zpool_name, szhp->zpool_name));
|
||||
nvlist_free(dzhp->zpool_old_config);
|
||||
dzhp->zpool_old_config = dzhp->zpool_config;
|
||||
dzhp->zpool_config = fnvlist_dup(szhp->zpool_config);
|
||||
dzhp->zpool_config_size = szhp->zpool_config_size;
|
||||
dzhp->zpool_state = szhp->zpool_state;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following environment variables are undocumented
|
||||
* and should be used for testing purposes only:
|
||||
|
||||
@@ -98,57 +98,57 @@ static const char *const zfs_msgid_table[] = {
|
||||
#define NMSGID (sizeof (zfs_msgid_table) / sizeof (zfs_msgid_table[0]))
|
||||
|
||||
static int
|
||||
vdev_missing(vdev_stat_t *vs, uint_t vsc)
|
||||
vdev_missing(vdev_stat_t *vs, uint_t vsc, void *arg)
|
||||
{
|
||||
(void) vsc;
|
||||
(void) vsc, (void) arg;
|
||||
return (vs->vs_state == VDEV_STATE_CANT_OPEN &&
|
||||
vs->vs_aux == VDEV_AUX_OPEN_FAILED);
|
||||
}
|
||||
|
||||
static int
|
||||
vdev_faulted(vdev_stat_t *vs, uint_t vsc)
|
||||
vdev_faulted(vdev_stat_t *vs, uint_t vsc, void *arg)
|
||||
{
|
||||
(void) vsc;
|
||||
(void) vsc, (void) arg;
|
||||
return (vs->vs_state == VDEV_STATE_FAULTED);
|
||||
}
|
||||
|
||||
static int
|
||||
vdev_errors(vdev_stat_t *vs, uint_t vsc)
|
||||
vdev_errors(vdev_stat_t *vs, uint_t vsc, void *arg)
|
||||
{
|
||||
(void) vsc;
|
||||
(void) vsc, (void) arg;
|
||||
return (vs->vs_state == VDEV_STATE_DEGRADED ||
|
||||
vs->vs_read_errors != 0 || vs->vs_write_errors != 0 ||
|
||||
vs->vs_checksum_errors != 0);
|
||||
}
|
||||
|
||||
static int
|
||||
vdev_broken(vdev_stat_t *vs, uint_t vsc)
|
||||
vdev_broken(vdev_stat_t *vs, uint_t vsc, void *arg)
|
||||
{
|
||||
(void) vsc;
|
||||
(void) vsc, (void) arg;
|
||||
return (vs->vs_state == VDEV_STATE_CANT_OPEN);
|
||||
}
|
||||
|
||||
static int
|
||||
vdev_offlined(vdev_stat_t *vs, uint_t vsc)
|
||||
vdev_offlined(vdev_stat_t *vs, uint_t vsc, void *arg)
|
||||
{
|
||||
(void) vsc;
|
||||
(void) vsc, (void) arg;
|
||||
return (vs->vs_state == VDEV_STATE_OFFLINE);
|
||||
}
|
||||
|
||||
static int
|
||||
vdev_removed(vdev_stat_t *vs, uint_t vsc)
|
||||
vdev_removed(vdev_stat_t *vs, uint_t vsc, void *arg)
|
||||
{
|
||||
(void) vsc;
|
||||
(void) vsc, (void) arg;
|
||||
return (vs->vs_state == VDEV_STATE_REMOVED);
|
||||
}
|
||||
|
||||
static int
|
||||
vdev_non_native_ashift(vdev_stat_t *vs, uint_t vsc)
|
||||
vdev_non_native_ashift(vdev_stat_t *vs, uint_t vsc, void *arg)
|
||||
{
|
||||
if (getenv("ZPOOL_STATUS_NON_NATIVE_ASHIFT_IGNORE") != NULL)
|
||||
return (0);
|
||||
uint64_t ashift = *(uint64_t *)arg;
|
||||
|
||||
return (VDEV_STAT_VALID(vs_physical_ashift, vsc) &&
|
||||
(ashift == 0 || vs->vs_configured_ashift < ashift) &&
|
||||
vs->vs_configured_ashift < vs->vs_physical_ashift);
|
||||
}
|
||||
|
||||
@@ -156,8 +156,8 @@ vdev_non_native_ashift(vdev_stat_t *vs, uint_t vsc)
|
||||
* Detect if any leaf devices that have seen errors or could not be opened.
|
||||
*/
|
||||
static boolean_t
|
||||
find_vdev_problem(nvlist_t *vdev, int (*func)(vdev_stat_t *, uint_t),
|
||||
boolean_t ignore_replacing)
|
||||
find_vdev_problem(nvlist_t *vdev, int (*func)(vdev_stat_t *, uint_t, void *),
|
||||
void *arg, boolean_t ignore_replacing)
|
||||
{
|
||||
nvlist_t **child;
|
||||
uint_t c, children;
|
||||
@@ -177,14 +177,16 @@ find_vdev_problem(nvlist_t *vdev, int (*func)(vdev_stat_t *, uint_t),
|
||||
|
||||
if (nvlist_lookup_nvlist_array(vdev, ZPOOL_CONFIG_CHILDREN, &child,
|
||||
&children) == 0) {
|
||||
for (c = 0; c < children; c++)
|
||||
if (find_vdev_problem(child[c], func, ignore_replacing))
|
||||
for (c = 0; c < children; c++) {
|
||||
if (find_vdev_problem(child[c], func, arg,
|
||||
ignore_replacing))
|
||||
return (B_TRUE);
|
||||
}
|
||||
} else {
|
||||
uint_t vsc;
|
||||
vdev_stat_t *vs = (vdev_stat_t *)fnvlist_lookup_uint64_array(
|
||||
vdev, ZPOOL_CONFIG_VDEV_STATS, &vsc);
|
||||
if (func(vs, vsc) != 0)
|
||||
if (func(vs, vsc, arg) != 0)
|
||||
return (B_TRUE);
|
||||
}
|
||||
|
||||
@@ -193,9 +195,11 @@ find_vdev_problem(nvlist_t *vdev, int (*func)(vdev_stat_t *, uint_t),
|
||||
*/
|
||||
if (nvlist_lookup_nvlist_array(vdev, ZPOOL_CONFIG_L2CACHE, &child,
|
||||
&children) == 0) {
|
||||
for (c = 0; c < children; c++)
|
||||
if (find_vdev_problem(child[c], func, ignore_replacing))
|
||||
for (c = 0; c < children; c++) {
|
||||
if (find_vdev_problem(child[c], func, arg,
|
||||
ignore_replacing))
|
||||
return (B_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return (B_FALSE);
|
||||
@@ -220,7 +224,7 @@ find_vdev_problem(nvlist_t *vdev, int (*func)(vdev_stat_t *, uint_t),
|
||||
*/
|
||||
static zpool_status_t
|
||||
check_status(nvlist_t *config, boolean_t isimport,
|
||||
zpool_errata_t *erratap, const char *compat)
|
||||
zpool_errata_t *erratap, const char *compat, uint64_t ashift)
|
||||
{
|
||||
pool_scan_stat_t *ps = NULL;
|
||||
uint_t vsc, psc;
|
||||
@@ -371,15 +375,15 @@ check_status(nvlist_t *config, boolean_t isimport,
|
||||
* Bad devices in non-replicated config.
|
||||
*/
|
||||
if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
|
||||
find_vdev_problem(nvroot, vdev_faulted, B_TRUE))
|
||||
find_vdev_problem(nvroot, vdev_faulted, NULL, B_TRUE))
|
||||
return (ZPOOL_STATUS_FAULTED_DEV_NR);
|
||||
|
||||
if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
|
||||
find_vdev_problem(nvroot, vdev_missing, B_TRUE))
|
||||
find_vdev_problem(nvroot, vdev_missing, NULL, B_TRUE))
|
||||
return (ZPOOL_STATUS_MISSING_DEV_NR);
|
||||
|
||||
if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
|
||||
find_vdev_problem(nvroot, vdev_broken, B_TRUE))
|
||||
find_vdev_problem(nvroot, vdev_broken, NULL, B_TRUE))
|
||||
return (ZPOOL_STATUS_CORRUPT_LABEL_NR);
|
||||
|
||||
/*
|
||||
@@ -402,35 +406,37 @@ check_status(nvlist_t *config, boolean_t isimport,
|
||||
/*
|
||||
* Missing devices in a replicated config.
|
||||
*/
|
||||
if (find_vdev_problem(nvroot, vdev_faulted, B_TRUE))
|
||||
if (find_vdev_problem(nvroot, vdev_faulted, NULL, B_TRUE))
|
||||
return (ZPOOL_STATUS_FAULTED_DEV_R);
|
||||
if (find_vdev_problem(nvroot, vdev_missing, B_TRUE))
|
||||
if (find_vdev_problem(nvroot, vdev_missing, NULL, B_TRUE))
|
||||
return (ZPOOL_STATUS_MISSING_DEV_R);
|
||||
if (find_vdev_problem(nvroot, vdev_broken, B_TRUE))
|
||||
if (find_vdev_problem(nvroot, vdev_broken, NULL, B_TRUE))
|
||||
return (ZPOOL_STATUS_CORRUPT_LABEL_R);
|
||||
|
||||
/*
|
||||
* Devices with errors
|
||||
*/
|
||||
if (!isimport && find_vdev_problem(nvroot, vdev_errors, B_TRUE))
|
||||
if (!isimport && find_vdev_problem(nvroot, vdev_errors, NULL, B_TRUE))
|
||||
return (ZPOOL_STATUS_FAILING_DEV);
|
||||
|
||||
/*
|
||||
* Offlined devices
|
||||
*/
|
||||
if (find_vdev_problem(nvroot, vdev_offlined, B_TRUE))
|
||||
if (find_vdev_problem(nvroot, vdev_offlined, NULL, B_TRUE))
|
||||
return (ZPOOL_STATUS_OFFLINE_DEV);
|
||||
|
||||
/*
|
||||
* Removed device
|
||||
*/
|
||||
if (find_vdev_problem(nvroot, vdev_removed, B_TRUE))
|
||||
if (find_vdev_problem(nvroot, vdev_removed, NULL, B_TRUE))
|
||||
return (ZPOOL_STATUS_REMOVED_DEV);
|
||||
|
||||
/*
|
||||
* Suboptimal, but usable, ashift configuration.
|
||||
*/
|
||||
if (find_vdev_problem(nvroot, vdev_non_native_ashift, B_FALSE))
|
||||
if (!isimport &&
|
||||
getenv("ZPOOL_STATUS_NON_NATIVE_ASHIFT_IGNORE") == NULL &&
|
||||
find_vdev_problem(nvroot, vdev_non_native_ashift, &ashift, B_FALSE))
|
||||
return (ZPOOL_STATUS_NON_NATIVE_ASHIFT);
|
||||
|
||||
/*
|
||||
@@ -510,8 +516,10 @@ zpool_get_status(zpool_handle_t *zhp, const char **msgid,
|
||||
ZFS_MAXPROPLEN, NULL, B_FALSE) != 0)
|
||||
compatibility[0] = '\0';
|
||||
|
||||
uint64_t ashift = zpool_get_prop_int(zhp, ZPOOL_PROP_ASHIFT, NULL);
|
||||
|
||||
zpool_status_t ret = check_status(zhp->zpool_config, B_FALSE, errata,
|
||||
compatibility);
|
||||
compatibility, ashift);
|
||||
|
||||
if (msgid != NULL) {
|
||||
if (ret >= NMSGID)
|
||||
@@ -526,7 +534,7 @@ zpool_status_t
|
||||
zpool_import_status(nvlist_t *config, const char **msgid,
|
||||
zpool_errata_t *errata)
|
||||
{
|
||||
zpool_status_t ret = check_status(config, B_TRUE, errata, NULL);
|
||||
zpool_status_t ret = check_status(config, B_TRUE, errata, NULL, 0);
|
||||
|
||||
if (ret >= NMSGID)
|
||||
*msgid = NULL;
|
||||
|
||||
@@ -617,6 +617,7 @@
|
||||
<array-type-def dimensions='1' type-id='de572c22' size-in-bits='1472' id='6d3c2f42'>
|
||||
<subrange length='23' type-id='7359adad' id='fdd0f594'/>
|
||||
</array-type-def>
|
||||
<type-decl name='long long int' size-in-bits='64' id='1eb56b1e'/>
|
||||
<array-type-def dimensions='1' type-id='3a47d82b' size-in-bits='256' id='a133ec23'>
|
||||
<subrange length='4' type-id='7359adad' id='16fe7105'/>
|
||||
</array-type-def>
|
||||
@@ -988,13 +989,6 @@
|
||||
</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='d315442e' size-in-bits='16' id='811205dc'>
|
||||
<subrange length='1' type-id='7359adad' id='52f813b4'/>
|
||||
</array-type-def>
|
||||
<array-type-def dimensions='1' type-id='d3130597' size-in-bits='768' id='f63f23b9'>
|
||||
<subrange length='12' type-id='7359adad' id='84827bdc'/>
|
||||
</array-type-def>
|
||||
<type-decl name='long long int' size-in-bits='64' id='1eb56b1e'/>
|
||||
<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'/>
|
||||
@@ -1029,93 +1023,6 @@
|
||||
<var-decl name='mnt_minor' type-id='3502e3ff' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='__u16' type-id='8efea9e5' id='d315442e'/>
|
||||
<typedef-decl name='__s32' type-id='95e97e5e' id='3158a266'/>
|
||||
<typedef-decl name='__u32' type-id='f0981eeb' id='3f1a6b60'/>
|
||||
<typedef-decl name='__s64' type-id='1eb56b1e' id='49659421'/>
|
||||
<typedef-decl name='__u64' type-id='3a47d82b' id='d3130597'/>
|
||||
<class-decl name='statx_timestamp' size-in-bits='128' is-struct='yes' visibility='default' id='94101016'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='tv_sec' type-id='49659421' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='tv_nsec' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='96'>
|
||||
<var-decl name='__reserved' type-id='3158a266' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<class-decl name='statx' size-in-bits='2048' is-struct='yes' visibility='default' id='720b04c5'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='stx_mask' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='32'>
|
||||
<var-decl name='stx_blksize' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='stx_attributes' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='stx_nlink' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='160'>
|
||||
<var-decl name='stx_uid' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='192'>
|
||||
<var-decl name='stx_gid' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='224'>
|
||||
<var-decl name='stx_mode' type-id='d315442e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='240'>
|
||||
<var-decl name='__spare0' type-id='811205dc' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='256'>
|
||||
<var-decl name='stx_ino' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='320'>
|
||||
<var-decl name='stx_size' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='384'>
|
||||
<var-decl name='stx_blocks' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='448'>
|
||||
<var-decl name='stx_attributes_mask' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='512'>
|
||||
<var-decl name='stx_atime' type-id='94101016' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='640'>
|
||||
<var-decl name='stx_btime' type-id='94101016' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='768'>
|
||||
<var-decl name='stx_ctime' type-id='94101016' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='896'>
|
||||
<var-decl name='stx_mtime' type-id='94101016' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1024'>
|
||||
<var-decl name='stx_rdev_major' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1056'>
|
||||
<var-decl name='stx_rdev_minor' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1088'>
|
||||
<var-decl name='stx_dev_major' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1120'>
|
||||
<var-decl name='stx_dev_minor' type-id='3f1a6b60' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1152'>
|
||||
<var-decl name='stx_mnt_id' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1216'>
|
||||
<var-decl name='__spare2' type-id='d3130597' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='1280'>
|
||||
<var-decl name='__spare3' type-id='f63f23b9' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<class-decl name='mntent' size-in-bits='320' is-struct='yes' visibility='default' id='56fe4a37'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='mnt_fsname' type-id='26a90f95' visibility='default'/>
|
||||
@@ -1191,8 +1098,6 @@
|
||||
<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'/>
|
||||
<pointer-type-def type-id='720b04c5' size-in-bits='64' id='936b8e35'/>
|
||||
<qualified-type-def type-id='936b8e35' restrict='yes' id='31d265b7'/>
|
||||
<function-decl name='getmntent_r' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<parameter type-id='3cad23cd'/>
|
||||
@@ -1208,14 +1113,6 @@
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='statx' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='f0981eeb'/>
|
||||
<parameter type-id='31d265b7'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='stat64' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter type-id='f1cadedf'/>
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2018 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2016 Actifio, Inc. All rights reserved.
|
||||
* Copyright (c) 2025, Klara, Inc.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
@@ -645,39 +646,60 @@ __dprintf(boolean_t dprint, const char *file, const char *func,
|
||||
* cmn_err() and panic()
|
||||
* =========================================================================
|
||||
*/
|
||||
static char ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
|
||||
static char ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
|
||||
|
||||
__attribute__((noreturn)) void
|
||||
vpanic(const char *fmt, va_list adx)
|
||||
static __attribute__((noreturn)) void
|
||||
panic_stop_or_abort(void)
|
||||
{
|
||||
(void) fprintf(stderr, "error: ");
|
||||
(void) vfprintf(stderr, fmt, adx);
|
||||
(void) fprintf(stderr, "\n");
|
||||
const char *stopenv = getenv("LIBZPOOL_PANIC_STOP");
|
||||
if (stopenv != NULL && atoi(stopenv)) {
|
||||
fputs("libzpool: LIBZPOOL_PANIC_STOP is set, sending "
|
||||
"SIGSTOP to process group\n", stderr);
|
||||
fflush(stderr);
|
||||
|
||||
kill(0, SIGSTOP);
|
||||
|
||||
fputs("libzpool: continued after panic stop, "
|
||||
"aborting\n", stderr);
|
||||
}
|
||||
|
||||
abort(); /* think of it as a "user-level crash dump" */
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void
|
||||
panic(const char *fmt, ...)
|
||||
static void
|
||||
vcmn_msg(int ce, const char *fmt, va_list adx)
|
||||
{
|
||||
va_list adx;
|
||||
switch (ce) {
|
||||
case CE_IGNORE:
|
||||
return;
|
||||
case CE_CONT:
|
||||
break;
|
||||
case CE_NOTE:
|
||||
fputs("libzpool: NOTICE: ", stderr);
|
||||
break;
|
||||
case CE_WARN:
|
||||
fputs("libzpool: WARNING: ", stderr);
|
||||
break;
|
||||
case CE_PANIC:
|
||||
fputs("libzpool: PANIC: ", stderr);
|
||||
break;
|
||||
default:
|
||||
fputs("libzpool: [unknown severity %d]: ", stderr);
|
||||
break;
|
||||
}
|
||||
|
||||
va_start(adx, fmt);
|
||||
vpanic(fmt, adx);
|
||||
va_end(adx);
|
||||
vfprintf(stderr, fmt, adx);
|
||||
if (ce != CE_CONT)
|
||||
fputc('\n', stderr);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
void
|
||||
vcmn_err(int ce, const char *fmt, va_list adx)
|
||||
{
|
||||
vcmn_msg(ce, fmt, adx);
|
||||
|
||||
if (ce == CE_PANIC)
|
||||
vpanic(fmt, adx);
|
||||
if (ce != CE_NOTE) { /* suppress noise in userland stress testing */
|
||||
(void) fprintf(stderr, "%s", ce_prefix[ce]);
|
||||
(void) vfprintf(stderr, fmt, adx);
|
||||
(void) fprintf(stderr, "%s", ce_suffix[ce]);
|
||||
}
|
||||
panic_stop_or_abort();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -690,6 +712,25 @@ cmn_err(int ce, const char *fmt, ...)
|
||||
va_end(adx);
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void
|
||||
panic(const char *fmt, ...)
|
||||
{
|
||||
va_list adx;
|
||||
|
||||
va_start(adx, fmt);
|
||||
vcmn_msg(CE_PANIC, fmt, adx);
|
||||
va_end(adx);
|
||||
|
||||
panic_stop_or_abort();
|
||||
}
|
||||
|
||||
__attribute__((noreturn)) void
|
||||
vpanic(const char *fmt, va_list adx)
|
||||
{
|
||||
vcmn_msg(CE_PANIC, fmt, adx);
|
||||
panic_stop_or_abort();
|
||||
}
|
||||
|
||||
/*
|
||||
* =========================================================================
|
||||
* misc routines
|
||||
|
||||
@@ -144,6 +144,20 @@ subcommand.
|
||||
Display statistics regarding the number, size
|
||||
.Pq logical, physical and allocated
|
||||
and deduplication of blocks.
|
||||
.It Fl -bin Ns = Ns ( Li lsize Ns | Ns Li psize Ns | Ns Li asize )
|
||||
When used with
|
||||
.Fl bb ,
|
||||
sort blocks into all three bins according to the given size (instead of binning
|
||||
a block for each size separately).
|
||||
.Pp
|
||||
For instance, with
|
||||
.Fl -bin Ns = Ns Li lsize ,
|
||||
a block with lsize of 16K and psize of 4K will be added to the 16K bin
|
||||
in all three columns.
|
||||
.It Fl -class Ns = Ns ( Li normal Ns | Ns Li special Ns | Ns Li dedup Ns | Ns Li other ) Ns Op , Ns …
|
||||
When used with
|
||||
.Fl bb ,
|
||||
only consider blocks from these allocation classes.
|
||||
.It Fl B , -backup
|
||||
Generate a backup stream, similar to
|
||||
.Nm zfs Cm send ,
|
||||
|
||||
@@ -138,6 +138,20 @@ This injector is automatically cleared after the import is finished.
|
||||
.
|
||||
.It Xo
|
||||
.Nm zinject
|
||||
.Fl E Ar delay
|
||||
.Op Fl a
|
||||
.Op Fl m
|
||||
.Op Fl f Ar freq
|
||||
.Op Fl l Ar level
|
||||
.Op Fl r Ar range
|
||||
.Op Fl T Ar iotype
|
||||
.Op Fl t Ar type Ns | Ns Fl b Ar bookmark
|
||||
.Xc
|
||||
Inject pipeline ready stage delays for the given object or bookmark.
|
||||
The delay is specified in milliseconds.
|
||||
.
|
||||
.It Xo
|
||||
.Nm zinject
|
||||
.Fl I
|
||||
.Op Fl s Ar seconds Ns | Ns Fl g Ar txgs
|
||||
.Ar pool
|
||||
|
||||
@@ -58,8 +58,8 @@ This command supports removing hot spare, cache, log, and both mirrored and
|
||||
non-redundant primary top-level vdevs, including dedup and special vdevs.
|
||||
.Pp
|
||||
Top-level vdevs can only be removed if the primary pool storage does not contain
|
||||
a top-level raidz vdev, all top-level vdevs have the same sector size, and the
|
||||
keys for all encrypted datasets are loaded.
|
||||
a top-level raidz or draid vdev, all top-level vdevs have the same ashift size,
|
||||
and the keys for all encrypted datasets are loaded.
|
||||
.Pp
|
||||
Removing a top-level vdev reduces the total amount of space in the storage pool.
|
||||
The specified device will be evacuated by copying all allocated space from it to
|
||||
|
||||
@@ -77,7 +77,8 @@ static const uint32_t SHA256_K[64] = {
|
||||
h = g, g = f, f = e, e = d + T1; \
|
||||
d = c, c = b, b = a, a = T1 + T2;
|
||||
|
||||
static void sha256_generic(uint32_t state[8], const void *data, size_t num_blks)
|
||||
static void
|
||||
icp_sha256_generic(uint32_t state[8], const void *data, size_t num_blks)
|
||||
{
|
||||
uint64_t blk;
|
||||
|
||||
@@ -173,7 +174,8 @@ static const uint64_t SHA512_K[80] = {
|
||||
0x5fcb6fab3ad6faec, 0x6c44198c4a475817
|
||||
};
|
||||
|
||||
static void sha512_generic(uint64_t state[8], const void *data, size_t num_blks)
|
||||
static void
|
||||
icp_sha512_generic(uint64_t state[8], const void *data, size_t num_blks)
|
||||
{
|
||||
uint64_t blk;
|
||||
|
||||
@@ -226,7 +228,8 @@ static void sha512_generic(uint64_t state[8], const void *data, size_t num_blks)
|
||||
}
|
||||
}
|
||||
|
||||
static void sha256_update(sha256_ctx *ctx, const uint8_t *data, size_t len)
|
||||
static void
|
||||
icp_sha256_update(sha256_ctx *ctx, const uint8_t *data, size_t len)
|
||||
{
|
||||
uint64_t pos = ctx->count[0];
|
||||
uint64_t total = ctx->count[1];
|
||||
@@ -258,7 +261,8 @@ static void sha256_update(sha256_ctx *ctx, const uint8_t *data, size_t len)
|
||||
ctx->count[1] = total;
|
||||
}
|
||||
|
||||
static void sha512_update(sha512_ctx *ctx, const uint8_t *data, size_t len)
|
||||
static void
|
||||
icp_sha512_update(sha512_ctx *ctx, const uint8_t *data, size_t len)
|
||||
{
|
||||
uint64_t pos = ctx->count[0];
|
||||
uint64_t total = ctx->count[1];
|
||||
@@ -290,7 +294,8 @@ static void sha512_update(sha512_ctx *ctx, const uint8_t *data, size_t len)
|
||||
ctx->count[1] = total;
|
||||
}
|
||||
|
||||
static void sha256_final(sha256_ctx *ctx, uint8_t *result, int bits)
|
||||
static void
|
||||
icp_sha256_final(sha256_ctx *ctx, uint8_t *result, int bits)
|
||||
{
|
||||
uint64_t mlen, pos = ctx->count[0];
|
||||
uint8_t *m = ctx->wbuf;
|
||||
@@ -334,7 +339,8 @@ static void sha256_final(sha256_ctx *ctx, uint8_t *result, int bits)
|
||||
memset(ctx, 0, sizeof (*ctx));
|
||||
}
|
||||
|
||||
static void sha512_final(sha512_ctx *ctx, uint8_t *result, int bits)
|
||||
static void
|
||||
icp_sha512_final(sha512_ctx *ctx, uint8_t *result, int bits)
|
||||
{
|
||||
uint64_t mlen, pos = ctx->count[0];
|
||||
uint8_t *m = ctx->wbuf, *r;
|
||||
@@ -461,14 +467,14 @@ SHA2Update(SHA2_CTX *ctx, const void *data, size_t len)
|
||||
|
||||
switch (ctx->algotype) {
|
||||
case SHA256:
|
||||
sha256_update(&ctx->sha256, data, len);
|
||||
icp_sha256_update(&ctx->sha256, data, len);
|
||||
break;
|
||||
case SHA512:
|
||||
case SHA512_HMAC_MECH_INFO_TYPE:
|
||||
sha512_update(&ctx->sha512, data, len);
|
||||
icp_sha512_update(&ctx->sha512, data, len);
|
||||
break;
|
||||
case SHA512_256:
|
||||
sha512_update(&ctx->sha512, data, len);
|
||||
icp_sha512_update(&ctx->sha512, data, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -479,32 +485,33 @@ SHA2Final(void *digest, SHA2_CTX *ctx)
|
||||
{
|
||||
switch (ctx->algotype) {
|
||||
case SHA256:
|
||||
sha256_final(&ctx->sha256, digest, 256);
|
||||
icp_sha256_final(&ctx->sha256, digest, 256);
|
||||
break;
|
||||
case SHA512:
|
||||
case SHA512_HMAC_MECH_INFO_TYPE:
|
||||
sha512_final(&ctx->sha512, digest, 512);
|
||||
icp_sha512_final(&ctx->sha512, digest, 512);
|
||||
break;
|
||||
case SHA512_256:
|
||||
sha512_final(&ctx->sha512, digest, 256);
|
||||
icp_sha512_final(&ctx->sha512, digest, 256);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* the generic implementation is always okay */
|
||||
static boolean_t sha2_is_supported(void)
|
||||
static boolean_t
|
||||
icp_sha2_is_supported(void)
|
||||
{
|
||||
return (B_TRUE);
|
||||
}
|
||||
|
||||
const sha256_ops_t sha256_generic_impl = {
|
||||
.name = "generic",
|
||||
.transform = sha256_generic,
|
||||
.is_supported = sha2_is_supported
|
||||
.transform = icp_sha256_generic,
|
||||
.is_supported = icp_sha2_is_supported
|
||||
};
|
||||
|
||||
const sha512_ops_t sha512_generic_impl = {
|
||||
.name = "generic",
|
||||
.transform = sha512_generic,
|
||||
.is_supported = sha2_is_supported
|
||||
.transform = icp_sha512_generic,
|
||||
.is_supported = icp_sha2_is_supported
|
||||
};
|
||||
@@ -762,8 +762,7 @@ zfsctl_common_pathconf(struct vop_pathconf_args *ap)
|
||||
return (0);
|
||||
|
||||
case _PC_MIN_HOLE_SIZE:
|
||||
*ap->a_retval = (int)SPA_MINBLOCKSIZE;
|
||||
return (0);
|
||||
return (EINVAL);
|
||||
|
||||
case _PC_ACL_EXTENDED:
|
||||
*ap->a_retval = 0;
|
||||
|
||||
@@ -4116,6 +4116,7 @@ zfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
|
||||
{
|
||||
znode_t *zp;
|
||||
zfsvfs_t *zfsvfs;
|
||||
uint_t blksize, iosize;
|
||||
int error;
|
||||
|
||||
switch (cmd) {
|
||||
@@ -4127,8 +4128,20 @@ zfs_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr,
|
||||
*valp = 64;
|
||||
return (0);
|
||||
case _PC_MIN_HOLE_SIZE:
|
||||
*valp = (int)SPA_MINBLOCKSIZE;
|
||||
return (0);
|
||||
iosize = vp->v_mount->mnt_stat.f_iosize;
|
||||
if (vp->v_type == VREG) {
|
||||
zp = VTOZ(vp);
|
||||
blksize = zp->z_blksz;
|
||||
if (zp->z_size <= blksize)
|
||||
blksize = MAX(blksize, iosize);
|
||||
*valp = (int)blksize;
|
||||
return (0);
|
||||
}
|
||||
if (vp->v_type == VDIR) {
|
||||
*valp = (int)iosize;
|
||||
return (0);
|
||||
}
|
||||
return (EINVAL);
|
||||
case _PC_ACL_EXTENDED:
|
||||
#if 0 /* POSIX ACLs are not implemented for ZFS on FreeBSD yet. */
|
||||
zp = VTOZ(vp);
|
||||
@@ -4210,8 +4223,20 @@ zfs_getpages(struct vnode *vp, vm_page_t *ma, int count, int *rbehind,
|
||||
|
||||
zfs_vmobject_wlock(object);
|
||||
(void) vm_page_grab_pages(object, OFF_TO_IDX(start),
|
||||
VM_ALLOC_NORMAL | VM_ALLOC_WAITOK | VM_ALLOC_ZERO,
|
||||
VM_ALLOC_NORMAL | VM_ALLOC_WAITOK,
|
||||
ma, count);
|
||||
if (!vm_page_all_valid(ma[count - 1])) {
|
||||
/*
|
||||
* Later in this function, we copy DMU data to
|
||||
* invalid pages only. The last page may not be
|
||||
* entirely filled though, if the file does not
|
||||
* end on a page boundary. Therefore, we zero
|
||||
* that last page here to make sure it does not
|
||||
* contain garbage after the end of file.
|
||||
*/
|
||||
ASSERT(vm_page_none_valid(ma[count - 1]));
|
||||
vm_page_zero_invalid(ma[count - 1], FALSE);
|
||||
}
|
||||
zfs_vmobject_wunlock(object);
|
||||
}
|
||||
if (blksz == zp->z_blksz)
|
||||
|
||||
@@ -25,6 +25,10 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2025, Rob Norris <robn@despairlabs.com>
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <sys/kmem.h>
|
||||
@@ -56,6 +60,19 @@ typedef struct zone_dataset {
|
||||
} zone_dataset_t;
|
||||
|
||||
#ifdef CONFIG_USER_NS
|
||||
|
||||
/*
|
||||
* Linux 6.18 moved the generic namespace type away from ns->ops->type onto
|
||||
* ns_common itself.
|
||||
*/
|
||||
#ifdef HAVE_NS_COMMON_TYPE
|
||||
#define ns_is_newuser(ns) \
|
||||
((ns)->ns_type == CLONE_NEWUSER)
|
||||
#else
|
||||
#define ns_is_newuser(ns) \
|
||||
((ns)->ops != NULL && (ns)->ops->type == CLONE_NEWUSER)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Returns:
|
||||
* - 0 on success
|
||||
@@ -84,7 +101,7 @@ user_ns_get(int fd, struct user_namespace **userns)
|
||||
goto done;
|
||||
}
|
||||
ns = get_proc_ns(file_inode(nsfile));
|
||||
if (ns->ops->type != CLONE_NEWUSER) {
|
||||
if (!ns_is_newuser(ns)) {
|
||||
error = ENOTTY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
* Copyright (c) 2014 by Chunwei Chen. All rights reserved.
|
||||
* Copyright (c) 2019 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2023, 2024, Klara Inc.
|
||||
* Copyright (c) 2025, Rob Norris <robn@despairlabs.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -1109,6 +1110,14 @@ abd_return_buf_copy(abd_t *abd, void *buf, size_t n)
|
||||
#define ABD_ITER_PAGE_SIZE(page) (PAGESIZE)
|
||||
#endif
|
||||
|
||||
#ifndef nth_page
|
||||
/*
|
||||
* Since 6.18 nth_page() no longer exists, and is no longer required to iterate
|
||||
* within a single SG entry, so we replace it with a simple addition.
|
||||
*/
|
||||
#define nth_page(p, n) ((p)+(n))
|
||||
#endif
|
||||
|
||||
void
|
||||
abd_iter_page(struct abd_iter *aiter)
|
||||
{
|
||||
|
||||
@@ -2524,7 +2524,7 @@ zfs_zaccess_common(znode_t *zp, uint32_t v4_mode, uint32_t *working_mode,
|
||||
* Also note: DOS R/O is ignored for directories.
|
||||
*/
|
||||
if ((v4_mode & WRITE_MASK_DATA) &&
|
||||
S_ISDIR(ZTOI(zp)->i_mode) &&
|
||||
!S_ISDIR(ZTOI(zp)->i_mode) &&
|
||||
(zp->z_pflags & ZFS_READONLY)) {
|
||||
return (SET_ERROR(EPERM));
|
||||
}
|
||||
|
||||
@@ -2033,10 +2033,7 @@ zfs_setattr(znode_t *zp, vattr_t *vap, int flags, cred_t *cr, zidmap_t *mnt_ns)
|
||||
goto out3;
|
||||
}
|
||||
|
||||
if ((mask & ATTR_SIZE) && (zp->z_pflags & ZFS_READONLY)) {
|
||||
err = SET_ERROR(EPERM);
|
||||
goto out3;
|
||||
}
|
||||
/* ZFS_READONLY will be handled in zfs_zaccess() */
|
||||
|
||||
/*
|
||||
* Verify timestamps doesn't overflow 32 bits.
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
* Copyright (c) 2011, Lawrence Livermore National Security, LLC.
|
||||
* Copyright (c) 2015 by Chunwei Chen. All rights reserved.
|
||||
* Copyright (c) 2025, Klara, Inc.
|
||||
* Copyright (c) 2025, Rob Norris <robn@despairlabs.com>
|
||||
*/
|
||||
|
||||
|
||||
@@ -478,6 +479,7 @@ zpl_putpage(struct page *pp, struct writeback_control *wbc, void *data)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#ifdef HAVE_WRITE_CACHE_PAGES
|
||||
#ifdef HAVE_WRITEPAGE_T_FOLIO
|
||||
static int
|
||||
zpl_putfolio(struct folio *pp, struct writeback_control *wbc, void *data)
|
||||
@@ -499,6 +501,78 @@ zpl_write_cache_pages(struct address_space *mapping,
|
||||
#endif
|
||||
return (result);
|
||||
}
|
||||
#else
|
||||
static inline int
|
||||
zpl_write_cache_pages(struct address_space *mapping,
|
||||
struct writeback_control *wbc, void *data)
|
||||
{
|
||||
pgoff_t start = wbc->range_start >> PAGE_SHIFT;
|
||||
pgoff_t end = wbc->range_end >> PAGE_SHIFT;
|
||||
|
||||
struct folio_batch fbatch;
|
||||
folio_batch_init(&fbatch);
|
||||
|
||||
/*
|
||||
* This atomically (-ish) tags all DIRTY pages in the range with
|
||||
* TOWRITE, allowing users to continue dirtying or undirtying pages
|
||||
* while we get on with writeback, without us treading on each other.
|
||||
*/
|
||||
tag_pages_for_writeback(mapping, start, end);
|
||||
|
||||
int err = 0;
|
||||
unsigned int npages;
|
||||
|
||||
/*
|
||||
* Grab references to the TOWRITE pages just flagged. This may not get
|
||||
* all of them, so we do it in a loop until there are none left.
|
||||
*/
|
||||
while ((npages = filemap_get_folios_tag(mapping, &start, end,
|
||||
PAGECACHE_TAG_TOWRITE, &fbatch)) != 0) {
|
||||
|
||||
/* Loop over each page and write it out. */
|
||||
struct folio *folio;
|
||||
while ((folio = folio_batch_next(&fbatch)) != NULL) {
|
||||
folio_lock(folio);
|
||||
|
||||
/*
|
||||
* If the folio has been remapped, or is no longer
|
||||
* dirty, then there's nothing to do.
|
||||
*/
|
||||
if (folio->mapping != mapping ||
|
||||
!folio_test_dirty(folio)) {
|
||||
folio_unlock(folio);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If writeback is already in progress, wait for it to
|
||||
* finish. We continue after this even if the page
|
||||
* ends up clean; zfs_putpage() will skip it if no
|
||||
* further work is required.
|
||||
*/
|
||||
while (folio_test_writeback(folio))
|
||||
folio_wait_bit(folio, PG_writeback);
|
||||
|
||||
/*
|
||||
* Write it out and collect any error. zfs_putpage()
|
||||
* will clear the TOWRITE and DIRTY flags, and return
|
||||
* with the page unlocked.
|
||||
*/
|
||||
int ferr = zpl_putpage(&folio->page, wbc, data);
|
||||
if (err == 0 && ferr != 0)
|
||||
err = ferr;
|
||||
|
||||
/* Housekeeping for the caller. */
|
||||
wbc->nr_to_write -= folio_nr_pages(folio);
|
||||
}
|
||||
|
||||
/* Release any remaining references on the batch. */
|
||||
folio_batch_release(&fbatch);
|
||||
}
|
||||
|
||||
return (err);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
zpl_writepages(struct address_space *mapping, struct writeback_control *wbc)
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
* Copyright (c) 2011, Lawrence Livermore National Security, LLC.
|
||||
* Copyright (c) 2023, Datto Inc. All rights reserved.
|
||||
* Copyright (c) 2025, Klara, Inc.
|
||||
* Copyright (c) 2025, Rob Norris <robn@despairlabs.com>
|
||||
*/
|
||||
|
||||
|
||||
@@ -33,6 +34,7 @@
|
||||
#include <sys/zpl.h>
|
||||
#include <linux/iversion.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/vfs_compat.h>
|
||||
|
||||
/*
|
||||
* What to do when the last reference to an inode is released. If 0, the kernel
|
||||
@@ -104,7 +106,7 @@ zpl_dirty_inode(struct inode *ip, int flags)
|
||||
* reporting memory pressure and requests OpenZFS release some memory (see
|
||||
* zfs_prune()).
|
||||
*
|
||||
* When set to 1, we call generic_delete_node(), which always returns "destroy
|
||||
* When set to 1, we call generic_delete_inode(), which always returns "destroy
|
||||
* immediately", resulting in inodes being destroyed immediately, releasing
|
||||
* their associated dnodes and dbufs to the dbuf cached and the ARC to be
|
||||
* evicted as normal.
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2012, 2020 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2024, Rob Norris <robn@despairlabs.com>
|
||||
* Copyright (c) 2024, 2025, Rob Norris <robn@despairlabs.com>
|
||||
* Copyright (c) 2024, 2025, Klara, Inc.
|
||||
*/
|
||||
|
||||
@@ -337,16 +337,14 @@ zvol_discard(zv_request_t *zvr)
|
||||
}
|
||||
|
||||
/*
|
||||
* Align the request to volume block boundaries when a secure erase is
|
||||
* not required. This will prevent dnode_free_range() from zeroing out
|
||||
* the unaligned parts which is slow (read-modify-write) and useless
|
||||
* since we are not freeing any space by doing so.
|
||||
* Align the request to volume block boundaries. This will prevent
|
||||
* dnode_free_range() from zeroing out the unaligned parts which is
|
||||
* slow (read-modify-write) and useless since we are not freeing any
|
||||
* space by doing so.
|
||||
*/
|
||||
if (!io_is_secure_erase(bio, rq)) {
|
||||
start = P2ROUNDUP(start, zv->zv_volblocksize);
|
||||
end = P2ALIGN_TYPED(end, zv->zv_volblocksize, uint64_t);
|
||||
size = end - start;
|
||||
}
|
||||
start = P2ROUNDUP(start, zv->zv_volblocksize);
|
||||
end = P2ALIGN_TYPED(end, zv->zv_volblocksize, uint64_t);
|
||||
size = end - start;
|
||||
|
||||
if (start >= end)
|
||||
goto unlock;
|
||||
@@ -467,6 +465,24 @@ zvol_read_task(void *arg)
|
||||
zv_request_task_free(task);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note:
|
||||
*
|
||||
* The kernel uses different enum names for the IO opcode, depending on the
|
||||
* kernel version ('req_opf', 'req_op'). To sidestep this, use macros rather
|
||||
* than inline functions for these checks.
|
||||
*/
|
||||
/* Should this IO go down the zvol write path? */
|
||||
#define ZVOL_OP_IS_WRITE(op) \
|
||||
(op == REQ_OP_WRITE || \
|
||||
op == REQ_OP_FLUSH || \
|
||||
op == REQ_OP_DISCARD)
|
||||
|
||||
/* Is this IO type supported by zvols? */
|
||||
#define ZVOL_OP_IS_SUPPORTED(op) (op == REQ_OP_READ || ZVOL_OP_IS_WRITE(op))
|
||||
|
||||
/* Get the IO opcode */
|
||||
#define ZVOL_OP(bio, rq) (bio != NULL ? bio_op(bio) : req_op(rq))
|
||||
|
||||
/*
|
||||
* Process a BIO or request
|
||||
@@ -486,27 +502,32 @@ zvol_request_impl(zvol_state_t *zv, struct bio *bio, struct request *rq,
|
||||
uint64_t size = io_size(bio, rq);
|
||||
int rw;
|
||||
|
||||
if (rq != NULL) {
|
||||
/*
|
||||
* Flush & trim requests go down the zvol_write codepath. Or
|
||||
* more specifically:
|
||||
*
|
||||
* If request is a write, or if it's op_is_sync() and not a
|
||||
* read, or if it's a flush, or if it's a discard, then send the
|
||||
* request down the write path.
|
||||
*/
|
||||
if (op_is_write(rq->cmd_flags) ||
|
||||
(op_is_sync(rq->cmd_flags) && req_op(rq) != REQ_OP_READ) ||
|
||||
req_op(rq) == REQ_OP_FLUSH ||
|
||||
op_is_discard(rq->cmd_flags)) {
|
||||
rw = WRITE;
|
||||
} else {
|
||||
rw = READ;
|
||||
}
|
||||
} else {
|
||||
rw = bio_data_dir(bio);
|
||||
if (unlikely(!ZVOL_OP_IS_SUPPORTED(ZVOL_OP(bio, rq)))) {
|
||||
zfs_dbgmsg("Unsupported zvol %s, op=%d, flags=0x%x",
|
||||
rq != NULL ? "request" : "BIO",
|
||||
ZVOL_OP(bio, rq),
|
||||
rq != NULL ? rq->cmd_flags : bio->bi_opf);
|
||||
ASSERT(ZVOL_OP_IS_SUPPORTED(ZVOL_OP(bio, rq)));
|
||||
zvol_end_io(bio, rq, SET_ERROR(ENOTSUPP));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ZVOL_OP_IS_WRITE(ZVOL_OP(bio, rq))) {
|
||||
rw = WRITE;
|
||||
} else {
|
||||
rw = READ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sanity check
|
||||
*
|
||||
* If we're a BIO, check our rw matches the kernel's
|
||||
* bio_data_dir(bio) rw. We need to check because we support fewer
|
||||
* IO operations, and want to verify that what we think are reads and
|
||||
* writes from those operations match what the kernel thinks.
|
||||
*/
|
||||
ASSERT(rq != NULL || rw == bio_data_dir(bio));
|
||||
|
||||
if (unlikely(zv->zv_flags & ZVOL_REMOVING)) {
|
||||
zvol_end_io(bio, rq, SET_ERROR(ENXIO));
|
||||
goto out;
|
||||
@@ -610,7 +631,7 @@ zvol_request_impl(zvol_state_t *zv, struct bio *bio, struct request *rq,
|
||||
* interfaces lack this functionality (they block waiting for
|
||||
* the i/o to complete).
|
||||
*/
|
||||
if (io_is_discard(bio, rq) || io_is_secure_erase(bio, rq)) {
|
||||
if (io_is_discard(bio, rq)) {
|
||||
if (force_sync) {
|
||||
zvol_discard(&zvr);
|
||||
} else {
|
||||
@@ -1011,12 +1032,12 @@ zvol_os_update_volsize(zvol_state_t *zv, uint64_t volsize)
|
||||
* tiny devices. For devices over 1 Mib a standard head and sector count
|
||||
* is used to keep the cylinders count reasonable.
|
||||
*/
|
||||
static int
|
||||
zvol_getgeo(struct block_device *bdev, struct hd_geometry *geo)
|
||||
static inline int
|
||||
zvol_getgeo_impl(struct gendisk *disk, struct hd_geometry *geo)
|
||||
{
|
||||
zvol_state_t *zv = atomic_load_ptr(&disk->private_data);
|
||||
sector_t sectors;
|
||||
|
||||
zvol_state_t *zv = atomic_load_ptr(&bdev->bd_disk->private_data);
|
||||
ASSERT3P(zv, !=, NULL);
|
||||
ASSERT3U(zv->zv_open_count, >, 0);
|
||||
|
||||
@@ -1036,6 +1057,20 @@ zvol_getgeo(struct block_device *bdev, struct hd_geometry *geo)
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifdef HAVE_BLOCK_DEVICE_OPERATIONS_GETGEO_GENDISK
|
||||
static int
|
||||
zvol_getgeo(struct gendisk *disk, struct hd_geometry *geo)
|
||||
{
|
||||
return (zvol_getgeo_impl(disk, geo));
|
||||
}
|
||||
#else
|
||||
static int
|
||||
zvol_getgeo(struct block_device *bdev, struct hd_geometry *geo)
|
||||
{
|
||||
return (zvol_getgeo_impl(bdev->bd_disk, geo));
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Why have two separate block_device_operations structs?
|
||||
*
|
||||
@@ -1479,7 +1514,7 @@ zvol_os_remove_minor(zvol_state_t *zv)
|
||||
if (zso->use_blk_mq)
|
||||
blk_mq_free_tag_set(&zso->tag_set);
|
||||
|
||||
ida_simple_remove(&zvol_ida, MINOR(zso->zvo_dev) >> ZVOL_MINOR_BITS);
|
||||
ida_free(&zvol_ida, MINOR(zso->zvo_dev) >> ZVOL_MINOR_BITS);
|
||||
|
||||
kmem_free(zso, sizeof (struct zvol_state_os));
|
||||
|
||||
@@ -1634,7 +1669,7 @@ zvol_os_create_minor(const char *name)
|
||||
if (zvol_inhibit_dev)
|
||||
return (0);
|
||||
|
||||
idx = ida_simple_get(&zvol_ida, 0, 0, kmem_flags_convert(KM_SLEEP));
|
||||
idx = ida_alloc(&zvol_ida, kmem_flags_convert(KM_SLEEP));
|
||||
if (idx < 0)
|
||||
return (SET_ERROR(-idx));
|
||||
minor = idx << ZVOL_MINOR_BITS;
|
||||
@@ -1642,7 +1677,7 @@ zvol_os_create_minor(const char *name)
|
||||
/* too many partitions can cause an overflow */
|
||||
zfs_dbgmsg("zvol: create minor overflow: %s, minor %u/%u",
|
||||
name, minor, MINOR(minor));
|
||||
ida_simple_remove(&zvol_ida, idx);
|
||||
ida_free(&zvol_ida, idx);
|
||||
return (SET_ERROR(EINVAL));
|
||||
}
|
||||
|
||||
@@ -1650,7 +1685,7 @@ zvol_os_create_minor(const char *name)
|
||||
if (zv) {
|
||||
ASSERT(MUTEX_HELD(&zv->zv_state_lock));
|
||||
mutex_exit(&zv->zv_state_lock);
|
||||
ida_simple_remove(&zvol_ida, idx);
|
||||
ida_free(&zvol_ida, idx);
|
||||
return (SET_ERROR(EEXIST));
|
||||
}
|
||||
|
||||
@@ -1750,7 +1785,7 @@ out_doi:
|
||||
rw_exit(&zvol_state_lock);
|
||||
error = zvol_os_add_disk(zv->zv_zso->zvo_disk);
|
||||
} else {
|
||||
ida_simple_remove(&zvol_ida, idx);
|
||||
ida_free(&zvol_ida, idx);
|
||||
}
|
||||
|
||||
return (error);
|
||||
|
||||
@@ -364,8 +364,8 @@ zfs_prop_init(void)
|
||||
|
||||
static const zprop_index_t xattr_table[] = {
|
||||
{ "off", ZFS_XATTR_OFF },
|
||||
{ "on", ZFS_XATTR_SA },
|
||||
{ "sa", ZFS_XATTR_SA },
|
||||
{ "on", ZFS_XATTR_SA },
|
||||
{ "dir", ZFS_XATTR_DIR },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@@ -1157,7 +1157,7 @@ buf_fini(void)
|
||||
#if defined(_KERNEL)
|
||||
/*
|
||||
* Large allocations which do not require contiguous pages
|
||||
* should be using vmem_free() in the linux kernel\
|
||||
* should be using vmem_free() in the linux kernel.
|
||||
*/
|
||||
vmem_free(buf_hash_table.ht_table,
|
||||
(buf_hash_table.ht_mask + 1) * sizeof (void *));
|
||||
@@ -1392,6 +1392,7 @@ arc_get_complevel(arc_buf_t *buf)
|
||||
return (buf->b_hdr->b_complevel);
|
||||
}
|
||||
|
||||
__maybe_unused
|
||||
static inline boolean_t
|
||||
arc_buf_is_shared(arc_buf_t *buf)
|
||||
{
|
||||
@@ -4650,10 +4651,10 @@ arc_flush_task(void *arg)
|
||||
arc_flush_impl(spa_guid, B_FALSE);
|
||||
arc_async_flush_remove(spa_guid, af->af_cache_level);
|
||||
|
||||
uint64_t elaspsed = NSEC2MSEC(gethrtime() - start_time);
|
||||
if (elaspsed > 0) {
|
||||
uint64_t elapsed = NSEC2MSEC(gethrtime() - start_time);
|
||||
if (elapsed > 0) {
|
||||
zfs_dbgmsg("spa %llu arc flushed in %llu ms",
|
||||
(u_longlong_t)spa_guid, (u_longlong_t)elaspsed);
|
||||
(u_longlong_t)spa_guid, (u_longlong_t)elapsed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9151,7 +9152,7 @@ top:
|
||||
if (dev->l2ad_first) {
|
||||
/*
|
||||
* This is the first sweep through the device. There is
|
||||
* nothing to evict. We have already trimmmed the
|
||||
* nothing to evict. We have already trimmed the
|
||||
* whole device.
|
||||
*/
|
||||
goto out;
|
||||
@@ -10085,12 +10086,12 @@ l2arc_device_teardown(void *arg)
|
||||
kmem_free(remdev->l2ad_dev_hdr, remdev->l2ad_dev_hdr_asize);
|
||||
vmem_free(remdev, sizeof (l2arc_dev_t));
|
||||
|
||||
uint64_t elaspsed = NSEC2MSEC(gethrtime() - start_time);
|
||||
if (elaspsed > 0) {
|
||||
uint64_t elapsed = NSEC2MSEC(gethrtime() - start_time);
|
||||
if (elapsed > 0) {
|
||||
zfs_dbgmsg("spa %llu, vdev %llu removed in %llu ms",
|
||||
(u_longlong_t)rva->rva_spa_gid,
|
||||
(u_longlong_t)rva->rva_vdev_gid,
|
||||
(u_longlong_t)elaspsed);
|
||||
(u_longlong_t)elapsed);
|
||||
}
|
||||
|
||||
if (rva->rva_async)
|
||||
|
||||
@@ -446,7 +446,7 @@ mmp_write_uberblock(spa_t *spa)
|
||||
uint64_t offset;
|
||||
|
||||
hrtime_t lock_acquire_time = gethrtime();
|
||||
spa_config_enter_mmp(spa, SCL_STATE, mmp_tag, RW_READER);
|
||||
spa_config_enter_priority(spa, SCL_STATE, mmp_tag, RW_READER);
|
||||
lock_acquire_time = gethrtime() - lock_acquire_time;
|
||||
if (lock_acquire_time > (MSEC2NSEC(MMP_MIN_INTERVAL) / 10))
|
||||
zfs_dbgmsg("MMP SCL_STATE acquisition pool '%s' took %llu ns "
|
||||
|
||||
@@ -510,7 +510,7 @@ spa_config_tryenter(spa_t *spa, int locks, const void *tag, krw_t rw)
|
||||
|
||||
static void
|
||||
spa_config_enter_impl(spa_t *spa, int locks, const void *tag, krw_t rw,
|
||||
int mmp_flag)
|
||||
int priority_flag)
|
||||
{
|
||||
(void) tag;
|
||||
int wlocks_held = 0;
|
||||
@@ -526,7 +526,7 @@ spa_config_enter_impl(spa_t *spa, int locks, const void *tag, krw_t rw,
|
||||
mutex_enter(&scl->scl_lock);
|
||||
if (rw == RW_READER) {
|
||||
while (scl->scl_writer ||
|
||||
(!mmp_flag && scl->scl_write_wanted)) {
|
||||
(!priority_flag && scl->scl_write_wanted)) {
|
||||
cv_wait(&scl->scl_cv, &scl->scl_lock);
|
||||
}
|
||||
} else {
|
||||
@@ -551,7 +551,7 @@ spa_config_enter(spa_t *spa, int locks, const void *tag, krw_t rw)
|
||||
}
|
||||
|
||||
/*
|
||||
* The spa_config_enter_mmp() allows the mmp thread to cut in front of
|
||||
* The spa_config_enter_priority() allows the mmp thread to cut in front of
|
||||
* outstanding write lock requests. This is needed since the mmp updates are
|
||||
* time sensitive and failure to service them promptly will result in a
|
||||
* suspended pool. This pool suspension has been seen in practice when there is
|
||||
@@ -560,7 +560,7 @@ spa_config_enter(spa_t *spa, int locks, const void *tag, krw_t rw)
|
||||
*/
|
||||
|
||||
void
|
||||
spa_config_enter_mmp(spa_t *spa, int locks, const void *tag, krw_t rw)
|
||||
spa_config_enter_priority(spa_t *spa, int locks, const void *tag, krw_t rw)
|
||||
{
|
||||
spa_config_enter_impl(spa, locks, tag, rw, 1);
|
||||
}
|
||||
|
||||
@@ -51,34 +51,70 @@
|
||||
#include <sys/trace_zfs.h>
|
||||
|
||||
/*
|
||||
* This file contains the necessary logic to remove vdevs from a
|
||||
* storage pool. Currently, the only devices that can be removed
|
||||
* are log, cache, and spare devices; and top level vdevs from a pool
|
||||
* w/o raidz or mirrors. (Note that members of a mirror can be removed
|
||||
* by the detach operation.)
|
||||
* This file contains the necessary logic to remove vdevs from a storage
|
||||
* pool. Note that members of a mirror can be removed by the detach
|
||||
* operation. Currently, the only devices that can be removed are:
|
||||
*
|
||||
* Log vdevs are removed by evacuating them and then turning the vdev
|
||||
* into a hole vdev while holding spa config locks.
|
||||
* 1) Traditional hot spare and cache vdevs. Note that draid distributed
|
||||
* spares are fixed at creation time and cannot be removed.
|
||||
*
|
||||
* Top level vdevs are removed and converted into an indirect vdev via
|
||||
* a multi-step process:
|
||||
* 2) Log vdevs are removed by evacuating them and then turning the vdev
|
||||
* into a hole vdev while holding spa config locks.
|
||||
*
|
||||
* - Disable allocations from this device (spa_vdev_remove_top).
|
||||
* 3) Top-level singleton and mirror vdevs, including dedup and special
|
||||
* vdevs, are removed and converted into an indirect vdev via a
|
||||
* multi-step process:
|
||||
*
|
||||
* - From a new thread (spa_vdev_remove_thread), copy data from
|
||||
* the removing vdev to a different vdev. The copy happens in open
|
||||
* context (spa_vdev_copy_impl) and issues a sync task
|
||||
* (vdev_mapping_sync) so the sync thread can update the partial
|
||||
* indirect mappings in core and on disk.
|
||||
* - Disable allocations from this device (spa_vdev_remove_top).
|
||||
*
|
||||
* - If a free happens during a removal, it is freed from the
|
||||
* removing vdev, and if it has already been copied, from the new
|
||||
* location as well (free_from_removing_vdev).
|
||||
* - From a new thread (spa_vdev_remove_thread), copy data from the
|
||||
* removing vdev to a different vdev. The copy happens in open context
|
||||
* (spa_vdev_copy_impl) and issues a sync task (vdev_mapping_sync) so
|
||||
* the sync thread can update the partial indirect mappings in core
|
||||
* and on disk.
|
||||
*
|
||||
* - After the removal is completed, the copy thread converts the vdev
|
||||
* into an indirect vdev (vdev_remove_complete) before instructing
|
||||
* the sync thread to destroy the space maps and finish the removal
|
||||
* (spa_finish_removal).
|
||||
* - If a free happens during a removal, it is freed from the removing
|
||||
* vdev, and if it has already been copied, from the new location as
|
||||
* well (free_from_removing_vdev).
|
||||
*
|
||||
* - After the removal is completed, the copy thread converts the vdev
|
||||
* into an indirect vdev (vdev_remove_complete) before instructing
|
||||
* the sync thread to destroy the space maps and finish the removal
|
||||
* (spa_finish_removal).
|
||||
*
|
||||
* The following constraints currently apply primary device removal:
|
||||
*
|
||||
* - All vdevs must be online, healthy, and not be missing any data
|
||||
* according to the DTLs.
|
||||
*
|
||||
* - When removing a singleton or mirror vdev, regardless of it's a
|
||||
* special, dedup, or primary device, it must have the same ashift
|
||||
* as the devices in the normal allocation class. Furthermore, all
|
||||
* vdevs in the normal allocation class must have the same ashift to
|
||||
* ensure the new allocations never includes additional padding.
|
||||
*
|
||||
* - The normal allocation class cannot contain any raidz or draid
|
||||
* top-level vdevs since segments are copied without regard for block
|
||||
* boundaries. This makes it impossible to calculate the required
|
||||
* parity columns when using these vdev types as the destination.
|
||||
*
|
||||
* - The encryption keys must be loaded so the ZIL logs can be reset
|
||||
* in order to prevent writing to the device being removed.
|
||||
*
|
||||
* N.B. ashift and raidz/draid constraints for primary top-level device
|
||||
* removal could be slightly relaxed if it were possible to request that
|
||||
* DVAs from a mirror or singleton in the specified allocation class be
|
||||
* used (metaslab_alloc_dva).
|
||||
*
|
||||
* This flexibility would be particularly useful for raidz/draid pools which
|
||||
* often include a mirrored special device. If a mistakenly added top-level
|
||||
* singleton were added it could then still be removed at the cost of some
|
||||
* special device capacity. This may be a worthwhile tradeoff depending on
|
||||
* the pool capacity and expense (cost, complexity, time) of creating a new
|
||||
* pool and copying all of the data to correct the configuration.
|
||||
*
|
||||
* Furthermore, while not currently supported it should be possible to allow
|
||||
* vdevs of any type to be removed as long as they've never been written to.
|
||||
*/
|
||||
|
||||
typedef struct vdev_copy_arg {
|
||||
|
||||
@@ -4574,8 +4574,29 @@ zio_vdev_io_start(zio_t *zio)
|
||||
ASSERT0(zio->io_child_error[ZIO_CHILD_VDEV]);
|
||||
|
||||
if (vd == NULL) {
|
||||
if (!(zio->io_flags & ZIO_FLAG_CONFIG_WRITER))
|
||||
spa_config_enter(spa, SCL_ZIO, zio, RW_READER);
|
||||
if (!(zio->io_flags & ZIO_FLAG_CONFIG_WRITER)) {
|
||||
/*
|
||||
* A deadlock workaround. The ddt_prune_unique_entries()
|
||||
* -> prune_candidates_sync() code path takes the
|
||||
* SCL_ZIO reader lock and may request it again here.
|
||||
* If there is another thread who wants the SCL_ZIO
|
||||
* writer lock, then scl_write_wanted will be set.
|
||||
* Thus, the spa_config_enter_priority() is used to
|
||||
* ignore pending writer requests.
|
||||
*
|
||||
* The locking should be revised to remove the need
|
||||
* for this workaround. If that's not workable then
|
||||
* it should only be applied to the zios involved in
|
||||
* the pruning process. This impacts the read/write
|
||||
* I/O balance while pruning.
|
||||
*/
|
||||
if (spa->spa_active_ddt_prune)
|
||||
spa_config_enter_priority(spa, SCL_ZIO, zio,
|
||||
RW_READER);
|
||||
else
|
||||
spa_config_enter(spa, SCL_ZIO, zio,
|
||||
RW_READER);
|
||||
}
|
||||
|
||||
/*
|
||||
* The mirror_ops handle multiple DVAs in a single BP.
|
||||
@@ -5305,6 +5326,16 @@ zio_ready(zio_t *zio)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (zio_injection_enabled) {
|
||||
hrtime_t target = zio_handle_ready_delay(zio);
|
||||
if (target != 0 && zio->io_target_timestamp == 0) {
|
||||
zio->io_stage >>= 1;
|
||||
zio->io_target_timestamp = target;
|
||||
zio_delay_interrupt(zio);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (zio->io_ready) {
|
||||
ASSERT(IO_IS_ALLOCATING(zio));
|
||||
ASSERT(BP_GET_BIRTH(bp) == zio->io_txg ||
|
||||
|
||||
@@ -827,6 +827,44 @@ zio_handle_export_delay(spa_t *spa, hrtime_t elapsed)
|
||||
zio_handle_pool_delay(spa, elapsed, ZINJECT_DELAY_EXPORT);
|
||||
}
|
||||
|
||||
/*
|
||||
* For testing, inject a delay before ready state.
|
||||
*/
|
||||
hrtime_t
|
||||
zio_handle_ready_delay(zio_t *zio)
|
||||
{
|
||||
inject_handler_t *handler;
|
||||
hrtime_t now = gethrtime();
|
||||
hrtime_t target = 0;
|
||||
|
||||
/*
|
||||
* Ignore I/O not associated with any logical data.
|
||||
*/
|
||||
if (zio->io_logical == NULL)
|
||||
return (0);
|
||||
|
||||
rw_enter(&inject_lock, RW_READER);
|
||||
|
||||
for (handler = list_head(&inject_handlers); handler != NULL;
|
||||
handler = list_next(&inject_handlers, handler)) {
|
||||
if (zio->io_spa != handler->zi_spa ||
|
||||
handler->zi_record.zi_cmd != ZINJECT_DELAY_READY)
|
||||
continue;
|
||||
|
||||
/* If this handler matches, inject the delay */
|
||||
if (zio_match_iotype(zio, handler->zi_record.zi_iotype) &&
|
||||
zio_match_handler(&zio->io_logical->io_bookmark,
|
||||
zio->io_bp ? BP_GET_TYPE(zio->io_bp) : DMU_OT_NONE,
|
||||
zio_match_dva(zio), &handler->zi_record, zio->io_error)) {
|
||||
target = now + (hrtime_t)handler->zi_record.zi_timer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rw_exit(&inject_lock);
|
||||
return (target);
|
||||
}
|
||||
|
||||
static int
|
||||
zio_calculate_range(const char *pool, zinject_record_t *record)
|
||||
{
|
||||
|
||||
@@ -410,7 +410,7 @@ zvol_set_volthreading(const char *name, boolean_t value)
|
||||
{
|
||||
zvol_state_t *zv = zvol_find_by_name(name, RW_NONE);
|
||||
if (zv == NULL)
|
||||
return (SET_ERROR(ENOENT));
|
||||
return (-1);
|
||||
zv->zv_threading = value;
|
||||
mutex_exit(&zv->zv_state_lock);
|
||||
return (0);
|
||||
|
||||
@@ -1090,7 +1090,8 @@ tags = ['functional', 'write_dirs']
|
||||
[tests/functional/xattr]
|
||||
tests = ['xattr_001_pos', 'xattr_002_neg', 'xattr_003_neg', 'xattr_004_pos',
|
||||
'xattr_005_pos', 'xattr_006_pos', 'xattr_007_neg',
|
||||
'xattr_011_pos', 'xattr_012_pos', 'xattr_013_pos', 'xattr_compat']
|
||||
'xattr_011_pos', 'xattr_012_pos', 'xattr_013_pos', 'xattr_014_pos',
|
||||
'xattr_compat']
|
||||
tags = ['functional', 'xattr']
|
||||
|
||||
[tests/functional/zvol/zvol_ENOSPC]
|
||||
|
||||
@@ -622,7 +622,7 @@ tags = ['functional', 'vdev_zaps']
|
||||
[tests/functional/xattr]
|
||||
tests = ['xattr_001_pos', 'xattr_002_neg', 'xattr_003_neg', 'xattr_004_pos',
|
||||
'xattr_005_pos', 'xattr_006_pos', 'xattr_007_neg',
|
||||
'xattr_011_pos', 'xattr_013_pos', 'xattr_compat']
|
||||
'xattr_011_pos', 'xattr_013_pos', 'xattr_014_pos', 'xattr_compat']
|
||||
tags = ['functional', 'xattr']
|
||||
|
||||
[tests/functional/zvol/zvol_ENOSPC]
|
||||
|
||||
@@ -47,25 +47,34 @@
|
||||
#endif
|
||||
|
||||
static void
|
||||
seek_data(int fd, off_t offset, off_t expected)
|
||||
seek_expect(int fd, off_t offset, int whence, off_t expect_offset)
|
||||
{
|
||||
off_t data_offset = lseek(fd, offset, SEEK_DATA);
|
||||
if (data_offset != expected) {
|
||||
fprintf(stderr, "lseek(fd, %d, SEEK_DATA) = %d (expected %d)\n",
|
||||
(int)offset, (int)data_offset, (int)expected);
|
||||
exit(2);
|
||||
}
|
||||
errno = 0;
|
||||
off_t seek_offset = lseek(fd, offset, whence);
|
||||
if (seek_offset == expect_offset)
|
||||
return;
|
||||
|
||||
int err = errno;
|
||||
fprintf(stderr, "lseek(fd, %ld, SEEK_%s) = %ld (expected %ld)",
|
||||
offset, (whence == SEEK_DATA ? "DATA" : "HOLE"),
|
||||
seek_offset, expect_offset);
|
||||
if (err != 0)
|
||||
fprintf(stderr, " (errno %d [%s])\n", err, strerror(err));
|
||||
else
|
||||
fputc('\n', stderr);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
static void
|
||||
static inline void
|
||||
seek_data(int fd, off_t offset, off_t expected)
|
||||
{
|
||||
seek_expect(fd, offset, SEEK_DATA, expected);
|
||||
}
|
||||
|
||||
static inline void
|
||||
seek_hole(int fd, off_t offset, off_t expected)
|
||||
{
|
||||
off_t hole_offset = lseek(fd, offset, SEEK_HOLE);
|
||||
if (hole_offset != expected) {
|
||||
fprintf(stderr, "lseek(fd, %d, SEEK_HOLE) = %d (expected %d)\n",
|
||||
(int)offset, (int)hole_offset, (int)expected);
|
||||
exit(2);
|
||||
}
|
||||
seek_expect(fd, offset, SEEK_HOLE, expected);
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
@@ -2234,6 +2234,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
|
||||
functional/xattr/xattr_011_pos.ksh \
|
||||
functional/xattr/xattr_012_pos.ksh \
|
||||
functional/xattr/xattr_013_pos.ksh \
|
||||
functional/xattr/xattr_014_pos.ksh \
|
||||
functional/xattr/xattr_compat.ksh \
|
||||
functional/zap_shrink/cleanup.ksh \
|
||||
functional/zap_shrink/zap_shrink_001_pos.ksh \
|
||||
|
||||
+2
@@ -47,6 +47,8 @@ function cleanup
|
||||
# bring back removed disk online for further tests
|
||||
insert_disk $REMOVED_DISK $scsi_host
|
||||
poolexists $TESTPOOL && destroy_pool $TESTPOOL
|
||||
# Since the disk was offline during destroy, remove the label
|
||||
zpool labelclear $DISK2 -f
|
||||
}
|
||||
|
||||
log_assert "Testing zpool reopen with pool name as argument"
|
||||
|
||||
+3
-3
@@ -1234,10 +1234,10 @@ function verify_fs_aedsx
|
||||
typeset oldval
|
||||
set -A modes "on" "off"
|
||||
oldval=$(get_prop $perm $fs)
|
||||
if [[ $oldval == "on" ]]; then
|
||||
n=1
|
||||
elif [[ $oldval == "off" ]]; then
|
||||
if [[ $oldval == "off" ]]; then
|
||||
n=0
|
||||
else
|
||||
n=1
|
||||
fi
|
||||
log_note "$user zfs set $perm=${modes[$n]} $fs"
|
||||
user_run $user zfs set $perm=${modes[$n]} $fs
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
#!/bin/ksh -p
|
||||
# SPDX-License-Identifier: CDDL-1.0
|
||||
#
|
||||
# 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) 2025 by Klara, Inc.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/xattr/xattr_common.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# The default xattr should be shown as 'sa', not 'on', for clarity.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create a filesystem.
|
||||
# 2. Verify that the xattra is shown as 'sa'.
|
||||
# 3. Manually set the value to 'dir', 'sa', 'on', and 'off'.
|
||||
# 4. Verify that it is shown as 'dir', 'sa', 'sa', and 'off.
|
||||
#
|
||||
|
||||
log_assert "The default and specific xattr values are displayed correctly."
|
||||
|
||||
set -A args "dir" "sa" "on" "off"
|
||||
set -A display "dir" "sa" "sa" "off"
|
||||
|
||||
log_must eval "[[ 'sa' == '$(zfs get -Hpo value xattr $TESTPOOL)' ]]"
|
||||
|
||||
for i in `seq 0 3`; do
|
||||
log_must zfs set xattr="${args[$i]}" $TESTPOOL
|
||||
log_must eval "[[ '${display[$i]}' == '$(zfs get -Hpo value xattr $TESTPOOL)' ]]"
|
||||
done
|
||||
log_pass "The default and specific xattr values are displayed correctly."
|
||||
@@ -41,6 +41,7 @@
|
||||
# 5. TRIM the first 1MB and last 2MB of the 5MB block of data.
|
||||
# 6. Observe 2MB of used space on the zvol
|
||||
# 7. Verify the trimmed regions are zero'd on the zvol
|
||||
# 8. Verify Secure Erase does not work on zvols (Linux only)
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
@@ -56,6 +57,7 @@ if is_linux ; then
|
||||
else
|
||||
trimcmd='blkdiscard'
|
||||
fi
|
||||
secure_trimcmd="$trimcmd --secure"
|
||||
else
|
||||
# By default, FreeBSD 'trim' always does a dry-run. '-f' makes
|
||||
# it perform the actual operation.
|
||||
@@ -114,6 +116,11 @@ function do_test {
|
||||
log_must diff $datafile1 $datafile2
|
||||
|
||||
log_must rm $datafile1 $datafile2
|
||||
|
||||
# Secure erase should not work (Linux check only).
|
||||
if [ -n "$secure_trimcmd" ] ; then
|
||||
log_mustnot $secure_trimcmd $zvolpath
|
||||
fi
|
||||
}
|
||||
|
||||
log_assert "Verify that a ZFS volume can be TRIMed"
|
||||
|
||||
Reference in new issue
Block a user