Path: blob/main/sys/contrib/openzfs/module/os/linux/zfs/zfs_ctldir.c
110498 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*/21/*22*23* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.24* Copyright (C) 2011 Lawrence Livermore National Security, LLC.25* Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).26* LLNL-CODE-403049.27* Rewritten for Linux by:28* Rohan Puri <[email protected]>29* Brian Behlendorf <[email protected]>30* Copyright (c) 2013 by Delphix. All rights reserved.31* Copyright 2015, OmniTI Computer Consulting, Inc. All rights reserved.32* Copyright (c) 2018 George Melikov. All Rights Reserved.33* Copyright (c) 2019 Datto, Inc. All rights reserved.34* Copyright (c) 2020 The MathWorks, Inc. All rights reserved.35*/3637/*38* ZFS control directory (a.k.a. ".zfs")39*40* This directory provides a common location for all ZFS meta-objects.41* Currently, this is only the 'snapshot' and 'shares' directory, but this may42* expand in the future. The elements are built dynamically, as the hierarchy43* does not actually exist on disk.44*45* For 'snapshot', we don't want to have all snapshots always mounted, because46* this would take up a huge amount of space in /etc/mnttab. We have three47* types of objects:48*49* ctldir ------> snapshotdir -------> snapshot50* |51* |52* V53* mounted fs54*55* The 'snapshot' node contains just enough information to lookup '..' and act56* as a mountpoint for the snapshot. Whenever we lookup a specific snapshot, we57* perform an automount of the underlying filesystem and return the58* corresponding inode.59*60* All mounts are handled automatically by an user mode helper which invokes61* the mount procedure. Unmounts are handled by allowing the mount62* point to expire so the kernel may automatically unmount it.63*64* The '.zfs', '.zfs/snapshot', and all directories created under65* '.zfs/snapshot' (ie: '.zfs/snapshot/<snapname>') all share the same66* zfsvfs_t as the head filesystem (what '.zfs' lives under).67*68* File systems mounted on top of the '.zfs/snapshot/<snapname>' paths69* (ie: snapshots) are complete ZFS filesystems and have their own unique70* zfsvfs_t. However, the fsid reported by these mounts will be the same71* as that used by the parent zfsvfs_t to make NFS happy.72*/7374#include <sys/types.h>75#include <sys/param.h>76#include <sys/time.h>77#include <sys/sysmacros.h>78#include <sys/pathname.h>79#include <sys/vfs.h>80#include <sys/zfs_ctldir.h>81#include <sys/zfs_ioctl.h>82#include <sys/zfs_vfsops.h>83#include <sys/zfs_vnops.h>84#include <sys/stat.h>85#include <sys/dmu.h>86#include <sys/dmu_objset.h>87#include <sys/dsl_destroy.h>88#include <sys/dsl_deleg.h>89#include <sys/zpl.h>90#include <sys/mntent.h>91#include "zfs_namecheck.h"9293/*94* Two AVL trees are maintained which contain all currently automounted95* snapshots. Every automounted snapshots maps to a single zfs_snapentry_t96* entry which MUST:97*98* - be attached to both trees, and99* - be unique, no duplicate entries are allowed.100*101* The zfs_snapshots_by_name tree is indexed by the full dataset name102* while the zfs_snapshots_by_objsetid tree is indexed by the unique103* objsetid. This allows for fast lookups either by name or objsetid.104*/105static avl_tree_t zfs_snapshots_by_name;106static avl_tree_t zfs_snapshots_by_objsetid;107static krwlock_t zfs_snapshot_lock;108109/*110* Control Directory Tunables (.zfs)111*/112int zfs_expire_snapshot = ZFSCTL_EXPIRE_SNAPSHOT;113static int zfs_admin_snapshot = 0;114static int zfs_snapshot_no_setuid = 0;115116typedef struct {117char *se_name; /* full snapshot name */118char *se_path; /* full mount path */119spa_t *se_spa; /* pool spa (NULL if pending) */120uint64_t se_objsetid; /* snapshot objset id */121struct dentry *se_root_dentry; /* snapshot root dentry */122taskqid_t se_taskqid; /* scheduled unmount taskqid */123avl_node_t se_node_name; /* zfs_snapshots_by_name link */124avl_node_t se_node_objsetid; /* zfs_snapshots_by_objsetid link */125zfs_refcount_t se_refcount; /* reference count */126kmutex_t se_mtx; /* protects se_mounting and se_cv */127kcondvar_t se_cv; /* signal mount completion */128boolean_t se_mounting; /* mount operation in progress */129int se_mount_error; /* error from failed mount */130} zfs_snapentry_t;131132static void zfsctl_snapshot_unmount_delay_impl(zfs_snapentry_t *se, int delay);133134/*135* Allocate a new zfs_snapentry_t being careful to make a copy of the136* the snapshot name and provided mount point. No reference is taken.137*/138static zfs_snapentry_t *139zfsctl_snapshot_alloc(const char *full_name, const char *full_path, spa_t *spa,140uint64_t objsetid, struct dentry *root_dentry)141{142zfs_snapentry_t *se;143144se = kmem_zalloc(sizeof (zfs_snapentry_t), KM_SLEEP);145146se->se_name = kmem_strdup(full_name);147se->se_path = kmem_strdup(full_path);148se->se_spa = spa;149se->se_objsetid = objsetid;150se->se_root_dentry = root_dentry;151se->se_taskqid = TASKQID_INVALID;152mutex_init(&se->se_mtx, NULL, MUTEX_DEFAULT, NULL);153cv_init(&se->se_cv, NULL, CV_DEFAULT, NULL);154se->se_mounting = B_FALSE;155se->se_mount_error = 0;156157zfs_refcount_create(&se->se_refcount);158159return (se);160}161162/*163* Free a zfs_snapentry_t the caller must ensure there are no active164* references.165*/166static void167zfsctl_snapshot_free(zfs_snapentry_t *se)168{169zfs_refcount_destroy(&se->se_refcount);170kmem_strfree(se->se_name);171kmem_strfree(se->se_path);172mutex_destroy(&se->se_mtx);173cv_destroy(&se->se_cv);174175kmem_free(se, sizeof (zfs_snapentry_t));176}177178/*179* Hold a reference on the zfs_snapentry_t.180*/181static void182zfsctl_snapshot_hold(zfs_snapentry_t *se)183{184zfs_refcount_add(&se->se_refcount, NULL);185}186187/*188* Release a reference on the zfs_snapentry_t. When the number of189* references drops to zero the structure will be freed.190*/191static void192zfsctl_snapshot_rele(zfs_snapentry_t *se)193{194if (zfs_refcount_remove(&se->se_refcount, NULL) == 0)195zfsctl_snapshot_free(se);196}197198/*199* Add a zfs_snapentry_t to the zfs_snapshots_by_name tree. If the entry200* is not pending (se_spa != NULL), also add to zfs_snapshots_by_objsetid.201* While the zfs_snapentry_t is part of the trees a reference is held.202*/203static void204zfsctl_snapshot_add(zfs_snapentry_t *se)205{206ASSERT(RW_WRITE_HELD(&zfs_snapshot_lock));207zfsctl_snapshot_hold(se);208avl_add(&zfs_snapshots_by_name, se);209if (se->se_spa != NULL)210avl_add(&zfs_snapshots_by_objsetid, se);211}212213/*214* Remove a zfs_snapentry_t from the zfs_snapshots_by_name tree and215* zfs_snapshots_by_objsetid tree (if not pending). Upon removal a216* reference is dropped, this can result in the structure being freed217* if that was the last remaining reference.218*/219static void220zfsctl_snapshot_remove(zfs_snapentry_t *se)221{222ASSERT(RW_WRITE_HELD(&zfs_snapshot_lock));223avl_remove(&zfs_snapshots_by_name, se);224if (se->se_spa != NULL)225avl_remove(&zfs_snapshots_by_objsetid, se);226zfsctl_snapshot_rele(se);227}228229/*230* Fill a pending zfs_snapentry_t after mount succeeds. Fills in the231* remaining fields and adds the entry to the zfs_snapshots_by_objsetid tree.232*/233static void234zfsctl_snapshot_fill(zfs_snapentry_t *se, spa_t *spa, uint64_t objsetid,235struct dentry *root_dentry)236{237ASSERT(RW_WRITE_HELD(&zfs_snapshot_lock));238ASSERT3P(se->se_spa, ==, NULL);239se->se_spa = spa;240se->se_objsetid = objsetid;241se->se_root_dentry = root_dentry;242avl_add(&zfs_snapshots_by_objsetid, se);243}244245/*246* Snapshot name comparison function for the zfs_snapshots_by_name.247*/248static int249snapentry_compare_by_name(const void *a, const void *b)250{251const zfs_snapentry_t *se_a = a;252const zfs_snapentry_t *se_b = b;253int ret;254255ret = strcmp(se_a->se_name, se_b->se_name);256257if (ret < 0)258return (-1);259else if (ret > 0)260return (1);261else262return (0);263}264265/*266* Snapshot name comparison function for the zfs_snapshots_by_objsetid.267*/268static int269snapentry_compare_by_objsetid(const void *a, const void *b)270{271const zfs_snapentry_t *se_a = a;272const zfs_snapentry_t *se_b = b;273274if (se_a->se_spa != se_b->se_spa)275return ((ulong_t)se_a->se_spa < (ulong_t)se_b->se_spa ? -1 : 1);276277if (se_a->se_objsetid < se_b->se_objsetid)278return (-1);279else if (se_a->se_objsetid > se_b->se_objsetid)280return (1);281else282return (0);283}284285/*286* Find a zfs_snapentry_t in zfs_snapshots_by_name. If the snapname287* is found a pointer to the zfs_snapentry_t is returned and a reference288* taken on the structure. The caller is responsible for dropping the289* reference with zfsctl_snapshot_rele(). If the snapname is not found290* NULL will be returned.291*/292static zfs_snapentry_t *293zfsctl_snapshot_find_by_name(const char *snapname)294{295zfs_snapentry_t *se, search;296297ASSERT(RW_LOCK_HELD(&zfs_snapshot_lock));298299search.se_name = (char *)snapname;300se = avl_find(&zfs_snapshots_by_name, &search, NULL);301if (se)302zfsctl_snapshot_hold(se);303304return (se);305}306307/*308* Find a zfs_snapentry_t in zfs_snapshots_by_objsetid given the objset id309* rather than the snapname. In all other respects it behaves the same310* as zfsctl_snapshot_find_by_name().311*/312static zfs_snapentry_t *313zfsctl_snapshot_find_by_objsetid(spa_t *spa, uint64_t objsetid)314{315zfs_snapentry_t *se, search;316317ASSERT(RW_LOCK_HELD(&zfs_snapshot_lock));318319search.se_spa = spa;320search.se_objsetid = objsetid;321se = avl_find(&zfs_snapshots_by_objsetid, &search, NULL);322if (se)323zfsctl_snapshot_hold(se);324325return (se);326}327328/*329* Rename a zfs_snapentry_t in the zfs_snapshots_by_name. The structure is330* removed, renamed, and added back to the new correct location in the tree.331*/332static int333zfsctl_snapshot_rename(const char *old_snapname, const char *new_snapname)334{335zfs_snapentry_t *se;336337ASSERT(RW_WRITE_HELD(&zfs_snapshot_lock));338339se = zfsctl_snapshot_find_by_name(old_snapname);340if (se == NULL)341return (SET_ERROR(ENOENT));342if (se->se_spa == NULL) {343/* Snapshot mount is in progress */344zfsctl_snapshot_rele(se);345return (SET_ERROR(EBUSY));346}347348zfsctl_snapshot_remove(se);349kmem_strfree(se->se_name);350se->se_name = kmem_strdup(new_snapname);351zfsctl_snapshot_add(se);352zfsctl_snapshot_rele(se);353354return (0);355}356357/*358* Delayed task responsible for unmounting an expired automounted snapshot.359*/360static void361snapentry_expire(void *data)362{363zfs_snapentry_t *se = (zfs_snapentry_t *)data;364spa_t *spa = se->se_spa;365uint64_t objsetid = se->se_objsetid;366367if (zfs_expire_snapshot <= 0) {368zfsctl_snapshot_rele(se);369return;370}371372(void) zfsctl_snapshot_unmount(se->se_name, MNT_EXPIRE);373374/*375* Clear taskqid and reschedule if the snapshot wasn't removed.376* This can occur when the snapshot is busy.377*/378rw_enter(&zfs_snapshot_lock, RW_WRITER);379se->se_taskqid = TASKQID_INVALID;380zfsctl_snapshot_rele(se);381if ((se = zfsctl_snapshot_find_by_objsetid(spa, objsetid)) != NULL) {382zfsctl_snapshot_unmount_delay_impl(se, zfs_expire_snapshot);383zfsctl_snapshot_rele(se);384}385rw_exit(&zfs_snapshot_lock);386}387388/*389* Cancel an automatic unmount of a snapname. This callback is responsible390* for dropping the reference on the zfs_snapentry_t which was taken when391* during dispatch.392*/393static void394zfsctl_snapshot_unmount_cancel(zfs_snapentry_t *se)395{396int err = 0;397398ASSERT(RW_WRITE_HELD(&zfs_snapshot_lock));399400err = taskq_cancel_id(system_delay_taskq, se->se_taskqid, B_FALSE);401/*402* Clear taskqid only if we successfully cancelled before execution.403* For ENOENT, task already cleared it. For EBUSY, task will clear404* it when done.405*/406if (err == 0) {407se->se_taskqid = TASKQID_INVALID;408zfsctl_snapshot_rele(se);409}410}411412/*413* Dispatch the unmount task for delayed handling with a hold protecting it.414*/415static void416zfsctl_snapshot_unmount_delay_impl(zfs_snapentry_t *se, int delay)417{418ASSERT(RW_LOCK_HELD(&zfs_snapshot_lock));419420if (delay <= 0)421return;422423/*424* If this condition happens, we managed to:425* - dispatch once426* - want to dispatch _again_ before it returned427*428* So let's just return - if that task fails at unmounting,429* we'll eventually dispatch again, and if it succeeds,430* no problem.431*/432if (se->se_taskqid != TASKQID_INVALID) {433return;434}435436zfsctl_snapshot_hold(se);437se->se_taskqid = taskq_dispatch_delay(system_delay_taskq,438snapentry_expire, se, TQ_SLEEP, ddi_get_lbolt() + delay * HZ);439}440441/*442* Schedule an automatic unmount of objset id to occur in delay seconds from443* now. Any previous delayed unmount will be cancelled in favor of the444* updated deadline. A reference is taken by zfsctl_snapshot_find_by_name()445* and held until the outstanding task is handled or cancelled.446*/447int448zfsctl_snapshot_unmount_delay(spa_t *spa, uint64_t objsetid, int delay)449{450zfs_snapentry_t *se;451int error = ENOENT;452453rw_enter(&zfs_snapshot_lock, RW_WRITER);454if ((se = zfsctl_snapshot_find_by_objsetid(spa, objsetid)) != NULL) {455zfsctl_snapshot_unmount_cancel(se);456zfsctl_snapshot_unmount_delay_impl(se, delay);457zfsctl_snapshot_rele(se);458error = 0;459}460rw_exit(&zfs_snapshot_lock);461462return (error);463}464465/*466* Check if the given inode is a part of the virtual .zfs directory.467*/468boolean_t469zfsctl_is_node(struct inode *ip)470{471return (ITOZ(ip)->z_is_ctldir);472}473474/*475* Check if the given inode is a .zfs/snapshots/snapname directory.476*/477boolean_t478zfsctl_is_snapdir(struct inode *ip)479{480return (zfsctl_is_node(ip) && (ip->i_ino <= ZFSCTL_INO_SNAPDIRS));481}482483/*484* Allocate a new inode with the passed id and ops.485*/486static struct inode *487zfsctl_inode_alloc(zfsvfs_t *zfsvfs, uint64_t id,488const struct file_operations *fops, const struct inode_operations *ops,489uint64_t creation)490{491struct inode *ip;492znode_t *zp;493inode_timespec_t now = {.tv_sec = creation};494495ip = new_inode(zfsvfs->z_sb);496if (ip == NULL)497return (NULL);498499if (!creation)500now = current_time(ip);501zp = ITOZ(ip);502ASSERT0P(zp->z_dirlocks);503ASSERT0P(zp->z_acl_cached);504ASSERT0P(zp->z_xattr_cached);505zp->z_id = id;506zp->z_unlinked = B_FALSE;507zp->z_atime_dirty = B_FALSE;508zp->z_zn_prefetch = B_FALSE;509zp->z_is_sa = B_FALSE;510zp->z_is_ctldir = B_TRUE;511zp->z_sa_hdl = NULL;512zp->z_blksz = 0;513zp->z_seq = 0;514zp->z_mapcnt = 0;515zp->z_size = 0;516zp->z_pflags = 0;517zp->z_mode = 0;518zp->z_sync_cnt = 0;519ip->i_generation = 0;520ip->i_ino = id;521ip->i_mode = (S_IFDIR | S_IRWXUGO);522ip->i_uid = SUID_TO_KUID(0);523ip->i_gid = SGID_TO_KGID(0);524ip->i_blkbits = SPA_MINBLOCKSHIFT;525zpl_inode_set_atime_to_ts(ip, now);526zpl_inode_set_mtime_to_ts(ip, now);527zpl_inode_set_ctime_to_ts(ip, now);528ip->i_fop = fops;529ip->i_op = ops;530#if defined(IOP_XATTR)531ip->i_opflags &= ~IOP_XATTR;532#endif533534if (insert_inode_locked(ip)) {535unlock_new_inode(ip);536iput(ip);537return (NULL);538}539540mutex_enter(&zfsvfs->z_znodes_lock);541list_insert_tail(&zfsvfs->z_all_znodes, zp);542membar_producer();543mutex_exit(&zfsvfs->z_znodes_lock);544545unlock_new_inode(ip);546547return (ip);548}549550/*551* Lookup the inode with given id, it will be allocated if needed.552*/553static struct inode *554zfsctl_inode_lookup(zfsvfs_t *zfsvfs, uint64_t id,555const struct file_operations *fops, const struct inode_operations *ops)556{557struct inode *ip = NULL;558uint64_t creation = 0;559dsl_dataset_t *snap_ds;560dsl_pool_t *pool;561562while (ip == NULL) {563ip = ilookup(zfsvfs->z_sb, (unsigned long)id);564if (ip)565break;566567if (id <= ZFSCTL_INO_SNAPDIRS && !creation) {568pool = dmu_objset_pool(zfsvfs->z_os);569dsl_pool_config_enter(pool, FTAG);570if (!dsl_dataset_hold_obj(pool,571ZFSCTL_INO_SNAPDIRS - id, FTAG, &snap_ds)) {572creation = dsl_get_creation(snap_ds);573dsl_dataset_rele(snap_ds, FTAG);574}575dsl_pool_config_exit(pool, FTAG);576}577578/* May fail due to concurrent zfsctl_inode_alloc() */579ip = zfsctl_inode_alloc(zfsvfs, id, fops, ops, creation);580}581582return (ip);583}584585/*586* Create the '.zfs' directory. This directory is cached as part of the VFS587* structure. This results in a hold on the zfsvfs_t. The code in zfs_umount()588* therefore checks against a vfs_count of 2 instead of 1. This reference589* is removed when the ctldir is destroyed in the unmount. All other entities590* under the '.zfs' directory are created dynamically as needed.591*592* Because the dynamically created '.zfs' directory entries assume the use593* of 64-bit inode numbers this support must be disabled on 32-bit systems.594*/595int596zfsctl_create(zfsvfs_t *zfsvfs)597{598ASSERT0P(zfsvfs->z_ctldir);599600zfsvfs->z_ctldir = zfsctl_inode_alloc(zfsvfs, ZFSCTL_INO_ROOT,601&zpl_fops_root, &zpl_ops_root, 0);602if (zfsvfs->z_ctldir == NULL)603return (SET_ERROR(ENOENT));604605return (0);606}607608/*609* Destroy the '.zfs' directory or remove a snapshot from zfs_snapshots_by_name.610* Only called when the filesystem is unmounted.611*/612void613zfsctl_destroy(zfsvfs_t *zfsvfs)614{615if (zfsvfs->z_issnap) {616zfs_snapentry_t *se;617spa_t *spa = zfsvfs->z_os->os_spa;618uint64_t objsetid = dmu_objset_id(zfsvfs->z_os);619620rw_enter(&zfs_snapshot_lock, RW_WRITER);621se = zfsctl_snapshot_find_by_objsetid(spa, objsetid);622if (se != NULL) {623zfsctl_snapshot_remove(se);624/*625* Don't wait if snapentry_expire task is calling626* umount, which may have resulted in this destroy627* call. Waiting would deadlock: snapentry_expire628* waits for umount while umount waits for task.629*/630zfsctl_snapshot_unmount_cancel(se);631zfsctl_snapshot_rele(se);632}633rw_exit(&zfs_snapshot_lock);634} else if (zfsvfs->z_ctldir) {635iput(zfsvfs->z_ctldir);636zfsvfs->z_ctldir = NULL;637}638}639640/*641* Given a root znode, retrieve the associated .zfs directory.642* Add a hold to the vnode and return it.643*/644struct inode *645zfsctl_root(znode_t *zp)646{647ASSERT(zfs_has_ctldir(zp));648/* Must have an existing ref, so igrab() cannot return NULL */649VERIFY3P(igrab(ZTOZSB(zp)->z_ctldir), !=, NULL);650return (ZTOZSB(zp)->z_ctldir);651}652653/*654* Generate a long fid to indicate a snapdir. We encode whether snapdir is655* already mounted in gen field. We do this because nfsd lookup will not656* trigger automount. Next time the nfsd does fh_to_dentry, we will notice657* this and do automount and return ESTALE to force nfsd revalidate and follow658* mount.659*/660static int661zfsctl_snapdir_fid(struct inode *ip, fid_t *fidp)662{663zfid_short_t *zfid = (zfid_short_t *)fidp;664zfid_long_t *zlfid = (zfid_long_t *)fidp;665uint32_t gen = 0;666uint64_t object;667uint64_t objsetid;668int i;669struct dentry *dentry;670671if (fidp->fid_len < LONG_FID_LEN) {672fidp->fid_len = LONG_FID_LEN;673return (SET_ERROR(ENOSPC));674}675676object = ip->i_ino;677objsetid = ZFSCTL_INO_SNAPDIRS - ip->i_ino;678zfid->zf_len = LONG_FID_LEN;679680dentry = d_obtain_alias(igrab(ip));681if (!IS_ERR(dentry)) {682gen = !!d_mountpoint(dentry);683dput(dentry);684}685686for (i = 0; i < sizeof (zfid->zf_object); i++)687zfid->zf_object[i] = (uint8_t)(object >> (8 * i));688689for (i = 0; i < sizeof (zfid->zf_gen); i++)690zfid->zf_gen[i] = (uint8_t)(gen >> (8 * i));691692for (i = 0; i < sizeof (zlfid->zf_setid); i++)693zlfid->zf_setid[i] = (uint8_t)(objsetid >> (8 * i));694695for (i = 0; i < sizeof (zlfid->zf_setgen); i++)696zlfid->zf_setgen[i] = 0;697698return (0);699}700701/*702* Generate an appropriate fid for an entry in the .zfs directory.703*/704int705zfsctl_fid(struct inode *ip, fid_t *fidp)706{707znode_t *zp = ITOZ(ip);708zfsvfs_t *zfsvfs = ITOZSB(ip);709uint64_t object = zp->z_id;710zfid_short_t *zfid;711int i;712int error;713714if ((error = zfs_enter(zfsvfs, FTAG)) != 0)715return (error);716717if (zfsctl_is_snapdir(ip)) {718zfs_exit(zfsvfs, FTAG);719return (zfsctl_snapdir_fid(ip, fidp));720}721722if (fidp->fid_len < SHORT_FID_LEN) {723fidp->fid_len = SHORT_FID_LEN;724zfs_exit(zfsvfs, FTAG);725return (SET_ERROR(ENOSPC));726}727728zfid = (zfid_short_t *)fidp;729730zfid->zf_len = SHORT_FID_LEN;731732for (i = 0; i < sizeof (zfid->zf_object); i++)733zfid->zf_object[i] = (uint8_t)(object >> (8 * i));734735/* .zfs znodes always have a generation number of 0 */736for (i = 0; i < sizeof (zfid->zf_gen); i++)737zfid->zf_gen[i] = 0;738739zfs_exit(zfsvfs, FTAG);740return (0);741}742743/*744* Construct a full dataset name in full_name: "pool/dataset@snap_name"745*/746static int747zfsctl_snapshot_name(zfsvfs_t *zfsvfs, const char *snap_name, int len,748char *full_name)749{750objset_t *os = zfsvfs->z_os;751752if (zfs_component_namecheck(snap_name, NULL, NULL) != 0)753return (SET_ERROR(EILSEQ));754755dmu_objset_name(os, full_name);756if ((strlen(full_name) + 1 + strlen(snap_name)) >= len)757return (SET_ERROR(ENAMETOOLONG));758759(void) strcat(full_name, "@");760(void) strcat(full_name, snap_name);761762return (0);763}764765/*766* Returns full path in full_path: "/pool/dataset/.zfs/snapshot/snap_name/"767*/768static int769zfsctl_snapshot_path_objset(zfsvfs_t *zfsvfs, uint64_t objsetid,770int path_len, char *full_path)771{772objset_t *os = zfsvfs->z_os;773fstrans_cookie_t cookie;774char *snapname;775boolean_t case_conflict;776uint64_t id, pos = 0;777int error = 0;778779cookie = spl_fstrans_mark();780snapname = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);781782while (error == 0) {783dsl_pool_config_enter(dmu_objset_pool(os), FTAG);784error = dmu_snapshot_list_next(zfsvfs->z_os,785ZFS_MAX_DATASET_NAME_LEN, snapname, &id, &pos,786&case_conflict);787dsl_pool_config_exit(dmu_objset_pool(os), FTAG);788if (error)789goto out;790791if (id == objsetid)792break;793}794795mutex_enter(&zfsvfs->z_vfs->vfs_mntpt_lock);796if (zfsvfs->z_vfs->vfs_mntpoint != NULL) {797snprintf(full_path, path_len, "%s/.zfs/snapshot/%s",798zfsvfs->z_vfs->vfs_mntpoint, snapname);799} else800error = SET_ERROR(ENOENT);801mutex_exit(&zfsvfs->z_vfs->vfs_mntpt_lock);802803out:804kmem_free(snapname, ZFS_MAX_DATASET_NAME_LEN);805spl_fstrans_unmark(cookie);806807return (error);808}809810/*811* Special case the handling of "..".812*/813int814zfsctl_root_lookup(struct inode *dip, const char *name, struct inode **ipp,815int flags, cred_t *cr, int *direntflags, pathname_t *realpnp)816{817zfsvfs_t *zfsvfs = ITOZSB(dip);818int error = 0;819820if ((error = zfs_enter(zfsvfs, FTAG)) != 0)821return (error);822823if (zfsvfs->z_show_ctldir == ZFS_SNAPDIR_DISABLED) {824*ipp = NULL;825} else if (strcmp(name, "..") == 0) {826*ipp = dip->i_sb->s_root->d_inode;827} else if (strcmp(name, ZFS_SNAPDIR_NAME) == 0) {828*ipp = zfsctl_inode_lookup(zfsvfs, ZFSCTL_INO_SNAPDIR,829&zpl_fops_snapdir, &zpl_ops_snapdir);830} else if (strcmp(name, ZFS_SHAREDIR_NAME) == 0) {831*ipp = zfsctl_inode_lookup(zfsvfs, ZFSCTL_INO_SHARES,832&zpl_fops_shares, &zpl_ops_shares);833} else {834*ipp = NULL;835}836837if (*ipp == NULL)838error = SET_ERROR(ENOENT);839840zfs_exit(zfsvfs, FTAG);841842return (error);843}844845/*846* Lookup entry point for the 'snapshot' directory. Try to open the847* snapshot if it exist, creating the pseudo filesystem inode as necessary.848*/849int850zfsctl_snapdir_lookup(struct inode *dip, const char *name, struct inode **ipp,851int flags, cred_t *cr, int *direntflags, pathname_t *realpnp)852{853zfsvfs_t *zfsvfs = ITOZSB(dip);854uint64_t id;855int error;856857if ((error = zfs_enter(zfsvfs, FTAG)) != 0)858return (error);859860error = dmu_snapshot_lookup(zfsvfs->z_os, name, &id);861if (error) {862zfs_exit(zfsvfs, FTAG);863return (error);864}865866*ipp = zfsctl_inode_lookup(zfsvfs, ZFSCTL_INO_SNAPDIRS - id,867&simple_dir_operations, &simple_dir_inode_operations);868if (*ipp == NULL)869error = SET_ERROR(ENOENT);870871zfs_exit(zfsvfs, FTAG);872873return (error);874}875876/*877* Renaming a directory under '.zfs/snapshot' will automatically trigger878* a rename of the snapshot to the new given name. The rename is confined879* to the '.zfs/snapshot' directory snapshots cannot be moved elsewhere.880*/881int882zfsctl_snapdir_rename(struct inode *sdip, const char *snm,883struct inode *tdip, const char *tnm, cred_t *cr, int flags)884{885zfsvfs_t *zfsvfs = ITOZSB(sdip);886char *to, *from, *real, *fsname;887int error;888889if (!zfs_admin_snapshot)890return (SET_ERROR(EACCES));891892if ((error = zfs_enter(zfsvfs, FTAG)) != 0)893return (error);894895to = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);896from = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);897real = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);898fsname = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);899900if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE) {901error = dmu_snapshot_realname(zfsvfs->z_os, snm, real,902ZFS_MAX_DATASET_NAME_LEN, NULL);903if (error == 0) {904snm = real;905} else if (error != ENOTSUP) {906goto out;907}908}909910dmu_objset_name(zfsvfs->z_os, fsname);911912error = zfsctl_snapshot_name(ITOZSB(sdip), snm,913ZFS_MAX_DATASET_NAME_LEN, from);914if (error == 0)915error = zfsctl_snapshot_name(ITOZSB(tdip), tnm,916ZFS_MAX_DATASET_NAME_LEN, to);917if (error == 0)918error = zfs_secpolicy_rename_perms(from, to, cr);919if (error != 0)920goto out;921922/*923* Cannot move snapshots out of the snapdir.924*/925if (sdip != tdip) {926error = SET_ERROR(EINVAL);927goto out;928}929930/*931* No-op when names are identical.932*/933if (strcmp(snm, tnm) == 0) {934error = 0;935goto out;936}937938rw_enter(&zfs_snapshot_lock, RW_WRITER);939940error = dsl_dataset_rename_snapshot(fsname, snm, tnm, B_FALSE);941if (error == 0)942(void) zfsctl_snapshot_rename(snm, tnm);943944rw_exit(&zfs_snapshot_lock);945out:946kmem_free(from, ZFS_MAX_DATASET_NAME_LEN);947kmem_free(to, ZFS_MAX_DATASET_NAME_LEN);948kmem_free(real, ZFS_MAX_DATASET_NAME_LEN);949kmem_free(fsname, ZFS_MAX_DATASET_NAME_LEN);950951zfs_exit(zfsvfs, FTAG);952953return (error);954}955956/*957* Removing a directory under '.zfs/snapshot' will automatically trigger958* the removal of the snapshot with the given name.959*/960int961zfsctl_snapdir_remove(struct inode *dip, const char *name, cred_t *cr,962int flags)963{964zfsvfs_t *zfsvfs = ITOZSB(dip);965char *snapname, *real;966int error;967968if (!zfs_admin_snapshot)969return (SET_ERROR(EACCES));970971if ((error = zfs_enter(zfsvfs, FTAG)) != 0)972return (error);973974snapname = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);975real = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);976977if (zfsvfs->z_case == ZFS_CASE_INSENSITIVE) {978error = dmu_snapshot_realname(zfsvfs->z_os, name, real,979ZFS_MAX_DATASET_NAME_LEN, NULL);980if (error == 0) {981name = real;982} else if (error != ENOTSUP) {983goto out;984}985}986987error = zfsctl_snapshot_name(ITOZSB(dip), name,988ZFS_MAX_DATASET_NAME_LEN, snapname);989if (error == 0)990error = zfs_secpolicy_destroy_perms(snapname, cr);991if (error != 0)992goto out;993994error = zfsctl_snapshot_unmount(snapname, MNT_FORCE);995if ((error == 0) || (error == ENOENT))996error = dsl_destroy_snapshot(snapname, B_FALSE);997out:998kmem_free(snapname, ZFS_MAX_DATASET_NAME_LEN);999kmem_free(real, ZFS_MAX_DATASET_NAME_LEN);10001001zfs_exit(zfsvfs, FTAG);10021003return (error);1004}10051006/*1007* Creating a directory under '.zfs/snapshot' will automatically trigger1008* the creation of a new snapshot with the given name.1009*/1010int1011zfsctl_snapdir_mkdir(struct inode *dip, const char *dirname, vattr_t *vap,1012struct inode **ipp, cred_t *cr, int flags)1013{1014zfsvfs_t *zfsvfs = ITOZSB(dip);1015char *dsname;1016int error;10171018if (!zfs_admin_snapshot)1019return (SET_ERROR(EACCES));10201021dsname = kmem_alloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);10221023if (zfs_component_namecheck(dirname, NULL, NULL) != 0) {1024error = SET_ERROR(EILSEQ);1025goto out;1026}10271028dmu_objset_name(zfsvfs->z_os, dsname);10291030error = zfs_secpolicy_snapshot_perms(dsname, cr);1031if (error != 0)1032goto out;10331034if (error == 0) {1035error = dmu_objset_snapshot_one(dsname, dirname);1036if (error != 0)1037goto out;10381039error = zfsctl_snapdir_lookup(dip, dirname, ipp,10400, cr, NULL, NULL);1041}1042out:1043kmem_free(dsname, ZFS_MAX_DATASET_NAME_LEN);10441045return (error);1046}10471048/*1049* Flush everything out of the kernel's export table and such.1050* This is needed as once the snapshot is used over NFS, its1051* entries in svc_export and svc_expkey caches hold reference1052* to the snapshot mount point. There is no known way of flushing1053* only the entries related to the snapshot.1054*/1055static void1056exportfs_flush(void)1057{1058char *argv[] = { "/usr/sbin/exportfs", "-f", NULL };1059char *envp[] = { NULL };10601061(void) call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);1062}10631064/*1065* Returns the path in char format for given struct path. Uses1066* d_path exported by kernel to convert struct path to char1067* format. Returns the correct path for mountpoints and chroot1068* environments.1069*1070* If chroot environment has directories that are mounted with1071* --bind or --rbind flag, d_path returns the complete path inside1072* chroot environment but does not return the absolute path, i.e.1073* the path to chroot environment is missing.1074*/1075static int1076get_root_path(struct path *path, char *buff, int len)1077{1078char *path_buffer, *path_ptr;1079int error = 0;10801081path_get(path);1082path_buffer = kmem_zalloc(len, KM_SLEEP);1083path_ptr = d_path(path, path_buffer, len);1084if (IS_ERR(path_ptr))1085error = SET_ERROR(-PTR_ERR(path_ptr));1086else1087strcpy(buff, path_ptr);10881089kmem_free(path_buffer, len);1090path_put(path);1091return (error);1092}10931094/*1095* Returns if the current process root is chrooted or not. Linux1096* kernel exposes the task_struct for current process and init.1097* Since init process root points to actual root filesystem when1098* Linux runtime is reached, we can compare the current process1099* root with init process root to determine if root of the current1100* process is different from init, which can reliably determine if1101* current process is in chroot context or not.1102*/1103static int1104is_current_chrooted(void)1105{1106struct task_struct *curr = current, *global = &init_task;1107struct path cr_root, gl_root;11081109task_lock(curr);1110get_fs_root(curr->fs, &cr_root);1111task_unlock(curr);11121113task_lock(global);1114get_fs_root(global->fs, &gl_root);1115task_unlock(global);11161117int chrooted = !path_equal(&cr_root, &gl_root);1118path_put(&gl_root);1119path_put(&cr_root);11201121return (chrooted);1122}11231124/*1125* Attempt to unmount a snapshot by making a call to user space.1126* There is no assurance that this can or will succeed, is just a1127* best effort. In the case where it does fail, perhaps because1128* it's in use, the unmount will fail harmlessly.1129*/1130int1131zfsctl_snapshot_unmount(const char *snapname, int flags)1132{1133char *argv[] = { "/usr/bin/env", "umount", "-t", "zfs", "-n", NULL,1134NULL };1135char *envp[] = { NULL };1136zfs_snapentry_t *se;1137int error;11381139rw_enter(&zfs_snapshot_lock, RW_READER);1140if ((se = zfsctl_snapshot_find_by_name(snapname)) == NULL) {1141rw_exit(&zfs_snapshot_lock);1142return (SET_ERROR(ENOENT));1143}1144rw_exit(&zfs_snapshot_lock);11451146/*1147* Wait for any pending auto-mount to complete before unmounting.1148*/1149mutex_enter(&se->se_mtx);1150while (se->se_mounting)1151cv_wait(&se->se_cv, &se->se_mtx);1152mutex_exit(&se->se_mtx);11531154exportfs_flush();11551156if (flags & MNT_FORCE)1157argv[4] = "-fn";1158argv[5] = se->se_path;1159dprintf("unmount; path=%s\n", se->se_path);1160error = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);1161zfsctl_snapshot_rele(se);116211631164/*1165* The umount system utility will return 256 on error. We must1166* assume this error is because the file system is busy so it is1167* converted to the more sensible EBUSY.1168*/1169if (error)1170error = SET_ERROR(EBUSY);11711172return (error);1173}11741175int1176zfsctl_snapshot_mount(struct path *path, int flags)1177{1178struct dentry *dentry = path->dentry;1179struct inode *ip = dentry->d_inode;1180zfsvfs_t *zfsvfs;1181zfsvfs_t *snap_zfsvfs;1182zfs_snapentry_t *se;1183char *full_name, *full_path, *options;1184char *argv[] = { "/usr/bin/env", "mount", "-i", "-t", "zfs", "-n",1185"-o", NULL, NULL, NULL, NULL };1186char *envp[] = { NULL };1187int error;1188struct path spath;11891190if (ip == NULL)1191return (SET_ERROR(EISDIR));11921193zfsvfs = ITOZSB(ip);1194if ((error = zfs_enter(zfsvfs, FTAG)) != 0)1195return (error);11961197full_name = kmem_zalloc(ZFS_MAX_DATASET_NAME_LEN, KM_SLEEP);1198full_path = kmem_zalloc(MAXPATHLEN, KM_SLEEP);1199options = kmem_zalloc(7, KM_SLEEP);12001201error = zfsctl_snapshot_name(zfsvfs, dname(dentry),1202ZFS_MAX_DATASET_NAME_LEN, full_name);1203if (error)1204goto error;12051206if (is_current_chrooted() == 0) {1207/*1208* Current process is not in chroot context1209*/12101211char *m = kmem_zalloc(MAXPATHLEN, KM_SLEEP);1212struct path mnt_path;1213mnt_path.mnt = path->mnt;1214mnt_path.dentry = path->mnt->mnt_root;12151216/*1217* Get path to current mountpoint1218*/1219error = get_root_path(&mnt_path, m, MAXPATHLEN);1220if (error != 0) {1221kmem_free(m, MAXPATHLEN);1222goto error;1223}1224mutex_enter(&zfsvfs->z_vfs->vfs_mntpt_lock);1225if (zfsvfs->z_vfs->vfs_mntpoint != NULL) {1226/*1227* If current mnountpoint and vfs_mntpoint are not same,1228* store current mountpoint in vfs_mntpoint.1229*/1230if (strcmp(zfsvfs->z_vfs->vfs_mntpoint, m) != 0) {1231kmem_strfree(zfsvfs->z_vfs->vfs_mntpoint);1232zfsvfs->z_vfs->vfs_mntpoint = kmem_strdup(m);1233}1234} else1235zfsvfs->z_vfs->vfs_mntpoint = kmem_strdup(m);1236mutex_exit(&zfsvfs->z_vfs->vfs_mntpt_lock);1237kmem_free(m, MAXPATHLEN);1238}12391240/*1241* Construct a mount point path from sb of the ctldir inode and dirent1242* name, instead of from d_path(), so that chroot'd process doesn't fail1243* on mount.zfs(8).1244*/1245mutex_enter(&zfsvfs->z_vfs->vfs_mntpt_lock);1246snprintf(full_path, MAXPATHLEN, "%s/.zfs/snapshot/%s",1247zfsvfs->z_vfs->vfs_mntpoint ? zfsvfs->z_vfs->vfs_mntpoint : "",1248dname(dentry));1249mutex_exit(&zfsvfs->z_vfs->vfs_mntpt_lock);12501251snprintf(options, 7, "%s",1252zfs_snapshot_no_setuid ? "nosuid" : "suid");12531254/*1255* Check if snapshot is already being mounted. If found, wait for1256* pending mount to complete before returning success.1257*/1258rw_enter(&zfs_snapshot_lock, RW_WRITER);1259if ((se = zfsctl_snapshot_find_by_name(full_name)) != NULL) {1260rw_exit(&zfs_snapshot_lock);1261mutex_enter(&se->se_mtx);1262while (se->se_mounting)1263cv_wait(&se->se_cv, &se->se_mtx);12641265/*1266* Return the same error as the first mount attempt (0 if1267* succeeded, error code if failed).1268*/1269error = se->se_mount_error;1270mutex_exit(&se->se_mtx);1271zfsctl_snapshot_rele(se);1272goto error;1273}12741275/*1276* Create pending entry and mark mount in progress.1277*/1278se = zfsctl_snapshot_alloc(full_name, full_path, NULL, 0, NULL);1279se->se_mounting = B_TRUE;1280zfsctl_snapshot_add(se);1281zfsctl_snapshot_hold(se);1282rw_exit(&zfs_snapshot_lock);12831284/*1285* Attempt to mount the snapshot from user space. Normally this1286* would be done using the vfs_kern_mount() function, however that1287* function is marked GPL-only and cannot be used. On error we1288* careful to log the real error to the console and return EISDIR1289* to safely abort the automount. This should be very rare.1290*1291* If the user mode helper happens to return EBUSY, a concurrent1292* mount is already in progress in which case the error is ignored.1293* Take note that if the program was executed successfully the return1294* value from call_usermodehelper() will be (exitcode << 8 + signal).1295*/1296dprintf("mount; name=%s path=%s\n", full_name, full_path);1297argv[7] = options;1298argv[8] = full_name;1299argv[9] = full_path;1300error = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);1301if (error) {1302/*1303* Mount failed - cleanup pending entry and signal waiters.1304*/1305if (!(error & MOUNT_BUSY << 8)) {1306zfs_dbgmsg("Unable to automount %s error=%d",1307full_path, error);1308error = SET_ERROR(EISDIR);1309} else {1310/*1311* EBUSY, this could mean a concurrent mount, or the1312* snapshot has already been mounted at completely1313* different place. We return 0 so VFS will retry. For1314* the latter case the VFS will retry several times1315* and return ELOOP, which is probably not a very good1316* behavior.1317*/1318error = 0;1319}13201321rw_enter(&zfs_snapshot_lock, RW_WRITER);1322zfsctl_snapshot_remove(se);1323rw_exit(&zfs_snapshot_lock);1324mutex_enter(&se->se_mtx);1325se->se_mount_error = error;1326se->se_mounting = B_FALSE;1327cv_broadcast(&se->se_cv);1328mutex_exit(&se->se_mtx);1329zfsctl_snapshot_rele(se);1330goto error;1331}13321333/*1334* Follow down in to the mounted snapshot and set MNT_SHRINKABLE1335* to identify this as an automounted filesystem.1336*/1337spath = *path;1338path_get(&spath);1339if (follow_down_one(&spath)) {1340snap_zfsvfs = ITOZSB(spath.dentry->d_inode);1341snap_zfsvfs->z_parent = zfsvfs;1342dentry = spath.dentry;1343spath.mnt->mnt_flags |= MNT_SHRINKABLE;13441345rw_enter(&zfs_snapshot_lock, RW_WRITER);1346zfsctl_snapshot_fill(se, snap_zfsvfs->z_os->os_spa,1347dmu_objset_id(snap_zfsvfs->z_os), dentry);1348zfsctl_snapshot_unmount_delay_impl(se, zfs_expire_snapshot);1349rw_exit(&zfs_snapshot_lock);1350} else {1351rw_enter(&zfs_snapshot_lock, RW_WRITER);1352zfsctl_snapshot_remove(se);1353rw_exit(&zfs_snapshot_lock);1354}1355path_put(&spath);13561357/*1358* Signal mount completion and cleanup.1359*/1360mutex_enter(&se->se_mtx);1361se->se_mounting = B_FALSE;1362cv_broadcast(&se->se_cv);1363mutex_exit(&se->se_mtx);1364zfsctl_snapshot_rele(se);1365error:1366kmem_free(full_name, ZFS_MAX_DATASET_NAME_LEN);1367kmem_free(full_path, MAXPATHLEN);13681369zfs_exit(zfsvfs, FTAG);13701371return (error);1372}13731374/*1375* Get the snapdir inode from fid1376*/1377int1378zfsctl_snapdir_vget(struct super_block *sb, uint64_t objsetid, int gen,1379struct inode **ipp)1380{1381int error;1382struct path path;1383char *mnt;1384struct dentry *dentry;13851386mnt = kmem_alloc(MAXPATHLEN, KM_SLEEP);13871388error = zfsctl_snapshot_path_objset(sb->s_fs_info, objsetid,1389MAXPATHLEN, mnt);1390if (error)1391goto out;13921393/* Trigger automount */1394error = -kern_path(mnt, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &path);1395if (error)1396goto out;13971398path_put(&path);1399/*1400* Get the snapdir inode. Note, we don't want to use the above1401* path because it contains the root of the snapshot rather1402* than the snapdir.1403*/1404*ipp = ilookup(sb, ZFSCTL_INO_SNAPDIRS - objsetid);1405if (*ipp == NULL) {1406error = SET_ERROR(ENOENT);1407goto out;1408}14091410/* check gen, see zfsctl_snapdir_fid */1411dentry = d_obtain_alias(igrab(*ipp));1412if (gen != (!IS_ERR(dentry) && d_mountpoint(dentry))) {1413iput(*ipp);1414*ipp = NULL;1415error = SET_ERROR(ENOENT);1416}1417if (!IS_ERR(dentry))1418dput(dentry);1419out:1420kmem_free(mnt, MAXPATHLEN);1421return (error);1422}14231424int1425zfsctl_shares_lookup(struct inode *dip, char *name, struct inode **ipp,1426int flags, cred_t *cr, int *direntflags, pathname_t *realpnp)1427{1428zfsvfs_t *zfsvfs = ITOZSB(dip);1429znode_t *zp;1430znode_t *dzp;1431int error;14321433if ((error = zfs_enter(zfsvfs, FTAG)) != 0)1434return (error);14351436if (zfsvfs->z_shares_dir == 0) {1437zfs_exit(zfsvfs, FTAG);1438return (SET_ERROR(ENOTSUP));1439}14401441if ((error = zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp)) == 0) {1442error = zfs_lookup(dzp, name, &zp, 0, cr, NULL, NULL);1443zrele(dzp);1444}14451446zfs_exit(zfsvfs, FTAG);14471448return (error);1449}14501451/*1452* Initialize the various pieces we'll need to create and manipulate .zfs1453* directories. Currently this is unused but available.1454*/1455void1456zfsctl_init(void)1457{1458avl_create(&zfs_snapshots_by_name, snapentry_compare_by_name,1459sizeof (zfs_snapentry_t), offsetof(zfs_snapentry_t,1460se_node_name));1461avl_create(&zfs_snapshots_by_objsetid, snapentry_compare_by_objsetid,1462sizeof (zfs_snapentry_t), offsetof(zfs_snapentry_t,1463se_node_objsetid));1464rw_init(&zfs_snapshot_lock, NULL, RW_DEFAULT, NULL);1465}14661467/*1468* Cleanup the various pieces we needed for .zfs directories. In particular1469* ensure the expiry timer is canceled safely.1470*/1471void1472zfsctl_fini(void)1473{1474avl_destroy(&zfs_snapshots_by_name);1475avl_destroy(&zfs_snapshots_by_objsetid);1476rw_destroy(&zfs_snapshot_lock);1477}14781479module_param(zfs_admin_snapshot, int, 0644);1480MODULE_PARM_DESC(zfs_admin_snapshot, "Enable mkdir/rmdir/mv in .zfs/snapshot");14811482module_param(zfs_expire_snapshot, int, 0644);1483MODULE_PARM_DESC(zfs_expire_snapshot, "Seconds to expire .zfs/snapshot");14841485module_param(zfs_snapshot_no_setuid, int, 0644);1486MODULE_PARM_DESC(zfs_snapshot_no_setuid,1487"Disable setuid/setgid for automounts in .zfs/snapshot");148814891490