zfs: merge openzfs/zfs@a582d5299
Notable upstream pull request merges:
#13717 Fix zpool status in case of unloaded keys
#13753 Prevent zevent list from consuming all of kernel memory
#13767 arcstat: fix -p option
#13785 Updates for snapshots_changed property
Obtained from: OpenZFS
OpenZFS commit: a582d52993
This commit is contained in:
commit
08aba0aec7
@ -271,7 +271,7 @@ def print_values():
|
||||
if pretty_print:
|
||||
fmt = lambda col: prettynum(cols[col][0], cols[col][1], v[col])
|
||||
else:
|
||||
fmt = lambda col: v[col]
|
||||
fmt = lambda col: str(v[col])
|
||||
|
||||
sys.stdout.write(sep.join(fmt(col) for col in hdr))
|
||||
sys.stdout.write("\n")
|
||||
|
@ -48,6 +48,7 @@ zed_conf_init(struct zed_conf *zcp)
|
||||
zcp->zevent_fd = -1; /* opened in zed_event_init() */
|
||||
|
||||
zcp->max_jobs = 16;
|
||||
zcp->max_zevent_buf_len = 1 << 20;
|
||||
|
||||
if (!(zcp->pid_file = strdup(ZED_PID_FILE)) ||
|
||||
!(zcp->zedlet_dir = strdup(ZED_ZEDLET_DIR)) ||
|
||||
@ -141,6 +142,8 @@ _zed_conf_display_help(const char *prog, boolean_t got_err)
|
||||
.v = ZED_STATE_FILE },
|
||||
{ .o = "-j JOBS", .d = "Start at most JOBS at once.",
|
||||
.v = "16" },
|
||||
{ .o = "-b LEN", .d = "Cap kernel event buffer at LEN entries.",
|
||||
.v = "1048576" },
|
||||
{},
|
||||
};
|
||||
|
||||
@ -230,7 +233,7 @@ _zed_conf_parse_path(char **resultp, const char *path)
|
||||
void
|
||||
zed_conf_parse_opts(struct zed_conf *zcp, int argc, char **argv)
|
||||
{
|
||||
const char * const opts = ":hLVd:p:P:s:vfFMZIj:";
|
||||
const char * const opts = ":hLVd:p:P:s:vfFMZIj:b:";
|
||||
int opt;
|
||||
unsigned long raw;
|
||||
|
||||
@ -291,6 +294,17 @@ zed_conf_parse_opts(struct zed_conf *zcp, int argc, char **argv)
|
||||
zcp->max_jobs = raw;
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
errno = 0;
|
||||
raw = strtoul(optarg, NULL, 0);
|
||||
if (errno == ERANGE || raw > INT32_MAX) {
|
||||
zed_log_die("%lu is too large", raw);
|
||||
} if (raw == 0) {
|
||||
zcp->max_zevent_buf_len = INT32_MAX;
|
||||
} else {
|
||||
zcp->max_zevent_buf_len = raw;
|
||||
}
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
if (optopt == '?')
|
||||
|
@ -33,6 +33,7 @@ struct zed_conf {
|
||||
int zevent_fd; /* fd for access to zevents */
|
||||
|
||||
int16_t max_jobs; /* max zedlets to run at one time */
|
||||
int32_t max_zevent_buf_len; /* max size of kernel event list */
|
||||
|
||||
boolean_t do_force:1; /* true if force enabled */
|
||||
boolean_t do_foreground:1; /* true if run in foreground */
|
||||
|
@ -38,6 +38,8 @@
|
||||
|
||||
#define MAXBUF 4096
|
||||
|
||||
static int max_zevent_buf_len = 1 << 20;
|
||||
|
||||
/*
|
||||
* Open the libzfs interface.
|
||||
*/
|
||||
@ -70,6 +72,9 @@ zed_event_init(struct zed_conf *zcp)
|
||||
zed_log_die("Failed to initialize disk events");
|
||||
}
|
||||
|
||||
if (zcp->max_zevent_buf_len != 0)
|
||||
max_zevent_buf_len = zcp->max_zevent_buf_len;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -105,7 +110,7 @@ _bump_event_queue_length(void)
|
||||
{
|
||||
int zzlm = -1, wr;
|
||||
char qlen_buf[12] = {0}; /* parameter is int => max "-2147483647\n" */
|
||||
long int qlen;
|
||||
long int qlen, orig_qlen;
|
||||
|
||||
zzlm = open("/sys/module/zfs/parameters/zfs_zevent_len_max", O_RDWR);
|
||||
if (zzlm < 0)
|
||||
@ -116,7 +121,7 @@ _bump_event_queue_length(void)
|
||||
qlen_buf[sizeof (qlen_buf) - 1] = '\0';
|
||||
|
||||
errno = 0;
|
||||
qlen = strtol(qlen_buf, NULL, 10);
|
||||
orig_qlen = qlen = strtol(qlen_buf, NULL, 10);
|
||||
if (errno == ERANGE)
|
||||
goto done;
|
||||
|
||||
@ -125,8 +130,14 @@ _bump_event_queue_length(void)
|
||||
else
|
||||
qlen *= 2;
|
||||
|
||||
if (qlen > INT_MAX)
|
||||
qlen = INT_MAX;
|
||||
/*
|
||||
* Don't consume all of kernel memory with event logs if something
|
||||
* goes wrong.
|
||||
*/
|
||||
if (qlen > max_zevent_buf_len)
|
||||
qlen = max_zevent_buf_len;
|
||||
if (qlen == orig_qlen)
|
||||
goto done;
|
||||
wr = snprintf(qlen_buf, sizeof (qlen_buf), "%ld", qlen);
|
||||
|
||||
if (pwrite(zzlm, qlen_buf, wr, 0) < 0)
|
||||
|
@ -8,5 +8,5 @@ ConditionKernelCommandLine=bootfs.snapshot
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/sh -c '. /lib/dracut-zfs-lib.sh; decode_root_args || exit; [ "$root" = "zfs:AUTO" ] && root="$BOOTFS"; SNAPNAME="$(getarg bootfs.snapshot)"; exec @sbindir@/zfs snapshot "$root@${SNAPNAME:-%v}"'
|
||||
ExecStart=-/bin/sh -c '. /lib/dracut-zfs-lib.sh; decode_root_args || exit; [ "$root" = "zfs:AUTO" ] && root="$BOOTFS"; SNAPNAME="$(getarg bootfs.snapshot)"; exec @sbindir@/zfs snapshot "$root@${SNAPNAME:-%v}"'
|
||||
RemainAfterExit=yes
|
||||
|
@ -222,5 +222,6 @@ int spa_do_crypt_abd(boolean_t encrypt, spa_t *spa, const zbookmark_phys_t *zb,
|
||||
dmu_object_type_t ot, boolean_t dedup, boolean_t bswap, uint8_t *salt,
|
||||
uint8_t *iv, uint8_t *mac, uint_t datalen, abd_t *pabd, abd_t *cabd,
|
||||
boolean_t *no_crypt);
|
||||
zfs_keystatus_t dsl_dataset_get_keystatus(dsl_dir_t *dd);
|
||||
|
||||
#endif
|
||||
|
@ -2947,7 +2947,7 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
|
||||
|
||||
if (literal ||
|
||||
localtime_r(&time, &t) == NULL ||
|
||||
strftime(propbuf, proplen, "%a %b %e %k:%M %Y",
|
||||
strftime(propbuf, proplen, "%a %b %e %k:%M:%S %Y",
|
||||
&t) == 0)
|
||||
(void) snprintf(propbuf, proplen, "%llu",
|
||||
(u_longlong_t)val);
|
||||
|
@ -526,6 +526,9 @@ Specifies the time at which a snapshot for a dataset was last
|
||||
created or deleted.
|
||||
.Pp
|
||||
This allows us to be more efficient how often we query snapshots.
|
||||
The property is persistent across mount and unmount operations only if the
|
||||
.Sy extensible_dataset
|
||||
feature is enabled.
|
||||
.It Sy volblocksize
|
||||
For volumes, specifies the block size of the volume.
|
||||
The
|
||||
@ -1545,7 +1548,7 @@ Access time is only updated if the previous
|
||||
access time was earlier than the current modify or change time or if the
|
||||
existing access time hasn't been updated within the past 24 hours.
|
||||
The default value is
|
||||
.Sy off .
|
||||
.Sy on .
|
||||
The values
|
||||
.Sy on
|
||||
and
|
||||
|
@ -545,6 +545,9 @@ This feature enables the upgraded version of errlog, which required an on-disk
|
||||
error log format change.
|
||||
Now the error log of each head dataset is stored separately in the zap object
|
||||
and keyed by the head id.
|
||||
In case of encrypted filesystems with unloaded keys or unmounted encrypted
|
||||
filesystems we are unable to check their snapshots or clones for errors and
|
||||
these will not be reported.
|
||||
With this feature enabled, every dataset affected by an error block is listed
|
||||
in the output of
|
||||
.Nm zpool Cm status .
|
||||
|
@ -27,6 +27,7 @@
|
||||
.Op Fl P Ar path
|
||||
.Op Fl s Ar statefile
|
||||
.Op Fl j Ar jobs
|
||||
.Op Fl b Ar buflen
|
||||
.
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
@ -96,6 +97,17 @@ ZEDLETs to run concurrently,
|
||||
delaying execution of new ones until they finish.
|
||||
Defaults to
|
||||
.Sy 16 .
|
||||
.It Fl b Ar buflen
|
||||
Cap kernel event buffer growth to
|
||||
.Ar buflen
|
||||
entries.
|
||||
This buffer is grown when the daemon misses an event, but results in
|
||||
unreclaimable memory use in the kernel.
|
||||
A value of
|
||||
.Sy 0
|
||||
removes the cap.
|
||||
Defaults to
|
||||
.Sy 1048576 .
|
||||
.El
|
||||
.Sh ZEVENTS
|
||||
A zevent is comprised of a list of nvpairs (name/value pairs).
|
||||
|
@ -465,7 +465,7 @@ zfs_prop_init(void)
|
||||
/* inherit index (boolean) properties */
|
||||
zprop_register_index(ZFS_PROP_ATIME, "atime", 1, PROP_INHERIT,
|
||||
ZFS_TYPE_FILESYSTEM, "on | off", "ATIME", boolean_table, sfeatures);
|
||||
zprop_register_index(ZFS_PROP_RELATIME, "relatime", 0, PROP_INHERIT,
|
||||
zprop_register_index(ZFS_PROP_RELATIME, "relatime", 1, PROP_INHERIT,
|
||||
ZFS_TYPE_FILESYSTEM, "on | off", "RELATIME", boolean_table,
|
||||
sfeatures);
|
||||
zprop_register_index(ZFS_PROP_DEVICES, "devices", 1, PROP_INHERIT,
|
||||
|
@ -1137,7 +1137,7 @@ dmu_objset_check_wkey_loaded(dsl_dir_t *dd)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static zfs_keystatus_t
|
||||
zfs_keystatus_t
|
||||
dsl_dataset_get_keystatus(dsl_dir_t *dd)
|
||||
{
|
||||
/* check if this dd has a has a dsl key */
|
||||
|
@ -88,6 +88,8 @@ int zfs_max_recordsize = 16 * 1024 * 1024;
|
||||
#endif
|
||||
static int zfs_allow_redacted_dataset_mount = 0;
|
||||
|
||||
int zfs_snapshot_history_enabled = 1;
|
||||
|
||||
#define SWITCH64(x, y) \
|
||||
{ \
|
||||
uint64_t __tmp = (x); \
|
||||
@ -1867,7 +1869,8 @@ dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname,
|
||||
|
||||
dsl_dir_snap_cmtime_update(ds->ds_dir, tx);
|
||||
|
||||
spa_history_log_internal_ds(ds->ds_prev, "snapshot", tx, " ");
|
||||
if (zfs_snapshot_history_enabled)
|
||||
spa_history_log_internal_ds(ds->ds_prev, "snapshot", tx, " ");
|
||||
}
|
||||
|
||||
void
|
||||
@ -4985,6 +4988,9 @@ ZFS_MODULE_PARAM(zfs, zfs_, max_recordsize, INT, ZMOD_RW,
|
||||
ZFS_MODULE_PARAM(zfs, zfs_, allow_redacted_dataset_mount, INT, ZMOD_RW,
|
||||
"Allow mounting of redacted datasets");
|
||||
|
||||
ZFS_MODULE_PARAM(zfs, zfs_, snapshot_history_enabled, INT, ZMOD_RW,
|
||||
"Include snapshot events in pool history/events");
|
||||
|
||||
EXPORT_SYMBOL(dsl_dataset_hold);
|
||||
EXPORT_SYMBOL(dsl_dataset_hold_flags);
|
||||
EXPORT_SYMBOL(dsl_dataset_hold_obj);
|
||||
|
@ -49,6 +49,8 @@
|
||||
#include <sys/zthr.h>
|
||||
#include <sys/spa_impl.h>
|
||||
|
||||
extern int zfs_snapshot_history_enabled;
|
||||
|
||||
int
|
||||
dsl_destroy_snapshot_check_impl(dsl_dataset_t *ds, boolean_t defer)
|
||||
{
|
||||
@ -321,14 +323,19 @@ dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx)
|
||||
ASSERT(spa_version(dp->dp_spa) >= SPA_VERSION_USERREFS);
|
||||
dmu_buf_will_dirty(ds->ds_dbuf, tx);
|
||||
dsl_dataset_phys(ds)->ds_flags |= DS_FLAG_DEFER_DESTROY;
|
||||
spa_history_log_internal_ds(ds, "defer_destroy", tx, " ");
|
||||
if (zfs_snapshot_history_enabled) {
|
||||
spa_history_log_internal_ds(ds, "defer_destroy", tx,
|
||||
" ");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT3U(dsl_dataset_phys(ds)->ds_num_children, <=, 1);
|
||||
|
||||
/* We need to log before removing it from the namespace. */
|
||||
spa_history_log_internal_ds(ds, "destroy", tx, " ");
|
||||
if (zfs_snapshot_history_enabled) {
|
||||
/* We need to log before removing it from the namespace. */
|
||||
spa_history_log_internal_ds(ds, "destroy", tx, " ");
|
||||
}
|
||||
|
||||
dsl_scan_ds_destroyed(ds, tx);
|
||||
|
||||
|
@ -268,13 +268,15 @@ dsl_dir_hold_obj(dsl_pool_t *dp, uint64_t ddobj,
|
||||
}
|
||||
}
|
||||
|
||||
inode_timespec_t t = {0};
|
||||
zap_lookup(dd->dd_pool->dp_meta_objset,
|
||||
dsl_dir_phys(dd)->dd_props_zapobj,
|
||||
zfs_prop_to_name(ZFS_PROP_SNAPSHOTS_CHANGED),
|
||||
sizeof (uint64_t),
|
||||
sizeof (inode_timespec_t) / sizeof (uint64_t), &t);
|
||||
dd->dd_snap_cmtime = t;
|
||||
if (dsl_dir_is_zapified(dd)) {
|
||||
inode_timespec_t t = {0};
|
||||
zap_lookup(dp->dp_meta_objset, ddobj,
|
||||
zfs_prop_to_name(ZFS_PROP_SNAPSHOTS_CHANGED),
|
||||
sizeof (uint64_t),
|
||||
sizeof (inode_timespec_t) / sizeof (uint64_t),
|
||||
&t);
|
||||
dd->dd_snap_cmtime = t;
|
||||
}
|
||||
|
||||
dmu_buf_init_user(&dd->dd_dbu, NULL, dsl_dir_evict_async,
|
||||
&dd->dd_dbuf);
|
||||
@ -2251,16 +2253,23 @@ dsl_dir_snap_cmtime(dsl_dir_t *dd)
|
||||
void
|
||||
dsl_dir_snap_cmtime_update(dsl_dir_t *dd, dmu_tx_t *tx)
|
||||
{
|
||||
dsl_pool_t *dp = dmu_tx_pool(tx);
|
||||
inode_timespec_t t;
|
||||
objset_t *mos = dd->dd_pool->dp_meta_objset;
|
||||
uint64_t zapobj = dsl_dir_phys(dd)->dd_props_zapobj;
|
||||
const char *prop_name = zfs_prop_to_name(ZFS_PROP_SNAPSHOTS_CHANGED);
|
||||
|
||||
gethrestime(&t);
|
||||
|
||||
mutex_enter(&dd->dd_lock);
|
||||
dd->dd_snap_cmtime = t;
|
||||
VERIFY0(zap_update(mos, zapobj, prop_name, sizeof (uint64_t),
|
||||
sizeof (inode_timespec_t) / sizeof (uint64_t), &t, tx));
|
||||
if (spa_feature_is_enabled(dp->dp_spa,
|
||||
SPA_FEATURE_EXTENSIBLE_DATASET)) {
|
||||
objset_t *mos = dd->dd_pool->dp_meta_objset;
|
||||
uint64_t ddobj = dd->dd_object;
|
||||
dsl_dir_zapify(dd, tx);
|
||||
VERIFY0(zap_update(mos, ddobj,
|
||||
zfs_prop_to_name(ZFS_PROP_SNAPSHOTS_CHANGED),
|
||||
sizeof (uint64_t),
|
||||
sizeof (inode_timespec_t) / sizeof (uint64_t),
|
||||
&t, tx));
|
||||
}
|
||||
mutex_exit(&dd->dd_lock);
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,8 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2014, Delphix. All rights reserved.
|
||||
* Copyright (c) 2021, George Amanakis. All rights reserved.
|
||||
* Copyright (c) 2019 Datto Inc.
|
||||
* Copyright (c) 2021, 2022, George Amanakis. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -68,6 +68,7 @@
|
||||
#include <sys/dsl_dir.h>
|
||||
#include <sys/dmu_objset.h>
|
||||
#include <sys/dbuf.h>
|
||||
#include <sys/zfs_znode.h>
|
||||
|
||||
#define NAME_MAX_LEN 64
|
||||
|
||||
@ -175,6 +176,23 @@ get_head_and_birth_txg(spa_t *spa, zbookmark_err_phys_t *zep, uint64_t ds_obj,
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the key is not loaded dbuf_dnode_findbp() will error out with
|
||||
* EACCES. However in that case dnode_hold() will eventually call
|
||||
* dbuf_read()->zio_wait() which may call spa_log_error(). This will
|
||||
* lead to a deadlock due to us holding the mutex spa_errlist_lock.
|
||||
* Avoid this by checking here if the keys are loaded, if not return.
|
||||
* If the keys are not loaded the head_errlog feature is meaningless
|
||||
* as we cannot figure out the birth txg of the block pointer.
|
||||
*/
|
||||
if (dsl_dataset_get_keystatus(ds->ds_dir) ==
|
||||
ZFS_KEYSTATUS_UNAVAILABLE) {
|
||||
zep->zb_birth = 0;
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
dsl_pool_config_exit(dp, FTAG);
|
||||
return (0);
|
||||
}
|
||||
|
||||
dnode_t *dn;
|
||||
blkptr_t bp;
|
||||
|
||||
@ -188,11 +206,22 @@ get_head_and_birth_txg(spa_t *spa, zbookmark_err_phys_t *zep, uint64_t ds_obj,
|
||||
rw_enter(&dn->dn_struct_rwlock, RW_READER);
|
||||
error = dbuf_dnode_findbp(dn, zep->zb_level, zep->zb_blkid, &bp, NULL,
|
||||
NULL);
|
||||
|
||||
if (error == 0 && BP_IS_HOLE(&bp))
|
||||
error = SET_ERROR(ENOENT);
|
||||
|
||||
zep->zb_birth = bp.blk_birth;
|
||||
/*
|
||||
* If the key is loaded but the encrypted filesystem is unmounted when
|
||||
* a scrub is run, then dbuf_dnode_findbp() will still error out with
|
||||
* EACCES (possibly due to the key mapping being removed upon
|
||||
* unmounting). In that case the head_errlog feature is also
|
||||
* meaningless as we cannot figure out the birth txg of the block
|
||||
* pointer.
|
||||
*/
|
||||
if (error == EACCES)
|
||||
error = 0;
|
||||
else if (!error)
|
||||
zep->zb_birth = bp.blk_birth;
|
||||
|
||||
rw_exit(&dn->dn_struct_rwlock);
|
||||
dnode_rele(dn, FTAG);
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
@ -264,7 +293,6 @@ find_birth_txg(dsl_dataset_t *ds, zbookmark_err_phys_t *zep,
|
||||
rw_enter(&dn->dn_struct_rwlock, RW_READER);
|
||||
error = dbuf_dnode_findbp(dn, zep->zb_level, zep->zb_blkid, &bp, NULL,
|
||||
NULL);
|
||||
|
||||
if (error == 0 && BP_IS_HOLE(&bp))
|
||||
error = SET_ERROR(ENOENT);
|
||||
|
||||
@ -298,27 +326,40 @@ check_filesystem(spa_t *spa, uint64_t head_ds, zbookmark_err_phys_t *zep,
|
||||
uint64_t txg_to_consider = spa->spa_syncing_txg;
|
||||
boolean_t check_snapshot = B_TRUE;
|
||||
error = find_birth_txg(ds, zep, &latest_txg);
|
||||
if (error == 0) {
|
||||
if (zep->zb_birth == latest_txg) {
|
||||
/* Block neither free nor rewritten. */
|
||||
if (!only_count) {
|
||||
zbookmark_phys_t zb;
|
||||
zep_to_zb(head_ds, zep, &zb);
|
||||
if (copyout(&zb, (char *)uaddr + (*count - 1)
|
||||
* sizeof (zbookmark_phys_t),
|
||||
sizeof (zbookmark_phys_t)) != 0) {
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
return (SET_ERROR(EFAULT));
|
||||
}
|
||||
(*count)--;
|
||||
} else {
|
||||
(*count)++;
|
||||
|
||||
/*
|
||||
* If we cannot figure out the current birth txg of the block pointer
|
||||
* error out. If the filesystem is encrypted and the key is not loaded
|
||||
* or the encrypted filesystem is not mounted the error will be EACCES.
|
||||
* In that case do not return an error.
|
||||
*/
|
||||
if (error == EACCES) {
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
return (0);
|
||||
}
|
||||
if (error) {
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
return (error);
|
||||
}
|
||||
if (zep->zb_birth == latest_txg) {
|
||||
/* Block neither free nor rewritten. */
|
||||
if (!only_count) {
|
||||
zbookmark_phys_t zb;
|
||||
zep_to_zb(head_ds, zep, &zb);
|
||||
if (copyout(&zb, (char *)uaddr + (*count - 1)
|
||||
* sizeof (zbookmark_phys_t),
|
||||
sizeof (zbookmark_phys_t)) != 0) {
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
return (SET_ERROR(EFAULT));
|
||||
}
|
||||
check_snapshot = B_FALSE;
|
||||
(*count)--;
|
||||
} else {
|
||||
ASSERT3U(zep->zb_birth, <, latest_txg);
|
||||
txg_to_consider = latest_txg;
|
||||
(*count)++;
|
||||
}
|
||||
check_snapshot = B_FALSE;
|
||||
} else {
|
||||
ASSERT3U(zep->zb_birth, <, latest_txg);
|
||||
txg_to_consider = latest_txg;
|
||||
}
|
||||
|
||||
/* How many snapshots reference this block. */
|
||||
@ -439,9 +480,31 @@ process_error_block(spa_t *spa, uint64_t head_ds, zbookmark_err_phys_t *zep,
|
||||
uint64_t *count, void *uaddr, boolean_t only_count)
|
||||
{
|
||||
dsl_pool_t *dp = spa->spa_dsl_pool;
|
||||
dsl_pool_config_enter(dp, FTAG);
|
||||
uint64_t top_affected_fs;
|
||||
|
||||
/*
|
||||
* If the zb_birth is 0 it means we failed to retrieve the birth txg
|
||||
* of the block pointer. This happens when an encrypted filesystem is
|
||||
* not mounted or when the key is not loaded. Do not proceed to
|
||||
* check_filesystem(), instead do the accounting here.
|
||||
*/
|
||||
if (zep->zb_birth == 0) {
|
||||
if (!only_count) {
|
||||
zbookmark_phys_t zb;
|
||||
zep_to_zb(head_ds, zep, &zb);
|
||||
if (copyout(&zb, (char *)uaddr + (*count - 1)
|
||||
* sizeof (zbookmark_phys_t),
|
||||
sizeof (zbookmark_phys_t)) != 0) {
|
||||
return (SET_ERROR(EFAULT));
|
||||
}
|
||||
(*count)--;
|
||||
} else {
|
||||
(*count)++;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
dsl_pool_config_enter(dp, FTAG);
|
||||
int error = find_top_affected_fs(spa, head_ds, zep, &top_affected_fs);
|
||||
if (error == 0)
|
||||
error = check_filesystem(spa, top_affected_fs, zep, count,
|
||||
@ -497,6 +560,7 @@ get_errlist_size(spa_t *spa, avl_tree_t *tree)
|
||||
zep.zb_object = se->se_bookmark.zb_object;
|
||||
zep.zb_level = se->se_bookmark.zb_level;
|
||||
zep.zb_blkid = se->se_bookmark.zb_blkid;
|
||||
zep.zb_birth = 0;
|
||||
|
||||
/*
|
||||
* If we cannot find out the head dataset and birth txg of
|
||||
@ -505,8 +569,10 @@ get_errlist_size(spa_t *spa, avl_tree_t *tree)
|
||||
* sync_error_list() and written to the on-disk error log.
|
||||
*/
|
||||
uint64_t head_ds_obj;
|
||||
if (get_head_and_birth_txg(spa, &zep,
|
||||
se->se_bookmark.zb_objset, &head_ds_obj) == 0)
|
||||
int error = get_head_and_birth_txg(spa, &zep,
|
||||
se->se_bookmark.zb_objset, &head_ds_obj);
|
||||
|
||||
if (!error)
|
||||
(void) process_error_block(spa, head_ds_obj, &zep,
|
||||
&total, NULL, B_TRUE);
|
||||
}
|
||||
@ -695,6 +761,7 @@ sync_upgrade_errlog(spa_t *spa, uint64_t spa_err_obj, uint64_t *newobj,
|
||||
zep.zb_object = zb.zb_object;
|
||||
zep.zb_level = zb.zb_level;
|
||||
zep.zb_blkid = zb.zb_blkid;
|
||||
zep.zb_birth = 0;
|
||||
|
||||
/*
|
||||
* We cannot use get_head_and_birth_txg() because it will
|
||||
@ -737,8 +804,11 @@ sync_upgrade_errlog(spa_t *spa, uint64_t spa_err_obj, uint64_t *newobj,
|
||||
rw_enter(&dn->dn_struct_rwlock, RW_READER);
|
||||
error = dbuf_dnode_findbp(dn, zep.zb_level, zep.zb_blkid, &bp,
|
||||
NULL, NULL);
|
||||
if (error == EACCES)
|
||||
error = 0;
|
||||
else if (!error)
|
||||
zep.zb_birth = bp.blk_birth;
|
||||
|
||||
zep.zb_birth = bp.blk_birth;
|
||||
rw_exit(&dn->dn_struct_rwlock);
|
||||
dnode_rele(dn, FTAG);
|
||||
dsl_dataset_rele(ds, FTAG);
|
||||
@ -885,16 +955,16 @@ process_error_list(spa_t *spa, avl_tree_t *list, void *uaddr, uint64_t *count)
|
||||
zep.zb_object = se->se_bookmark.zb_object;
|
||||
zep.zb_level = se->se_bookmark.zb_level;
|
||||
zep.zb_blkid = se->se_bookmark.zb_blkid;
|
||||
zep.zb_birth = 0;
|
||||
|
||||
uint64_t head_ds_obj;
|
||||
int error = get_head_and_birth_txg(spa, &zep,
|
||||
se->se_bookmark.zb_objset, &head_ds_obj);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
error = process_error_block(spa, head_ds_obj, &zep, count,
|
||||
uaddr, B_FALSE);
|
||||
if (error != 0)
|
||||
if (!error)
|
||||
error = process_error_block(spa, head_ds_obj, &zep,
|
||||
count, uaddr, B_FALSE);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
return (0);
|
||||
@ -1013,6 +1083,7 @@ sync_error_list(spa_t *spa, avl_tree_t *t, uint64_t *obj, dmu_tx_t *tx)
|
||||
zep.zb_object = se->se_bookmark.zb_object;
|
||||
zep.zb_level = se->se_bookmark.zb_level;
|
||||
zep.zb_blkid = se->se_bookmark.zb_blkid;
|
||||
zep.zb_birth = 0;
|
||||
|
||||
/*
|
||||
* If we cannot find out the head dataset and birth txg
|
||||
@ -1024,7 +1095,7 @@ sync_error_list(spa_t *spa, avl_tree_t *t, uint64_t *obj, dmu_tx_t *tx)
|
||||
uint64_t head_dataset_obj;
|
||||
int error = get_head_and_birth_txg(spa, &zep,
|
||||
se->se_bookmark.zb_objset, &head_dataset_obj);
|
||||
if (error != 0)
|
||||
if (error)
|
||||
continue;
|
||||
|
||||
uint64_t err_obj;
|
||||
|
@ -494,7 +494,7 @@ tags = ['functional', 'cli_root', 'zpool_split']
|
||||
[tests/functional/cli_root/zpool_status]
|
||||
tests = ['zpool_status_001_pos', 'zpool_status_002_pos',
|
||||
'zpool_status_003_pos', 'zpool_status_004_pos',
|
||||
'zpool_status_features_001_pos']
|
||||
'zpool_status_005_pos', 'zpool_status_features_001_pos']
|
||||
tags = ['functional', 'cli_root', 'zpool_status']
|
||||
|
||||
[tests/functional/cli_root/zpool_sync]
|
||||
|
@ -1161,6 +1161,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
|
||||
functional/cli_root/zpool_status/zpool_status_002_pos.ksh \
|
||||
functional/cli_root/zpool_status/zpool_status_003_pos.ksh \
|
||||
functional/cli_root/zpool_status/zpool_status_004_pos.ksh \
|
||||
functional/cli_root/zpool_status/zpool_status_005_pos.ksh \
|
||||
functional/cli_root/zpool_status/zpool_status_features_001_pos.ksh \
|
||||
functional/cli_root/zpool_sync/cleanup.ksh \
|
||||
functional/cli_root/zpool_sync/setup.ksh \
|
||||
|
@ -62,11 +62,9 @@ do
|
||||
mtpt=$(snapshot_mountpoint $dst)
|
||||
log_mustnot check_atime_updated $mtpt/$TESTFILE
|
||||
else
|
||||
if is_linux; then
|
||||
log_must zfs set relatime=off $dst
|
||||
fi
|
||||
|
||||
log_must zfs set atime=on $dst
|
||||
log_must zfs set relatime=off $dst
|
||||
|
||||
log_must check_atime_updated $mtpt/$TESTFILE
|
||||
log_must check_atime_updated $mtpt/$TESTFILE
|
||||
fi
|
||||
|
@ -62,6 +62,7 @@ do
|
||||
else
|
||||
log_must zfs set atime=on $dst
|
||||
log_must zfs set relatime=on $dst
|
||||
|
||||
log_must check_atime_updated $mtpt/$TESTFILE
|
||||
log_mustnot check_atime_updated $mtpt/$TESTFILE
|
||||
fi
|
||||
|
@ -65,11 +65,10 @@ do
|
||||
mtpt=$(snapshot_mountpoint $dst)
|
||||
log_mustnot check_atime_updated $mtpt/$TESTFILE
|
||||
else
|
||||
if is_linux; then
|
||||
log_must zfs set relatime=off $(dirname $dst)
|
||||
fi
|
||||
|
||||
log_must zfs set atime=on $(dirname $dst)
|
||||
# inherited relatime won't apply because of mount option, set explicitly
|
||||
log_must zfs set relatime=off $dst
|
||||
|
||||
log_must check_atime_updated $mtpt/$TESTFILE
|
||||
log_must check_atime_updated $mtpt/$TESTFILE
|
||||
fi
|
||||
|
@ -68,6 +68,7 @@ do
|
||||
else
|
||||
log_must zfs set atime=on $(dirname $dst)
|
||||
log_must zfs set relatime=on $(dirname $dst)
|
||||
|
||||
log_must check_atime_updated $mtpt/$TESTFILE
|
||||
log_mustnot check_atime_updated $mtpt/$TESTFILE
|
||||
fi
|
||||
|
@ -33,7 +33,7 @@
|
||||
# for 10 sec.
|
||||
# 4. Verify that l2arc_write_max is set back to the default.
|
||||
# 5. Set l2arc_write_max to a value less than the cache device size but
|
||||
# larger than the default (64MB).
|
||||
# larger than the default (256MB).
|
||||
# 6. Record the l2_size.
|
||||
# 7. Random read for 1 sec.
|
||||
# 8. Record the l2_size again.
|
||||
@ -87,6 +87,9 @@ log_must truncate -s $VDEV_SZ $VDEV
|
||||
|
||||
log_must zpool create -f $TESTPOOL $VDEV cache $VCACHE
|
||||
|
||||
# Actually, this test relies on atime writes to force the L2 ARC discards
|
||||
log_must zfs set relatime=off $TESTPOOL
|
||||
|
||||
log_must fio $FIO_SCRIPTS/mkfiles.fio
|
||||
log_must fio $FIO_SCRIPTS/random_reads.fio
|
||||
|
||||
@ -94,7 +97,7 @@ typeset write_max2=$(get_tunable L2ARC_WRITE_MAX)
|
||||
|
||||
log_must test $write_max2 -eq $write_max
|
||||
|
||||
log_must set_tunable32 L2ARC_WRITE_MAX $(( 64 * 1024 * 1024 ))
|
||||
log_must set_tunable32 L2ARC_WRITE_MAX $(( 256 * 1024 * 1024 ))
|
||||
export RUNTIME=1
|
||||
|
||||
typeset do_once=true
|
||||
|
@ -63,6 +63,7 @@ log_must zfs snapshot $TESTPOOL2@snap
|
||||
log_must zfs clone $TESTPOOL2@snap $TESTPOOL2/clone
|
||||
|
||||
# Look to see that snapshot, clone and filesystem our files report errors
|
||||
log_must zpool status -v $TESTPOOL2
|
||||
log_must eval "zpool status -v | grep '$TESTPOOL2@snap:/10m_file'"
|
||||
log_must eval "zpool status -v | grep '$TESTPOOL2/clone/10m_file'"
|
||||
log_must eval "zpool status -v | grep '$TESTPOOL2/10m_file'"
|
||||
|
@ -74,6 +74,7 @@ log_must eval "zpool status -v | grep '$TESTPOOL2/10m_file'"
|
||||
|
||||
# Check that enabling the feature reports the error properly.
|
||||
log_must zpool set feature@head_errlog=enabled $TESTPOOL2
|
||||
log_must zpool status -v $TESTPOOL2
|
||||
log_must eval "zpool status -v | grep '$TESTPOOL2@snap:/10m_file'"
|
||||
log_must eval "zpool status -v | grep '$TESTPOOL2/clone/10m_file'"
|
||||
log_must eval "zpool status -v | grep '$TESTPOOL2/10m_file'"
|
||||
|
@ -0,0 +1,78 @@
|
||||
#!/bin/ksh -p
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or https://opensource.org/licenses/CDDL-1.0.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2022 George Amanakis. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Verify correct output with 'zpool status -v' after corrupting a file
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create a pool, an ancrypted filesystem and a file
|
||||
# 2. zinject checksum errors
|
||||
# 3. Unmount the filesystem and unload the key
|
||||
# 4. Scrub the pool
|
||||
# 5. Verify we report errors in the pool in 'zpool status -v'
|
||||
|
||||
verify_runnable "both"
|
||||
|
||||
DISK=${DISKS%% *}
|
||||
|
||||
function cleanup
|
||||
{
|
||||
log_must zinject -c all
|
||||
destroy_pool $TESTPOOL2
|
||||
rm -f $TESTDIR/vdev_a
|
||||
}
|
||||
|
||||
log_assert "Verify reporting errors with unloaded keys works"
|
||||
log_onexit cleanup
|
||||
|
||||
typeset passphrase="password"
|
||||
typeset file="/$TESTPOOL2/$TESTFS1/$TESTFILE0"
|
||||
|
||||
truncate -s $MINVDEVSIZE $TESTDIR/vdev_a
|
||||
log_must zpool create -f -o feature@head_errlog=enabled $TESTPOOL2 $TESTDIR/vdev_a
|
||||
|
||||
log_must eval "echo $passphrase > /$TESTPOOL2/pwd"
|
||||
|
||||
log_must zfs create -o encryption=aes-256-ccm -o keyformat=passphrase \
|
||||
-o keylocation=file:///$TESTPOOL2/pwd -o primarycache=none \
|
||||
$TESTPOOL2/$TESTFS1
|
||||
|
||||
log_must dd if=/dev/urandom of=$file bs=1024 count=1024 oflag=sync
|
||||
log_must eval "echo 'aaaaaaaa' >> "$file
|
||||
|
||||
corrupt_blocks_at_level $file 0
|
||||
log_must zfs unmount $TESTPOOL2/$TESTFS1
|
||||
log_must zfs unload-key $TESTPOOL2/$TESTFS1
|
||||
log_must zpool sync $TESTPOOL2
|
||||
log_must zpool scrub $TESTPOOL2
|
||||
log_must zpool wait -t scrub $TESTPOOL2
|
||||
log_must zpool status -v $TESTPOOL2
|
||||
log_must eval "zpool status -v $TESTPOOL2 | \
|
||||
grep \"Permanent errors have been detected\""
|
||||
|
||||
log_pass "Verify reporting errors with unloaded keys works"
|
@ -940,7 +940,7 @@
|
||||
/* #undef ZFS_IS_GPL_COMPATIBLE */
|
||||
|
||||
/* Define the project alias string. */
|
||||
#define ZFS_META_ALIAS "zfs-2.1.99-FreeBSD_gb3d0568cf"
|
||||
#define ZFS_META_ALIAS "zfs-2.1.99-FreeBSD_ga582d5299"
|
||||
|
||||
/* Define the project author. */
|
||||
#define ZFS_META_AUTHOR "OpenZFS"
|
||||
@ -970,7 +970,7 @@
|
||||
#define ZFS_META_NAME "zfs"
|
||||
|
||||
/* Define the project release. */
|
||||
#define ZFS_META_RELEASE "FreeBSD_gb3d0568cf"
|
||||
#define ZFS_META_RELEASE "FreeBSD_ga582d5299"
|
||||
|
||||
/* Define the project version. */
|
||||
#define ZFS_META_VERSION "2.1.99"
|
||||
|
@ -1 +1 @@
|
||||
#define ZFS_META_GITREV "zfs-2.1.99-1329-gb3d0568cf"
|
||||
#define ZFS_META_GITREV "zfs-2.1.99-1335-ga582d5299"
|
||||
|
Loading…
Reference in New Issue
Block a user