Speed up "zpool import" in the presence of many zvols

By default, FreeBSD does not allow zpools to be backed by zvols (that
can be changed with the "vfs.zfs.vol.recursive" sysctl). When that
sysctl is set to 0, the kernel does not attempt to read zvols when
looking for vdevs. But the zpool command still does. This change brings
the zpool command into line with the kernel's behavior. It speeds "zpool
import" when an already imported pool has many zvols, or a zvol with
many snapshots.

https://svnweb.freebsd.org/base?view=revision&revision=357235
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=241083
https://reviews.freebsd.org/D22077

Obtained from: FreeBSD
Reported by: Martin Birgmeier <d8zNeCFG@aon.at>
Sponsored by: Axcient
Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Signed-off-by: Alan Somers <asomers@gmail.com>
Closes #11502
This commit is contained in:
Alan Somers 2021-01-24 17:02:45 -07:00 committed by GitHub
parent 8887760aef
commit fd95af8dd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 15 additions and 5 deletions

View File

@ -42,6 +42,12 @@
* using our derived config, and record the results. * using our derived config, and record the results.
*/ */
#include <sys/types.h>
#include <sys/disk.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <aio.h> #include <aio.h>
#include <ctype.h> #include <ctype.h>
#include <dirent.h> #include <dirent.h>
@ -51,9 +57,6 @@
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/disk.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
@ -181,6 +184,7 @@ int
zpool_find_import_blkid(libpc_handle_t *hdl, pthread_mutex_t *lock, zpool_find_import_blkid(libpc_handle_t *hdl, pthread_mutex_t *lock,
avl_tree_t **slice_cache) avl_tree_t **slice_cache)
{ {
const char *oid = "vfs.zfs.vol.recursive";
char *end, path[MAXPATHLEN]; char *end, path[MAXPATHLEN];
rdsk_node_t *slice; rdsk_node_t *slice;
struct gmesh mesh; struct gmesh mesh;
@ -188,8 +192,9 @@ zpool_find_import_blkid(libpc_handle_t *hdl, pthread_mutex_t *lock,
struct ggeom *gp; struct ggeom *gp;
struct gprovider *pp; struct gprovider *pp;
avl_index_t where; avl_index_t where;
size_t pathleft; int error, value;
int error; size_t pathleft, size = sizeof (value);
boolean_t skip_zvols = B_FALSE;
end = stpcpy(path, "/dev/"); end = stpcpy(path, "/dev/");
pathleft = &path[sizeof (path)] - end; pathleft = &path[sizeof (path)] - end;
@ -198,11 +203,16 @@ zpool_find_import_blkid(libpc_handle_t *hdl, pthread_mutex_t *lock,
if (error != 0) if (error != 0)
return (error); return (error);
if (sysctlbyname(oid, &value, &size, NULL, 0) == 0 && value == 0)
skip_zvols = B_TRUE;
*slice_cache = zutil_alloc(hdl, sizeof (avl_tree_t)); *slice_cache = zutil_alloc(hdl, sizeof (avl_tree_t));
avl_create(*slice_cache, slice_cache_compare, sizeof (rdsk_node_t), avl_create(*slice_cache, slice_cache_compare, sizeof (rdsk_node_t),
offsetof(rdsk_node_t, rn_node)); offsetof(rdsk_node_t, rn_node));
LIST_FOREACH(mp, &mesh.lg_class, lg_class) { LIST_FOREACH(mp, &mesh.lg_class, lg_class) {
if (skip_zvols && strcmp(mp->lg_name, "ZFS::ZVOL") == 0)
continue;
LIST_FOREACH(gp, &mp->lg_geom, lg_geom) { LIST_FOREACH(gp, &mp->lg_geom, lg_geom) {
LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
strlcpy(end, pp->lg_name, pathleft); strlcpy(end, pp->lg_name, pathleft);