Skip to content

Commit

Permalink
Rescan enclosure sysfs path on import
Browse files Browse the repository at this point in the history
When you create a pool, zfs writes vd->vdev_enc_sysfs_path with the
enclosure sysfs path to the fault LEDs, like:

  vdev_enc_sysfs_path = /sys/class/enclosure/0:0:1:0/SLOT8

However, this enclosure path doesn't get updated on successive imports
even if enclosure path to the disk changes.  This patch fixes the issue.

The largest part of this patch is moving for_each_vdev_vdev() and
associated function from zpool_iter.c to libzfs_internal.  This was
needed to make those functions visible to the cache import codepath for
sysfs path re-scan.  libzfs_internal is for code that is used by both
the libraries and the cmd/ code, but that we don't want to export with
the ABI.

Signed-off-by: Tony Hutter <hutter2@llnl.gov>
Fixes: #11950
  • Loading branch information
tonyhutter committed Sep 9, 2021
1 parent ab15b1f commit c3abcdb
Show file tree
Hide file tree
Showing 18 changed files with 239 additions and 92 deletions.
3 changes: 2 additions & 1 deletion cmd/zpool/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ zpool_LDADD = \
$(abs_top_builddir)/lib/libzfs/libzfs.la \
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
$(abs_top_builddir)/lib/libnvpair/libnvpair.la \
$(abs_top_builddir)/lib/libuutil/libuutil.la
$(abs_top_builddir)/lib/libuutil/libuutil.la \
$(abs_top_builddir)/lib/libzfs_internal/libzfs_internal.la

zpool_LDADD += $(LTLIBINTL)

Expand Down
67 changes: 1 addition & 66 deletions cmd/zpool/zpool_iter.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

#include <libzfs.h>
#include <libzutil.h>
#include <libzfs_internal.h>
#include <sys/zfs_context.h>
#include <sys/wait.h>

Expand Down Expand Up @@ -264,72 +265,6 @@ for_each_pool(int argc, char **argv, boolean_t unavail,
return (ret);
}

static int
for_each_vdev_cb(zpool_handle_t *zhp, nvlist_t *nv, pool_vdev_iter_f func,
void *data)
{
nvlist_t **child;
uint_t c, children;
int ret = 0;
int i;
char *type;

const char *list[] = {
ZPOOL_CONFIG_SPARES,
ZPOOL_CONFIG_L2CACHE,
ZPOOL_CONFIG_CHILDREN
};

for (i = 0; i < ARRAY_SIZE(list); i++) {
if (nvlist_lookup_nvlist_array(nv, list[i], &child,
&children) == 0) {
for (c = 0; c < children; c++) {
uint64_t ishole = 0;

(void) nvlist_lookup_uint64(child[c],
ZPOOL_CONFIG_IS_HOLE, &ishole);

if (ishole)
continue;

ret |= for_each_vdev_cb(zhp, child[c], func,
data);
}
}
}

if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0)
return (ret);

/* Don't run our function on root vdevs */
if (strcmp(type, VDEV_TYPE_ROOT) != 0) {
ret |= func(zhp, nv, data);
}

return (ret);
}

/*
* This is the equivalent of for_each_pool() for vdevs. It iterates thorough
* all vdevs in the pool, ignoring root vdevs and holes, calling func() on
* each one.
*
* @zhp: Zpool handle
* @func: Function to call on each vdev
* @data: Custom data to pass to the function
*/
int
for_each_vdev(zpool_handle_t *zhp, pool_vdev_iter_f func, void *data)
{
nvlist_t *config, *nvroot = NULL;

if ((config = zpool_get_config(zhp, NULL)) != NULL) {
verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
&nvroot) == 0);
}
return (for_each_vdev_cb(zhp, nvroot, func, data));
}

/*
* Process the vcdl->vdev_cmd_data[] array to figure out all the unique column
* names and their widths. When this function is done, vcdl->uniq_cols,
Expand Down
1 change: 1 addition & 0 deletions cmd/zpool/zpool_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@

#include <libzfs.h>
#include <libzutil.h>
#include <libzfs_internal.h>

#include "zpool_util.h"
#include "zfs_comutil.h"
Expand Down
4 changes: 0 additions & 4 deletions cmd/zpool/zpool_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,6 @@ nvlist_t *split_mirror_vdev(zpool_handle_t *zhp, char *newname,
int for_each_pool(int, char **, boolean_t unavail, zprop_list_t **,
boolean_t, zpool_iter_f, void *);

/* Vdev list functions */
typedef int (*pool_vdev_iter_f)(zpool_handle_t *, nvlist_t *, void *);
int for_each_vdev(zpool_handle_t *zhp, pool_vdev_iter_f func, void *data);

typedef struct zpool_list zpool_list_t;

zpool_list_t *pool_list_get(int, char **, zprop_list_t **, boolean_t, int *);
Expand Down
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ AC_CONFIG_FILES([
lib/libzpool/Makefile
lib/libzstd/Makefile
lib/libzutil/Makefile
lib/libzfs_internal/Makefile
man/Makefile
module/Kbuild
module/Makefile
Expand Down
3 changes: 2 additions & 1 deletion include/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ COMMON_H = \
zfs_deleg.h \
zfs_fletcher.h \
zfs_namecheck.h \
zfs_prop.h
zfs_prop.h \
libzfs_internal.h

USER_H = \
libnvpair.h \
Expand Down
17 changes: 17 additions & 0 deletions include/libzfs_internal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef _LIBZUTIL_INTERNAL
#define _LIBZUTIL_INTERNAL

#include <libzfs.h>

/* Vdev list functions */
typedef int (*pool_vdev_iter_f)(zpool_handle_t *, nvlist_t *, void *);
extern int for_each_vdev(zpool_handle_t *zhp, pool_vdev_iter_f func,
void *data);
extern int for_each_vdev_in_nvlist(nvlist_t *nvroot, pool_vdev_iter_f func,
void *data);

/* Only used by libzfs_config.c */
nvlist_t *
zpool_get_config_impl(zpool_handle_t *zhp, nvlist_t **oldconfig);

#endif
3 changes: 2 additions & 1 deletion include/libzutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ struct udev_device;
_LIBZUTIL_H int zfs_device_get_devid(struct udev_device *, char *, size_t);
_LIBZUTIL_H int zfs_device_get_physical(struct udev_device *, char *, size_t);

_LIBZUTIL_H void update_vdev_config_dev_strs(nvlist_t *);
_LIBZUTIL_H void update_vdev_config_dev_strs(nvlist_t *nv);
_LIBZUTIL_H void update_vdevs_config_dev_sysfs_path(nvlist_t *config);

/*
* Default device paths
Expand Down
2 changes: 1 addition & 1 deletion lib/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ endif
SUBDIRS += libnvpair

# libzutil depends on libefi if present
SUBDIRS += libzutil libunicode
SUBDIRS += libzfs_internal libzutil libunicode

# These five libraries, which are installed as the final build product,
# incorporate the eight convenience libraries given above.
Expand Down
4 changes: 3 additions & 1 deletion lib/libzfs/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ libzfs_la_LIBADD = \
$(abs_top_builddir)/lib/libshare/libshare.la \
$(abs_top_builddir)/lib/libzfs_core/libzfs_core.la \
$(abs_top_builddir)/lib/libnvpair/libnvpair.la \
$(abs_top_builddir)/lib/libuutil/libuutil.la
$(abs_top_builddir)/lib/libuutil/libuutil.la \
$(abs_top_builddir)/lib/libzutil/libzutil.la \
$(abs_top_builddir)/lib/libzfs_internal/libzfs_internal.la

libzfs_la_LIBADD += -lm $(LIBCRYPTO_LIBS) $(ZLIB_LIBS) $(LIBFETCH_LIBS) $(LTLIBINTL)

Expand Down
5 changes: 2 additions & 3 deletions lib/libzfs/libzfs_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include <unistd.h>
#include <libintl.h>
#include <libuutil.h>
#include <libzfs_internal.h>

#include "libzfs_impl.h"

Expand Down Expand Up @@ -219,9 +220,7 @@ namespace_reload(libzfs_handle_t *hdl)
nvlist_t *
zpool_get_config(zpool_handle_t *zhp, nvlist_t **oldconfig)
{
if (oldconfig)
*oldconfig = zhp->zpool_old_config;
return (zhp->zpool_config);
return (zpool_get_config_impl(zhp, oldconfig));
}

/*
Expand Down
18 changes: 18 additions & 0 deletions lib/libzfs_internal/Makefile.am
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#
# libzfs_internal is library that contains functions that are common to both
# userspace code (like zpool_main.c) and to the libraries themselves, but
# are not exported as in the ABI.
#
include $(top_srcdir)/config/Rules.am

DEFAULT_INCLUDES += -I$(srcdir) -I$(top_srcdir)/lib/libzfs

lib_LTLIBRARIES = libzfs_internal.la

dist_libzfs_internal_la_SOURCES = \
libzfs_internal.c

libzfs_internal_la_LIBADD = \
$(abs_top_builddir)/lib/libnvpair/libnvpair.la

include $(top_srcdir)/config/CppCheck.am
100 changes: 100 additions & 0 deletions lib/libzfs_internal/libzfs_internal.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#include <sys/fs/zfs.h>
#include <libzutil.h>
#include <libzfs.h>
#include <libzfs_impl.h>
#include <libzfs_internal.h>

/*
* We want to call zpool_get_config() in this file, but that requires linking
* against libzfs... which requires this file as a dependency. We can't
* just move zpool_get_config() to this file, since zpool_get_config() is part
* of the ABI, and wouldn't get exposed here.
*
* To get around this, we add the zpool_get_config_impl() dummy function which
* we can call directly in this file, and then update zpool_get_config() to
* call zpool_get_config_impl().
*/
nvlist_t *
zpool_get_config_impl(zpool_handle_t *zhp, nvlist_t **oldconfig)
{
if (oldconfig)
*oldconfig = zhp->zpool_old_config;
return (zhp->zpool_config);
}

static int
for_each_vdev_cb(zpool_handle_t *zhp, nvlist_t *nv, pool_vdev_iter_f func,
void *data)
{
nvlist_t **child;
uint_t c, children;
int ret = 0;
int i;
char *type;

const char *list[] = {
ZPOOL_CONFIG_SPARES,
ZPOOL_CONFIG_L2CACHE,
ZPOOL_CONFIG_CHILDREN
};

for (i = 0; i < ARRAY_SIZE(list); i++) {
if (nvlist_lookup_nvlist_array(nv, list[i], &child,
&children) == 0) {
for (c = 0; c < children; c++) {
uint64_t ishole = 0;

(void) nvlist_lookup_uint64(child[c],
ZPOOL_CONFIG_IS_HOLE, &ishole);

if (ishole)
continue;

ret |= for_each_vdev_cb(zhp, child[c], func,
data);
}
}
}

if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0)
return (ret);

/* Don't run our function on root vdevs */
if (strcmp(type, VDEV_TYPE_ROOT) != 0) {
ret |= func(zhp, nv, data);
}

return (ret);
}

/*
* This is the equivalent of for_each_pool() for vdevs. It iterates through
* all vdevs in the pool, ignoring root vdevs and holes, calling func() on
* each one.
*
* @zhp: Zpool handle
* @func: Function to call on each vdev
* @data: Custom data to pass to the function
*/
int
for_each_vdev(zpool_handle_t *zhp, pool_vdev_iter_f func, void *data)
{
nvlist_t *config, *nvroot = NULL;

if ((config = zpool_get_config_impl(zhp, NULL)) != NULL) {
verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
&nvroot) == 0);
}
return (for_each_vdev_cb(zhp, nvroot, func, data));
}

/*
* Given an ZPOOL_CONFIG_VDEV_TREE nvpair, iterate over all the vdevs, calling
* func() for each one. func() is passed the vdev's nvlist and an optional
* user-defined 'data' pointer.
*/
int
for_each_vdev_in_nvlist(nvlist_t *nvroot, pool_vdev_iter_f func, void *data)
{
return (for_each_vdev_cb(NULL, nvroot, func, data));
}
3 changes: 2 additions & 1 deletion lib/libzutil/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ libzutil_la_LIBADD = \
$(abs_top_builddir)/lib/libavl/libavl.la \
$(abs_top_builddir)/lib/libtpool/libtpool.la \
$(abs_top_builddir)/lib/libnvpair/libnvpair.la \
$(abs_top_builddir)/lib/libspl/libspl.la
$(abs_top_builddir)/lib/libspl/libspl.la \
$(abs_top_builddir)/lib/libzfs_internal/libzfs_internal.la

if BUILD_LINUX
libzutil_la_LIBADD += \
Expand Down
5 changes: 5 additions & 0 deletions lib/libzutil/os/freebsd/zutil_import_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,8 @@ zfs_dev_flush(int fd __unused)
{
return (0);
}

void
update_vdevs_config_dev_sysfs_path(nvlist_t *config)
{
}
Loading

0 comments on commit c3abcdb

Please sign in to comment.