1789Sahrens /* 2789Sahrens * CDDL HEADER START 3789Sahrens * 4789Sahrens * The contents of this file are subject to the terms of the 5*1512Sek110237 * Common Development and Distribution License (the "License"). 6*1512Sek110237 * 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 /* 221298Sperrin * Copyright 2006 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. 56789Sahrens */ 57789Sahrens 58789Sahrens #include <fs/fs_subr.h> 59789Sahrens #include <sys/zfs_ctldir.h> 60789Sahrens #include <sys/zfs_ioctl.h> 61789Sahrens #include <sys/zfs_vfsops.h> 62789Sahrens #include <sys/gfs.h> 63789Sahrens #include <sys/stat.h> 64789Sahrens #include <sys/dmu.h> 65789Sahrens #include <sys/mount.h> 66789Sahrens 67789Sahrens typedef struct { 68789Sahrens char *se_name; 69789Sahrens vnode_t *se_root; 70789Sahrens avl_node_t se_node; 71789Sahrens } zfs_snapentry_t; 72789Sahrens 73789Sahrens static int 74789Sahrens snapentry_compare(const void *a, const void *b) 75789Sahrens { 76789Sahrens const zfs_snapentry_t *sa = a; 77789Sahrens const zfs_snapentry_t *sb = b; 78789Sahrens int ret = strcmp(sa->se_name, sb->se_name); 79789Sahrens 80789Sahrens if (ret < 0) 81789Sahrens return (-1); 82789Sahrens else if (ret > 0) 83789Sahrens return (1); 84789Sahrens else 85789Sahrens return (0); 86789Sahrens } 87789Sahrens 88789Sahrens vnodeops_t *zfsctl_ops_root; 89789Sahrens vnodeops_t *zfsctl_ops_snapdir; 90789Sahrens vnodeops_t *zfsctl_ops_snapshot; 91789Sahrens 92789Sahrens static const fs_operation_def_t zfsctl_tops_root[]; 93789Sahrens static const fs_operation_def_t zfsctl_tops_snapdir[]; 94789Sahrens static const fs_operation_def_t zfsctl_tops_snapshot[]; 95789Sahrens 96789Sahrens static vnode_t *zfsctl_mknode_snapdir(vnode_t *); 97789Sahrens static vnode_t *zfsctl_snapshot_mknode(vnode_t *, uint64_t objset); 98789Sahrens 99789Sahrens static gfs_opsvec_t zfsctl_opsvec[] = { 100789Sahrens { ".zfs", zfsctl_tops_root, &zfsctl_ops_root }, 101789Sahrens { ".zfs/snapshot", zfsctl_tops_snapdir, &zfsctl_ops_snapdir }, 102789Sahrens { ".zfs/snapshot/vnode", zfsctl_tops_snapshot, &zfsctl_ops_snapshot }, 103789Sahrens { NULL } 104789Sahrens }; 105789Sahrens 106789Sahrens typedef struct zfsctl_node { 107789Sahrens gfs_dir_t zc_gfs_private; 108789Sahrens uint64_t zc_id; 109789Sahrens } zfsctl_node_t; 110789Sahrens 111789Sahrens typedef struct zfsctl_snapdir { 112789Sahrens zfsctl_node_t sd_node; 113789Sahrens kmutex_t sd_lock; 114789Sahrens avl_tree_t sd_snaps; 115789Sahrens } zfsctl_snapdir_t; 116789Sahrens 117789Sahrens /* 118789Sahrens * Root directory elements. We have only a single static entry, 'snapshot'. 119789Sahrens */ 120789Sahrens static gfs_dirent_t zfsctl_root_entries[] = { 121789Sahrens { "snapshot", zfsctl_mknode_snapdir, GFS_CACHE_VNODE }, 122789Sahrens { NULL } 123789Sahrens }; 124789Sahrens 125789Sahrens /* include . and .. in the calculation */ 126789Sahrens #define NROOT_ENTRIES ((sizeof (zfsctl_root_entries) / \ 127789Sahrens sizeof (gfs_dirent_t)) + 1) 128789Sahrens 129789Sahrens 130789Sahrens /* 131789Sahrens * Initialize the various GFS pieces we'll need to create and manipulate .zfs 132789Sahrens * directories. This is called from the ZFS init routine, and initializes the 133789Sahrens * vnode ops vectors that we'll be using. 134789Sahrens */ 135789Sahrens void 136789Sahrens zfsctl_init(void) 137789Sahrens { 138789Sahrens VERIFY(gfs_make_opsvec(zfsctl_opsvec) == 0); 139789Sahrens } 140789Sahrens 141789Sahrens void 142789Sahrens zfsctl_fini(void) 143789Sahrens { 144789Sahrens /* 145789Sahrens * Remove vfsctl vnode ops 146789Sahrens */ 147789Sahrens if (zfsctl_ops_root) 148789Sahrens vn_freevnodeops(zfsctl_ops_root); 149789Sahrens if (zfsctl_ops_snapdir) 150789Sahrens vn_freevnodeops(zfsctl_ops_snapdir); 151789Sahrens if (zfsctl_ops_snapshot) 152789Sahrens vn_freevnodeops(zfsctl_ops_snapshot); 153789Sahrens 154789Sahrens zfsctl_ops_root = NULL; 155789Sahrens zfsctl_ops_snapdir = NULL; 156789Sahrens zfsctl_ops_snapshot = NULL; 157789Sahrens } 158789Sahrens 159789Sahrens /* 160789Sahrens * Return the inode number associated with the 'snapshot' directory. 161789Sahrens */ 162789Sahrens /* ARGSUSED */ 163789Sahrens static ino64_t 164789Sahrens zfsctl_root_inode_cb(vnode_t *vp, int index) 165789Sahrens { 166789Sahrens ASSERT(index == 0); 167789Sahrens return (ZFSCTL_INO_SNAPDIR); 168789Sahrens } 169789Sahrens 170789Sahrens /* 171789Sahrens * Create the '.zfs' directory. This directory is cached as part of the VFS 172789Sahrens * structure. This results in a hold on the vfs_t. The code in zfs_umount() 173789Sahrens * therefore checks against a vfs_count of 2 instead of 1. This reference 174789Sahrens * is removed when the ctldir is destroyed in the unmount. 175789Sahrens */ 176789Sahrens void 177789Sahrens zfsctl_create(zfsvfs_t *zfsvfs) 178789Sahrens { 179789Sahrens vnode_t *vp; 180789Sahrens zfsctl_node_t *zcp; 181789Sahrens 182789Sahrens ASSERT(zfsvfs->z_ctldir == NULL); 183789Sahrens 184789Sahrens vp = gfs_root_create(sizeof (zfsctl_node_t), zfsvfs->z_vfs, 185789Sahrens zfsctl_ops_root, ZFSCTL_INO_ROOT, zfsctl_root_entries, 186789Sahrens zfsctl_root_inode_cb, MAXNAMELEN, NULL, NULL); 187789Sahrens zcp = vp->v_data; 188789Sahrens zcp->zc_id = ZFSCTL_INO_ROOT; 189789Sahrens 190789Sahrens /* 191789Sahrens * We're only faking the fact that we have a root of a filesystem for 192789Sahrens * the sake of the GFS interfaces. Undo the flag manipulation it did 193789Sahrens * for us. 194789Sahrens */ 195789Sahrens vp->v_flag &= ~(VROOT | VNOCACHE | VNOMAP | VNOSWAP | VNOMOUNT); 196789Sahrens 197789Sahrens zfsvfs->z_ctldir = vp; 198789Sahrens } 199789Sahrens 200789Sahrens /* 2011298Sperrin * Destroy the '.zfs' directory. Only called when the filesystem is unmounted. 2021298Sperrin * There might still be more references if we were force unmounted, but only 2031298Sperrin * new zfs_inactive() calls can occur and they don't reference .zfs 204789Sahrens */ 205789Sahrens void 206789Sahrens zfsctl_destroy(zfsvfs_t *zfsvfs) 207789Sahrens { 208789Sahrens VN_RELE(zfsvfs->z_ctldir); 209789Sahrens zfsvfs->z_ctldir = NULL; 210789Sahrens } 211789Sahrens 212789Sahrens /* 213789Sahrens * Given a root znode, retrieve the associated .zfs directory. 214789Sahrens * Add a hold to the vnode and return it. 215789Sahrens */ 216789Sahrens vnode_t * 217789Sahrens zfsctl_root(znode_t *zp) 218789Sahrens { 219789Sahrens ASSERT(zfs_has_ctldir(zp)); 220789Sahrens VN_HOLD(zp->z_zfsvfs->z_ctldir); 221789Sahrens return (zp->z_zfsvfs->z_ctldir); 222789Sahrens } 223789Sahrens 224789Sahrens /* 225789Sahrens * Common open routine. Disallow any write access. 226789Sahrens */ 227789Sahrens /* ARGSUSED */ 228789Sahrens static int 229789Sahrens zfsctl_common_open(vnode_t **vpp, int flags, cred_t *cr) 230789Sahrens { 231789Sahrens if (flags & FWRITE) 232789Sahrens return (EACCES); 233789Sahrens 234789Sahrens return (0); 235789Sahrens } 236789Sahrens 237789Sahrens /* 238789Sahrens * Common close routine. Nothing to do here. 239789Sahrens */ 240789Sahrens /* ARGSUSED */ 241789Sahrens static int 242789Sahrens zfsctl_common_close(vnode_t *vpp, int flags, int count, offset_t off, 243789Sahrens cred_t *cr) 244789Sahrens { 245789Sahrens return (0); 246789Sahrens } 247789Sahrens 248789Sahrens /* 249789Sahrens * Common access routine. Disallow writes. 250789Sahrens */ 251789Sahrens /* ARGSUSED */ 252789Sahrens static int 253789Sahrens zfsctl_common_access(vnode_t *vp, int mode, int flags, cred_t *cr) 254789Sahrens { 255789Sahrens if (mode & VWRITE) 256789Sahrens return (EACCES); 257789Sahrens 258789Sahrens return (0); 259789Sahrens } 260789Sahrens 261789Sahrens /* 262789Sahrens * Common getattr function. Fill in basic information. 263789Sahrens */ 264789Sahrens static void 265789Sahrens zfsctl_common_getattr(vnode_t *vp, vattr_t *vap) 266789Sahrens { 267789Sahrens timestruc_t now; 268789Sahrens 269789Sahrens vap->va_uid = 0; 270789Sahrens vap->va_gid = 0; 271789Sahrens vap->va_rdev = 0; 272789Sahrens /* 273789Sahrens * We are a purly virtual object, so we have no 274789Sahrens * blocksize or allocated blocks. 275789Sahrens */ 276789Sahrens vap->va_blksize = 0; 277789Sahrens vap->va_nblocks = 0; 278789Sahrens vap->va_seq = 0; 279789Sahrens vap->va_fsid = vp->v_vfsp->vfs_dev; 280789Sahrens vap->va_mode = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | 281789Sahrens S_IROTH | S_IXOTH; 282789Sahrens vap->va_type = VDIR; 283789Sahrens /* 284789Sahrens * We live in the now. 285789Sahrens */ 286789Sahrens gethrestime(&now); 287789Sahrens vap->va_mtime = vap->va_ctime = vap->va_atime = now; 288789Sahrens } 289789Sahrens 290789Sahrens static int 291789Sahrens zfsctl_common_fid(vnode_t *vp, fid_t *fidp) 292789Sahrens { 293789Sahrens zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data; 294789Sahrens zfsctl_node_t *zcp = vp->v_data; 295789Sahrens uint64_t object = zcp->zc_id; 296789Sahrens zfid_short_t *zfid; 297789Sahrens int i; 298789Sahrens 299789Sahrens ZFS_ENTER(zfsvfs); 300789Sahrens 301789Sahrens if (fidp->fid_len < SHORT_FID_LEN) { 302789Sahrens fidp->fid_len = SHORT_FID_LEN; 303*1512Sek110237 ZFS_EXIT(zfsvfs); 304789Sahrens return (ENOSPC); 305789Sahrens } 306789Sahrens 307789Sahrens zfid = (zfid_short_t *)fidp; 308789Sahrens 309789Sahrens zfid->zf_len = SHORT_FID_LEN; 310789Sahrens 311789Sahrens for (i = 0; i < sizeof (zfid->zf_object); i++) 312789Sahrens zfid->zf_object[i] = (uint8_t)(object >> (8 * i)); 313789Sahrens 314789Sahrens /* .zfs znodes always have a generation number of 0 */ 315789Sahrens for (i = 0; i < sizeof (zfid->zf_gen); i++) 316789Sahrens zfid->zf_gen[i] = 0; 317789Sahrens 318789Sahrens ZFS_EXIT(zfsvfs); 319789Sahrens return (0); 320789Sahrens } 321789Sahrens 322789Sahrens /* 323789Sahrens * .zfs inode namespace 324789Sahrens * 325789Sahrens * We need to generate unique inode numbers for all files and directories 326789Sahrens * within the .zfs pseudo-filesystem. We use the following scheme: 327789Sahrens * 328789Sahrens * ENTRY ZFSCTL_INODE 329789Sahrens * .zfs 1 330789Sahrens * .zfs/snapshot 2 331789Sahrens * .zfs/snapshot/<snap> objectid(snap) 332789Sahrens */ 333789Sahrens 334789Sahrens #define ZFSCTL_INO_SNAP(id) (id) 335789Sahrens 336789Sahrens /* 337789Sahrens * Get root directory attributes. 338789Sahrens */ 339789Sahrens /* ARGSUSED */ 340789Sahrens static int 341789Sahrens zfsctl_root_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr) 342789Sahrens { 343789Sahrens zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data; 344789Sahrens 345789Sahrens ZFS_ENTER(zfsvfs); 346789Sahrens vap->va_nodeid = ZFSCTL_INO_ROOT; 347789Sahrens vap->va_nlink = vap->va_size = NROOT_ENTRIES; 348789Sahrens 349789Sahrens zfsctl_common_getattr(vp, vap); 350789Sahrens ZFS_EXIT(zfsvfs); 351789Sahrens 352789Sahrens return (0); 353789Sahrens } 354789Sahrens 355789Sahrens /* 356789Sahrens * Special case the handling of "..". 357789Sahrens */ 358789Sahrens /* ARGSUSED */ 359789Sahrens int 360789Sahrens zfsctl_root_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp, 361789Sahrens int flags, vnode_t *rdir, cred_t *cr) 362789Sahrens { 363789Sahrens zfsvfs_t *zfsvfs = dvp->v_vfsp->vfs_data; 364789Sahrens int err; 365789Sahrens 366789Sahrens ZFS_ENTER(zfsvfs); 367789Sahrens 368789Sahrens if (strcmp(nm, "..") == 0) { 369789Sahrens err = VFS_ROOT(dvp->v_vfsp, vpp); 370789Sahrens } else { 371789Sahrens err = gfs_dir_lookup(dvp, nm, vpp); 372789Sahrens } 373789Sahrens 374789Sahrens ZFS_EXIT(zfsvfs); 375789Sahrens 376789Sahrens return (err); 377789Sahrens } 378789Sahrens 379789Sahrens static const fs_operation_def_t zfsctl_tops_root[] = { 380789Sahrens { VOPNAME_OPEN, zfsctl_common_open }, 381789Sahrens { VOPNAME_CLOSE, zfsctl_common_close }, 382789Sahrens { VOPNAME_IOCTL, fs_inval }, 383789Sahrens { VOPNAME_GETATTR, zfsctl_root_getattr }, 384789Sahrens { VOPNAME_ACCESS, zfsctl_common_access }, 385789Sahrens { VOPNAME_READDIR, gfs_vop_readdir }, 386789Sahrens { VOPNAME_LOOKUP, zfsctl_root_lookup }, 387789Sahrens { VOPNAME_SEEK, fs_seek }, 388789Sahrens { VOPNAME_INACTIVE, (fs_generic_func_p) gfs_vop_inactive }, 389789Sahrens { VOPNAME_FID, zfsctl_common_fid }, 390789Sahrens { NULL } 391789Sahrens }; 392789Sahrens 393789Sahrens static int 394789Sahrens zfsctl_snapshot_zname(vnode_t *vp, const char *name, int len, char *zname) 395789Sahrens { 396789Sahrens objset_t *os = ((zfsvfs_t *)((vp)->v_vfsp->vfs_data))->z_os; 397789Sahrens 398789Sahrens dmu_objset_name(os, zname); 3991154Smaybee if (strlen(zname) + 1 + strlen(name) >= len) 4001154Smaybee return (ENAMETOOLONG); 401789Sahrens (void) strcat(zname, "@"); 402789Sahrens (void) strcat(zname, name); 403789Sahrens return (0); 404789Sahrens } 405789Sahrens 406789Sahrens static int 407789Sahrens zfsctl_unmount_snap(vnode_t *dvp, const char *name, int force, cred_t *cr) 408789Sahrens { 409789Sahrens zfsctl_snapdir_t *sdp = dvp->v_data; 410789Sahrens zfs_snapentry_t search, *sep; 411789Sahrens avl_index_t where; 412789Sahrens int err; 413789Sahrens 414789Sahrens ASSERT(MUTEX_HELD(&sdp->sd_lock)); 415789Sahrens 416789Sahrens search.se_name = (char *)name; 417789Sahrens if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) == NULL) 418789Sahrens return (ENOENT); 419789Sahrens 420789Sahrens ASSERT(vn_ismntpt(sep->se_root)); 421789Sahrens 422789Sahrens /* this will be dropped by dounmount() */ 423789Sahrens if ((err = vn_vfswlock(sep->se_root)) != 0) 424789Sahrens return (err); 425789Sahrens 426789Sahrens VN_HOLD(sep->se_root); 427789Sahrens if ((err = dounmount(vn_mountedvfs(sep->se_root), force, kcred)) != 0) 428789Sahrens return (err); 429789Sahrens ASSERT(sep->se_root->v_count == 1); 430789Sahrens gfs_vop_inactive(sep->se_root, cr); 431789Sahrens 432789Sahrens avl_remove(&sdp->sd_snaps, sep); 433789Sahrens kmem_free(sep->se_name, strlen(sep->se_name) + 1); 434789Sahrens kmem_free(sep, sizeof (zfs_snapentry_t)); 435789Sahrens 436789Sahrens return (0); 437789Sahrens } 438789Sahrens 439789Sahrens 4401154Smaybee static void 441789Sahrens zfsctl_rename_snap(zfsctl_snapdir_t *sdp, zfs_snapentry_t *sep, const char *nm) 442789Sahrens { 443789Sahrens avl_index_t where; 444789Sahrens vfs_t *vfsp; 445789Sahrens refstr_t *pathref; 446789Sahrens char newpath[MAXNAMELEN]; 447789Sahrens const char *oldpath; 448789Sahrens char *tail; 449789Sahrens 450789Sahrens ASSERT(MUTEX_HELD(&sdp->sd_lock)); 451789Sahrens ASSERT(sep != NULL); 452789Sahrens 453789Sahrens vfsp = vn_mountedvfs(sep->se_root); 454789Sahrens ASSERT(vfsp != NULL); 455789Sahrens 4561154Smaybee vfs_lock_wait(vfsp); 457789Sahrens 458789Sahrens /* 459789Sahrens * Change the name in the AVL tree. 460789Sahrens */ 461789Sahrens avl_remove(&sdp->sd_snaps, sep); 462789Sahrens kmem_free(sep->se_name, strlen(sep->se_name) + 1); 463789Sahrens sep->se_name = kmem_alloc(strlen(nm) + 1, KM_SLEEP); 464789Sahrens (void) strcpy(sep->se_name, nm); 465789Sahrens VERIFY(avl_find(&sdp->sd_snaps, sep, &where) == NULL); 466789Sahrens avl_insert(&sdp->sd_snaps, sep, where); 467789Sahrens 468789Sahrens /* 469789Sahrens * Change the current mountpoint info: 470789Sahrens * - update the tail of the mntpoint path 471789Sahrens * - update the tail of the resource path 472789Sahrens */ 473789Sahrens pathref = vfs_getmntpoint(vfsp); 474789Sahrens oldpath = refstr_value(pathref); 475789Sahrens VERIFY((tail = strrchr(oldpath, '/')) != NULL); 476789Sahrens ASSERT((tail - oldpath) + strlen(nm) + 2 < MAXNAMELEN); 477789Sahrens (void) strncpy(newpath, oldpath, tail - oldpath + 1); 478789Sahrens (void) strcat(newpath, nm); 479789Sahrens refstr_rele(pathref); 480789Sahrens vfs_setmntpoint(vfsp, newpath); 481789Sahrens 482789Sahrens pathref = vfs_getresource(vfsp); 483789Sahrens oldpath = refstr_value(pathref); 484789Sahrens VERIFY((tail = strrchr(oldpath, '@')) != NULL); 485789Sahrens ASSERT((tail - oldpath) + strlen(nm) + 2 < MAXNAMELEN); 486789Sahrens (void) strncpy(newpath, oldpath, tail - oldpath + 1); 487789Sahrens (void) strcat(newpath, nm); 488789Sahrens refstr_rele(pathref); 489789Sahrens vfs_setresource(vfsp, newpath); 490789Sahrens 491789Sahrens vfs_unlock(vfsp); 492789Sahrens } 493789Sahrens 494789Sahrens static int 495789Sahrens zfsctl_snapdir_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, 496789Sahrens cred_t *cr) 497789Sahrens { 498789Sahrens zfsctl_snapdir_t *sdp = sdvp->v_data; 499789Sahrens zfs_snapentry_t search, *sep; 500789Sahrens avl_index_t where; 501789Sahrens char from[MAXNAMELEN], to[MAXNAMELEN]; 502789Sahrens int err; 503789Sahrens 5041154Smaybee err = zfsctl_snapshot_zname(sdvp, snm, MAXNAMELEN, from); 5051154Smaybee if (err) 5061154Smaybee return (err); 507789Sahrens err = zfs_secpolicy_write(from, NULL, cr); 508789Sahrens if (err) 509789Sahrens return (err); 510789Sahrens 511789Sahrens /* 512789Sahrens * Cannot move snapshots out of the snapdir. 513789Sahrens */ 514789Sahrens if (sdvp != tdvp) 515789Sahrens return (EINVAL); 516789Sahrens 517789Sahrens if (strcmp(snm, tnm) == 0) 518789Sahrens return (0); 519789Sahrens 5201154Smaybee err = zfsctl_snapshot_zname(tdvp, tnm, MAXNAMELEN, to); 5211154Smaybee if (err) 5221154Smaybee return (err); 5231154Smaybee 524789Sahrens mutex_enter(&sdp->sd_lock); 525789Sahrens 526789Sahrens search.se_name = (char *)snm; 5271154Smaybee if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) == NULL) { 5281154Smaybee mutex_exit(&sdp->sd_lock); 5291154Smaybee return (ENOENT); 530789Sahrens } 531789Sahrens 532789Sahrens err = dmu_objset_rename(from, to); 5331154Smaybee if (err == 0) 5341154Smaybee zfsctl_rename_snap(sdp, sep, tnm); 535789Sahrens 536789Sahrens mutex_exit(&sdp->sd_lock); 537789Sahrens 538789Sahrens return (err); 539789Sahrens } 540789Sahrens 541789Sahrens /* ARGSUSED */ 542789Sahrens static int 543789Sahrens zfsctl_snapdir_remove(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr) 544789Sahrens { 545789Sahrens zfsctl_snapdir_t *sdp = dvp->v_data; 546789Sahrens char snapname[MAXNAMELEN]; 547789Sahrens int err; 548789Sahrens 5491154Smaybee err = zfsctl_snapshot_zname(dvp, name, MAXNAMELEN, snapname); 5501154Smaybee if (err) 5511154Smaybee return (err); 552789Sahrens err = zfs_secpolicy_write(snapname, NULL, cr); 553789Sahrens if (err) 554789Sahrens return (err); 555789Sahrens 556789Sahrens mutex_enter(&sdp->sd_lock); 557789Sahrens 558789Sahrens err = zfsctl_unmount_snap(dvp, name, 0, cr); 559789Sahrens if (err) { 560789Sahrens mutex_exit(&sdp->sd_lock); 561789Sahrens return (err); 562789Sahrens } 563789Sahrens 564789Sahrens err = dmu_objset_destroy(snapname); 565789Sahrens 566789Sahrens mutex_exit(&sdp->sd_lock); 567789Sahrens 568789Sahrens return (err); 569789Sahrens } 570789Sahrens 571789Sahrens /* 572789Sahrens * Lookup entry point for the 'snapshot' directory. Try to open the 573789Sahrens * snapshot if it exist, creating the pseudo filesystem vnode as necessary. 574789Sahrens * Perform a mount of the associated dataset on top of the vnode. 575789Sahrens */ 576789Sahrens /* ARGSUSED */ 577789Sahrens static int 578789Sahrens zfsctl_snapdir_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp, 579789Sahrens int flags, vnode_t *rdir, cred_t *cr) 580789Sahrens { 581789Sahrens zfsctl_snapdir_t *sdp = dvp->v_data; 582789Sahrens objset_t *snap; 583789Sahrens char snapname[MAXNAMELEN]; 584789Sahrens char *mountpoint; 585789Sahrens zfs_snapentry_t *sep, search; 586789Sahrens struct mounta margs; 587789Sahrens vfs_t *vfsp; 588789Sahrens size_t mountpoint_len; 589789Sahrens avl_index_t where; 590789Sahrens zfsvfs_t *zfsvfs = dvp->v_vfsp->vfs_data; 591789Sahrens int err; 592789Sahrens 593789Sahrens ASSERT(dvp->v_type == VDIR); 594789Sahrens 595789Sahrens if (gfs_lookup_dot(vpp, dvp, zfsvfs->z_ctldir, nm) == 0) 596789Sahrens return (0); 597789Sahrens 598789Sahrens /* 599789Sahrens * If we get a recursive call, that means we got called 600789Sahrens * from the domount() code while it was trying to look up the 601789Sahrens * spec (which looks like a local path for zfs). We need to 602789Sahrens * add some flag to domount() to tell it not to do this lookup. 603789Sahrens */ 604789Sahrens if (MUTEX_HELD(&sdp->sd_lock)) 605789Sahrens return (ENOENT); 606789Sahrens 607789Sahrens ZFS_ENTER(zfsvfs); 608789Sahrens 609789Sahrens mutex_enter(&sdp->sd_lock); 610789Sahrens search.se_name = (char *)nm; 611789Sahrens if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) != NULL) { 612789Sahrens *vpp = sep->se_root; 613789Sahrens VN_HOLD(*vpp); 614789Sahrens /* 615789Sahrens * If the snapshot was unmounted behind our backs, remount it. 616789Sahrens */ 617789Sahrens if (!vn_ismntpt(*vpp)) 618789Sahrens goto domount; 619789Sahrens VERIFY(traverse(vpp) == 0); 620789Sahrens mutex_exit(&sdp->sd_lock); 621789Sahrens ZFS_EXIT(zfsvfs); 622789Sahrens return (0); 623789Sahrens } 624789Sahrens 625789Sahrens /* 626789Sahrens * The requested snapshot is not currently mounted, look it up. 627789Sahrens */ 6281154Smaybee err = zfsctl_snapshot_zname(dvp, nm, MAXNAMELEN, snapname); 6291154Smaybee if (err) { 6301154Smaybee mutex_exit(&sdp->sd_lock); 6311154Smaybee ZFS_EXIT(zfsvfs); 6321154Smaybee return (err); 6331154Smaybee } 634789Sahrens if (dmu_objset_open(snapname, DMU_OST_ZFS, 635789Sahrens DS_MODE_STANDARD | DS_MODE_READONLY, &snap) != 0) { 636789Sahrens mutex_exit(&sdp->sd_lock); 637789Sahrens ZFS_EXIT(zfsvfs); 638789Sahrens return (ENOENT); 639789Sahrens } 640789Sahrens 641789Sahrens sep = kmem_alloc(sizeof (zfs_snapentry_t), KM_SLEEP); 642789Sahrens sep->se_name = kmem_alloc(strlen(nm) + 1, KM_SLEEP); 643789Sahrens (void) strcpy(sep->se_name, nm); 644789Sahrens *vpp = sep->se_root = zfsctl_snapshot_mknode(dvp, dmu_objset_id(snap)); 645789Sahrens avl_insert(&sdp->sd_snaps, sep, where); 646789Sahrens 647789Sahrens dmu_objset_close(snap); 648789Sahrens domount: 649789Sahrens mountpoint_len = strlen(refstr_value(dvp->v_vfsp->vfs_mntpt)) + 650789Sahrens strlen("/.zfs/snapshot/") + strlen(nm) + 1; 651789Sahrens mountpoint = kmem_alloc(mountpoint_len, KM_SLEEP); 652789Sahrens (void) snprintf(mountpoint, mountpoint_len, "%s/.zfs/snapshot/%s", 653789Sahrens refstr_value(dvp->v_vfsp->vfs_mntpt), nm); 654789Sahrens 655789Sahrens margs.spec = snapname; 656789Sahrens margs.dir = mountpoint; 657789Sahrens margs.flags = MS_SYSSPACE | MS_NOMNTTAB; 658789Sahrens margs.fstype = "zfs"; 659789Sahrens margs.dataptr = NULL; 660789Sahrens margs.datalen = 0; 661789Sahrens margs.optptr = NULL; 662789Sahrens margs.optlen = 0; 663789Sahrens 664789Sahrens err = domount("zfs", &margs, *vpp, kcred, &vfsp); 665789Sahrens kmem_free(mountpoint, mountpoint_len); 666789Sahrens 667816Smaybee if (err == 0) { 668816Smaybee /* 669816Smaybee * Return the mounted root rather than the covered mount point. 670816Smaybee */ 671816Smaybee VFS_RELE(vfsp); 672816Smaybee err = traverse(vpp); 673816Smaybee } 674789Sahrens 675816Smaybee if (err == 0) { 676816Smaybee /* 677816Smaybee * Fix up the root vnode. 678816Smaybee */ 679816Smaybee ASSERT(VTOZ(*vpp)->z_zfsvfs != zfsvfs); 680816Smaybee VTOZ(*vpp)->z_zfsvfs->z_parent = zfsvfs; 681816Smaybee (*vpp)->v_vfsp = zfsvfs->z_vfs; 682816Smaybee (*vpp)->v_flag &= ~VROOT; 683816Smaybee } 684789Sahrens mutex_exit(&sdp->sd_lock); 685789Sahrens ZFS_EXIT(zfsvfs); 686789Sahrens 687816Smaybee if (err) 688816Smaybee VN_RELE(*vpp); 689816Smaybee return (err); 690789Sahrens } 691789Sahrens 692789Sahrens /* ARGSUSED */ 693789Sahrens static int 694789Sahrens zfsctl_snapdir_readdir_cb(vnode_t *vp, struct dirent64 *dp, int *eofp, 695789Sahrens offset_t *offp, offset_t *nextp, void *data) 696789Sahrens { 697789Sahrens zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data; 698789Sahrens char snapname[MAXNAMELEN]; 699789Sahrens uint64_t id, cookie; 700789Sahrens 701789Sahrens ZFS_ENTER(zfsvfs); 702789Sahrens 703789Sahrens cookie = *offp; 704789Sahrens if (dmu_snapshot_list_next(zfsvfs->z_os, MAXNAMELEN, snapname, &id, 705789Sahrens &cookie) == ENOENT) { 706789Sahrens *eofp = 1; 707789Sahrens ZFS_EXIT(zfsvfs); 708789Sahrens return (0); 709789Sahrens } 710789Sahrens 711789Sahrens (void) strcpy(dp->d_name, snapname); 712789Sahrens dp->d_ino = ZFSCTL_INO_SNAP(id); 713789Sahrens *nextp = cookie; 714789Sahrens 715789Sahrens ZFS_EXIT(zfsvfs); 716789Sahrens 717789Sahrens return (0); 718789Sahrens } 719789Sahrens 720789Sahrens vnode_t * 721789Sahrens zfsctl_mknode_snapdir(vnode_t *pvp) 722789Sahrens { 723789Sahrens vnode_t *vp; 724789Sahrens zfsctl_snapdir_t *sdp; 725789Sahrens 726789Sahrens vp = gfs_dir_create(sizeof (zfsctl_snapdir_t), pvp, 727789Sahrens zfsctl_ops_snapdir, NULL, NULL, MAXNAMELEN, 728789Sahrens zfsctl_snapdir_readdir_cb, NULL); 729789Sahrens sdp = vp->v_data; 730789Sahrens sdp->sd_node.zc_id = ZFSCTL_INO_SNAPDIR; 731789Sahrens mutex_init(&sdp->sd_lock, NULL, MUTEX_DEFAULT, NULL); 732789Sahrens avl_create(&sdp->sd_snaps, snapentry_compare, 733789Sahrens sizeof (zfs_snapentry_t), offsetof(zfs_snapentry_t, se_node)); 734789Sahrens return (vp); 735789Sahrens } 736789Sahrens 737789Sahrens /* ARGSUSED */ 738789Sahrens static int 739789Sahrens zfsctl_snapdir_getattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr) 740789Sahrens { 741789Sahrens zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data; 742789Sahrens zfsctl_snapdir_t *sdp = vp->v_data; 743789Sahrens 744789Sahrens ZFS_ENTER(zfsvfs); 745789Sahrens zfsctl_common_getattr(vp, vap); 746789Sahrens vap->va_nodeid = gfs_file_inode(vp); 747789Sahrens vap->va_nlink = vap->va_size = avl_numnodes(&sdp->sd_snaps) + 2; 748789Sahrens ZFS_EXIT(zfsvfs); 749789Sahrens 750789Sahrens return (0); 751789Sahrens } 752789Sahrens 753789Sahrens static void 754789Sahrens zfsctl_snapdir_inactive(vnode_t *vp, cred_t *cr) 755789Sahrens { 756789Sahrens zfsctl_snapdir_t *sdp = vp->v_data; 757789Sahrens 758789Sahrens ASSERT(avl_numnodes(&sdp->sd_snaps) == 0); 759789Sahrens mutex_destroy(&sdp->sd_lock); 760789Sahrens avl_destroy(&sdp->sd_snaps); 761789Sahrens gfs_vop_inactive(vp, cr); 762789Sahrens } 763789Sahrens 764789Sahrens static const fs_operation_def_t zfsctl_tops_snapdir[] = { 765789Sahrens { VOPNAME_OPEN, zfsctl_common_open }, 766789Sahrens { VOPNAME_CLOSE, zfsctl_common_close }, 767789Sahrens { VOPNAME_IOCTL, fs_inval }, 768789Sahrens { VOPNAME_GETATTR, zfsctl_snapdir_getattr }, 769789Sahrens { VOPNAME_ACCESS, zfsctl_common_access }, 770789Sahrens { VOPNAME_RENAME, zfsctl_snapdir_rename }, 771789Sahrens { VOPNAME_RMDIR, zfsctl_snapdir_remove }, 772789Sahrens { VOPNAME_READDIR, gfs_vop_readdir }, 773789Sahrens { VOPNAME_LOOKUP, zfsctl_snapdir_lookup }, 774789Sahrens { VOPNAME_SEEK, fs_seek }, 775789Sahrens { VOPNAME_INACTIVE, (fs_generic_func_p) zfsctl_snapdir_inactive }, 776789Sahrens { VOPNAME_FID, zfsctl_common_fid }, 777789Sahrens { NULL } 778789Sahrens }; 779789Sahrens 780789Sahrens static vnode_t * 781789Sahrens zfsctl_snapshot_mknode(vnode_t *pvp, uint64_t objset) 782789Sahrens { 783789Sahrens vnode_t *vp; 784789Sahrens zfsctl_node_t *zcp; 785789Sahrens 786789Sahrens vp = gfs_dir_create(sizeof (zfsctl_node_t), pvp, 787789Sahrens zfsctl_ops_snapshot, NULL, NULL, MAXNAMELEN, NULL, NULL); 788789Sahrens zcp = vp->v_data; 789789Sahrens zcp->zc_id = objset; 790789Sahrens 791789Sahrens return (vp); 792789Sahrens } 793789Sahrens 794789Sahrens static void 795789Sahrens zfsctl_snapshot_inactive(vnode_t *vp, cred_t *cr) 796789Sahrens { 797789Sahrens zfsctl_snapdir_t *sdp; 798789Sahrens zfs_snapentry_t *sep, *next; 799789Sahrens vnode_t *dvp; 800789Sahrens 801789Sahrens VERIFY(gfs_dir_lookup(vp, "..", &dvp) == 0); 802789Sahrens sdp = dvp->v_data; 803789Sahrens 804789Sahrens mutex_enter(&sdp->sd_lock); 805789Sahrens 806789Sahrens if (vp->v_count > 1) { 807789Sahrens mutex_exit(&sdp->sd_lock); 808789Sahrens return; 809789Sahrens } 810789Sahrens ASSERT(!vn_ismntpt(vp)); 811789Sahrens 812789Sahrens sep = avl_first(&sdp->sd_snaps); 813789Sahrens while (sep != NULL) { 814789Sahrens next = AVL_NEXT(&sdp->sd_snaps, sep); 815789Sahrens 816789Sahrens if (sep->se_root == vp) { 817789Sahrens avl_remove(&sdp->sd_snaps, sep); 818789Sahrens kmem_free(sep->se_name, strlen(sep->se_name) + 1); 819789Sahrens kmem_free(sep, sizeof (zfs_snapentry_t)); 820789Sahrens break; 821789Sahrens } 822789Sahrens sep = next; 823789Sahrens } 824789Sahrens ASSERT(sep != NULL); 825789Sahrens 826789Sahrens mutex_exit(&sdp->sd_lock); 827789Sahrens VN_RELE(dvp); 828789Sahrens 829789Sahrens gfs_vop_inactive(vp, cr); 830789Sahrens } 831789Sahrens 832789Sahrens 833789Sahrens /* 834789Sahrens * These VP's should never see the light of day. They should always 835789Sahrens * be covered. 836789Sahrens */ 837789Sahrens static const fs_operation_def_t zfsctl_tops_snapshot[] = { 838789Sahrens VOPNAME_INACTIVE, (fs_generic_func_p) zfsctl_snapshot_inactive, 839789Sahrens NULL, NULL 840789Sahrens }; 841789Sahrens 842789Sahrens int 843789Sahrens zfsctl_lookup_objset(vfs_t *vfsp, uint64_t objsetid, zfsvfs_t **zfsvfsp) 844789Sahrens { 845789Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 846789Sahrens vnode_t *dvp, *vp; 847789Sahrens zfsctl_snapdir_t *sdp; 848789Sahrens zfsctl_node_t *zcp; 849789Sahrens zfs_snapentry_t *sep; 850789Sahrens int error; 851789Sahrens 852789Sahrens ASSERT(zfsvfs->z_ctldir != NULL); 853789Sahrens error = zfsctl_root_lookup(zfsvfs->z_ctldir, "snapshot", &dvp, 854789Sahrens NULL, 0, NULL, kcred); 855789Sahrens if (error != 0) 856789Sahrens return (error); 857789Sahrens sdp = dvp->v_data; 858789Sahrens 859789Sahrens mutex_enter(&sdp->sd_lock); 860789Sahrens sep = avl_first(&sdp->sd_snaps); 861789Sahrens while (sep != NULL) { 862789Sahrens vp = sep->se_root; 863789Sahrens zcp = vp->v_data; 864789Sahrens if (zcp->zc_id == objsetid) 865789Sahrens break; 866789Sahrens 867789Sahrens sep = AVL_NEXT(&sdp->sd_snaps, sep); 868789Sahrens } 869789Sahrens 870789Sahrens if (sep != NULL) { 871789Sahrens VN_HOLD(vp); 872789Sahrens error = traverse(&vp); 873789Sahrens if (error == 0) 874789Sahrens *zfsvfsp = VTOZ(vp)->z_zfsvfs; 875789Sahrens VN_RELE(vp); 876789Sahrens } else { 877789Sahrens error = EINVAL; 878789Sahrens } 879789Sahrens 880789Sahrens mutex_exit(&sdp->sd_lock); 881789Sahrens VN_RELE(dvp); 882789Sahrens 883789Sahrens return (error); 884789Sahrens } 885789Sahrens 886789Sahrens /* 887789Sahrens * Unmount any snapshots for the given filesystem. This is called from 888789Sahrens * zfs_umount() - if we have a ctldir, then go through and unmount all the 889789Sahrens * snapshots. 890789Sahrens */ 891789Sahrens int 892789Sahrens zfsctl_umount_snapshots(vfs_t *vfsp, int fflags, cred_t *cr) 893789Sahrens { 894789Sahrens zfsvfs_t *zfsvfs = vfsp->vfs_data; 895789Sahrens vnode_t *dvp, *svp; 896789Sahrens zfsctl_snapdir_t *sdp; 897789Sahrens zfs_snapentry_t *sep, *next; 898789Sahrens int error; 899789Sahrens 900789Sahrens ASSERT(zfsvfs->z_ctldir != NULL); 901789Sahrens error = zfsctl_root_lookup(zfsvfs->z_ctldir, "snapshot", &dvp, 902789Sahrens NULL, 0, NULL, cr); 903789Sahrens if (error != 0) 904789Sahrens return (error); 905789Sahrens sdp = dvp->v_data; 906789Sahrens 907789Sahrens mutex_enter(&sdp->sd_lock); 908789Sahrens 909789Sahrens sep = avl_first(&sdp->sd_snaps); 910789Sahrens while (sep != NULL) { 911789Sahrens svp = sep->se_root; 912789Sahrens next = AVL_NEXT(&sdp->sd_snaps, sep); 913789Sahrens 914789Sahrens /* 915789Sahrens * If this snapshot is not mounted, then it must 916789Sahrens * have just been unmounted by somebody else, and 917789Sahrens * will be cleaned up by zfsctl_snapdir_inactive(). 918789Sahrens */ 919789Sahrens if (vn_ismntpt(svp)) { 920789Sahrens if ((error = vn_vfswlock(svp)) != 0) 921789Sahrens goto out; 922789Sahrens 923789Sahrens VN_HOLD(svp); 924789Sahrens error = dounmount(vn_mountedvfs(svp), fflags, cr); 925789Sahrens if (error) { 926789Sahrens VN_RELE(svp); 927789Sahrens goto out; 928789Sahrens } 929789Sahrens 930789Sahrens avl_remove(&sdp->sd_snaps, sep); 931789Sahrens kmem_free(sep->se_name, strlen(sep->se_name) + 1); 932789Sahrens kmem_free(sep, sizeof (zfs_snapentry_t)); 933789Sahrens 934789Sahrens /* 935789Sahrens * We can't use VN_RELE(), as that will try to 936789Sahrens * invoke zfsctl_snapdir_inactive(), and that 937789Sahrens * would lead to an attempt to re-grab the sd_lock. 938789Sahrens */ 939789Sahrens ASSERT3U(svp->v_count, ==, 1); 940789Sahrens gfs_vop_inactive(svp, cr); 941789Sahrens } 942789Sahrens sep = next; 943789Sahrens } 944789Sahrens out: 945789Sahrens mutex_exit(&sdp->sd_lock); 946789Sahrens VN_RELE(dvp); 947789Sahrens 948789Sahrens return (error); 949789Sahrens } 950