aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/openzfs/lib/libzfs/libzfs_mnttab.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/openzfs/lib/libzfs/libzfs_mnttab.c')
-rw-r--r--sys/contrib/openzfs/lib/libzfs/libzfs_mnttab.c211
1 files changed, 211 insertions, 0 deletions
diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_mnttab.c b/sys/contrib/openzfs/lib/libzfs/libzfs_mnttab.c
new file mode 100644
index 000000000000..473e3a7b45a1
--- /dev/null
+++ b/sys/contrib/openzfs/lib/libzfs/libzfs_mnttab.c
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: CDDL-1.0
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or https://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2019 Joyent, Inc.
+ * Copyright (c) 2011, 2020 by Delphix. All rights reserved.
+ * Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
+ * Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
+ * Copyright (c) 2013 Martin Matuska. All rights reserved.
+ * Copyright (c) 2013 Steven Hartland. All rights reserved.
+ * Copyright 2017 Nexenta Systems, Inc.
+ * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
+ * Copyright 2017-2018 RackTop Systems.
+ * Copyright (c) 2019 Datto Inc.
+ * Copyright (c) 2019, loli10K <ezomori.nozomu@gmail.com>
+ * Copyright (c) 2021 Matt Fiddaman
+ * Copyright (c) 2026, TrueNAS.
+ */
+
+#include <sys/mntent.h>
+#include <sys/mutex.h>
+#include <libzfs.h>
+#include "libzfs_impl.h"
+
+typedef struct mnttab_node {
+ struct mnttab mtn_mt;
+ avl_node_t mtn_node;
+} mnttab_node_t;
+
+static mnttab_node_t *
+mnttab_node_alloc(libzfs_handle_t *hdl, const char *special,
+ const char *mountp, const char *mntopts)
+{
+ mnttab_node_t *mtn = zfs_alloc(hdl, sizeof (mnttab_node_t));
+ mtn->mtn_mt.mnt_special = zfs_strdup(hdl, special);
+ mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, mountp);
+ mtn->mtn_mt.mnt_fstype = (char *)MNTTYPE_ZFS;
+ mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, mntopts);
+ return (mtn);
+}
+
+static void
+mnttab_node_free(libzfs_handle_t *hdl, mnttab_node_t *mtn)
+{
+ (void) hdl;
+ free(mtn->mtn_mt.mnt_special);
+ free(mtn->mtn_mt.mnt_mountp);
+ free(mtn->mtn_mt.mnt_mntopts);
+ free(mtn);
+}
+
+static int
+mnttab_compare(const void *arg1, const void *arg2)
+{
+ const mnttab_node_t *mtn1 = (const mnttab_node_t *)arg1;
+ const mnttab_node_t *mtn2 = (const mnttab_node_t *)arg2;
+ int rv;
+
+ rv = strcmp(mtn1->mtn_mt.mnt_special, mtn2->mtn_mt.mnt_special);
+
+ return (TREE_ISIGN(rv));
+}
+
+void
+libzfs_mnttab_init(libzfs_handle_t *hdl)
+{
+ mutex_init(&hdl->zh_mnttab_lock, NULL, MUTEX_DEFAULT, NULL);
+ assert(avl_numnodes(&hdl->zh_mnttab) == 0);
+ avl_create(&hdl->zh_mnttab, mnttab_compare,
+ sizeof (mnttab_node_t), offsetof(mnttab_node_t, mtn_node));
+}
+
+void
+libzfs_mnttab_fini(libzfs_handle_t *hdl)
+{
+ void *cookie = NULL;
+ mnttab_node_t *mtn;
+
+ while ((mtn = avl_destroy_nodes(&hdl->zh_mnttab, &cookie))
+ != NULL)
+ mnttab_node_free(hdl, mtn);
+
+ avl_destroy(&hdl->zh_mnttab);
+ (void) mutex_destroy(&hdl->zh_mnttab_lock);
+}
+
+void
+libzfs_mnttab_cache(libzfs_handle_t *hdl, boolean_t enable)
+{
+ /* This is a no-op to preserve ABI backward compatibility. */
+ (void) hdl, (void) enable;
+}
+
+static int
+mnttab_update(libzfs_handle_t *hdl)
+{
+ FILE *mnttab;
+ struct mnttab entry;
+
+ ASSERT(MUTEX_HELD(&hdl->zh_mnttab_lock));
+
+ if ((mnttab = fopen(MNTTAB, "re")) == NULL)
+ return (ENOENT);
+
+ while (getmntent(mnttab, &entry) == 0) {
+ mnttab_node_t *mtn;
+ avl_index_t where;
+
+ if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0)
+ continue;
+
+ mtn = mnttab_node_alloc(hdl, entry.mnt_special,
+ entry.mnt_mountp, entry.mnt_mntopts);
+
+ /* Exclude duplicate mounts */
+ if (avl_find(&hdl->zh_mnttab, mtn, &where) != NULL) {
+ mnttab_node_free(hdl, mtn);
+ continue;
+ }
+
+ avl_add(&hdl->zh_mnttab, mtn);
+ }
+
+ (void) fclose(mnttab);
+ return (0);
+}
+
+int
+libzfs_mnttab_find(libzfs_handle_t *hdl, const char *fsname,
+ struct mnttab *entry)
+{
+ mnttab_node_t find;
+ mnttab_node_t *mtn;
+ int ret = ENOENT;
+
+ mutex_enter(&hdl->zh_mnttab_lock);
+ if (avl_numnodes(&hdl->zh_mnttab) == 0) {
+ int error;
+
+ if ((error = mnttab_update(hdl)) != 0) {
+ mutex_exit(&hdl->zh_mnttab_lock);
+ return (error);
+ }
+ }
+
+ find.mtn_mt.mnt_special = (char *)fsname;
+ mtn = avl_find(&hdl->zh_mnttab, &find, NULL);
+ if (mtn) {
+ *entry = mtn->mtn_mt;
+ ret = 0;
+ }
+ mutex_exit(&hdl->zh_mnttab_lock);
+ return (ret);
+}
+
+void
+libzfs_mnttab_add(libzfs_handle_t *hdl, const char *special,
+ const char *mountp, const char *mntopts)
+{
+ mnttab_node_t *mtn;
+
+ mutex_enter(&hdl->zh_mnttab_lock);
+
+ mtn = mnttab_node_alloc(hdl, special, mountp, mntopts);
+
+ /*
+ * Another thread may have already added this entry
+ * via mnttab_update. If so we should skip it.
+ */
+ if (avl_find(&hdl->zh_mnttab, mtn, NULL) != NULL)
+ mnttab_node_free(hdl, mtn);
+ else
+ avl_add(&hdl->zh_mnttab, mtn);
+
+ mutex_exit(&hdl->zh_mnttab_lock);
+}
+
+void
+libzfs_mnttab_remove(libzfs_handle_t *hdl, const char *fsname)
+{
+ mnttab_node_t find;
+ mnttab_node_t *ret;
+
+ mutex_enter(&hdl->zh_mnttab_lock);
+ find.mtn_mt.mnt_special = (char *)fsname;
+ if ((ret = avl_find(&hdl->zh_mnttab, (void *)&find, NULL)) != NULL) {
+ avl_remove(&hdl->zh_mnttab, ret);
+ mnttab_node_free(hdl, ret);
+ }
+ mutex_exit(&hdl->zh_mnttab_lock);
+}