Path: blob/main/sys/contrib/openzfs/lib/libzfs/libzfs_mnttab.c
178703 views
// SPDX-License-Identifier: CDDL-1.01/*2* CDDL HEADER START3*4* The contents of this file are subject to the terms of the5* Common Development and Distribution License (the "License").6* You may not use this file except in compliance with the License.7*8* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE9* or https://opensource.org/licenses/CDDL-1.0.10* See the License for the specific language governing permissions11* and limitations under the License.12*13* When distributing Covered Code, include this CDDL HEADER in each14* file and include the License file at usr/src/OPENSOLARIS.LICENSE.15* If applicable, add the following below this CDDL HEADER, with the16* fields enclosed by brackets "[]" replaced with your own identifying17* information: Portions Copyright [yyyy] [name of copyright owner]18*19* CDDL HEADER END20*/2122/*23* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.24* Copyright 2019 Joyent, Inc.25* Copyright (c) 2011, 2020 by Delphix. All rights reserved.26* Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.27* Copyright (c) 2012 Pawel Jakub Dawidek <[email protected]>.28* Copyright (c) 2013 Martin Matuska. All rights reserved.29* Copyright (c) 2013 Steven Hartland. All rights reserved.30* Copyright 2017 Nexenta Systems, Inc.31* Copyright 2016 Igor Kozhukhov <[email protected]>32* Copyright 2017-2018 RackTop Systems.33* Copyright (c) 2019 Datto Inc.34* Copyright (c) 2019, loli10K <[email protected]>35* Copyright (c) 2021 Matt Fiddaman36* Copyright (c) 2026, TrueNAS.37*/3839#include <sys/mntent.h>40#include <sys/mutex.h>41#include <libzfs.h>42#include "libzfs_impl.h"4344typedef struct mnttab_node {45struct mnttab mtn_mt;46avl_node_t mtn_node;47} mnttab_node_t;4849static mnttab_node_t *50mnttab_node_alloc(libzfs_handle_t *hdl, const char *special,51const char *mountp, const char *mntopts)52{53mnttab_node_t *mtn = zfs_alloc(hdl, sizeof (mnttab_node_t));54mtn->mtn_mt.mnt_special = zfs_strdup(hdl, special);55mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, mountp);56mtn->mtn_mt.mnt_fstype = (char *)MNTTYPE_ZFS;57mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, mntopts);58return (mtn);59}6061static void62mnttab_node_free(libzfs_handle_t *hdl, mnttab_node_t *mtn)63{64(void) hdl;65free(mtn->mtn_mt.mnt_special);66free(mtn->mtn_mt.mnt_mountp);67free(mtn->mtn_mt.mnt_mntopts);68free(mtn);69}7071static int72mnttab_compare(const void *arg1, const void *arg2)73{74const mnttab_node_t *mtn1 = (const mnttab_node_t *)arg1;75const mnttab_node_t *mtn2 = (const mnttab_node_t *)arg2;76int rv;7778rv = strcmp(mtn1->mtn_mt.mnt_special, mtn2->mtn_mt.mnt_special);7980return (TREE_ISIGN(rv));81}8283void84libzfs_mnttab_init(libzfs_handle_t *hdl)85{86mutex_init(&hdl->zh_mnttab_lock, NULL, MUTEX_DEFAULT, NULL);87assert(avl_numnodes(&hdl->zh_mnttab) == 0);88avl_create(&hdl->zh_mnttab, mnttab_compare,89sizeof (mnttab_node_t), offsetof(mnttab_node_t, mtn_node));90}9192void93libzfs_mnttab_fini(libzfs_handle_t *hdl)94{95void *cookie = NULL;96mnttab_node_t *mtn;9798while ((mtn = avl_destroy_nodes(&hdl->zh_mnttab, &cookie))99!= NULL)100mnttab_node_free(hdl, mtn);101102avl_destroy(&hdl->zh_mnttab);103(void) mutex_destroy(&hdl->zh_mnttab_lock);104}105106void107libzfs_mnttab_cache(libzfs_handle_t *hdl, boolean_t enable)108{109/* This is a no-op to preserve ABI backward compatibility. */110(void) hdl, (void) enable;111}112113static int114mnttab_update(libzfs_handle_t *hdl)115{116FILE *mnttab;117struct mnttab entry;118119ASSERT(MUTEX_HELD(&hdl->zh_mnttab_lock));120121if ((mnttab = fopen(MNTTAB, "re")) == NULL)122return (ENOENT);123124while (getmntent(mnttab, &entry) == 0) {125mnttab_node_t *mtn;126avl_index_t where;127128if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0)129continue;130131mtn = mnttab_node_alloc(hdl, entry.mnt_special,132entry.mnt_mountp, entry.mnt_mntopts);133134/* Exclude duplicate mounts */135if (avl_find(&hdl->zh_mnttab, mtn, &where) != NULL) {136mnttab_node_free(hdl, mtn);137continue;138}139140avl_add(&hdl->zh_mnttab, mtn);141}142143(void) fclose(mnttab);144return (0);145}146147int148libzfs_mnttab_find(libzfs_handle_t *hdl, const char *fsname,149struct mnttab *entry)150{151mnttab_node_t find;152mnttab_node_t *mtn;153int ret = ENOENT;154155mutex_enter(&hdl->zh_mnttab_lock);156if (avl_numnodes(&hdl->zh_mnttab) == 0) {157int error;158159if ((error = mnttab_update(hdl)) != 0) {160mutex_exit(&hdl->zh_mnttab_lock);161return (error);162}163}164165find.mtn_mt.mnt_special = (char *)fsname;166mtn = avl_find(&hdl->zh_mnttab, &find, NULL);167if (mtn) {168*entry = mtn->mtn_mt;169ret = 0;170}171mutex_exit(&hdl->zh_mnttab_lock);172return (ret);173}174175void176libzfs_mnttab_add(libzfs_handle_t *hdl, const char *special,177const char *mountp, const char *mntopts)178{179mnttab_node_t *mtn;180181mutex_enter(&hdl->zh_mnttab_lock);182183mtn = mnttab_node_alloc(hdl, special, mountp, mntopts);184185/*186* Another thread may have already added this entry187* via mnttab_update. If so we should skip it.188*/189if (avl_find(&hdl->zh_mnttab, mtn, NULL) != NULL)190mnttab_node_free(hdl, mtn);191else192avl_add(&hdl->zh_mnttab, mtn);193194mutex_exit(&hdl->zh_mnttab_lock);195}196197void198libzfs_mnttab_remove(libzfs_handle_t *hdl, const char *fsname)199{200mnttab_node_t find;201mnttab_node_t *ret;202203mutex_enter(&hdl->zh_mnttab_lock);204find.mtn_mt.mnt_special = (char *)fsname;205if ((ret = avl_find(&hdl->zh_mnttab, (void *)&find, NULL)) != NULL) {206avl_remove(&hdl->zh_mnttab, ret);207mnttab_node_free(hdl, ret);208}209mutex_exit(&hdl->zh_mnttab_lock);210}211212213