zfs: merge OpenZFS master-9312e0fd1
Notable upstream changes: 778869fa1 Fix reporting of mount progress e7adccf7f Disable use of hardware crypto offload drivers on FreeBSD 03e02e5b5 Fix checksum errors not being counted on repeated repair 64e0fe14f Restore FreeBSD resource usage accounting 11f2e9a49 Fix panic if scrubbing after removing a slog device MFC after: 2 weeks
This commit is contained in:
commit
ba27dd8be8
@ -162,6 +162,7 @@ KERNEL_C = \
|
||||
zfs_fuid.c \
|
||||
zfs_sa.c \
|
||||
zfs_znode.c \
|
||||
zfs_racct.c \
|
||||
zfs_ratelimit.c \
|
||||
zfs_rlock.c \
|
||||
zil.c \
|
||||
|
@ -37,4 +37,9 @@ __FBSDID("$FreeBSD$");
|
||||
#define ZFS_MODULE_PARAM_ARGS void
|
||||
typedef int boolean_t; /* This one may be tough to get rid of */
|
||||
|
||||
/* TODO: openzfs/include/sys/uio_impl.h must not be included */
|
||||
#ifndef _SYS_UIO_IMPL_H
|
||||
#define _SYS_UIO_IMPL_H
|
||||
#endif
|
||||
|
||||
#include <contrib/openzfs/module/zstd/zfs_zstd.c>
|
||||
|
@ -6912,9 +6912,6 @@ report_mount_progress(int current, int total)
|
||||
time_t now = time(NULL);
|
||||
char info[32];
|
||||
|
||||
/* report 1..n instead of 0..n-1 */
|
||||
++current;
|
||||
|
||||
/* display header if we're here for the first time */
|
||||
if (current == 1) {
|
||||
set_progress_header(gettext("Mounting ZFS filesystems"));
|
||||
|
@ -158,6 +158,9 @@ enum ztest_class_state {
|
||||
ZTEST_VDEV_CLASS_RND
|
||||
};
|
||||
|
||||
#define ZO_GVARS_MAX_ARGLEN ((size_t)64)
|
||||
#define ZO_GVARS_MAX_COUNT ((size_t)10)
|
||||
|
||||
typedef struct ztest_shared_opts {
|
||||
char zo_pool[ZFS_MAX_DATASET_NAME_LEN];
|
||||
char zo_dir[ZFS_MAX_DATASET_NAME_LEN];
|
||||
@ -185,6 +188,8 @@ typedef struct ztest_shared_opts {
|
||||
int zo_mmp_test;
|
||||
int zo_special_vdevs;
|
||||
int zo_dump_dbgmsg;
|
||||
int zo_gvars_count;
|
||||
char zo_gvars[ZO_GVARS_MAX_COUNT][ZO_GVARS_MAX_ARGLEN];
|
||||
} ztest_shared_opts_t;
|
||||
|
||||
static const ztest_shared_opts_t ztest_opts_defaults = {
|
||||
@ -212,6 +217,7 @@ static const ztest_shared_opts_t ztest_opts_defaults = {
|
||||
.zo_maxloops = 50, /* max loops during spa_freeze() */
|
||||
.zo_metaslab_force_ganging = 64 << 10,
|
||||
.zo_special_vdevs = ZTEST_VDEV_CLASS_RND,
|
||||
.zo_gvars_count = 0,
|
||||
};
|
||||
|
||||
extern uint64_t metaslab_force_ganging;
|
||||
@ -918,8 +924,21 @@ process_options(int argc, char **argv)
|
||||
ztest_parse_name_value(optarg, zo);
|
||||
break;
|
||||
case 'o':
|
||||
if (set_global_var(optarg) != 0)
|
||||
if (zo->zo_gvars_count >= ZO_GVARS_MAX_COUNT) {
|
||||
(void) fprintf(stderr,
|
||||
"max global var count (%zu) exceeded\n",
|
||||
ZO_GVARS_MAX_COUNT);
|
||||
usage(B_FALSE);
|
||||
}
|
||||
char *v = zo->zo_gvars[zo->zo_gvars_count];
|
||||
if (strlcpy(v, optarg, ZO_GVARS_MAX_ARGLEN) >=
|
||||
ZO_GVARS_MAX_ARGLEN) {
|
||||
(void) fprintf(stderr,
|
||||
"global var option '%s' is too long\n",
|
||||
optarg);
|
||||
usage(B_FALSE);
|
||||
}
|
||||
zo->zo_gvars_count++;
|
||||
break;
|
||||
case 'G':
|
||||
zo->zo_dump_dbgmsg = 1;
|
||||
@ -6373,6 +6392,75 @@ ztest_fletcher_incr(ztest_ds_t *zd, uint64_t id)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ztest_set_global_vars(void)
|
||||
{
|
||||
for (size_t i = 0; i < ztest_opts.zo_gvars_count; i++) {
|
||||
char *kv = ztest_opts.zo_gvars[i];
|
||||
VERIFY3U(strlen(kv), <=, ZO_GVARS_MAX_ARGLEN);
|
||||
VERIFY3U(strlen(kv), >, 0);
|
||||
int err = set_global_var(kv);
|
||||
if (ztest_opts.zo_verbose > 0) {
|
||||
(void) printf("setting global var %s ... %s\n", kv,
|
||||
err ? "failed" : "ok");
|
||||
}
|
||||
if (err != 0) {
|
||||
(void) fprintf(stderr,
|
||||
"failed to set global var '%s'\n", kv);
|
||||
return (err);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static char **
|
||||
ztest_global_vars_to_zdb_args(void)
|
||||
{
|
||||
char **args = calloc(2*ztest_opts.zo_gvars_count + 1, sizeof (char *));
|
||||
char **cur = args;
|
||||
for (size_t i = 0; i < ztest_opts.zo_gvars_count; i++) {
|
||||
char *kv = ztest_opts.zo_gvars[i];
|
||||
*cur = "-o";
|
||||
cur++;
|
||||
*cur = strdup(kv);
|
||||
cur++;
|
||||
}
|
||||
ASSERT3P(cur, ==, &args[2*ztest_opts.zo_gvars_count]);
|
||||
*cur = NULL;
|
||||
return (args);
|
||||
}
|
||||
|
||||
/* The end of strings is indicated by a NULL element */
|
||||
static char *
|
||||
join_strings(char **strings, const char *sep)
|
||||
{
|
||||
size_t totallen = 0;
|
||||
for (char **sp = strings; *sp != NULL; sp++) {
|
||||
totallen += strlen(*sp);
|
||||
totallen += strlen(sep);
|
||||
}
|
||||
if (totallen > 0) {
|
||||
ASSERT(totallen >= strlen(sep));
|
||||
totallen -= strlen(sep);
|
||||
}
|
||||
|
||||
size_t buflen = totallen + 1;
|
||||
char *o = malloc(buflen); /* trailing 0 byte */
|
||||
o[0] = '\0';
|
||||
for (char **sp = strings; *sp != NULL; sp++) {
|
||||
size_t would;
|
||||
would = strlcat(o, *sp, buflen);
|
||||
VERIFY3U(would, <, buflen);
|
||||
if (*(sp+1) == NULL) {
|
||||
break;
|
||||
}
|
||||
would = strlcat(o, sep, buflen);
|
||||
VERIFY3U(would, <, buflen);
|
||||
}
|
||||
ASSERT3S(strlen(o), ==, totallen);
|
||||
return (o);
|
||||
}
|
||||
|
||||
static int
|
||||
ztest_check_path(char *path)
|
||||
{
|
||||
@ -6601,13 +6689,21 @@ ztest_run_zdb(char *pool)
|
||||
|
||||
ztest_get_zdb_bin(bin, len);
|
||||
|
||||
(void) sprintf(zdb,
|
||||
"%s -bcc%s%s -G -d -Y -e -y -p %s %s",
|
||||
char **set_gvars_args = ztest_global_vars_to_zdb_args();
|
||||
char *set_gvars_args_joined = join_strings(set_gvars_args, " ");
|
||||
free(set_gvars_args);
|
||||
|
||||
size_t would = snprintf(zdb, len,
|
||||
"%s -bcc%s%s -G -d -Y -e -y %s -p %s %s",
|
||||
bin,
|
||||
ztest_opts.zo_verbose >= 3 ? "s" : "",
|
||||
ztest_opts.zo_verbose >= 4 ? "v" : "",
|
||||
set_gvars_args_joined,
|
||||
ztest_opts.zo_dir,
|
||||
pool);
|
||||
ASSERT3U(would, <, len);
|
||||
|
||||
free(set_gvars_args_joined);
|
||||
|
||||
if (ztest_opts.zo_verbose >= 5)
|
||||
(void) printf("Executing %s\n", strstr(zdb, "zdb "));
|
||||
@ -7727,7 +7823,7 @@ main(int argc, char **argv)
|
||||
char numbuf[NN_NUMBUF_SZ];
|
||||
char *cmd;
|
||||
boolean_t hasalt;
|
||||
int f;
|
||||
int f, err;
|
||||
char *fd_data_str = getenv("ZTEST_FD_DATA");
|
||||
struct sigaction action;
|
||||
|
||||
@ -7794,6 +7890,15 @@ main(int argc, char **argv)
|
||||
}
|
||||
ASSERT3U(ztest_opts.zo_datasets, ==, ztest_shared_hdr->zh_ds_count);
|
||||
|
||||
err = ztest_set_global_vars();
|
||||
if (err != 0 && !fd_data_str) {
|
||||
/* error message done by ztest_set_global_vars */
|
||||
exit(EXIT_FAILURE);
|
||||
} else {
|
||||
/* children should not be spawned if setting gvars fails */
|
||||
VERIFY3S(err, ==, 0);
|
||||
}
|
||||
|
||||
/* Override location of zpool.cache */
|
||||
VERIFY3S(asprintf((char **)&spa_config_path, "%s/zpool.cache",
|
||||
ztest_opts.zo_dir), !=, -1);
|
||||
|
@ -55,38 +55,12 @@ typedef struct zfs_uio {
|
||||
#define zfs_uio_fault_disable(u, set)
|
||||
#define zfs_uio_prefaultpages(size, u) (0)
|
||||
|
||||
|
||||
static __inline void
|
||||
zfs_uio_init(zfs_uio_t *uio, struct uio *uio_s)
|
||||
{
|
||||
GET_UIO_STRUCT(uio) = uio_s;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
static inline void
|
||||
zfs_uio_setoffset(zfs_uio_t *uio, offset_t off)
|
||||
{
|
||||
zfs_uio_offset(uio) = off;
|
||||
}
|
||||
|
||||
static __inline int
|
||||
zfs_uiomove(void *cp, size_t n, zfs_uio_rw_t dir, zfs_uio_t *uio)
|
||||
{
|
||||
ASSERT(zfs_uio_rw(uio) == dir);
|
||||
return (uiomove(cp, (int)n, GET_UIO_STRUCT(uio)));
|
||||
}
|
||||
|
||||
int zfs_uiocopy(void *p, size_t n, zfs_uio_rw_t rw, zfs_uio_t *uio,
|
||||
size_t *cbytes);
|
||||
void zfs_uioskip(zfs_uio_t *uiop, size_t n);
|
||||
int zfs_uio_fault_move(void *p, size_t n, zfs_uio_rw_t dir, zfs_uio_t *uio);
|
||||
|
||||
static inline void
|
||||
zfs_uio_iov_at_index(zfs_uio_t *uio, uint_t idx, void **base, uint64_t *len)
|
||||
{
|
||||
*base = zfs_uio_iovbase(uio, idx);
|
||||
*len = zfs_uio_iovlen(uio, idx);
|
||||
}
|
||||
|
||||
static inline void
|
||||
zfs_uio_advance(zfs_uio_t *uio, size_t size)
|
||||
{
|
||||
@ -94,18 +68,13 @@ zfs_uio_advance(zfs_uio_t *uio, size_t size)
|
||||
zfs_uio_offset(uio) += size;
|
||||
}
|
||||
|
||||
static inline offset_t
|
||||
zfs_uio_index_at_offset(zfs_uio_t *uio, offset_t off, uint_t *vec_idx)
|
||||
static __inline void
|
||||
zfs_uio_init(zfs_uio_t *uio, struct uio *uio_s)
|
||||
{
|
||||
*vec_idx = 0;
|
||||
while (*vec_idx < zfs_uio_iovcnt(uio) &&
|
||||
off >= zfs_uio_iovlen(uio, *vec_idx)) {
|
||||
off -= zfs_uio_iovlen(uio, *vec_idx);
|
||||
(*vec_idx)++;
|
||||
GET_UIO_STRUCT(uio) = uio_s;
|
||||
}
|
||||
|
||||
return (off);
|
||||
}
|
||||
int zfs_uio_fault_move(void *p, size_t n, zfs_uio_rw_t dir, zfs_uio_t *uio);
|
||||
|
||||
#endif /* !_STANDALONE */
|
||||
|
||||
|
@ -78,19 +78,14 @@ typedef struct zfs_uio {
|
||||
#define zfs_uio_rlimit_fsize(z, u) (0)
|
||||
#define zfs_uio_fault_move(p, n, rw, u) zfs_uiomove((p), (n), (rw), (u))
|
||||
|
||||
extern int zfs_uio_prefaultpages(ssize_t, zfs_uio_t *);
|
||||
|
||||
static inline void
|
||||
zfs_uio_setoffset(zfs_uio_t *uio, offset_t off)
|
||||
{
|
||||
uio->uio_loffset = off;
|
||||
}
|
||||
|
||||
static inline void
|
||||
zfs_uio_iov_at_index(zfs_uio_t *uio, uint_t idx, void **base, uint64_t *len)
|
||||
{
|
||||
*base = zfs_uio_iovbase(uio, idx);
|
||||
*len = zfs_uio_iovlen(uio, idx);
|
||||
}
|
||||
|
||||
static inline void
|
||||
zfs_uio_advance(zfs_uio_t *uio, size_t size)
|
||||
{
|
||||
@ -98,19 +93,6 @@ zfs_uio_advance(zfs_uio_t *uio, size_t size)
|
||||
uio->uio_loffset += size;
|
||||
}
|
||||
|
||||
static inline offset_t
|
||||
zfs_uio_index_at_offset(zfs_uio_t *uio, offset_t off, uint_t *vec_idx)
|
||||
{
|
||||
*vec_idx = 0;
|
||||
while (*vec_idx < zfs_uio_iovcnt(uio) &&
|
||||
off >= zfs_uio_iovlen(uio, *vec_idx)) {
|
||||
off -= zfs_uio_iovlen(uio, *vec_idx);
|
||||
(*vec_idx)++;
|
||||
}
|
||||
|
||||
return (off);
|
||||
}
|
||||
|
||||
static inline void
|
||||
zfs_uio_iovec_init(zfs_uio_t *uio, const struct iovec *iov,
|
||||
unsigned long nr_segs, offset_t offset, zfs_uio_seg_t seg, ssize_t resid,
|
||||
|
@ -23,7 +23,6 @@
|
||||
#ifndef ZFS_CONTEXT_OS_H
|
||||
#define ZFS_CONTEXT_OS_H
|
||||
|
||||
#include <sys/uio_impl.h>
|
||||
#include <linux/dcache_compat.h>
|
||||
#include <linux/utsname_compat.h>
|
||||
|
||||
|
@ -111,6 +111,7 @@ COMMON_H = \
|
||||
zfs_fuid.h \
|
||||
zfs_project.h \
|
||||
zfs_quota.h \
|
||||
zfs_racct.h \
|
||||
zfs_ratelimit.h \
|
||||
zfs_refcount.h \
|
||||
zfs_rlock.h \
|
||||
|
@ -20,7 +20,7 @@
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2020 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2021 by Delphix. All rights reserved.
|
||||
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
|
||||
* Copyright 2013 Saso Kiselkov. All rights reserved.
|
||||
@ -1150,6 +1150,7 @@ extern int zfs_ereport_post(const char *clazz, spa_t *spa, vdev_t *vd,
|
||||
extern boolean_t zfs_ereport_is_valid(const char *clazz, spa_t *spa, vdev_t *vd,
|
||||
zio_t *zio);
|
||||
extern void zfs_ereport_taskq_fini(void);
|
||||
extern void zfs_ereport_clear(spa_t *spa, vdev_t *vd);
|
||||
extern nvlist_t *zfs_event_create(spa_t *spa, vdev_t *vd, const char *type,
|
||||
const char *name, nvlist_t *aux);
|
||||
extern void zfs_post_remove(spa_t *spa, vdev_t *vd);
|
||||
|
@ -42,8 +42,27 @@
|
||||
#include <sys/uio.h>
|
||||
|
||||
extern int zfs_uiomove(void *, size_t, zfs_uio_rw_t, zfs_uio_t *);
|
||||
extern int zfs_uio_prefaultpages(ssize_t, zfs_uio_t *);
|
||||
extern int zfs_uiocopy(void *, size_t, zfs_uio_rw_t, zfs_uio_t *, size_t *);
|
||||
extern void zfs_uioskip(zfs_uio_t *, size_t);
|
||||
|
||||
static inline void
|
||||
zfs_uio_iov_at_index(zfs_uio_t *uio, uint_t idx, void **base, uint64_t *len)
|
||||
{
|
||||
*base = zfs_uio_iovbase(uio, idx);
|
||||
*len = zfs_uio_iovlen(uio, idx);
|
||||
}
|
||||
|
||||
static inline offset_t
|
||||
zfs_uio_index_at_offset(zfs_uio_t *uio, offset_t off, uint_t *vec_idx)
|
||||
{
|
||||
*vec_idx = 0;
|
||||
while (*vec_idx < zfs_uio_iovcnt(uio) &&
|
||||
off >= zfs_uio_iovlen(uio, *vec_idx)) {
|
||||
off -= zfs_uio_iovlen(uio, *vec_idx);
|
||||
(*vec_idx)++;
|
||||
}
|
||||
|
||||
return (off);
|
||||
}
|
||||
|
||||
#endif /* _SYS_UIO_IMPL_H */
|
||||
|
@ -72,6 +72,7 @@ extern "C" {
|
||||
#include <sys/trace.h>
|
||||
#include <sys/procfs_list.h>
|
||||
#include <sys/mod.h>
|
||||
#include <sys/uio_impl.h>
|
||||
#include <sys/zfs_context_os.h>
|
||||
#else /* _KERNEL || _STANDALONE */
|
||||
|
||||
@ -652,7 +653,7 @@ extern void random_fini(void);
|
||||
|
||||
struct spa;
|
||||
extern void show_pool_stats(struct spa *);
|
||||
extern int set_global_var(char *arg);
|
||||
extern int set_global_var(char const *arg);
|
||||
|
||||
typedef struct callb_cpr {
|
||||
kmutex_t *cc_lockp;
|
||||
|
37
sys/contrib/openzfs/include/sys/zfs_racct.h
Normal file
37
sys/contrib/openzfs/include/sys/zfs_racct.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 http://www.opensolaris.org/os/licensing.
|
||||
* 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
|
||||
*/
|
||||
|
||||
/*
|
||||
* Portions Copyright 2021 iXsystems, Inc.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_ZFS_RACCT_H
|
||||
#define _SYS_ZFS_RACCT_H
|
||||
|
||||
#include <sys/zfs_context.h>
|
||||
|
||||
/*
|
||||
* Platform-dependent resource accounting hooks
|
||||
*/
|
||||
void zfs_racct_read(uint64_t size, uint64_t iops);
|
||||
void zfs_racct_write(uint64_t size, uint64_t iops);
|
||||
|
||||
#endif /* _SYS_ZFS_RACCT_H */
|
@ -163,6 +163,7 @@ KERNEL_C = \
|
||||
zfs_debug.c \
|
||||
zfs_fm.c \
|
||||
zfs_fuid.c \
|
||||
zfs_racct.c \
|
||||
zfs_sa.c \
|
||||
zfs_znode.c \
|
||||
zfs_ratelimit.c \
|
||||
|
@ -148,18 +148,54 @@ show_pool_stats(spa_t *spa)
|
||||
nvlist_free(config);
|
||||
}
|
||||
|
||||
/* *k_out must be freed by the caller */
|
||||
static int
|
||||
set_global_var_parse_kv(const char *arg, char **k_out, u_longlong_t *v_out)
|
||||
{
|
||||
int err;
|
||||
VERIFY(arg);
|
||||
char *d = strdup(arg);
|
||||
|
||||
char *save = NULL;
|
||||
char *k = strtok_r(d, "=", &save);
|
||||
char *v_str = strtok_r(NULL, "=", &save);
|
||||
char *follow = strtok_r(NULL, "=", &save);
|
||||
if (k == NULL || v_str == NULL || follow != NULL) {
|
||||
err = EINVAL;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
u_longlong_t val = strtoull(v_str, NULL, 0);
|
||||
if (val > UINT32_MAX) {
|
||||
fprintf(stderr, "Value for global variable '%s' must "
|
||||
"be a 32-bit unsigned integer, got '%s'\n", k, v_str);
|
||||
err = EOVERFLOW;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
*k_out = k;
|
||||
*v_out = val;
|
||||
return (0);
|
||||
|
||||
err_free:
|
||||
free(k);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets given global variable in libzpool to given unsigned 32-bit value.
|
||||
* arg: "<variable>=<value>"
|
||||
*/
|
||||
int
|
||||
set_global_var(char *arg)
|
||||
set_global_var(char const *arg)
|
||||
{
|
||||
void *zpoolhdl;
|
||||
char *varname = arg, *varval;
|
||||
char *varname;
|
||||
u_longlong_t val;
|
||||
int ret;
|
||||
|
||||
#ifndef _LITTLE_ENDIAN
|
||||
#ifndef _ZFS_LITTLE_ENDIAN
|
||||
/*
|
||||
* On big endian systems changing a 64-bit variable would set the high
|
||||
* 32 bits instead of the low 32 bits, which could cause unexpected
|
||||
@ -167,19 +203,12 @@ set_global_var(char *arg)
|
||||
*/
|
||||
fprintf(stderr, "Setting global variables is only supported on "
|
||||
"little-endian systems\n");
|
||||
return (ENOTSUP);
|
||||
ret = ENOTSUP;
|
||||
goto out_ret;
|
||||
#endif
|
||||
if (arg != NULL && (varval = strchr(arg, '=')) != NULL) {
|
||||
*varval = '\0';
|
||||
varval++;
|
||||
val = strtoull(varval, NULL, 0);
|
||||
if (val > UINT32_MAX) {
|
||||
fprintf(stderr, "Value for global variable '%s' must "
|
||||
"be a 32-bit unsigned integer\n", varname);
|
||||
return (EOVERFLOW);
|
||||
}
|
||||
} else {
|
||||
return (EINVAL);
|
||||
|
||||
if ((ret = set_global_var_parse_kv(arg, &varname, &val)) != 0) {
|
||||
goto out_ret;
|
||||
}
|
||||
|
||||
zpoolhdl = dlopen("libzpool.so", RTLD_LAZY);
|
||||
@ -189,18 +218,25 @@ set_global_var(char *arg)
|
||||
if (var == NULL) {
|
||||
fprintf(stderr, "Global variable '%s' does not exist "
|
||||
"in libzpool.so\n", varname);
|
||||
return (EINVAL);
|
||||
ret = EINVAL;
|
||||
goto out_dlclose;
|
||||
}
|
||||
*var = (uint32_t)val;
|
||||
|
||||
dlclose(zpoolhdl);
|
||||
} else {
|
||||
fprintf(stderr, "Failed to open libzpool.so to set global "
|
||||
"variable\n");
|
||||
return (EIO);
|
||||
ret = EIO;
|
||||
goto out_dlclose;
|
||||
}
|
||||
|
||||
return (0);
|
||||
ret = 0;
|
||||
|
||||
out_dlclose:
|
||||
dlclose(zpoolhdl);
|
||||
free(varname);
|
||||
out_ret:
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static nvlist_t *
|
||||
|
@ -154,15 +154,124 @@ zfs_strip_path(char *path)
|
||||
return (strrchr(path, '/') + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a dev name like "sda", return the full enclosure sysfs path to
|
||||
* the disk. You can also pass in the name with "/dev" prepended
|
||||
* to it (like /dev/sda).
|
||||
*
|
||||
* For example, disk "sda" in enclosure slot 1:
|
||||
* dev: "sda"
|
||||
* returns: "/sys/class/enclosure/1:0:3:0/Slot 1"
|
||||
*
|
||||
* 'dev' must be a non-devicemapper device.
|
||||
*
|
||||
* Returned string must be freed.
|
||||
*/
|
||||
char *
|
||||
zfs_get_enclosure_sysfs_path(const char *dev_name)
|
||||
{
|
||||
DIR *dp = NULL;
|
||||
struct dirent *ep;
|
||||
char buf[MAXPATHLEN];
|
||||
char *tmp1 = NULL;
|
||||
char *tmp2 = NULL;
|
||||
char *tmp3 = NULL;
|
||||
char *path = NULL;
|
||||
size_t size;
|
||||
int tmpsize;
|
||||
|
||||
if (dev_name == NULL)
|
||||
return (NULL);
|
||||
|
||||
/* If they preface 'dev' with a path (like "/dev") then strip it off */
|
||||
tmp1 = strrchr(dev_name, '/');
|
||||
if (tmp1 != NULL)
|
||||
dev_name = tmp1 + 1; /* +1 since we want the chr after '/' */
|
||||
|
||||
tmpsize = asprintf(&tmp1, "/sys/block/%s/device", dev_name);
|
||||
if (tmpsize == -1 || tmp1 == NULL) {
|
||||
tmp1 = NULL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
dp = opendir(tmp1);
|
||||
if (dp == NULL) {
|
||||
tmp1 = NULL; /* To make free() at the end a NOP */
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look though all sysfs entries in /sys/block/<dev>/device for
|
||||
* the enclosure symlink.
|
||||
*/
|
||||
while ((ep = readdir(dp))) {
|
||||
/* Ignore everything that's not our enclosure_device link */
|
||||
if (strstr(ep->d_name, "enclosure_device") == NULL)
|
||||
continue;
|
||||
|
||||
if (asprintf(&tmp2, "%s/%s", tmp1, ep->d_name) == -1 ||
|
||||
tmp2 == NULL)
|
||||
break;
|
||||
|
||||
size = readlink(tmp2, buf, sizeof (buf));
|
||||
|
||||
/* Did readlink fail or crop the link name? */
|
||||
if (size == -1 || size >= sizeof (buf)) {
|
||||
free(tmp2);
|
||||
tmp2 = NULL; /* To make free() at the end a NOP */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We got a valid link. readlink() doesn't terminate strings
|
||||
* so we have to do it.
|
||||
*/
|
||||
buf[size] = '\0';
|
||||
|
||||
/*
|
||||
* Our link will look like:
|
||||
*
|
||||
* "../../../../port-11:1:2/..STUFF../enclosure/1:0:3:0/SLOT 1"
|
||||
*
|
||||
* We want to grab the "enclosure/1:0:3:0/SLOT 1" part
|
||||
*/
|
||||
tmp3 = strstr(buf, "enclosure");
|
||||
if (tmp3 == NULL)
|
||||
break;
|
||||
|
||||
if (asprintf(&path, "/sys/class/%s", tmp3) == -1) {
|
||||
/* If asprintf() fails, 'path' is undefined */
|
||||
path = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (path == NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
end:
|
||||
free(tmp2);
|
||||
free(tmp1);
|
||||
|
||||
if (dp != NULL)
|
||||
closedir(dp);
|
||||
|
||||
return (path);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate and return the underlying device name for a device mapper device.
|
||||
* If a device mapper device maps to multiple devices, return the first device.
|
||||
*
|
||||
* For example, dm_name = "/dev/dm-0" could return "/dev/sda". Symlinks to a
|
||||
* DM device (like /dev/disk/by-vdev/A0) are also allowed.
|
||||
*
|
||||
* Returns device name, or NULL on error or no match. If dm_name is not a DM
|
||||
* device then return NULL.
|
||||
* If the DM device has multiple underlying devices (like with multipath
|
||||
* DM devices), then favor underlying devices that have a symlink back to their
|
||||
* back to their enclosure device in sysfs. This will be useful for the
|
||||
* zedlet scripts that toggle the fault LED.
|
||||
*
|
||||
* Returns an underlying device name, or NULL on error or no match. If dm_name
|
||||
* is not a DM device then return NULL.
|
||||
*
|
||||
* NOTE: The returned name string must be *freed*.
|
||||
*/
|
||||
@ -176,6 +285,8 @@ dm_get_underlying_path(const char *dm_name)
|
||||
char *path = NULL;
|
||||
char *dev_str;
|
||||
int size;
|
||||
char *first_path = NULL;
|
||||
char *enclosure_path;
|
||||
|
||||
if (dm_name == NULL)
|
||||
return (NULL);
|
||||
@ -204,13 +315,27 @@ dm_get_underlying_path(const char *dm_name)
|
||||
goto end;
|
||||
|
||||
/*
|
||||
* Return first entry (that isn't itself a directory) in the
|
||||
* directory containing device-mapper dependent (underlying)
|
||||
* devices.
|
||||
* A device-mapper device can have multiple paths to it (multipath).
|
||||
* Favor paths that have a symlink back to their enclosure device.
|
||||
* We have to do this since some enclosures may only provide a symlink
|
||||
* back for one underlying path to a disk and not the other.
|
||||
*
|
||||
* If no paths have links back to their enclosure, then just return the
|
||||
* first path.
|
||||
*/
|
||||
while ((ep = readdir(dp))) {
|
||||
if (ep->d_type != DT_DIR) { /* skip "." and ".." dirs */
|
||||
if (!first_path)
|
||||
first_path = strdup(ep->d_name);
|
||||
|
||||
enclosure_path =
|
||||
zfs_get_enclosure_sysfs_path(ep->d_name);
|
||||
|
||||
if (!enclosure_path)
|
||||
continue;
|
||||
|
||||
size = asprintf(&path, "/dev/%s", ep->d_name);
|
||||
free(enclosure_path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -220,6 +345,17 @@ dm_get_underlying_path(const char *dm_name)
|
||||
closedir(dp);
|
||||
free(tmp);
|
||||
free(realp);
|
||||
|
||||
if (!path) {
|
||||
/*
|
||||
* None of the underlying paths had a link back to their
|
||||
* enclosure devices. Throw up out hands and return the first
|
||||
* underlying path.
|
||||
*/
|
||||
size = asprintf(&path, "/dev/%s", first_path);
|
||||
}
|
||||
|
||||
free(first_path);
|
||||
return (path);
|
||||
}
|
||||
|
||||
@ -331,110 +467,6 @@ zfs_get_underlying_path(const char *dev_name)
|
||||
return (name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a dev name like "sda", return the full enclosure sysfs path to
|
||||
* the disk. You can also pass in the name with "/dev" prepended
|
||||
* to it (like /dev/sda).
|
||||
*
|
||||
* For example, disk "sda" in enclosure slot 1:
|
||||
* dev: "sda"
|
||||
* returns: "/sys/class/enclosure/1:0:3:0/Slot 1"
|
||||
*
|
||||
* 'dev' must be a non-devicemapper device.
|
||||
*
|
||||
* Returned string must be freed.
|
||||
*/
|
||||
char *
|
||||
zfs_get_enclosure_sysfs_path(const char *dev_name)
|
||||
{
|
||||
DIR *dp = NULL;
|
||||
struct dirent *ep;
|
||||
char buf[MAXPATHLEN];
|
||||
char *tmp1 = NULL;
|
||||
char *tmp2 = NULL;
|
||||
char *tmp3 = NULL;
|
||||
char *path = NULL;
|
||||
size_t size;
|
||||
int tmpsize;
|
||||
|
||||
if (dev_name == NULL)
|
||||
return (NULL);
|
||||
|
||||
/* If they preface 'dev' with a path (like "/dev") then strip it off */
|
||||
tmp1 = strrchr(dev_name, '/');
|
||||
if (tmp1 != NULL)
|
||||
dev_name = tmp1 + 1; /* +1 since we want the chr after '/' */
|
||||
|
||||
tmpsize = asprintf(&tmp1, "/sys/block/%s/device", dev_name);
|
||||
if (tmpsize == -1 || tmp1 == NULL) {
|
||||
tmp1 = NULL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
dp = opendir(tmp1);
|
||||
if (dp == NULL) {
|
||||
tmp1 = NULL; /* To make free() at the end a NOP */
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look though all sysfs entries in /sys/block/<dev>/device for
|
||||
* the enclosure symlink.
|
||||
*/
|
||||
while ((ep = readdir(dp))) {
|
||||
/* Ignore everything that's not our enclosure_device link */
|
||||
if (strstr(ep->d_name, "enclosure_device") == NULL)
|
||||
continue;
|
||||
|
||||
if (asprintf(&tmp2, "%s/%s", tmp1, ep->d_name) == -1 ||
|
||||
tmp2 == NULL)
|
||||
break;
|
||||
|
||||
size = readlink(tmp2, buf, sizeof (buf));
|
||||
|
||||
/* Did readlink fail or crop the link name? */
|
||||
if (size == -1 || size >= sizeof (buf)) {
|
||||
free(tmp2);
|
||||
tmp2 = NULL; /* To make free() at the end a NOP */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We got a valid link. readlink() doesn't terminate strings
|
||||
* so we have to do it.
|
||||
*/
|
||||
buf[size] = '\0';
|
||||
|
||||
/*
|
||||
* Our link will look like:
|
||||
*
|
||||
* "../../../../port-11:1:2/..STUFF../enclosure/1:0:3:0/SLOT 1"
|
||||
*
|
||||
* We want to grab the "enclosure/1:0:3:0/SLOT 1" part
|
||||
*/
|
||||
tmp3 = strstr(buf, "enclosure");
|
||||
if (tmp3 == NULL)
|
||||
break;
|
||||
|
||||
if (asprintf(&path, "/sys/class/%s", tmp3) == -1) {
|
||||
/* If asprintf() fails, 'path' is undefined */
|
||||
path = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (path == NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
end:
|
||||
free(tmp2);
|
||||
free(tmp1);
|
||||
|
||||
if (dp != NULL)
|
||||
closedir(dp);
|
||||
|
||||
return (path);
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBUDEV
|
||||
|
||||
|
@ -153,6 +153,7 @@ SRCS+= abd_os.c \
|
||||
zfs_dir.c \
|
||||
zfs_ioctl_compat.c \
|
||||
zfs_ioctl_os.c \
|
||||
zfs_racct.c \
|
||||
zfs_vfsops.c \
|
||||
zfs_vnops_os.c \
|
||||
zfs_znode.c \
|
||||
|
@ -41,10 +41,17 @@
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/uio_impl.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/zfs_znode.h>
|
||||
|
||||
int
|
||||
zfs_uiomove(void *cp, size_t n, zfs_uio_rw_t dir, zfs_uio_t *uio)
|
||||
{
|
||||
ASSERT(zfs_uio_rw(uio) == dir);
|
||||
return (uiomove(cp, (int)n, GET_UIO_STRUCT(uio)));
|
||||
}
|
||||
|
||||
/*
|
||||
* same as zfs_uiomove() but doesn't modify uio structure.
|
||||
* return in cbytes how many bytes were copied.
|
||||
|
@ -293,8 +293,19 @@ freebsd_crypt_newsession(freebsd_crypt_session_t *sessp,
|
||||
error = ENOTSUP;
|
||||
goto bad;
|
||||
}
|
||||
error = crypto_newsession(&sessp->fs_sid, &csp,
|
||||
CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE);
|
||||
|
||||
/*
|
||||
* Disable the use of hardware drivers on FreeBSD 13 and later since
|
||||
* common crypto offload drivers impose constraints on AES-GCM AAD
|
||||
* lengths that make them unusable for ZFS, and we currently do not have
|
||||
* a mechanism to fall back to a software driver for requests not
|
||||
* handled by a hardware driver.
|
||||
*
|
||||
* On 12 we continue to permit the use of hardware drivers since
|
||||
* CPU-accelerated drivers such as aesni(4) register themselves as
|
||||
* hardware drivers.
|
||||
*/
|
||||
error = crypto_newsession(&sessp->fs_sid, &csp, CRYPTOCAP_F_SOFTWARE);
|
||||
mtx_init(&sessp->fs_lock, "FreeBSD Cryptographic Session Lock",
|
||||
NULL, MTX_DEF);
|
||||
crypt_sessions++;
|
||||
|
55
sys/contrib/openzfs/module/os/freebsd/zfs/zfs_racct.c
Normal file
55
sys/contrib/openzfs/module/os/freebsd/zfs/zfs_racct.c
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2021 iXsystems, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/zfs_racct.h>
|
||||
#include <sys/racct.h>
|
||||
|
||||
void
|
||||
zfs_racct_read(uint64_t size, uint64_t iops)
|
||||
{
|
||||
curthread->td_ru.ru_inblock += iops;
|
||||
#ifdef RACCT
|
||||
if (racct_enable) {
|
||||
PROC_LOCK(curproc);
|
||||
racct_add_force(curproc, RACCT_READBPS, size);
|
||||
racct_add_force(curproc, RACCT_READIOPS, iops);
|
||||
PROC_UNLOCK(curproc);
|
||||
}
|
||||
#endif /* RACCT */
|
||||
}
|
||||
|
||||
void
|
||||
zfs_racct_write(uint64_t size, uint64_t iops)
|
||||
{
|
||||
curthread->td_ru.ru_oublock += iops;
|
||||
#ifdef RACCT
|
||||
if (racct_enable) {
|
||||
PROC_LOCK(curproc);
|
||||
racct_add_force(curproc, RACCT_WRITEBPS, size);
|
||||
racct_add_force(curproc, RACCT_WRITEIOPS, iops);
|
||||
PROC_UNLOCK(curproc);
|
||||
}
|
||||
#endif /* RACCT */
|
||||
}
|
@ -22,6 +22,7 @@ $(MODULE)-objs += ../os/linux/zfs/zfs_debug.o
|
||||
$(MODULE)-objs += ../os/linux/zfs/zfs_dir.o
|
||||
$(MODULE)-objs += ../os/linux/zfs/zfs_file_os.o
|
||||
$(MODULE)-objs += ../os/linux/zfs/zfs_ioctl_os.o
|
||||
$(MODULE)-objs += ../os/linux/zfs/zfs_racct.o
|
||||
$(MODULE)-objs += ../os/linux/zfs/zfs_sysfs.o
|
||||
$(MODULE)-objs += ../os/linux/zfs/zfs_uio.o
|
||||
$(MODULE)-objs += ../os/linux/zfs/zfs_vfsops.o
|
||||
|
36
sys/contrib/openzfs/module/os/linux/zfs/zfs_racct.c
Normal file
36
sys/contrib/openzfs/module/os/linux/zfs/zfs_racct.c
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2021 iXsystems, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/zfs_racct.h>
|
||||
|
||||
void
|
||||
zfs_racct_read(uint64_t size, uint64_t iops)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
zfs_racct_write(uint64_t size, uint64_t iops)
|
||||
{
|
||||
}
|
@ -308,6 +308,7 @@
|
||||
#include <sys/aggsum.h>
|
||||
#include <cityhash.h>
|
||||
#include <sys/vdev_trim.h>
|
||||
#include <sys/zfs_racct.h>
|
||||
#include <sys/zstd/zstd.h>
|
||||
|
||||
#ifndef _KERNEL
|
||||
@ -6302,6 +6303,7 @@ arc_read(zio_t *pio, spa_t *spa, const blkptr_t *bp,
|
||||
ARCSTAT_CONDSTAT(!HDR_PREFETCH(hdr),
|
||||
demand, prefetch, !HDR_ISTYPE_METADATA(hdr), data,
|
||||
metadata, misses);
|
||||
zfs_racct_read(size, 1);
|
||||
}
|
||||
|
||||
/* Check if the spa even has l2 configured */
|
||||
|
@ -52,6 +52,7 @@
|
||||
#include <sys/zfeature.h>
|
||||
#include <sys/abd.h>
|
||||
#include <sys/trace_zfs.h>
|
||||
#include <sys/zfs_racct.h>
|
||||
#include <sys/zfs_rlock.h>
|
||||
#ifdef _KERNEL
|
||||
#include <sys/vmsystm.h>
|
||||
@ -551,6 +552,9 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length,
|
||||
dbp[i] = &db->db;
|
||||
}
|
||||
|
||||
if (!read)
|
||||
zfs_racct_write(length, nblks);
|
||||
|
||||
if ((flags & DMU_READ_NO_PREFETCH) == 0 &&
|
||||
DNODE_META_IS_CACHEABLE(dn) && length <= zfetch_array_rd_sz) {
|
||||
dmu_zfetch(&dn->dn_zfetch, blkid, nblks,
|
||||
@ -1440,6 +1444,7 @@ dmu_assign_arcbuf_by_dnode(dnode_t *dn, uint64_t offset, arc_buf_t *buf,
|
||||
* same size as the dbuf.
|
||||
*/
|
||||
if (offset == db->db.db_offset && blksz == db->db.db_size) {
|
||||
zfs_racct_write(blksz, 1);
|
||||
dbuf_assign_arcbuf(db, buf, tx);
|
||||
dbuf_rele(db, FTAG);
|
||||
} else {
|
||||
|
@ -20,7 +20,7 @@
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2018 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2021 by Delphix. All rights reserved.
|
||||
* Copyright 2016 Gary Mills
|
||||
* Copyright (c) 2017, 2019, Datto Inc. All rights reserved.
|
||||
* Copyright (c) 2015, Nexenta Systems, Inc. All rights reserved.
|
||||
@ -987,6 +987,10 @@ dsl_scan_done(dsl_scan_t *scn, boolean_t complete, dmu_tx_t *tx)
|
||||
(u_longlong_t)spa_get_errlog_size(spa));
|
||||
spa_async_request(spa, SPA_ASYNC_RESILVER);
|
||||
}
|
||||
|
||||
/* Clear recent error events (i.e. duplicate events tracking) */
|
||||
if (complete)
|
||||
zfs_ereport_clear(spa, NULL);
|
||||
}
|
||||
|
||||
scn->scn_phys.scn_end_time = gethrestime_sec();
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include <sys/fm/fs/zfs.h>
|
||||
#include <sys/spa_impl.h>
|
||||
#include <sys/nvpair.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/fs/zfs.h>
|
||||
#include <sys/vdev_impl.h>
|
||||
#include <sys/zfs_ioctl.h>
|
||||
@ -40,6 +39,7 @@
|
||||
#include <sys/sunddi.h>
|
||||
#include <sys/zfeature.h>
|
||||
#include <sys/zfs_file.h>
|
||||
#include <sys/zfs_context.h>
|
||||
#ifdef _KERNEL
|
||||
#include <sys/zone.h>
|
||||
#endif
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2020 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2021 by Delphix. All rights reserved.
|
||||
* Copyright 2017 Nexenta Systems, Inc.
|
||||
* Copyright (c) 2014 Integros [integros.com]
|
||||
* Copyright 2016 Toomas Soome <tsoome@me.com>
|
||||
@ -2527,7 +2527,7 @@ vdev_hold(vdev_t *vd)
|
||||
for (int c = 0; c < vd->vdev_children; c++)
|
||||
vdev_hold(vd->vdev_child[c]);
|
||||
|
||||
if (vd->vdev_ops->vdev_op_leaf)
|
||||
if (vd->vdev_ops->vdev_op_leaf && vd->vdev_ops->vdev_op_hold != NULL)
|
||||
vd->vdev_ops->vdev_op_hold(vd);
|
||||
}
|
||||
|
||||
@ -2538,7 +2538,7 @@ vdev_rele(vdev_t *vd)
|
||||
for (int c = 0; c < vd->vdev_children; c++)
|
||||
vdev_rele(vd->vdev_child[c]);
|
||||
|
||||
if (vd->vdev_ops->vdev_op_leaf)
|
||||
if (vd->vdev_ops->vdev_op_leaf && vd->vdev_ops->vdev_op_rele != NULL)
|
||||
vd->vdev_ops->vdev_op_rele(vd);
|
||||
}
|
||||
|
||||
@ -4170,6 +4170,9 @@ vdev_clear(spa_t *spa, vdev_t *vd)
|
||||
vd->vdev_parent->vdev_ops == &vdev_spare_ops &&
|
||||
vd->vdev_parent->vdev_child[0] == vd)
|
||||
vd->vdev_unspare = B_TRUE;
|
||||
|
||||
/* Clear recent error events cache (i.e. duplicate events tracking) */
|
||||
zfs_ereport_clear(spa, vd);
|
||||
}
|
||||
|
||||
boolean_t
|
||||
|
@ -1485,17 +1485,15 @@ vdev_indirect_all_checksum_errors(zio_t *zio)
|
||||
|
||||
vdev_t *vd = ic->ic_vdev;
|
||||
|
||||
int ret = zfs_ereport_post_checksum(zio->io_spa, vd,
|
||||
(void) zfs_ereport_post_checksum(zio->io_spa, vd,
|
||||
NULL, zio, is->is_target_offset, is->is_size,
|
||||
NULL, NULL, NULL);
|
||||
if (ret != EALREADY) {
|
||||
mutex_enter(&vd->vdev_stat_lock);
|
||||
vd->vdev_stat.vs_checksum_errors++;
|
||||
mutex_exit(&vd->vdev_stat_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy data from all the splits to a main zio then validate the checksum.
|
||||
|
@ -1852,16 +1852,14 @@ raidz_checksum_error(zio_t *zio, raidz_col_t *rc, abd_t *bad_data)
|
||||
zbc.zbc_has_cksum = 0;
|
||||
zbc.zbc_injected = rm->rm_ecksuminjected;
|
||||
|
||||
int ret = zfs_ereport_post_checksum(zio->io_spa, vd,
|
||||
(void) zfs_ereport_post_checksum(zio->io_spa, vd,
|
||||
&zio->io_bookmark, zio, rc->rc_offset, rc->rc_size,
|
||||
rc->rc_abd, bad_data, &zbc);
|
||||
if (ret != EALREADY) {
|
||||
mutex_enter(&vd->vdev_stat_lock);
|
||||
vd->vdev_stat.vs_checksum_errors++;
|
||||
mutex_exit(&vd->vdev_stat_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We keep track of whether or not there were any injected errors, so that
|
||||
@ -2453,17 +2451,15 @@ vdev_raidz_io_done_unrecoverable(zio_t *zio)
|
||||
zbc.zbc_has_cksum = 0;
|
||||
zbc.zbc_injected = rm->rm_ecksuminjected;
|
||||
|
||||
int ret = zfs_ereport_start_checksum(zio->io_spa,
|
||||
(void) zfs_ereport_start_checksum(zio->io_spa,
|
||||
cvd, &zio->io_bookmark, zio, rc->rc_offset,
|
||||
rc->rc_size, (void *)(uintptr_t)c, &zbc);
|
||||
if (ret != EALREADY) {
|
||||
mutex_enter(&cvd->vdev_stat_lock);
|
||||
cvd->vdev_stat.vs_checksum_errors++;
|
||||
mutex_exit(&cvd->vdev_stat_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
vdev_raidz_io_done(zio_t *zio)
|
||||
|
@ -338,6 +338,9 @@ vdev_rebuild_complete_sync(void *arg, dmu_tx_t *tx)
|
||||
}
|
||||
|
||||
cv_broadcast(&vd->vdev_rebuild_cv);
|
||||
|
||||
/* Clear recent error events (i.e. duplicate events tracking) */
|
||||
zfs_ereport_clear(spa, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -24,7 +24,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012,2020 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012,2021 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <sys/spa.h>
|
||||
@ -247,6 +247,44 @@ zfs_ereport_schedule_cleaner(void)
|
||||
ddi_get_lbolt() + NSEC_TO_TICK(timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear entries for a given vdev or all vdevs in a pool when vdev == NULL
|
||||
*/
|
||||
void
|
||||
zfs_ereport_clear(spa_t *spa, vdev_t *vd)
|
||||
{
|
||||
uint64_t vdev_guid, pool_guid;
|
||||
int cnt = 0;
|
||||
|
||||
ASSERT(vd != NULL || spa != NULL);
|
||||
if (vd == NULL) {
|
||||
vdev_guid = 0;
|
||||
pool_guid = spa_guid(spa);
|
||||
} else {
|
||||
vdev_guid = vd->vdev_guid;
|
||||
pool_guid = 0;
|
||||
}
|
||||
|
||||
mutex_enter(&recent_events_lock);
|
||||
|
||||
recent_events_node_t *next = list_head(&recent_events_list);
|
||||
while (next != NULL) {
|
||||
recent_events_node_t *entry = next;
|
||||
|
||||
next = list_next(&recent_events_list, next);
|
||||
|
||||
if (entry->re_vdev_guid == vdev_guid ||
|
||||
entry->re_pool_guid == pool_guid) {
|
||||
avl_remove(&recent_events_tree, entry);
|
||||
list_remove(&recent_events_list, entry);
|
||||
kmem_free(entry, sizeof (*entry));
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_exit(&recent_events_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if an ereport would be a duplicate of one recently posted.
|
||||
*
|
||||
@ -951,6 +989,12 @@ annotate_ecksum(nvlist_t *ereport, zio_bad_cksum_t *info,
|
||||
}
|
||||
return (eip);
|
||||
}
|
||||
#else
|
||||
/*ARGSUSED*/
|
||||
void
|
||||
zfs_ereport_clear(spa_t *spa, vdev_t *vd)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -159,7 +159,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/uio_impl.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/kmem.h>
|
||||
#include <sys/cmn_err.h>
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <sys/vfs.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/uio_impl.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/kmem.h>
|
||||
|
@ -4286,17 +4286,14 @@ zio_checksum_verify(zio_t *zio)
|
||||
zio->io_error = error;
|
||||
if (error == ECKSUM &&
|
||||
!(zio->io_flags & ZIO_FLAG_SPECULATIVE)) {
|
||||
int ret = zfs_ereport_start_checksum(zio->io_spa,
|
||||
(void) zfs_ereport_start_checksum(zio->io_spa,
|
||||
zio->io_vd, &zio->io_bookmark, zio,
|
||||
zio->io_offset, zio->io_size, NULL, &info);
|
||||
|
||||
if (ret != EALREADY) {
|
||||
mutex_enter(&zio->io_vd->vdev_stat_lock);
|
||||
zio->io_vd->vdev_stat.vs_checksum_errors++;
|
||||
mutex_exit(&zio->io_vd->vdev_stat_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (zio);
|
||||
}
|
||||
|
@ -198,7 +198,7 @@ unload_modules_linux() {
|
||||
|
||||
if [ "$USE_COUNT" = "0" ] ; then
|
||||
unload_module_linux "$KMOD" || return 1
|
||||
else
|
||||
elif [ "$USE_COUNT" != "" ] ; then
|
||||
echo "Module ${NAME} is still in use!"
|
||||
return 1
|
||||
fi
|
||||
|
@ -362,7 +362,8 @@ tags = ['functional', 'cli_root', 'zpool_detach']
|
||||
|
||||
[tests/functional/cli_root/zpool_events]
|
||||
tests = ['zpool_events_clear', 'zpool_events_cliargs', 'zpool_events_follow',
|
||||
'zpool_events_poolname', 'zpool_events_errors', 'zpool_events_duplicates']
|
||||
'zpool_events_poolname', 'zpool_events_errors', 'zpool_events_duplicates',
|
||||
'zpool_events_clear_retained']
|
||||
tags = ['functional', 'cli_root', 'zpool_events']
|
||||
|
||||
[tests/functional/cli_root/zpool_export]
|
||||
|
@ -11,7 +11,8 @@ dist_pkgdata_SCRIPTS = \
|
||||
zpool_events_follow.ksh \
|
||||
zpool_events_poolname.ksh \
|
||||
zpool_events_errors.ksh \
|
||||
zpool_events_duplicates.ksh
|
||||
zpool_events_duplicates.ksh \
|
||||
zpool_events_clear_retained.ksh
|
||||
|
||||
dist_pkgdata_DATA = \
|
||||
zpool_events.cfg \
|
||||
|
@ -0,0 +1,135 @@
|
||||
#!/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 http://www.opensolaris.org/os/licensing.
|
||||
# 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) 2018 by Lawrence Livermore National Security, LLC.
|
||||
# Copyright (c) 2021 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
# DESCRIPTION:
|
||||
# Verify that new errors after a pool scrub are considered a duplicate
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create a raidz pool with a file
|
||||
# 2. Inject garbage into one of the vdevs
|
||||
# 3. Scrub the pool
|
||||
# 4. Observe the checksum error counts
|
||||
# 5. Repeat inject and pool scrub
|
||||
# 6. Verify that second pass also produces similar errors (i.e. not
|
||||
# treated as a duplicate)
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
verify_runnable "both"
|
||||
|
||||
MOUNTDIR=$TEST_BASE_DIR/mount
|
||||
FILEPATH=$MOUNTDIR/target
|
||||
VDEV1=$TEST_BASE_DIR/vfile1
|
||||
VDEV2=$TEST_BASE_DIR/vfile2
|
||||
VDEV3=$TEST_BASE_DIR/vfile3
|
||||
SUPPLY=$TEST_BASE_DIR/supply
|
||||
POOL=test_pool
|
||||
FILESIZE="15M"
|
||||
DAMAGEBLKS=10
|
||||
|
||||
OLD_LEN_MAX=$(get_tunable ZEVENT_LEN_MAX)
|
||||
RETAIN_MAX=$(get_tunable ZEVENT_RETAIN_MAX)
|
||||
OLD_CHECKSUMS=$(get_tunable CHECKSUM_EVENTS_PER_SECOND)
|
||||
|
||||
EREPORTS="$STF_SUITE/tests/functional/cli_root/zpool_events/ereports"
|
||||
|
||||
function cleanup
|
||||
{
|
||||
log_must set_tunable64 CHECKSUM_EVENTS_PER_SECOND $OLD_CHECKSUMS
|
||||
log_must set_tunable64 ZEVENT_LEN_MAX $OLD_LEN_MAX
|
||||
|
||||
zpool events -c
|
||||
if poolexists $POOL ; then
|
||||
zpool export $POOL
|
||||
fi
|
||||
log_must rm -f $VDEV1 $VDEV2 $VDEV3
|
||||
}
|
||||
|
||||
function damage_and_repair
|
||||
{
|
||||
log_must zpool clear $POOL $VDEV1
|
||||
log_must zpool events -c
|
||||
|
||||
log_note injecting damage to $VDEV1
|
||||
log_must dd conv=notrunc if=$SUPPLY of=$VDEV1 bs=1M seek=4 count=$DAMAGEBLKS
|
||||
log_must zpool scrub $POOL
|
||||
log_must zpool wait -t scrub $POOL
|
||||
log_note "pass $1 observed $($EREPORTS | grep -c checksum) checksum ereports"
|
||||
|
||||
repaired=$(zpool status $POOL | grep "scan: scrub repaired" | awk '{print $4}')
|
||||
if [ "$repaired" == "0B" ]; then
|
||||
log_fail "INVALID TEST -- expected scrub to repair some blocks"
|
||||
else
|
||||
log_note "$repaired repaired during scrub"
|
||||
fi
|
||||
}
|
||||
|
||||
function checksum_error_count
|
||||
{
|
||||
zpool status -p $POOL | grep $VDEV1 | awk '{print $5}'
|
||||
}
|
||||
|
||||
assertion="Damage to recently repaired blocks should be reported/counted"
|
||||
log_assert "$assertion"
|
||||
log_note "zevent retain max setting: $RETAIN_MAX"
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
# Set our threshold high to avoid dropping events.
|
||||
set_tunable64 ZEVENT_LEN_MAX 20000
|
||||
set_tunable64 CHECKSUM_EVENTS_PER_SECOND 20000
|
||||
|
||||
# Initialize resources for the test
|
||||
log_must truncate -s $MINVDEVSIZE $VDEV1 $VDEV2 $VDEV3
|
||||
log_must dd if=/dev/urandom of=$SUPPLY bs=1M count=$DAMAGEBLKS
|
||||
log_must mkdir -p $MOUNTDIR
|
||||
log_must zpool create -f -m $MOUNTDIR -o failmode=continue $POOL raidz $VDEV1 $VDEV2 $VDEV3
|
||||
log_must zfs set compression=off recordsize=16k $POOL
|
||||
# create a file full of zeros
|
||||
log_must mkfile -v $FILESIZE $FILEPATH
|
||||
log_must zpool sync $POOL
|
||||
|
||||
# run once and observe the checksum errors
|
||||
damage_and_repair 1
|
||||
errcnt=$(checksum_error_count)
|
||||
log_note "$errcnt errors observed"
|
||||
# set expectaton of at least 75% of what we observed in first pass
|
||||
(( expected = (errcnt * 75) / 100 ))
|
||||
|
||||
# run again and we should observe new checksum errors
|
||||
damage_and_repair 2
|
||||
errcnt=$(checksum_error_count)
|
||||
|
||||
log_must zpool destroy $POOL
|
||||
|
||||
if (( errcnt < expected )); then
|
||||
log_fail "FAILED -- expecting at least $expected checksum errors but only observed $errcnt"
|
||||
else
|
||||
log_note observed $errcnt new checksum errors after a scrub
|
||||
log_pass "$assertion"
|
||||
fi
|
||||
|
@ -114,21 +114,10 @@ function do_dup_test
|
||||
if [ "$RW" == "write" ] ; then
|
||||
log_must mkfile $FILESIZE $FILEPATH
|
||||
log_must zpool sync $POOL
|
||||
else
|
||||
# scrub twice to generate some duplicates
|
||||
log_must zpool scrub $POOL
|
||||
log_must zpool wait -t scrub $POOL
|
||||
log_must zpool scrub $POOL
|
||||
log_must zpool wait -t scrub $POOL
|
||||
fi
|
||||
|
||||
log_must zinject -c all
|
||||
|
||||
# Wait for the pool to settle down and finish resilvering (if
|
||||
# necessary). We want the errors to stop incrementing before we
|
||||
# check for duplicates.
|
||||
zpool wait -t resilver $POOL
|
||||
|
||||
ereports="$($EREPORTS | sort)"
|
||||
actual=$(echo "$ereports" | wc -l)
|
||||
unique=$(echo "$ereports" | uniq | wc -l)
|
||||
|
@ -126,6 +126,7 @@ SRCS+= abd_os.c \
|
||||
zfs_ioctl_compat.c \
|
||||
zfs_ioctl_os.c \
|
||||
zfs_log.c \
|
||||
zfs_racct.c \
|
||||
zfs_replay.c \
|
||||
zfs_vfsops.c \
|
||||
zfs_vnops_os.c \
|
||||
|
@ -764,7 +764,7 @@
|
||||
#define ZFS_META_NAME "zfs"
|
||||
|
||||
/* Define the project release. */
|
||||
#define ZFS_META_RELEASE "FreeBSD_gbf156c966"
|
||||
#define ZFS_META_RELEASE "FreeBSD_g9312e0fd1"
|
||||
|
||||
/* Define the project version. */
|
||||
#define ZFS_META_VERSION "2.0.0"
|
||||
|
Loading…
Reference in New Issue
Block a user