Skip to content

Commit

Permalink
zfs: merge openzfs/zfs@269b5dadc (master) into main
Browse files Browse the repository at this point in the history
Notable upstream pull request merges:
  #12285 Introduce a tunable to exclude special class buffers from L2ARC
  #12689 Check l2cache vdevs pending list inside the vdev_inuse()
  #12735 Enable edonr in FreeBSD
  #12743 FreeBSD: fix world build after de198f2
  #12745 Restore dirty dnode detection logic

Obtained from:	OpenZFS
OpenZFS commit:	269b5da
  • Loading branch information
mmatuska committed Nov 17, 2021
2 parents b6cbbca + 269b5da commit dae1713
Show file tree
Hide file tree
Showing 69 changed files with 685 additions and 192 deletions.
11 changes: 7 additions & 4 deletions sys/contrib/openzfs/cmd/vdev_id/vdev_id
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,9 @@ enclosure_handler () {
# DEVPATH=/sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0/host0/subsystem/devices/0:0:0:0/scsi_generic/sg0

# Get the enclosure ID ("0:0:0:0")
ENC=$(basename $(readlink -m "/sys/$DEVPATH/../.."))
ENC="${DEVPATH%/*}"
ENC="${ENC%/*}"
ENC="${ENC##*/}"
if [ ! -d "/sys/class/enclosure/$ENC" ] ; then
# Not an enclosure, bail out
return
Expand All @@ -616,10 +618,11 @@ enclosure_handler () {

# The PCI directory is two directories up from the port directory
# /sys/devices/pci0000:00/0000:00:03.0/0000:05:00.0
PCI_ID_LONG=$(basename $(readlink -m "/sys/$PORT_DIR/../.."))
PCI_ID_LONG="$(readlink -m "/sys/$PORT_DIR/../..")"
PCI_ID_LONG="${PCI_ID_LONG##*/}"

# Strip down the PCI address from 0000:05:00.0 to 05:00.0
PCI_ID=$(echo "$PCI_ID_LONG" | sed -r 's/^[0-9]+://g')
PCI_ID="${PCI_ID_LONG#[0-9]*:}"

# Name our device according to vdev_id.conf (like "L0" or "U1").
NAME=$(awk "/channel/{if (\$1 == \"channel\" && \$2 == \"$PCI_ID\" && \
Expand Down Expand Up @@ -674,7 +677,7 @@ alias_handler () {
link=$(echo "$link" | sed 's/p[0-9][0-9]*$//')
fi
# Check both the fully qualified and the base name of link.
for l in $link $(basename "$link") ; do
for l in $link ${link##*/} ; do
if [ ! -z "$l" ]; then
alias=$(awk -v var="$l" '($1 == "alias") && \
($3 == var) \
Expand Down
52 changes: 48 additions & 4 deletions sys/contrib/openzfs/cmd/zdb/zdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -4221,11 +4221,13 @@ print_label_numbers(char *prefix, cksum_record_t *rec)

typedef struct zdb_label {
vdev_label_t label;
uint64_t label_offset;
nvlist_t *config_nv;
cksum_record_t *config;
cksum_record_t *uberblocks[MAX_UBERBLOCK_COUNT];
boolean_t header_printed;
boolean_t read_failed;
boolean_t cksum_valid;
} zdb_label_t;

static void
Expand All @@ -4239,7 +4241,8 @@ print_label_header(zdb_label_t *label, int l)
return;

(void) printf("------------------------------------\n");
(void) printf("LABEL %d\n", l);
(void) printf("LABEL %d %s\n", l,
label->cksum_valid ? "" : "(Bad label cksum)");
(void) printf("------------------------------------\n");

label->header_printed = B_TRUE;
Expand Down Expand Up @@ -4751,6 +4754,42 @@ zdb_copy_object(objset_t *os, uint64_t srcobj, char *destfile)
return (err);
}

static boolean_t
label_cksum_valid(vdev_label_t *label, uint64_t offset)
{
zio_checksum_info_t *ci = &zio_checksum_table[ZIO_CHECKSUM_LABEL];
zio_cksum_t expected_cksum;
zio_cksum_t actual_cksum;
zio_cksum_t verifier;
zio_eck_t *eck;
int byteswap;

void *data = (char *)label + offsetof(vdev_label_t, vl_vdev_phys);
eck = (zio_eck_t *)((char *)(data) + VDEV_PHYS_SIZE) - 1;

offset += offsetof(vdev_label_t, vl_vdev_phys);
ZIO_SET_CHECKSUM(&verifier, offset, 0, 0, 0);

byteswap = (eck->zec_magic == BSWAP_64(ZEC_MAGIC));
if (byteswap)
byteswap_uint64_array(&verifier, sizeof (zio_cksum_t));

expected_cksum = eck->zec_cksum;
eck->zec_cksum = verifier;

abd_t *abd = abd_get_from_buf(data, VDEV_PHYS_SIZE);
ci->ci_func[byteswap](abd, VDEV_PHYS_SIZE, NULL, &actual_cksum);
abd_free(abd);

if (byteswap)
byteswap_uint64_array(&expected_cksum, sizeof (zio_cksum_t));

if (ZIO_CHECKSUM_EQUAL(actual_cksum, expected_cksum))
return (B_TRUE);

return (B_FALSE);
}

static int
dump_label(const char *dev)
{
Expand Down Expand Up @@ -4817,8 +4856,9 @@ dump_label(const char *dev)

/*
* 1. Read the label from disk
* 2. Unpack the configuration and insert in config tree.
* 3. Traverse all uberblocks and insert in uberblock tree.
* 2. Verify label cksum
* 3. Unpack the configuration and insert in config tree.
* 4. Traverse all uberblocks and insert in uberblock tree.
*/
for (int l = 0; l < VDEV_LABELS; l++) {
zdb_label_t *label = &labels[l];
Expand All @@ -4829,8 +4869,10 @@ dump_label(const char *dev)
zio_cksum_t cksum;
vdev_t vd;

label->label_offset = vdev_label_offset(psize, l, 0);

if (pread64(fd, &label->label, sizeof (label->label),
vdev_label_offset(psize, l, 0)) != sizeof (label->label)) {
label->label_offset) != sizeof (label->label)) {
if (!dump_opt['q'])
(void) printf("failed to read label %d\n", l);
label->read_failed = B_TRUE;
Expand All @@ -4839,6 +4881,8 @@ dump_label(const char *dev)
}

label->read_failed = B_FALSE;
label->cksum_valid = label_cksum_valid(&label->label,
label->label_offset);

if (nvlist_unpack(buf, buflen, &config, 0) == 0) {
nvlist_t *vdev_tree = NULL;
Expand Down
2 changes: 1 addition & 1 deletion sys/contrib/openzfs/cmd/zed/zed.d/all-syslog.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ if [ "${ZED_SYSLOG_DISPLAY_GUIDS}" = "1" ]; then
[ -n "${ZEVENT_VDEV_GUID}" ] && msg="${msg} vdev_guid=${ZEVENT_VDEV_GUID}"
else
[ -n "${ZEVENT_POOL}" ] && msg="${msg} pool='${ZEVENT_POOL}'"
[ -n "${ZEVENT_VDEV_PATH}" ] && msg="${msg} vdev=$(basename "${ZEVENT_VDEV_PATH}")"
[ -n "${ZEVENT_VDEV_PATH}" ] && msg="${msg} vdev=${ZEVENT_VDEV_PATH##*/}"
fi

# log pool state if state is anything other than 'ACTIVE'
Expand Down
2 changes: 1 addition & 1 deletion sys/contrib/openzfs/cmd/zed/zed.d/generic-notify.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

# Rate-limit the notification based in part on the filename.
#
rate_limit_tag="${ZEVENT_POOL};${ZEVENT_SUBCLASS};$(basename -- "$0")"
rate_limit_tag="${ZEVENT_POOL};${ZEVENT_SUBCLASS};${0##*/}"
rate_limit_interval="${ZED_NOTIFY_INTERVAL_SECS}"
zed_rate_limit "${rate_limit_tag}" "${rate_limit_interval}" || exit 3

Expand Down
6 changes: 3 additions & 3 deletions sys/contrib/openzfs/cmd/zed/zed.d/zed-functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ zed_log_msg()
zed_log_err()
{
logger -p "${ZED_SYSLOG_PRIORITY}" -t "${ZED_SYSLOG_TAG}" -- "error:" \
"$(basename -- "$0"):""${ZEVENT_EID:+" eid=${ZEVENT_EID}:"}" "$@"
"${0##*/}:""${ZEVENT_EID:+" eid=${ZEVENT_EID}:"}" "$@"
}


Expand Down Expand Up @@ -258,7 +258,7 @@ zed_notify_email()
[ -n "${subject}" ] || return 1
if [ ! -r "${pathname}" ]; then
zed_log_err \
"$(basename "${ZED_EMAIL_PROG}") cannot read \"${pathname}\""
"${ZED_EMAIL_PROG##*/} cannot read \"${pathname}\""
return 1
fi

Expand All @@ -270,7 +270,7 @@ zed_notify_email()
eval ${ZED_EMAIL_PROG} ${ZED_EMAIL_OPTS} < "${pathname}" >/dev/null 2>&1
rv=$?
if [ "${rv}" -ne 0 ]; then
zed_log_err "$(basename "${ZED_EMAIL_PROG}") exit=${rv}"
zed_log_err "${ZED_EMAIL_PROG##*/} exit=${rv}"
return 1
fi
return 0
Expand Down
171 changes: 170 additions & 1 deletion sys/contrib/openzfs/cmd/zhack/zhack.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/zfs_context.h>
#include <sys/spa.h>
#include <sys/spa_impl.h>
Expand All @@ -41,6 +42,7 @@
#include <sys/zfs_znode.h>
#include <sys/dsl_synctask.h>
#include <sys/vdev.h>
#include <sys/vdev_impl.h>
#include <sys/fs/zfs.h>
#include <sys/dmu_objset.h>
#include <sys/dsl_pool.h>
Expand Down Expand Up @@ -76,7 +78,12 @@ usage(void)
" -d decrease instead of increase the refcount\n"
" -m add the feature to the label if increasing refcount\n"
"\n"
" <feature> : should be a feature guid\n");
" <feature> : should be a feature guid\n"
"\n"
" label repair <device>\n"
" repair corrupted label checksums\n"
"\n"
" <device> : path to vdev\n");
exit(1);
}

Expand Down Expand Up @@ -471,6 +478,166 @@ zhack_do_feature(int argc, char **argv)
return (0);
}

static int
zhack_repair_label_cksum(int argc, char **argv)
{
zio_checksum_info_t *ci = &zio_checksum_table[ZIO_CHECKSUM_LABEL];
const char *cfg_keys[] = { ZPOOL_CONFIG_VERSION,
ZPOOL_CONFIG_POOL_STATE, ZPOOL_CONFIG_GUID };
boolean_t labels_repaired[VDEV_LABELS];
boolean_t repaired = B_FALSE;
vdev_label_t labels[VDEV_LABELS];
struct stat st;
int fd;

bzero(labels_repaired, sizeof (labels_repaired));
bzero(labels, sizeof (labels));

abd_init();

argc -= 1;
argv += 1;

if (argc < 1) {
(void) fprintf(stderr, "error: missing device\n");
usage();
}

if ((fd = open(argv[0], O_RDWR)) == -1)
fatal(NULL, FTAG, "cannot open '%s': %s", argv[0],
strerror(errno));

if (stat(argv[0], &st) != 0)
fatal(NULL, FTAG, "cannot stat '%s': %s", argv[0],
strerror(errno));

for (int l = 0; l < VDEV_LABELS; l++) {
uint64_t label_offset, offset;
zio_cksum_t expected_cksum;
zio_cksum_t actual_cksum;
zio_cksum_t verifier;
zio_eck_t *eck;
nvlist_t *cfg;
int byteswap;
uint64_t val;
ssize_t err;

vdev_label_t *vl = &labels[l];

label_offset = vdev_label_offset(st.st_size, l, 0);
err = pread64(fd, vl, sizeof (vdev_label_t), label_offset);
if (err == -1) {
(void) fprintf(stderr, "error: cannot read "
"label %d: %s\n", l, strerror(errno));
continue;
} else if (err != sizeof (vdev_label_t)) {
(void) fprintf(stderr, "error: bad label %d read size "
"\n", l);
continue;
}

err = nvlist_unpack(vl->vl_vdev_phys.vp_nvlist,
VDEV_PHYS_SIZE - sizeof (zio_eck_t), &cfg, 0);
if (err) {
(void) fprintf(stderr, "error: cannot unpack nvlist "
"label %d\n", l);
continue;
}

for (int i = 0; i < ARRAY_SIZE(cfg_keys); i++) {
err = nvlist_lookup_uint64(cfg, cfg_keys[i], &val);
if (err) {
(void) fprintf(stderr, "error: label %d: "
"cannot find nvlist key %s\n",
l, cfg_keys[i]);
continue;
}
}

void *data = (char *)vl + offsetof(vdev_label_t, vl_vdev_phys);
eck = (zio_eck_t *)((char *)(data) + VDEV_PHYS_SIZE) - 1;

offset = label_offset + offsetof(vdev_label_t, vl_vdev_phys);
ZIO_SET_CHECKSUM(&verifier, offset, 0, 0, 0);

byteswap = (eck->zec_magic == BSWAP_64(ZEC_MAGIC));
if (byteswap)
byteswap_uint64_array(&verifier, sizeof (zio_cksum_t));

expected_cksum = eck->zec_cksum;
eck->zec_cksum = verifier;

abd_t *abd = abd_get_from_buf(data, VDEV_PHYS_SIZE);
ci->ci_func[byteswap](abd, VDEV_PHYS_SIZE, NULL, &actual_cksum);
abd_free(abd);

if (byteswap)
byteswap_uint64_array(&expected_cksum,
sizeof (zio_cksum_t));

if (ZIO_CHECKSUM_EQUAL(actual_cksum, expected_cksum))
continue;

eck->zec_cksum = actual_cksum;

err = pwrite64(fd, data, VDEV_PHYS_SIZE, offset);
if (err == -1) {
(void) fprintf(stderr, "error: cannot write "
"label %d: %s\n", l, strerror(errno));
continue;
} else if (err != VDEV_PHYS_SIZE) {
(void) fprintf(stderr, "error: bad write size "
"label %d\n", l);
continue;
}

fsync(fd);

labels_repaired[l] = B_TRUE;
}

close(fd);

abd_fini();

for (int l = 0; l < VDEV_LABELS; l++) {
(void) printf("label %d: %s\n", l,
labels_repaired[l] ? "repaired" : "skipped");
repaired |= labels_repaired[l];
}

if (repaired)
return (0);

return (1);
}

static int
zhack_do_label(int argc, char **argv)
{
char *subcommand;
int err;

argc--;
argv++;
if (argc == 0) {
(void) fprintf(stderr,
"error: no label operation specified\n");
usage();
}

subcommand = argv[0];
if (strcmp(subcommand, "repair") == 0) {
err = zhack_repair_label_cksum(argc, argv);
} else {
(void) fprintf(stderr, "error: unknown subcommand: %s\n",
subcommand);
usage();
}

return (err);
}

#define MAX_NUM_PATHS 1024

int
Expand Down Expand Up @@ -516,6 +683,8 @@ main(int argc, char **argv)

if (strcmp(subcommand, "feature") == 0) {
rv = zhack_do_feature(argc, argv);
} else if (strcmp(subcommand, "label") == 0) {
return (zhack_do_label(argc, argv));
} else {
(void) fprintf(stderr, "error: unknown subcommand: %s\n",
subcommand);
Expand Down
Loading

0 comments on commit dae1713

Please sign in to comment.