1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 51512Sek110237 * Common Development and Distribution License (the "License"). 61512Sek110237 * You may not use this file except in compliance with the License. 7789Sahrens * 8789Sahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9789Sahrens * or http://www.opensolaris.org/os/licensing. 10789Sahrens * See the License for the specific language governing permissions 11789Sahrens * and limitations under the License. 12789Sahrens * 13789Sahrens * When distributing Covered Code, include this CDDL HEADER in each 14789Sahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15789Sahrens * If applicable, add the following below this CDDL HEADER, with the 16789Sahrens * fields enclosed by brackets "[]" replaced with your own identifying 17789Sahrens * information: Portions Copyright [yyyy] [name of copyright owner] 18789Sahrens * 19789Sahrens * CDDL HEADER END 20789Sahrens */ 21789Sahrens /* 223898Srsb * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23789Sahrens * Use is subject to license terms. 24789Sahrens */ 25789Sahrens 26789Sahrens #pragma ident "%Z%%M% %I% %E% SMI" 27789Sahrens 28789Sahrens /* 29789Sahrens * ZFS control directory (a.k.a. ".zfs") 30789Sahrens * 31789Sahrens * This directory provides a common location for all ZFS meta-objects. 32789Sahrens * Currently, this is only the 'snapshot' directory, but this may expand in the 33789Sahrens * future. The elements are built using the GFS primitives, as the hierarchy 34789Sahrens * does not actually exist on disk. 35789Sahrens * 36789Sahrens * For 'snapshot', we don't want to have all snapshots always mounted, because 37789Sahrens * this would take up a huge amount of space in /etc/mnttab. We have three 38789Sahrens * types of objects: 39789Sahrens * 40789Sahrens * ctldir ------> snapshotdir -------> snapshot 41789Sahrens * | 42789Sahrens * | 43789Sahrens * V 44789Sahrens * mounted fs 45789Sahrens * 46789Sahrens * The 'snapshot' node contains just enough information to lookup '..' and act 47789Sahrens * as a mountpoint for the snapshot. Whenever we lookup a specific snapshot, we 48789Sahrens * perform an automount of the underlying filesystem and return the 49789Sahrens * corresponding vnode. 50789Sahrens * 51789Sahrens * All mounts are handled automatically by the kernel, but unmounts are 52789Sahrens * (currently) handled from user land. The main reason is that there is no 53789Sahrens * reliable way to auto-unmount the filesystem when it's "no longer in use". 54789Sahrens * When the user unmounts a filesystem, we call zfsctl_unmount(), which 55789Sahrens * unmounts any snapshots within the snapshot directory. 565326Sek110237 * 575326Sek110237 * The '.zfs', '.zfs/snapshot', and all directories created under 585326Sek110237 * '.zfs/snapshot' (ie: '.zfs/snapshot/<snapname>') are all GFS nodes and 595326Sek110237 * share the same vfs_t as the head filesystem (what '.zfs' lives under). 605326Sek110237 * 615326Sek110237 * File systems mounted ontop of the GFS nodes '.zfs/snapshot/<snapname>' 625326Sek110237 * (ie: snapshots) are ZFS nodes and have their own unique vfs_t. 635326Sek110237 * However, vnodes within these mounted on file systems have their v_vfsp 645326Sek110237 * fields set to the head filesystem to make NFS happy (see 655326Sek110237 * zfsctl_snapdir_lookup()). 66789Sahrens */ 67789Sahrens 68789Sahrens #include <fs/fs_subr.h> 69789Sahrens #include <sys/zfs_ctldir.h> 70789Sahrens #include <sys/zfs_ioctl.h> 71789Sahrens #include <sys/zfs_vfsops.h> 723898Srsb #include <sys/vfs_opreg.h> 73789Sahrens #include <sys/gfs.h> 74789Sahrens #include <sys/stat.h> 75789Sahrens #include <sys/dmu.h> 764543Smarks #include <sys/dsl_deleg.h> 77789Sahrens #include <sys/mount.h> 78789Sahrens 79789Sahrens typedef struct { 80789Sahrens char *se_name; 81789Sahrens vnode_t *se_root; 82789Sahrens avl_node_t se_node; 83789Sahrens } zfs_snapentry_t; 84789Sahrens 85789Sahrens static int 86789Sahrens snapentry_compare(const void *a, const void *b) 87789Sahrens { 88789Sahrens const zfs_snapentry_t *sa = a; 89789Sahrens const zfs_snapentry_t *sb = b; 90789Sahrens int ret = strcmp(sa->se_name, sb->se_name); 91789Sahrens 92789Sahrens if (ret < 0) 93789Sahrens return (-1); 94789Sahrens else if (ret > 0) 95789Sahrens return (1); 96789Sahrens else 97789Sahrens return (0); 98789Sahrens } 99789Sahrens 100789Sahrens vnodeops_t *zfsctl_ops_root; 101789Sahrens vnodeops_t *zfsctl_ops_snapdir; 102789Sahrens vnodeops_t *zfsctl_ops_snapshot; 103789Sahrens 104789Sahrens static const fs_operation_def_t zfsctl_tops_root[]; 105789Sahrens static const fs_operation_def_t zfsctl_tops_snapdir[]; 106789Sahrens static const fs_operation_def_t zfsctl_tops_snapshot[]; 107789Sahrens 108789Sahrens static vnode_t *zfsctl_mknode_snapdir(vnode_t *); 109789Sahrens static vnode_t *zfsctl_snapshot_mknode(vnode_t *, uint64_t objset); 110789Sahrens 111789Sahrens static gfs_opsvec_t zfsctl_opsvec[] = { 112789Sahrens { ".zfs", zfsctl_tops_root, &zfsctl_ops_root }, 113789Sahrens { ".zfs/snapshot", zfsctl_tops_snapdir, &zfsctl_ops_snapdir }, 114789Sahrens { ".zfs/snapshot/vnode", zfsctl_tops_snapshot, &zfsctl_ops_snapshot }, 115789Sahrens { NULL } 116789Sahrens }; 117789Sahrens 118789Sahrens typedef struct zfsctl_node { 119789Sahrens gfs_dir_t zc_gfs_private; 120789Sahrens uint64_t zc_id; 1211571Sek110237 timestruc_t zc_cmtime; /* ctime and mtime, always the same */ 122789Sahrens } zfsctl_node_t; 123789Sahrens 124789Sahrens typedef struct zfsctl_snapdir { 125789Sahrens zfsctl_node_t sd_node; 126789Sahrens kmutex_t sd_lock; 127789Sahrens avl_tree_t sd_snaps; 128789Sahrens } zfsctl_snapdir_t; 129789Sahrens 130789Sahrens /* 131789Sahrens * Root directory elements. We have only a single static entry, 'snapshot'. 132789Sahrens */ 133789Sahrens static gfs_dirent_t zfsctl_root_entries[] = { 134789Sahrens { "snapshot", zfsctl_mknode_snapdir, GFS_CACHE_VNODE }, 135789Sahrens { NULL } 136789Sahrens }; 137789Sahrens 138789Sahrens /* include . and .. in the calculation */ 139789Sahrens #define NROOT_ENTRIES ((sizeof (zfsctl_root_entries) / \ 140789Sahrens sizeof (gfs_dirent_t)) + 1) 141789Sahrens 142789Sahrens 143789Sahrens /* 144789Sahrens * Initialize the various GFS pieces we'll need to create and manipulate .zfs 145789Sahrens * directories. This is called from the ZFS init routine, and initializes the 146789Sahrens * vnode ops vectors that we'll be using. 147789Sahrens */ 148789Sahrens void 149789Sahrens zfsctl_init(void) 150789Sahrens { 151789Sahrens VERIFY(gfs_make_opsvec(zfsctl_opsvec) == 0); 152789Sahrens } 153789Sahrens 154789Sahrens void 155789Sahrens zfsctl_fini(void) 156789Sahrens { 157789Sahrens /* 158789Sahrens * Remove vfsctl vnode ops 159789Sahrens */ 160789Sahrens if (zfsctl_ops_root) 161789Sahrens vn_freevnodeops(zfsctl_ops_root); 162789Sahrens if (zfsctl_ops_snapdir) 163789Sahrens vn_freevnodeops(zfsctl_ops_snapdir); 164789Sahrens if (zfsctl_ops_snapshot) 165789Sahrens vn_freevnodeops(zfsctl_ops_snapshot); 166789Sahrens 167789Sahrens zfsctl_ops_root = NULL; 168789Sahrens zfsctl_ops_snapdir = NULL; 169789Sahrens zfsctl_ops_snapshot = NULL; 170789Sahrens } 171789Sahrens 172789Sahrens /* 173789Sahrens * Return the inode number associated with the 'snapshot' directory. 174789Sahrens */ 175789Sahrens /* ARGSUSED */ 176789Sahrens static ino64_t 177789Sahrens zfsctl_root_inode_cb(vnode_t *vp, int index) 178789Sahrens { 179789Sahrens ASSERT(index == 0); 180789Sahrens return (ZFSCTL_INO_SNAPDIR); 181789Sahrens } 182789Sahrens 183789Sahrens /* 184789Sahrens * Create the '.zfs' directory. This directory is cached as part of the VFS 185789Sahrens * structure. This results in a hold on the vfs_t. The code in zfs_umount() 186789Sahrens * therefore checks against a vfs_count of 2 instead of 1. This reference 187789Sahrens * is removed when the ctldir is destroyed in the unmount. 188789Sahrens */ 189789Sahrens void 190789Sahrens zfsctl_create(zfsvfs_t *zfsvfs) 191789Sahrens { 1921571Sek110237 vnode_t *vp, *rvp; 193789Sahrens zfsctl_node_t *zcp; 194789Sahrens 195789Sahrens ASSERT(zfsvfs->z_ctldir == NULL); 196789Sahrens 197789Sahrens vp = gfs_root_create(sizeof (zfsctl_node_t), zfsvfs->z_vfs, 198789Sahrens zfsctl_ops_root, ZFSCTL_INO_ROOT, zfsctl_root_entries, 199789Sahrens zfsctl_root_inode_cb, MAXNAMELEN, NULL, NULL); 200789Sahrens zcp = vp->v_data; 201789Sahrens zcp->zc_id = ZFSCTL_INO_ROOT; 202789Sahrens 2031571Sek110237 VERIFY(VFS_ROOT(zfsvfs->z_vfs, &rvp) == 0); 2041571Sek110237 ZFS_TIME_DECODE(&zcp->zc_cmtime, VTOZ(rvp)->z_phys->zp_crtime); 2051571Sek110237 VN_RELE(rvp); 2061571Sek110237 207789Sahrens /* 208789Sahrens * We're only faking the fact that we have a root of a filesystem for 209789Sahrens * the sake of the GFS interfaces. Undo the flag manipulation it did 210789Sahrens * for us. 211789Sahrens */ 212789Sahrens vp->v_flag &= ~(VROOT | VNOCACHE | VNOMAP | VNOSWAP | VNOMOUNT); 213789Sahrens 214789Sahrens zfsvfs->z_ctldir = vp; 215789Sahrens } 216789Sahrens 217789Sahrens /* 2181298Sperrin * Destroy the '.zfs' directory. Only called when the filesystem is unmounted. 2191298Sperrin * There might still be more references if we were force unmounted, but only 2201298Sperrin * new zfs_inactive() calls can occur and they don't reference .zfs 221789Sahrens */ 222789Sahrens void 223789Sahrens zfsctl_destroy(zfsvfs_t *zfsvfs) 224789Sahrens { 225789Sahrens VN_RELE(zfsvfs->z_ctldir); 226789Sahrens zfsvfs->z_ctldir = NULL; 227789Sahrens } 228789Sahrens 229789Sahrens /* 230789Sahrens * Given a root znode, retrieve the associated .zfs directory. 231789Sahrens * Add a hold to the vnode and return it. 232789Sahrens */ 233789Sahrens vnode_t * 234789Sahrens zfsctl_root(znode_t *zp) 235789Sahrens { 236789Sahrens ASSERT(zfs_has_ctldir(zp)); 237789Sahrens VN_HOLD(zp->z_zfsvfs->z_ctldir); 238789Sahrens return (zp->z_zfsvfs->z_ctldir); 239789Sahrens } 240789Sahrens 241789Sahrens /* 242789Sahrens * Common open routine. Disallow any write access. 243789Sahrens */ 244789Sahrens /* ARGSUSED */ 245789Sahrens static int 246*5331Samw zfsctl_common_open(vnode_t **vpp, int flags, cred_t *cr, caller_context_t *ct) 247789Sahrens { 248789Sahrens if (flags & FWRITE) 249789Sahrens return (EACCES); 250789Sahrens 251789Sahrens return (0); 252789Sahrens } 253789Sahrens 254789Sahrens /* 255789Sahrens * Common close routine. Nothing to do here. 256789Sahrens */ 257789Sahrens /* ARGSUSED */ 258789Sahrens static int 259789Sahrens zfsctl_common_close(vnode_t *vpp, int flags, int count, offset_t off, 260*5331Samw cred_t *cr, caller_context_t *ct) 261789Sahrens { 262789Sahrens return (0); 263789Sahrens } 264789Sahrens 265789Sahrens /* 266789Sahrens * Common access routine. Disallow writes. 267789Sahrens */ 268789Sahrens /* ARGSUSED */ 269789Sahrens static int 270*5331Samw zfsctl_common_access(vnode_t *vp, int mode, int flags, cred_t *cr, 271*5331Samw caller_context_t *ct) 272789Sahrens { 273789Sahrens if (mode & VWRITE) 274789Sahrens return (EACCES); 275789Sahrens 276789Sahrens return (0); 277789Sahrens } 278789Sahrens 279789Sahrens /* 280789Sahrens * Common getattr function. Fill in basic information. 281789Sahrens */ 282789Sahrens static void 283789Sahrens zfsctl_common_getattr(vnode_t *vp, vattr_t *vap) 284789Sahrens { 2851571Sek110237 zfsctl_node_t *zcp = vp->v_data; 2861571Sek110237 timestruc_t now; 287789Sahrens 288789Sahrens vap->va_uid = 0; 289789Sahrens vap->va_gid = 0; 290789Sahrens vap->va_rdev = 0; 291789Sahrens /* 292789Sahrens * We are a purly virtual object, so we have no 293789Sahrens * blocksize or allocated blocks. 294789Sahrens */ 295789Sahrens vap->va_blksize = 0; 296789Sahrens vap->va_nblocks = 0; 297789Sahrens vap->va_seq = 0; 298789Sahrens vap->va_fsid = vp->v_vfsp->vfs_dev; 299789Sahrens vap->va_mode = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | 300789Sahrens S_IROTH | S_IXOTH; 301789Sahrens vap->va_type = VDIR; 302789Sahrens /* 3031571Sek110237 * We live in the now (for atime). 304789Sahrens */ 305789Sahrens gethrestime(&now); 3061571Sek110237 vap->va_atime = now; 3071571Sek110237 vap->va_mtime = vap->va_ctime = zcp->zc_cmtime; 308789Sahrens } 309789Sahrens 310*5331Samw /*ARGSUSED*/ 311789Sahrens static int 312*5331Samw zfsctl_common_fid(vnode_t *vp, fid_t *fidp, caller_context_t *ct) 313789Sahrens { 314789Sahrens zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data; 315789Sahrens zfsctl_node_t *zcp = vp->v_data; 316789Sahrens uint64_t object = zcp->zc_id; 317789Sahrens zfid_short_t *zfid; 318789Sahrens int i; 319789Sahrens 320789Sahrens ZFS_ENTER(zfsvfs); 321789Sahrens 322789Sahrens if (fidp->fid_len < SHORT_FID_LEN) { 323789Sahrens fidp->fid_len = SHORT_FID_LEN; 3241512Sek110237 ZFS_EXIT(zfsvfs); 325789Sahrens return (ENOSPC); 326789Sahrens } 327789Sahrens 328789Sahrens zfid = (zfid_short_t *)fidp; 329789Sahrens 330789Sahrens zfid->zf_len = SHORT_FID_LEN; 331789Sahrens 332789Sahrens for (i = 0; i < sizeof (zfid->zf_object); i++) 333789Sahrens zfid->zf_object[i] = (uint8_t)(object >> (8 * i)); 334789Sahrens 335789Sahrens /* .zfs znodes always have a generation number of 0 */ 336789Sahrens for (i = 0; i < sizeof (zfid->zf_gen); i++) 337789Sahrens zfid->zf_gen[i] = 0; 338789Sahrens 339789Sahrens ZFS_EXIT(zfsvfs); 340789Sahrens return (0); 341789Sahrens } 342789Sahrens 343789Sahrens /* 344789Sahrens * .zfs inode namespace 345789Sahrens * 346789Sahrens * We need to generate unique inode numbers for all files and directories 347789Sahrens * within the .zfs pseudo-filesystem. We use the following scheme: 348789Sahrens * 349789Sahrens * ENTRY ZFSCTL_INODE 350789Sahrens * .zfs 1 351789Sahrens * .zfs/snapshot 2 352789Sahrens * .zfs/snapshot/<snap> objectid(snap) 353789Sahrens */ 354789Sahrens 355789Sahrens #define ZFSCTL_INO_SNAP(id) (id) 356789Sahrens 357789Sahrens /* 358789Sahrens * Get root directory attributes. 359789Sahrens */ 360789Sahrens /* ARGSUSED */ 361789Sahrens static int 362*5331Samw zfsctl_root_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, 363*5331Samw caller_context_t *ct) 364789Sahrens { 365789Sahrens zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data; 366789Sahrens 367789Sahrens ZFS_ENTER(zfsvfs); 368789Sahrens vap->va_nodeid = ZFSCTL_INO_ROOT; 369789Sahrens vap->va_nlink = vap->va_size = NROOT_ENTRIES; 370789Sahrens 371789Sahrens zfsctl_common_getattr(vp, vap); 372789Sahrens ZFS_EXIT(zfsvfs); 373789Sahrens 374789Sahrens return (0); 375789Sahrens } 376789Sahrens 377789Sahrens /* 378789Sahrens * Special case the handling of "..". 379789Sahrens */ 380789Sahrens /* ARGSUSED */ 381789Sahrens int 382789Sahrens zfsctl_root_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp, 383*5331Samw int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct, 384*5331Samw int *direntflags, pathname_t *realpnp) 385789Sahrens { 386789Sahrens zfsvfs_t *zfsvfs = dvp->v_vfsp->vfs_data; 387789Sahrens int err; 388789Sahrens 389*5331Samw /* 390*5331Samw * No extended attributes allowed under .zfs 391*5331Samw */ 392*5331Samw if (flags & LOOKUP_XATTR) 393*5331Samw return (EINVAL); 394*5331Samw 395789Sahrens ZFS_ENTER(zfsvfs); 396789Sahrens 397789Sahrens if (strcmp(nm, "..") == 0) { 398789Sahrens err = VFS_ROOT(dvp->v_vfsp, vpp); 399789Sahrens } else { 400*5331Samw err = gfs_dir_lookup(dvp, nm, vpp, cr); 401789Sahrens } 402789Sahrens 403789Sahrens ZFS_EXIT(zfsvfs); 404789Sahrens 405789Sahrens return (err); 406789Sahrens } 407789Sahrens 408789Sahrens static const fs_operation_def_t zfsctl_tops_root[] = { 4093898Srsb { VOPNAME_OPEN, { .vop_open = zfsctl_common_open } }, 4103898Srsb { VOPNAME_CLOSE, { .vop_close = zfsctl_common_close } }, 4113898Srsb { VOPNAME_IOCTL, { .error = fs_inval } }, 4123898Srsb { VOPNAME_GETATTR, { .vop_getattr = zfsctl_root_getattr } }, 4133898Srsb { VOPNAME_ACCESS, { .vop_access = zfsctl_common_access } }, 4143898Srsb { VOPNAME_READDIR, { .vop_readdir = gfs_vop_readdir } }, 4153898Srsb { VOPNAME_LOOKUP, { .vop_lookup = zfsctl_root_lookup } }, 4163898Srsb { VOPNAME_SEEK, { .vop_seek = fs_seek } }, 4173898Srsb { VOPNAME_INACTIVE, { .vop_inactive = gfs_vop_inactive } }, 4183898Srsb { VOPNAME_FID, { .vop_fid = zfsctl_common_fid } }, 419789Sahrens { NULL } 420789Sahrens }; 421789Sahrens 422789Sahrens static int 423789Sahrens zfsctl_snapshot_zname(vnode_t *vp, const char *name, int len, char *zname) 424789Sahrens { 425789Sahrens objset_t *os = ((zfsvfs_t *)((vp)->v_vfsp->vfs_data))->z_os; 426789Sahrens 427789Sahrens dmu_objset_name(os, zname); 4281154Smaybee if (strlen(zname) + 1 + strlen(name) >= len) 4291154Smaybee return (ENAMETOOLONG); 430789Sahrens (void) strcat(zname, "@"); 431789Sahrens (void) strcat(zname, name); 432789Sahrens return (0); 433789Sahrens } 434789Sahrens 4354543Smarks int 436789Sahrens zfsctl_unmount_snap(vnode_t *dvp, const char *name, int force, cred_t *cr) 437789Sahrens { 438789Sahrens zfsctl_snapdir_t *sdp = dvp->v_data; 439789Sahrens zfs_snapentry_t search, *sep; 440789Sahrens avl_index_t where; 441789Sahrens int err; 442789Sahrens 443789Sahrens ASSERT(MUTEX_HELD(&sdp->sd_lock)); 444789Sahrens 445789Sahrens search.se_name = (char *)name; 446789Sahrens if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) == NULL) 447789Sahrens return (ENOENT); 448789Sahrens 449789Sahrens ASSERT(vn_ismntpt(sep->se_root)); 450789Sahrens 451789Sahrens /* this will be dropped by dounmount() */ 452789Sahrens if ((err = vn_vfswlock(sep->se_root)) != 0) 453789Sahrens return (err); 454789Sahrens 455789Sahrens VN_HOLD(sep->se_root); 4561589Smaybee err = dounmount(vn_mountedvfs(sep->se_root), force, kcred); 4571589Smaybee if (err) { 4581589Smaybee VN_RELE(sep->se_root); 459789Sahrens return (err); 4601589Smaybee } 461789Sahrens ASSERT(sep->se_root->v_count == 1); 462*5331Samw gfs_vop_inactive(sep->se_root, cr, NULL); 463789Sahrens 464789Sahrens avl_remove(&sdp->sd_snaps, sep); 465789Sahrens kmem_free(sep->se_name, strlen(sep->se_name) + 1); 466789Sahrens kmem_free(sep, sizeof (zfs_snapentry_t)); 467789Sahrens 468789Sahrens return (0); 469789Sahrens } 470789Sahrens 471789Sahrens 4721154Smaybee static void 473789Sahrens zfsctl_rename_snap(zfsctl_snapdir_t *sdp, zfs_snapentry_t *sep, const char *nm) 474789Sahrens { 475789Sahrens avl_index_t where; 476789Sahrens vfs_t *vfsp; 477789Sahrens refstr_t *pathref; 478789Sahrens char newpath[MAXNAMELEN]; 479789Sahrens char *tail; 480789Sahrens 481789Sahrens ASSERT(MUTEX_HELD(&sdp->sd_lock)); 482789Sahrens ASSERT(sep != NULL); 483789Sahrens 484789Sahrens vfsp = vn_mountedvfs(sep->se_root); 485789Sahrens ASSERT(vfsp != NULL); 486789Sahrens 4871154Smaybee vfs_lock_wait(vfsp); 488789Sahrens 489789Sahrens /* 490789Sahrens * Change the name in the AVL tree. 491789Sahrens */ 492789Sahrens avl_remove(&sdp->sd_snaps, sep); 493789Sahrens kmem_free(sep->se_name, strlen(sep->se_name) + 1); 494789Sahrens sep->se_name = kmem_alloc(strlen(nm) + 1, KM_SLEEP); 495789Sahrens (void) strcpy(sep->se_name, nm); 496789Sahrens VERIFY(avl_find(&sdp->sd_snaps, sep, &where) == NULL); 497789Sahrens avl_insert(&sdp->sd_snaps, sep, where); 498789Sahrens 499789Sahrens /* 500789Sahrens * Change the current mountpoint info: 501789Sahrens * - update the tail of the mntpoint path 502789Sahrens * - update the tail of the resource path 503789Sahrens */ 504789Sahrens pathref = vfs_getmntpoint(vfsp); 5052417Sahrens (void) strncpy(newpath, refstr_value(pathref), sizeof (newpath)); 5062417Sahrens VERIFY((tail = strrchr(newpath, '/')) != NULL); 5072417Sahrens *(tail+1) = '\0'; 5082417Sahrens ASSERT3U(strlen(newpath) + strlen(nm), <, sizeof (newpath)); 509789Sahrens (void) strcat(newpath, nm); 510789Sahrens refstr_rele(pathref); 511789Sahrens vfs_setmntpoint(vfsp, newpath); 512789Sahrens 513789Sahrens pathref = vfs_getresource(vfsp); 5142417Sahrens (void) strncpy(newpath, refstr_value(pathref), sizeof (newpath)); 5152417Sahrens VERIFY((tail = strrchr(newpath, '@')) != NULL); 5162417Sahrens *(tail+1) = '\0'; 5172417Sahrens ASSERT3U(strlen(newpath) + strlen(nm), <, sizeof (newpath)); 518789Sahrens (void) strcat(newpath, nm); 519789Sahrens refstr_rele(pathref); 520789Sahrens vfs_setresource(vfsp, newpath); 521789Sahrens 522789Sahrens vfs_unlock(vfsp); 523789Sahrens } 524789Sahrens 525*5331Samw /*ARGSUSED*/ 526789Sahrens static int 527789Sahrens zfsctl_snapdir_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, 528*5331Samw cred_t *cr, caller_context_t *ct, int flags) 529789Sahrens { 530789Sahrens zfsctl_snapdir_t *sdp = sdvp->v_data; 531789Sahrens zfs_snapentry_t search, *sep; 532789Sahrens avl_index_t where; 533789Sahrens char from[MAXNAMELEN], to[MAXNAMELEN]; 534789Sahrens int err; 535789Sahrens 5361154Smaybee err = zfsctl_snapshot_zname(sdvp, snm, MAXNAMELEN, from); 5371154Smaybee if (err) 5381154Smaybee return (err); 5394543Smarks 5404543Smarks err = zfsctl_snapshot_zname(tdvp, tnm, MAXNAMELEN, to); 541789Sahrens if (err) 542789Sahrens return (err); 543789Sahrens 5444543Smarks if (err = zfs_secpolicy_rename_perms(from, to, cr)) 5454543Smarks return (err); 546789Sahrens /* 547789Sahrens * Cannot move snapshots out of the snapdir. 548789Sahrens */ 549789Sahrens if (sdvp != tdvp) 550789Sahrens return (EINVAL); 551789Sahrens 552789Sahrens if (strcmp(snm, tnm) == 0) 553789Sahrens return (0); 554789Sahrens 555789Sahrens mutex_enter(&sdp->sd_lock); 556789Sahrens 557789Sahrens search.se_name = (char *)snm; 5581154Smaybee if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) == NULL) { 5591154Smaybee mutex_exit(&sdp->sd_lock); 5601154Smaybee return (ENOENT); 561789Sahrens } 562789Sahrens 5634007Smmusante err = dmu_objset_rename(from, to, B_FALSE); 5641154Smaybee if (err == 0) 5651154Smaybee zfsctl_rename_snap(sdp, sep, tnm); 566789Sahrens 567789Sahrens mutex_exit(&sdp->sd_lock); 568789Sahrens 569789Sahrens return (err); 570789Sahrens } 571789Sahrens 572789Sahrens /* ARGSUSED */ 573789Sahrens static int 574*5331Samw zfsctl_snapdir_remove(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr, 575*5331Samw caller_context_t *ct, int flags) 576789Sahrens { 577789Sahrens zfsctl_snapdir_t *sdp = dvp->v_data; 578789Sahrens char snapname[MAXNAMELEN]; 579789Sahrens int err; 580789Sahrens 5811154Smaybee err = zfsctl_snapshot_zname(dvp, name, MAXNAMELEN, snapname); 5821154Smaybee if (err) 5831154Smaybee return (err); 5844543Smarks 5854543Smarks if (err = zfs_secpolicy_destroy_perms(snapname, cr)) 586789Sahrens return (err); 587789Sahrens 588789Sahrens mutex_enter(&sdp->sd_lock); 589789Sahrens 5904543Smarks err = zfsctl_unmount_snap(dvp, name, MS_FORCE, cr); 591789Sahrens if (err) { 592789Sahrens mutex_exit(&sdp->sd_lock); 593789Sahrens return (err); 594789Sahrens } 595789Sahrens 596789Sahrens err = dmu_objset_destroy(snapname); 597789Sahrens 598789Sahrens mutex_exit(&sdp->sd_lock); 599789Sahrens 600789Sahrens return (err); 601789Sahrens } 602789Sahrens 6035326Sek110237 /* 6045326Sek110237 * This creates a snapshot under '.zfs/snapshot'. 6055326Sek110237 */ 6064543Smarks /* ARGSUSED */ 6074543Smarks static int 6084543Smarks zfsctl_snapdir_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp, 609*5331Samw cred_t *cr, caller_context_t *cc, int flags, vsecattr_t *vsecp) 6104543Smarks { 6114543Smarks zfsvfs_t *zfsvfs = dvp->v_vfsp->vfs_data; 6124543Smarks char name[MAXNAMELEN]; 6134543Smarks int err; 6144543Smarks static enum symfollow follow = NO_FOLLOW; 6154543Smarks static enum uio_seg seg = UIO_SYSSPACE; 6164543Smarks 6174543Smarks dmu_objset_name(zfsvfs->z_os, name); 6184543Smarks 6194543Smarks *vpp = NULL; 6204543Smarks 6214543Smarks err = zfs_secpolicy_snapshot_perms(name, cr); 6224543Smarks if (err) 6234543Smarks return (err); 6244543Smarks 6254543Smarks if (err == 0) { 6264543Smarks err = dmu_objset_snapshot(name, dirname, B_FALSE); 6274543Smarks if (err) 6284543Smarks return (err); 6294543Smarks err = lookupnameat(dirname, seg, follow, NULL, vpp, dvp); 6304543Smarks } 6314543Smarks 6324543Smarks return (err); 6334543Smarks } 6344543Smarks 635789Sahrens /* 636789Sahrens * Lookup entry point for the 'snapshot' directory. Try to open the 637789Sahrens * snapshot if it exist, creating the pseudo filesystem vnode as necessary. 638789Sahrens * Perform a mount of the associated dataset on top of the vnode. 639789Sahrens */ 640789Sahrens /* ARGSUSED */ 641789Sahrens static int 642789Sahrens zfsctl_snapdir_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp, 643*5331Samw int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct, 644*5331Samw int *direntflags, pathname_t *realpnp) 645789Sahrens { 646789Sahrens zfsctl_snapdir_t *sdp = dvp->v_data; 647789Sahrens objset_t *snap; 648789Sahrens char snapname[MAXNAMELEN]; 649789Sahrens char *mountpoint; 650789Sahrens zfs_snapentry_t *sep, search; 651789Sahrens struct mounta margs; 652789Sahrens vfs_t *vfsp; 653789Sahrens size_t mountpoint_len; 654789Sahrens avl_index_t where; 655789Sahrens zfsvfs_t *zfsvfs = dvp->v_vfsp->vfs_data; 656789Sahrens int err; 657789Sahrens 658*5331Samw /* 659*5331Samw * No extended attributes allowed under .zfs 660*5331Samw */ 661*5331Samw if (flags & LOOKUP_XATTR) 662*5331Samw return (EINVAL); 663*5331Samw 664789Sahrens ASSERT(dvp->v_type == VDIR); 665789Sahrens 666789Sahrens if (gfs_lookup_dot(vpp, dvp, zfsvfs->z_ctldir, nm) == 0) 667789Sahrens return (0); 668789Sahrens 669789Sahrens /* 670789Sahrens * If we get a recursive call, that means we got called 671789Sahrens * from the domount() code while it was trying to look up the 672789Sahrens * spec (which looks like a local path for zfs). We need to 673789Sahrens * add some flag to domount() to tell it not to do this lookup. 674789Sahrens */ 675789Sahrens if (MUTEX_HELD(&sdp->sd_lock)) 676789Sahrens return (ENOENT); 677789Sahrens 678789Sahrens ZFS_ENTER(zfsvfs); 679789Sahrens 680789Sahrens mutex_enter(&sdp->sd_lock); 681789Sahrens search.se_name = (char *)nm; 682789Sahrens if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) != NULL) { 683789Sahrens *vpp = sep->se_root; 684789Sahrens VN_HOLD(*vpp); 6851589Smaybee err = traverse(vpp); 6861589Smaybee if (err) { 6871589Smaybee VN_RELE(*vpp); 6881589Smaybee *vpp = NULL; 6891589Smaybee } else if (*vpp == sep->se_root) { 6901589Smaybee /* 6911589Smaybee * The snapshot was unmounted behind our backs, 6921589Smaybee * try to remount it. 6931589Smaybee */ 694789Sahrens goto domount; 6951566Smaybee } 696789Sahrens mutex_exit(&sdp->sd_lock); 697789Sahrens ZFS_EXIT(zfsvfs); 6981589Smaybee return (err); 699789Sahrens } 700789Sahrens 701789Sahrens /* 702789Sahrens * The requested snapshot is not currently mounted, look it up. 703789Sahrens */ 7041154Smaybee err = zfsctl_snapshot_zname(dvp, nm, MAXNAMELEN, snapname); 7051154Smaybee if (err) { 7061154Smaybee mutex_exit(&sdp->sd_lock); 7071154Smaybee ZFS_EXIT(zfsvfs); 7081154Smaybee return (err); 7091154Smaybee } 710789Sahrens if (dmu_objset_open(snapname, DMU_OST_ZFS, 711789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &snap) != 0) { 712789Sahrens mutex_exit(&sdp->sd_lock); 713789Sahrens ZFS_EXIT(zfsvfs); 714789Sahrens return (ENOENT); 715789Sahrens } 716789Sahrens 717789Sahrens sep = kmem_alloc(sizeof (zfs_snapentry_t), KM_SLEEP); 718789Sahrens sep->se_name = kmem_alloc(strlen(nm) + 1, KM_SLEEP); 719789Sahrens (void) strcpy(sep->se_name, nm); 720789Sahrens *vpp = sep->se_root = zfsctl_snapshot_mknode(dvp, dmu_objset_id(snap)); 721789Sahrens avl_insert(&sdp->sd_snaps, sep, where); 722789Sahrens 723789Sahrens dmu_objset_close(snap); 724789Sahrens domount: 725789Sahrens mountpoint_len = strlen(refstr_value(dvp->v_vfsp->vfs_mntpt)) + 726789Sahrens strlen("/.zfs/snapshot/") + strlen(nm) + 1; 727789Sahrens mountpoint = kmem_alloc(mountpoint_len, KM_SLEEP); 728789Sahrens (void) snprintf(mountpoint, mountpoint_len, "%s/.zfs/snapshot/%s", 729789Sahrens refstr_value(dvp->v_vfsp->vfs_mntpt), nm); 730789Sahrens 731789Sahrens margs.spec = snapname; 732789Sahrens margs.dir = mountpoint; 733789Sahrens margs.flags = MS_SYSSPACE | MS_NOMNTTAB; 734789Sahrens margs.fstype = "zfs"; 735789Sahrens margs.dataptr = NULL; 736789Sahrens margs.datalen = 0; 737789Sahrens margs.optptr = NULL; 738789Sahrens margs.optlen = 0; 739789Sahrens 740789Sahrens err = domount("zfs", &margs, *vpp, kcred, &vfsp); 741789Sahrens kmem_free(mountpoint, mountpoint_len); 742789Sahrens 743816Smaybee if (err == 0) { 744816Smaybee /* 745816Smaybee * Return the mounted root rather than the covered mount point. 7465326Sek110237 * Takes the GFS vnode at .zfs/snapshot/<snapname> and returns 7475326Sek110237 * the ZFS vnode mounted on top of the GFS node. This ZFS 7485326Sek110237 * vnode is the root the newly created vfsp. 749816Smaybee */ 750816Smaybee VFS_RELE(vfsp); 751816Smaybee err = traverse(vpp); 752816Smaybee } 753789Sahrens 754816Smaybee if (err == 0) { 755816Smaybee /* 7565326Sek110237 * Fix up the root vnode mounted on .zfs/snapshot/<snapname>. 7574736Sek110237 * 7584736Sek110237 * This is where we lie about our v_vfsp in order to 7595326Sek110237 * make .zfs/snapshot/<snapname> accessible over NFS 7605326Sek110237 * without requiring manual mounts of <snapname>. 761816Smaybee */ 762816Smaybee ASSERT(VTOZ(*vpp)->z_zfsvfs != zfsvfs); 763816Smaybee VTOZ(*vpp)->z_zfsvfs->z_parent = zfsvfs; 764816Smaybee (*vpp)->v_vfsp = zfsvfs->z_vfs; 765816Smaybee (*vpp)->v_flag &= ~VROOT; 766816Smaybee } 767789Sahrens mutex_exit(&sdp->sd_lock); 768789Sahrens ZFS_EXIT(zfsvfs); 769789Sahrens 7701566Smaybee /* 7711566Smaybee * If we had an error, drop our hold on the vnode and 7721566Smaybee * zfsctl_snapshot_inactive() will clean up. 7731566Smaybee */ 7741566Smaybee if (err) { 775816Smaybee VN_RELE(*vpp); 7761566Smaybee *vpp = NULL; 7771566Smaybee } 778816Smaybee return (err); 779789Sahrens } 780789Sahrens 781789Sahrens /* ARGSUSED */ 782789Sahrens static int 783789Sahrens zfsctl_snapdir_readdir_cb(vnode_t *vp, struct dirent64 *dp, int *eofp, 784789Sahrens offset_t *offp, offset_t *nextp, void *data) 785789Sahrens { 786789Sahrens zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data; 787789Sahrens char snapname[MAXNAMELEN]; 788789Sahrens uint64_t id, cookie; 789789Sahrens 790789Sahrens ZFS_ENTER(zfsvfs); 791789Sahrens 792789Sahrens cookie = *offp; 793789Sahrens if (dmu_snapshot_list_next(zfsvfs->z_os, MAXNAMELEN, snapname, &id, 794789Sahrens &cookie) == ENOENT) { 795789Sahrens *eofp = 1; 796789Sahrens ZFS_EXIT(zfsvfs); 797789Sahrens return (0); 798789Sahrens } 799789Sahrens 800789Sahrens (void) strcpy(dp->d_name, snapname); 801789Sahrens dp->d_ino = ZFSCTL_INO_SNAP(id); 802789Sahrens *nextp = cookie; 803789Sahrens 804789Sahrens ZFS_EXIT(zfsvfs); 805789Sahrens 806789Sahrens return (0); 807789Sahrens } 808789Sahrens 8095326Sek110237 /* 8105326Sek110237 * pvp is the '.zfs' directory (zfsctl_node_t). 8115326Sek110237 * Creates vp, which is '.zfs/snapshot' (zfsctl_snapdir_t). 8125326Sek110237 * 8135326Sek110237 * This function is the callback to create a GFS vnode for '.zfs/snapshot' 8145326Sek110237 * when a lookup is performed on .zfs for "snapshot". 8155326Sek110237 */ 816789Sahrens vnode_t * 817789Sahrens zfsctl_mknode_snapdir(vnode_t *pvp) 818789Sahrens { 819789Sahrens vnode_t *vp; 820789Sahrens zfsctl_snapdir_t *sdp; 821789Sahrens 822789Sahrens vp = gfs_dir_create(sizeof (zfsctl_snapdir_t), pvp, 823789Sahrens zfsctl_ops_snapdir, NULL, NULL, MAXNAMELEN, 824789Sahrens zfsctl_snapdir_readdir_cb, NULL); 825789Sahrens sdp = vp->v_data; 826789Sahrens sdp->sd_node.zc_id = ZFSCTL_INO_SNAPDIR; 8271571Sek110237 sdp->sd_node.zc_cmtime = ((zfsctl_node_t *)pvp->v_data)->zc_cmtime; 828789Sahrens mutex_init(&sdp->sd_lock, NULL, MUTEX_DEFAULT, NULL); 829789Sahrens avl_create(&sdp->sd_snaps, snapentry_compare, 830789Sahrens sizeof (zfs_snapentry_t), offsetof(zfs_snapentry_t, se_node)); 831789Sahrens return (vp); 832789Sahrens } 833789Sahrens 834789Sahrens /* ARGSUSED */ 835789Sahrens static int 836*5331Samw zfsctl_snapdir_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, 837*5331Samw caller_context_t *ct) 838789Sahrens { 839789Sahrens zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data; 840789Sahrens zfsctl_snapdir_t *sdp = vp->v_data; 841789Sahrens 842789Sahrens ZFS_ENTER(zfsvfs); 843789Sahrens zfsctl_common_getattr(vp, vap); 844789Sahrens vap->va_nodeid = gfs_file_inode(vp); 845789Sahrens vap->va_nlink = vap->va_size = avl_numnodes(&sdp->sd_snaps) + 2; 846789Sahrens ZFS_EXIT(zfsvfs); 847789Sahrens 848789Sahrens return (0); 849789Sahrens } 850789Sahrens 8511566Smaybee /* ARGSUSED */ 852789Sahrens static void 853*5331Samw zfsctl_snapdir_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct) 854789Sahrens { 855789Sahrens zfsctl_snapdir_t *sdp = vp->v_data; 8561566Smaybee void *private; 857789Sahrens 8581566Smaybee private = gfs_dir_inactive(vp); 8591566Smaybee if (private != NULL) { 8601566Smaybee ASSERT(avl_numnodes(&sdp->sd_snaps) == 0); 8611566Smaybee mutex_destroy(&sdp->sd_lock); 8621566Smaybee avl_destroy(&sdp->sd_snaps); 8631566Smaybee kmem_free(private, sizeof (zfsctl_snapdir_t)); 8641566Smaybee } 865789Sahrens } 866789Sahrens 867789Sahrens static const fs_operation_def_t zfsctl_tops_snapdir[] = { 8683898Srsb { VOPNAME_OPEN, { .vop_open = zfsctl_common_open } }, 8693898Srsb { VOPNAME_CLOSE, { .vop_close = zfsctl_common_close } }, 8703898Srsb { VOPNAME_IOCTL, { .error = fs_inval } }, 8713898Srsb { VOPNAME_GETATTR, { .vop_getattr = zfsctl_snapdir_getattr } }, 8723898Srsb { VOPNAME_ACCESS, { .vop_access = zfsctl_common_access } }, 8733898Srsb { VOPNAME_RENAME, { .vop_rename = zfsctl_snapdir_rename } }, 8743898Srsb { VOPNAME_RMDIR, { .vop_rmdir = zfsctl_snapdir_remove } }, 8754543Smarks { VOPNAME_MKDIR, { .vop_mkdir = zfsctl_snapdir_mkdir } }, 8763898Srsb { VOPNAME_READDIR, { .vop_readdir = gfs_vop_readdir } }, 8773898Srsb { VOPNAME_LOOKUP, { .vop_lookup = zfsctl_snapdir_lookup } }, 8783898Srsb { VOPNAME_SEEK, { .vop_seek = fs_seek } }, 8793898Srsb { VOPNAME_INACTIVE, { .vop_inactive = zfsctl_snapdir_inactive } }, 8803898Srsb { VOPNAME_FID, { .vop_fid = zfsctl_common_fid } }, 881789Sahrens { NULL } 882789Sahrens }; 883789Sahrens 8845326Sek110237 /* 8855326Sek110237 * pvp is the GFS vnode '.zfs/snapshot'. 8865326Sek110237 * 8875326Sek110237 * This creates a GFS node under '.zfs/snapshot' representing each 8885326Sek110237 * snapshot. This newly created GFS node is what we mount snapshot 8895326Sek110237 * vfs_t's ontop of. 8905326Sek110237 */ 891789Sahrens static vnode_t * 892789Sahrens zfsctl_snapshot_mknode(vnode_t *pvp, uint64_t objset) 893789Sahrens { 894789Sahrens vnode_t *vp; 895789Sahrens zfsctl_node_t *zcp; 896789Sahrens 897789Sahrens vp = gfs_dir_create(sizeof (zfsctl_node_t), pvp, 898789Sahrens zfsctl_ops_snapshot, NULL, NULL, MAXNAMELEN, NULL, NULL); 899789Sahrens zcp = vp->v_data; 900789Sahrens zcp->zc_id = objset; 901789Sahrens 902789Sahrens return (vp); 903789Sahrens } 904789Sahrens 905789Sahrens static void 906*5331Samw zfsctl_snapshot_inactive(vnode_t *vp, cred_t *cr, caller_context_t *ct) 907789Sahrens { 908789Sahrens zfsctl_snapdir_t *sdp; 909789Sahrens zfs_snapentry_t *sep, *next; 910789Sahrens vnode_t *dvp; 911789Sahrens 912*5331Samw VERIFY(gfs_dir_lookup(vp, "..", &dvp, cr) == 0); 913789Sahrens sdp = dvp->v_data; 914789Sahrens 915789Sahrens mutex_enter(&sdp->sd_lock); 916789Sahrens 917789Sahrens if (vp->v_count > 1) { 918789Sahrens mutex_exit(&sdp->sd_lock); 919789Sahrens return; 920789Sahrens } 921789Sahrens ASSERT(!vn_ismntpt(vp)); 922789Sahrens 923789Sahrens sep = avl_first(&sdp->sd_snaps); 924789Sahrens while (sep != NULL) { 925789Sahrens next = AVL_NEXT(&sdp->sd_snaps, sep); 926789Sahrens 927789Sahrens if (sep->se_root == vp) { 928789Sahrens avl_remove(&sdp->sd_snaps, sep); 929789Sahrens kmem_free(sep->se_name, strlen(sep->se_name) + 1); 930789Sahrens kmem_free(sep, sizeof (zfs_snapentry_t)); 931789Sahrens break; 932789Sahrens } 933789Sahrens sep = next; 934789Sahrens } 935789Sahrens ASSERT(sep != NULL); 936789Sahrens 937789Sahrens mutex_exit(&sdp->sd_lock); 938789Sahrens VN_RELE(dvp); 939789Sahrens 9401566Smaybee /* 9411566Smaybee * Dispose of the vnode for the snapshot mount point. 9421566Smaybee * This is safe to do because once this entry has been removed 9431566Smaybee * from the AVL tree, it can't be found again, so cannot become 9441566Smaybee * "active". If we lookup the same name again we will end up 9451566Smaybee * creating a new vnode. 9461566Smaybee */ 947*5331Samw gfs_vop_inactive(vp, cr, ct); 948789Sahrens } 949789Sahrens 950789Sahrens 951789Sahrens /* 952789Sahrens * These VP's should never see the light of day. They should always 953789Sahrens * be covered. 954789Sahrens */ 955789Sahrens static const fs_operation_def_t zfsctl_tops_snapshot[] = { 9563898Srsb VOPNAME_INACTIVE, { .vop_inactive = zfsctl_snapshot_inactive }, 957789Sahrens NULL, NULL 958789Sahrens }; 959789Sahrens 960789Sahrens int 961789Sahrens zfsctl_lookup_objset(vfs_t *vfsp, uint64_t objsetid, zfsvfs_t **zfsvfsp) 962789Sahrens { 963789Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 964789Sahrens vnode_t *dvp, *vp; 965789Sahrens zfsctl_snapdir_t *sdp; 966789Sahrens zfsctl_node_t *zcp; 967789Sahrens zfs_snapentry_t *sep; 968789Sahrens int error; 969789Sahrens 970789Sahrens ASSERT(zfsvfs->z_ctldir != NULL); 971789Sahrens error = zfsctl_root_lookup(zfsvfs->z_ctldir, "snapshot", &dvp, 972*5331Samw NULL, 0, NULL, kcred, NULL, NULL, NULL); 973789Sahrens if (error != 0) 974789Sahrens return (error); 975789Sahrens sdp = dvp->v_data; 976789Sahrens 977789Sahrens mutex_enter(&sdp->sd_lock); 978789Sahrens sep = avl_first(&sdp->sd_snaps); 979789Sahrens while (sep != NULL) { 980789Sahrens vp = sep->se_root; 981789Sahrens zcp = vp->v_data; 982789Sahrens if (zcp->zc_id == objsetid) 983789Sahrens break; 984789Sahrens 985789Sahrens sep = AVL_NEXT(&sdp->sd_snaps, sep); 986789Sahrens } 987789Sahrens 988789Sahrens if (sep != NULL) { 989789Sahrens VN_HOLD(vp); 9905326Sek110237 /* 9915326Sek110237 * Return the mounted root rather than the covered mount point. 9925326Sek110237 * Takes the GFS vnode at .zfs/snapshot/<snapshot objsetid> 9935326Sek110237 * and returns the ZFS vnode mounted on top of the GFS node. 9945326Sek110237 * This ZFS vnode is the root of the vfs for objset 'objsetid'. 9955326Sek110237 */ 996789Sahrens error = traverse(&vp); 9971589Smaybee if (error == 0) { 9981589Smaybee if (vp == sep->se_root) 9991589Smaybee error = EINVAL; 10001589Smaybee else 10011589Smaybee *zfsvfsp = VTOZ(vp)->z_zfsvfs; 10021589Smaybee } 10031572Snd150628 mutex_exit(&sdp->sd_lock); 1004789Sahrens VN_RELE(vp); 1005789Sahrens } else { 1006789Sahrens error = EINVAL; 10071572Snd150628 mutex_exit(&sdp->sd_lock); 1008789Sahrens } 1009789Sahrens 1010789Sahrens VN_RELE(dvp); 1011789Sahrens 1012789Sahrens return (error); 1013789Sahrens } 1014789Sahrens 1015789Sahrens /* 1016789Sahrens * Unmount any snapshots for the given filesystem. This is called from 1017789Sahrens * zfs_umount() - if we have a ctldir, then go through and unmount all the 1018789Sahrens * snapshots. 1019789Sahrens */ 1020789Sahrens int 1021789Sahrens zfsctl_umount_snapshots(vfs_t *vfsp, int fflags, cred_t *cr) 1022789Sahrens { 1023789Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 1024789Sahrens vnode_t *dvp, *svp; 1025789Sahrens zfsctl_snapdir_t *sdp; 1026789Sahrens zfs_snapentry_t *sep, *next; 1027789Sahrens int error; 1028789Sahrens 1029789Sahrens ASSERT(zfsvfs->z_ctldir != NULL); 1030789Sahrens error = zfsctl_root_lookup(zfsvfs->z_ctldir, "snapshot", &dvp, 1031*5331Samw NULL, 0, NULL, cr, NULL, NULL, NULL); 1032789Sahrens if (error != 0) 1033789Sahrens return (error); 1034789Sahrens sdp = dvp->v_data; 1035789Sahrens 1036789Sahrens mutex_enter(&sdp->sd_lock); 1037789Sahrens 1038789Sahrens sep = avl_first(&sdp->sd_snaps); 1039789Sahrens while (sep != NULL) { 1040789Sahrens svp = sep->se_root; 1041789Sahrens next = AVL_NEXT(&sdp->sd_snaps, sep); 1042789Sahrens 1043789Sahrens /* 1044789Sahrens * If this snapshot is not mounted, then it must 1045789Sahrens * have just been unmounted by somebody else, and 1046789Sahrens * will be cleaned up by zfsctl_snapdir_inactive(). 1047789Sahrens */ 1048789Sahrens if (vn_ismntpt(svp)) { 1049789Sahrens if ((error = vn_vfswlock(svp)) != 0) 1050789Sahrens goto out; 1051789Sahrens 1052789Sahrens VN_HOLD(svp); 1053789Sahrens error = dounmount(vn_mountedvfs(svp), fflags, cr); 1054789Sahrens if (error) { 1055789Sahrens VN_RELE(svp); 1056789Sahrens goto out; 1057789Sahrens } 1058789Sahrens 1059789Sahrens avl_remove(&sdp->sd_snaps, sep); 1060789Sahrens kmem_free(sep->se_name, strlen(sep->se_name) + 1); 1061789Sahrens kmem_free(sep, sizeof (zfs_snapentry_t)); 1062789Sahrens 1063789Sahrens /* 1064789Sahrens * We can't use VN_RELE(), as that will try to 1065789Sahrens * invoke zfsctl_snapdir_inactive(), and that 1066789Sahrens * would lead to an attempt to re-grab the sd_lock. 1067789Sahrens */ 1068789Sahrens ASSERT3U(svp->v_count, ==, 1); 1069*5331Samw gfs_vop_inactive(svp, cr, NULL); 1070789Sahrens } 1071789Sahrens sep = next; 1072789Sahrens } 1073789Sahrens out: 1074789Sahrens mutex_exit(&sdp->sd_lock); 1075789Sahrens VN_RELE(dvp); 1076789Sahrens 1077789Sahrens return (error); 1078789Sahrens } 1079