From 0c6d09361dd8ab83f3193e6d7f398b4d20c9c300 Mon Sep 17 00:00:00 2001 From: Alek P Date: Tue, 2 Oct 2018 15:30:58 -0400 Subject: changelist should be able to iter on mounts Modified changelist_gather()ing for the mountpoint property. Now instead of iterating on all dataset descendants, we read /proc/self/mounts and iterate on the mounted descendant datasets only. Switched changelist implementation from a uu_list_* to uu_avl_* in order to reduce changlist code-path's worst case time complexity. Reviewed by: Don Brady Reviewed-by: Brian Behlendorf Signed-off-by: Alek Pinchuk Closes #7967 --- lib/libzfs/libzfs_iter.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) (limited to 'lib/libzfs/libzfs_iter.c') diff --git a/lib/libzfs/libzfs_iter.c b/lib/libzfs/libzfs_iter.c index 6f9b3f465..73dc2c793 100644 --- a/lib/libzfs/libzfs_iter.c +++ b/lib/libzfs/libzfs_iter.c @@ -23,6 +23,7 @@ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, 2015 by Delphix. All rights reserved. * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright (c) 2018 Datto Inc. */ #include @@ -32,6 +33,7 @@ #include #include #include +#include #include "libzfs_impl.h" @@ -522,3 +524,50 @@ zfs_iter_dependents(zfs_handle_t *zhp, boolean_t allowrecursion, ida.first = B_TRUE; return (iter_dependents_cb(zfs_handle_dup(zhp), &ida)); } + +/* + * Iterate over mounted children of the specified dataset + */ +int +zfs_iter_mounted(zfs_handle_t *zhp, zfs_iter_f func, void *data) +{ + char mnt_prop[ZFS_MAXPROPLEN]; + struct mnttab entry; + zfs_handle_t *mtab_zhp; + size_t namelen = strlen(zhp->zfs_name); + FILE *mnttab; + int err = 0; + + if ((mnttab = fopen(MNTTAB, "r")) == NULL) + return (ENOENT); + + while (err == 0 && getmntent(mnttab, &entry) == 0) { + /* Ignore non-ZFS entries */ + if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) + continue; + + /* Ignore datasets not within the provided dataset */ + if (strncmp(entry.mnt_special, zhp->zfs_name, namelen) != 0 || + (entry.mnt_special[namelen] != '/' && + entry.mnt_special[namelen] != '@')) + continue; + + if ((mtab_zhp = zfs_open(zhp->zfs_hdl, entry.mnt_special, + ZFS_TYPE_FILESYSTEM)) == NULL) + continue; + + /* Ignore legacy mounts as they are user managed */ + verify(zfs_prop_get(mtab_zhp, ZFS_PROP_MOUNTPOINT, mnt_prop, + sizeof (mnt_prop), NULL, NULL, 0, B_FALSE) == 0); + if (strcmp(mnt_prop, "legacy") == 0) { + zfs_close(mtab_zhp); + continue; + } + + err = func(mtab_zhp, data); + } + + fclose(mnttab); + + return (err); +} -- cgit v1.2.3