From e4288a8397bb1f9df763c08bf93260062da8173a Mon Sep 17 00:00:00 2001 From: Alan Somers Date: Thu, 29 Apr 2021 15:19:44 -0600 Subject: [PATCH] zfs get: don't lookup mount options when using "-s local" Looking up mount options can be very expensive on servers with many mounted file systems. When doing "zfs get" with any "-s" option that does not include "temporary", the mount list will never be used. This commit optimizes for that case. This is a breaking commit for libzfs! Callers of zfs_get_prop are now required to initialize src. To preserve existing behavior, they should initialize it to ZPROP_SRC_NONE. Sponsored by: Axcient Reviewed-by: Brian Behlendorf Signed-off-by: Alan Somers Closes #11955 --- cmd/zfs/zfs_main.c | 4 ++-- lib/libzfs/libzfs_dataset.c | 19 ++++++++++++------- lib/libzfs/libzfs_diff.c | 2 +- lib/libzfs/libzfs_mount.c | 4 ++-- lib/libzfs/libzfs_sendrecv.c | 2 +- 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index 24ff074c4..9859a866f 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -1882,7 +1882,6 @@ get_callback(zfs_handle_t *zhp, void *data) { char buf[ZFS_MAXPROPLEN]; char rbuf[ZFS_MAXPROPLEN]; - zprop_source_t sourcetype; char source[ZFS_MAX_DATASET_NAME_LEN]; zprop_get_cbdata_t *cbp = data; nvlist_t *user_props = zfs_get_user_props(zhp); @@ -1893,6 +1892,7 @@ get_callback(zfs_handle_t *zhp, void *data) boolean_t received = is_recvd_column(cbp); for (; pl != NULL; pl = pl->pl_next) { + zprop_source_t sourcetype = cbp->cb_sources; char *recvdval = NULL; /* * Skip the special fake placeholder. This will also skip over @@ -4660,7 +4660,7 @@ zfs_do_send(int argc, char **argv) */ if (fromname && (cp = strchr(fromname, '@')) != NULL) { char origin[ZFS_MAX_DATASET_NAME_LEN]; - zprop_source_t src; + zprop_source_t src = ZPROP_SRC_NONE; (void) zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, sizeof (origin), &src, NULL, 0, B_FALSE); diff --git a/lib/libzfs/libzfs_dataset.c b/lib/libzfs/libzfs_dataset.c index 823fcb284..dd2572b01 100644 --- a/lib/libzfs/libzfs_dataset.c +++ b/lib/libzfs/libzfs_dataset.c @@ -2180,7 +2180,8 @@ get_numeric_property(zfs_handle_t *zhp, zfs_prop_t prop, zprop_source_t *src, * its presence. */ if (!zhp->zfs_mntcheck && - (mntopt_on != NULL || prop == ZFS_PROP_MOUNTED)) { + (mntopt_on != NULL || prop == ZFS_PROP_MOUNTED) && + (src && (*src & ZPROP_SRC_TEMPORARY))) { libzfs_handle_t *hdl = zhp->zfs_hdl; struct mnttab entry; @@ -2595,9 +2596,16 @@ zcp_check(zfs_handle_t *zhp, zfs_prop_t prop, uint64_t intval, } /* - * Retrieve a property from the given object. If 'literal' is specified, then - * numbers are left as exact values. Otherwise, numbers are converted to a - * human-readable form. + * Retrieve a property from the given object. + * + * Arguments: + * src : On call, this must contain the bitmap of ZPROP_SRC_* types to + * query. Properties whose values come from a different source + * may not be returned. NULL will be treated as ZPROP_SRC_ALL. On + * return, if not NULL, this variable will contain the source for + * the queried property. + * literal : If specified, then numbers are left as exact values. Otherwise, + * they are converted to a human-readable form. * * Returns 0 on success, or -1 on error. */ @@ -2620,9 +2628,6 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen, if (received && zfs_prop_readonly(prop)) return (-1); - if (src) - *src = ZPROP_SRC_NONE; - switch (prop) { case ZFS_PROP_CREATION: /* diff --git a/lib/libzfs/libzfs_diff.c b/lib/libzfs/libzfs_diff.c index 12e079b0e..1eda8bad1 100644 --- a/lib/libzfs/libzfs_diff.c +++ b/lib/libzfs/libzfs_diff.c @@ -575,7 +575,7 @@ get_snapshot_names(differ_info_t *di, const char *fromsnap, * tosnap is a clone of a fromsnap descendant. */ char origin[ZFS_MAX_DATASET_NAME_LEN]; - zprop_source_t src; + zprop_source_t src = ZPROP_SRC_NONE; zfs_handle_t *zhp; di->ds = zfs_alloc(di->zhp->zfs_hdl, tdslen + 1); diff --git a/lib/libzfs/libzfs_mount.c b/lib/libzfs/libzfs_mount.c index 3df42e2dc..37958a342 100644 --- a/lib/libzfs/libzfs_mount.c +++ b/lib/libzfs/libzfs_mount.c @@ -266,7 +266,7 @@ zfs_is_mountable(zfs_handle_t *zhp, char *buf, size_t buflen, zprop_source_t *source, int flags) { char sourceloc[MAXNAMELEN]; - zprop_source_t sourcetype; + zprop_source_t sourcetype = ZPROP_SRC_NONE; if (!zfs_prop_valid_for_type(ZFS_PROP_MOUNTPOINT, zhp->zfs_type, B_FALSE)) @@ -765,7 +765,7 @@ zfs_share_proto(zfs_handle_t *zhp, zfs_share_proto_t *proto) char shareopts[ZFS_MAXPROPLEN]; char sourcestr[ZFS_MAXPROPLEN]; zfs_share_proto_t *curr_proto; - zprop_source_t sourcetype; + zprop_source_t sourcetype = ZPROP_SRC_NONE; int err = 0; if (!zfs_is_mountable(zhp, mountpoint, sizeof (mountpoint), NULL, 0)) diff --git a/lib/libzfs/libzfs_sendrecv.c b/lib/libzfs/libzfs_sendrecv.c index 511895d18..8c55d6044 100644 --- a/lib/libzfs/libzfs_sendrecv.c +++ b/lib/libzfs/libzfs_sendrecv.c @@ -2662,7 +2662,7 @@ static zfs_handle_t * recv_open_grand_origin(zfs_handle_t *zhp) { char origin[ZFS_MAX_DATASET_NAME_LEN]; - zprop_source_t src; + zprop_source_t src = ZPROP_SRC_NONE; zfs_handle_t *ozhp = zfs_handle_dup(zhp); while (ozhp != NULL) {