FreeBSD ZFS
The Zettabyte File System
|
00001 /* 00002 * CDDL HEADER START 00003 * 00004 * The contents of this file are subject to the terms of the 00005 * Common Development and Distribution License (the "License"). 00006 * You may not use this file except in compliance with the License. 00007 * 00008 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 00009 * or http://www.opensolaris.org/os/licensing. 00010 * See the License for the specific language governing permissions 00011 * and limitations under the License. 00012 * 00013 * When distributing Covered Code, include this CDDL HEADER in each 00014 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 00015 * If applicable, add the following below this CDDL HEADER, with the 00016 * fields enclosed by brackets "[]" replaced with your own identifying 00017 * information: Portions Copyright [yyyy] [name of copyright owner] 00018 * 00019 * CDDL HEADER END 00020 */ 00021 /* 00022 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 00023 * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>. 00024 * All rights reserved. 00025 */ 00026 00071 #include <sys/zfs_context.h> 00072 #include <sys/zfs_ctldir.h> 00073 #include <sys/zfs_ioctl.h> 00074 #include <sys/zfs_vfsops.h> 00075 #include <sys/namei.h> 00076 #include <sys/gfs.h> 00077 #include <sys/stat.h> 00078 #include <sys/dmu.h> 00079 #include <sys/dsl_deleg.h> 00080 #include <sys/mount.h> 00081 #include <sys/sunddi.h> 00082 00083 #include "zfs_namecheck.h" 00084 00085 typedef struct zfsctl_node { 00086 gfs_dir_t zc_gfs_private; 00087 uint64_t zc_id; 00088 timestruc_t zc_cmtime; 00089 } zfsctl_node_t; 00090 00091 typedef struct zfsctl_snapdir { 00092 zfsctl_node_t sd_node; 00093 kmutex_t sd_lock; 00094 avl_tree_t sd_snaps; 00095 } zfsctl_snapdir_t; 00096 00097 typedef struct { 00098 char *se_name; 00099 vnode_t *se_root; 00100 avl_node_t se_node; 00101 } zfs_snapentry_t; 00102 00103 static int 00104 snapentry_compare(const void *a, const void *b) 00105 { 00106 const zfs_snapentry_t *sa = a; 00107 const zfs_snapentry_t *sb = b; 00108 int ret = strcmp(sa->se_name, sb->se_name); 00109 00110 if (ret < 0) 00111 return (-1); 00112 else if (ret > 0) 00113 return (1); 00114 else 00115 return (0); 00116 } 00117 00118 #ifdef sun 00119 vnodeops_t *zfsctl_ops_root; 00120 vnodeops_t *zfsctl_ops_snapdir; 00121 vnodeops_t *zfsctl_ops_snapshot; 00122 vnodeops_t *zfsctl_ops_shares; 00123 vnodeops_t *zfsctl_ops_shares_dir; 00124 00125 static const fs_operation_def_t zfsctl_tops_root[]; 00126 static const fs_operation_def_t zfsctl_tops_snapdir[]; 00127 static const fs_operation_def_t zfsctl_tops_snapshot[]; 00128 static const fs_operation_def_t zfsctl_tops_shares[]; 00129 #else /* !sun */ 00130 static struct vop_vector zfsctl_ops_root; 00131 static struct vop_vector zfsctl_ops_snapdir; 00132 static struct vop_vector zfsctl_ops_snapshot; 00133 static struct vop_vector zfsctl_ops_shares; 00134 static struct vop_vector zfsctl_ops_shares_dir; 00135 #endif /* !sun */ 00136 00137 static vnode_t *zfsctl_mknode_snapdir(vnode_t *); 00138 static vnode_t *zfsctl_mknode_shares(vnode_t *); 00139 static vnode_t *zfsctl_snapshot_mknode(vnode_t *, uint64_t objset); 00140 static int zfsctl_unmount_snap(zfs_snapentry_t *, int, cred_t *); 00141 00142 #ifdef sun 00143 static gfs_opsvec_t zfsctl_opsvec[] = { 00144 { ".zfs", zfsctl_tops_root, &zfsctl_ops_root }, 00145 { ".zfs/snapshot", zfsctl_tops_snapdir, &zfsctl_ops_snapdir }, 00146 { ".zfs/snapshot/vnode", zfsctl_tops_snapshot, &zfsctl_ops_snapshot }, 00147 { ".zfs/shares", zfsctl_tops_shares, &zfsctl_ops_shares_dir }, 00148 { ".zfs/shares/vnode", zfsctl_tops_shares, &zfsctl_ops_shares }, 00149 { NULL } 00150 }; 00151 #endif /* sun */ 00152 00157 static gfs_dirent_t zfsctl_root_entries[] = { 00158 { "snapshot", zfsctl_mknode_snapdir, GFS_CACHE_VNODE }, 00159 { "shares", zfsctl_mknode_shares, GFS_CACHE_VNODE }, 00160 { NULL } 00161 }; 00162 00163 /* include . and .. in the calculation */ 00164 #define NROOT_ENTRIES ((sizeof (zfsctl_root_entries) / \ 00165 sizeof (gfs_dirent_t)) + 1) 00166 00167 00173 void 00174 zfsctl_init(void) 00175 { 00176 #ifdef sun 00177 VERIFY(gfs_make_opsvec(zfsctl_opsvec) == 0); 00178 #endif 00179 } 00180 00181 void 00182 zfsctl_fini(void) 00183 { 00184 #ifdef sun 00185 /* 00186 * Remove vfsctl vnode ops 00187 */ 00188 if (zfsctl_ops_root) 00189 vn_freevnodeops(zfsctl_ops_root); 00190 if (zfsctl_ops_snapdir) 00191 vn_freevnodeops(zfsctl_ops_snapdir); 00192 if (zfsctl_ops_snapshot) 00193 vn_freevnodeops(zfsctl_ops_snapshot); 00194 if (zfsctl_ops_shares) 00195 vn_freevnodeops(zfsctl_ops_shares); 00196 if (zfsctl_ops_shares_dir) 00197 vn_freevnodeops(zfsctl_ops_shares_dir); 00198 00199 zfsctl_ops_root = NULL; 00200 zfsctl_ops_snapdir = NULL; 00201 zfsctl_ops_snapshot = NULL; 00202 zfsctl_ops_shares = NULL; 00203 zfsctl_ops_shares_dir = NULL; 00204 #endif /* sun */ 00205 } 00206 00207 boolean_t 00208 zfsctl_is_node(vnode_t *vp) 00209 { 00210 return (vn_matchops(vp, zfsctl_ops_root) || 00211 vn_matchops(vp, zfsctl_ops_snapdir) || 00212 vn_matchops(vp, zfsctl_ops_snapshot) || 00213 vn_matchops(vp, zfsctl_ops_shares) || 00214 vn_matchops(vp, zfsctl_ops_shares_dir)); 00215 00216 } 00217 00222 /* ARGSUSED */ 00223 static ino64_t 00224 zfsctl_root_inode_cb(vnode_t *vp, int index) 00225 { 00226 zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data; 00227 00228 ASSERT(index <= 2); 00229 00230 if (index == 0) 00231 return (ZFSCTL_INO_SNAPDIR); 00232 00233 return (zfsvfs->z_shares_dir); 00234 } 00235 00242 void 00243 zfsctl_create(zfsvfs_t *zfsvfs) 00244 { 00245 vnode_t *vp, *rvp; 00246 zfsctl_node_t *zcp; 00247 uint64_t crtime[2]; 00248 00249 ASSERT(zfsvfs->z_ctldir == NULL); 00250 00251 vp = gfs_root_create(sizeof (zfsctl_node_t), zfsvfs->z_vfs, 00252 &zfsctl_ops_root, ZFSCTL_INO_ROOT, zfsctl_root_entries, 00253 zfsctl_root_inode_cb, MAXNAMELEN, NULL, NULL); 00254 zcp = vp->v_data; 00255 zcp->zc_id = ZFSCTL_INO_ROOT; 00256 00257 VERIFY(VFS_ROOT(zfsvfs->z_vfs, LK_EXCLUSIVE, &rvp) == 0); 00258 VERIFY(0 == sa_lookup(VTOZ(rvp)->z_sa_hdl, SA_ZPL_CRTIME(zfsvfs), 00259 &crtime, sizeof (crtime))); 00260 ZFS_TIME_DECODE(&zcp->zc_cmtime, crtime); 00261 VN_URELE(rvp); 00262 00263 /* 00264 * We're only faking the fact that we have a root of a filesystem for 00265 * the sake of the GFS interfaces. Undo the flag manipulation it did 00266 * for us. 00267 */ 00268 vp->v_vflag &= ~VV_ROOT; 00269 00270 zfsvfs->z_ctldir = vp; 00271 00272 VOP_UNLOCK(vp, 0); 00273 } 00274 00280 void 00281 zfsctl_destroy(zfsvfs_t *zfsvfs) 00282 { 00283 VN_RELE(zfsvfs->z_ctldir); 00284 zfsvfs->z_ctldir = NULL; 00285 } 00286 00291 vnode_t * 00292 zfsctl_root(znode_t *zp) 00293 { 00294 ASSERT(zfs_has_ctldir(zp)); 00295 VN_HOLD(zp->z_zfsvfs->z_ctldir); 00296 return (zp->z_zfsvfs->z_ctldir); 00297 } 00298 00302 /* ARGSUSED */ 00303 static int 00304 zfsctl_common_open(struct vop_open_args *ap) 00305 { 00306 int flags = ap->a_mode; 00307 00308 if (flags & FWRITE) 00309 return (EACCES); 00310 00311 return (0); 00312 } 00313 00317 /* ARGSUSED */ 00318 static int 00319 zfsctl_common_close(struct vop_close_args *ap) 00320 { 00321 return (0); 00322 } 00323 00327 /* ARGSUSED */ 00328 static int 00329 zfsctl_common_access(ap) 00330 struct vop_access_args /* { 00331 struct vnode *a_vp; 00332 accmode_t a_accmode; 00333 struct ucred *a_cred; 00334 struct thread *a_td; 00335 } */ *ap; 00336 { 00337 accmode_t accmode = ap->a_accmode; 00338 00339 #ifdef TODO 00340 if (flags & V_ACE_MASK) { 00341 if (accmode & ACE_ALL_WRITE_PERMS) 00342 return (EACCES); 00343 } else { 00344 #endif 00345 if (accmode & VWRITE) 00346 return (EACCES); 00347 #ifdef TODO 00348 } 00349 #endif 00350 00351 return (0); 00352 } 00353 00357 static void 00358 zfsctl_common_getattr(vnode_t *vp, vattr_t *vap) 00359 { 00360 timestruc_t now; 00361 00362 vap->va_uid = 0; 00363 vap->va_gid = 0; 00364 vap->va_rdev = 0; 00365 /* 00366 * We are a purely virtual object, so we have no 00367 * blocksize or allocated blocks. 00368 */ 00369 vap->va_blksize = 0; 00370 vap->va_nblocks = 0; 00371 vap->va_seq = 0; 00372 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 00373 vap->va_mode = S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | 00374 S_IROTH | S_IXOTH; 00375 vap->va_type = VDIR; 00376 /* 00377 * We live in the now (for atime). 00378 */ 00379 gethrestime(&now); 00380 vap->va_atime = now; 00381 /* FreeBSD: Reset chflags(2) flags. */ 00382 vap->va_flags = 0; 00383 } 00384 00385 /*ARGSUSED*/ 00386 static int 00387 zfsctl_common_fid(ap) 00388 struct vop_fid_args /* { 00389 struct vnode *a_vp; 00390 struct fid *a_fid; 00391 } */ *ap; 00392 { 00393 vnode_t *vp = ap->a_vp; 00394 fid_t *fidp = (void *)ap->a_fid; 00395 zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data; 00396 zfsctl_node_t *zcp = vp->v_data; 00397 uint64_t object = zcp->zc_id; 00398 zfid_short_t *zfid; 00399 int i; 00400 00401 ZFS_ENTER(zfsvfs); 00402 00403 fidp->fid_len = SHORT_FID_LEN; 00404 00405 zfid = (zfid_short_t *)fidp; 00406 00407 zfid->zf_len = SHORT_FID_LEN; 00408 00409 for (i = 0; i < sizeof (zfid->zf_object); i++) 00410 zfid->zf_object[i] = (uint8_t)(object >> (8 * i)); 00411 00412 /* .zfs znodes always have a generation number of 0 */ 00413 for (i = 0; i < sizeof (zfid->zf_gen); i++) 00414 zfid->zf_gen[i] = 0; 00415 00416 ZFS_EXIT(zfsvfs); 00417 return (0); 00418 } 00419 00420 00421 /*ARGSUSED*/ 00422 static int 00423 zfsctl_shares_fid(ap) 00424 struct vop_fid_args /* { 00425 struct vnode *a_vp; 00426 struct fid *a_fid; 00427 } */ *ap; 00428 { 00429 vnode_t *vp = ap->a_vp; 00430 fid_t *fidp = (void *)ap->a_fid; 00431 zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data; 00432 znode_t *dzp; 00433 int error; 00434 00435 ZFS_ENTER(zfsvfs); 00436 00437 if (zfsvfs->z_shares_dir == 0) { 00438 ZFS_EXIT(zfsvfs); 00439 return (ENOTSUP); 00440 } 00441 00442 if ((error = zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp)) == 0) { 00443 error = VOP_FID(ZTOV(dzp), fidp); 00444 VN_RELE(ZTOV(dzp)); 00445 } 00446 00447 ZFS_EXIT(zfsvfs); 00448 return (error); 00449 } 00450 00451 static int 00452 zfsctl_common_reclaim(ap) 00453 struct vop_reclaim_args /* { 00454 struct vnode *a_vp; 00455 struct thread *a_td; 00456 } */ *ap; 00457 { 00458 vnode_t *vp = ap->a_vp; 00459 00460 /* 00461 * Destroy the vm object and flush associated pages. 00462 */ 00463 vnode_destroy_vobject(vp); 00464 VI_LOCK(vp); 00465 vp->v_data = NULL; 00466 VI_UNLOCK(vp); 00467 return (0); 00468 } 00469 00482 #define ZFSCTL_INO_SNAP(id) (id) 00483 00487 /* ARGSUSED */ 00488 static int 00489 zfsctl_root_getattr(ap) 00490 struct vop_getattr_args /* { 00491 struct vnode *a_vp; 00492 struct vattr *a_vap; 00493 struct ucred *a_cred; 00494 } */ *ap; 00495 { 00496 struct vnode *vp = ap->a_vp; 00497 struct vattr *vap = ap->a_vap; 00498 zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data; 00499 zfsctl_node_t *zcp = vp->v_data; 00500 00501 ZFS_ENTER(zfsvfs); 00502 vap->va_nodeid = ZFSCTL_INO_ROOT; 00503 vap->va_nlink = vap->va_size = NROOT_ENTRIES; 00504 vap->va_mtime = vap->va_ctime = zcp->zc_cmtime; 00505 vap->va_birthtime = vap->va_ctime; 00506 00507 zfsctl_common_getattr(vp, vap); 00508 ZFS_EXIT(zfsvfs); 00509 00510 return (0); 00511 } 00512 00516 /* ARGSUSED */ 00517 int 00518 zfsctl_root_lookup(vnode_t *dvp, char *nm, vnode_t **vpp, pathname_t *pnp, 00519 int flags, vnode_t *rdir, cred_t *cr, caller_context_t *ct, 00520 int *direntflags, pathname_t *realpnp) 00521 { 00522 zfsvfs_t *zfsvfs = dvp->v_vfsp->vfs_data; 00523 int err; 00524 00525 /* 00526 * No extended attributes allowed under .zfs 00527 */ 00528 if (flags & LOOKUP_XATTR) 00529 return (EINVAL); 00530 00531 ZFS_ENTER(zfsvfs); 00532 00533 if (strcmp(nm, "..") == 0) { 00534 err = VFS_ROOT(dvp->v_vfsp, LK_EXCLUSIVE, vpp); 00535 if (err == 0) 00536 VOP_UNLOCK(*vpp, 0); 00537 } else { 00538 err = gfs_vop_lookup(dvp, nm, vpp, pnp, flags, rdir, 00539 cr, ct, direntflags, realpnp); 00540 } 00541 00542 ZFS_EXIT(zfsvfs); 00543 00544 return (err); 00545 } 00546 00547 #ifdef sun 00548 static int 00549 zfsctl_pathconf(vnode_t *vp, int cmd, ulong_t *valp, cred_t *cr, 00550 caller_context_t *ct) 00551 { 00552 /* 00553 * We only care about ACL_ENABLED so that libsec can 00554 * display ACL correctly and not default to POSIX draft. 00555 */ 00556 if (cmd == _PC_ACL_ENABLED) { 00557 *valp = _ACL_ACE_ENABLED; 00558 return (0); 00559 } 00560 00561 return (fs_pathconf(vp, cmd, valp, cr, ct)); 00562 } 00563 #endif /* sun */ 00564 00565 #ifdef sun 00566 static const fs_operation_def_t zfsctl_tops_root[] = { 00567 { VOPNAME_OPEN, { .vop_open = zfsctl_common_open } }, 00568 { VOPNAME_CLOSE, { .vop_close = zfsctl_common_close } }, 00569 { VOPNAME_IOCTL, { .error = fs_inval } }, 00570 { VOPNAME_GETATTR, { .vop_getattr = zfsctl_root_getattr } }, 00571 { VOPNAME_ACCESS, { .vop_access = zfsctl_common_access } }, 00572 { VOPNAME_READDIR, { .vop_readdir = gfs_vop_readdir } }, 00573 { VOPNAME_LOOKUP, { .vop_lookup = zfsctl_root_lookup } }, 00574 { VOPNAME_SEEK, { .vop_seek = fs_seek } }, 00575 { VOPNAME_INACTIVE, { .vop_inactive = gfs_vop_inactive } }, 00576 { VOPNAME_PATHCONF, { .vop_pathconf = zfsctl_pathconf } }, 00577 { VOPNAME_FID, { .vop_fid = zfsctl_common_fid } }, 00578 { NULL } 00579 }; 00580 #endif /* sun */ 00581 00585 /* ARGSUSED */ 00586 int 00587 zfsctl_freebsd_root_lookup(ap) 00588 struct vop_lookup_args /* { 00589 struct vnode *a_dvp; 00590 struct vnode **a_vpp; 00591 struct componentname *a_cnp; 00592 } */ *ap; 00593 { 00594 vnode_t *dvp = ap->a_dvp; 00595 vnode_t **vpp = ap->a_vpp; 00596 cred_t *cr = ap->a_cnp->cn_cred; 00597 int flags = ap->a_cnp->cn_flags; 00598 int nameiop = ap->a_cnp->cn_nameiop; 00599 char nm[NAME_MAX + 1]; 00600 int err; 00601 00602 if ((flags & ISLASTCN) && (nameiop == RENAME || nameiop == CREATE)) 00603 return (EOPNOTSUPP); 00604 00605 ASSERT(ap->a_cnp->cn_namelen < sizeof(nm)); 00606 strlcpy(nm, ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen + 1); 00607 00608 err = zfsctl_root_lookup(dvp, nm, vpp, NULL, 0, NULL, cr, NULL, NULL, NULL); 00609 if (err == 0 && (nm[0] != '.' || nm[1] != '\0')) 00610 vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); 00611 return (err); 00612 } 00613 00614 static struct vop_vector zfsctl_ops_root = { 00615 .vop_default = &default_vnodeops, 00616 .vop_open = zfsctl_common_open, 00617 .vop_close = zfsctl_common_close, 00618 .vop_ioctl = VOP_EINVAL, 00619 .vop_getattr = zfsctl_root_getattr, 00620 .vop_access = zfsctl_common_access, 00621 .vop_readdir = gfs_vop_readdir, 00622 .vop_lookup = zfsctl_freebsd_root_lookup, 00623 .vop_inactive = gfs_vop_inactive, 00624 .vop_reclaim = zfsctl_common_reclaim, 00625 #ifdef TODO 00626 .vop_pathconf = zfsctl_pathconf, 00627 #endif 00628 .vop_fid = zfsctl_common_fid, 00629 }; 00630 00631 static int 00632 zfsctl_snapshot_zname(vnode_t *vp, const char *name, int len, char *zname) 00633 { 00634 objset_t *os = ((zfsvfs_t *)((vp)->v_vfsp->vfs_data))->z_os; 00635 00636 if (snapshot_namecheck(name, NULL, NULL) != 0) 00637 return (EILSEQ); 00638 dmu_objset_name(os, zname); 00639 if (strlen(zname) + 1 + strlen(name) >= len) 00640 return (ENAMETOOLONG); 00641 (void) strcat(zname, "@"); 00642 (void) strcat(zname, name); 00643 return (0); 00644 } 00645 00646 static int 00647 zfsctl_unmount_snap(zfs_snapentry_t *sep, int fflags, cred_t *cr) 00648 { 00649 vnode_t *svp = sep->se_root; 00650 int error; 00651 00652 ASSERT(vn_ismntpt(svp)); 00653 00654 /* this will be dropped by dounmount() */ 00655 if ((error = vn_vfswlock(svp)) != 0) 00656 return (error); 00657 00658 #ifdef sun 00659 VN_HOLD(svp); 00660 error = dounmount(vn_mountedvfs(svp), fflags, cr); 00661 if (error) { 00662 VN_RELE(svp); 00663 return (error); 00664 } 00665 00666 /* 00667 * We can't use VN_RELE(), as that will try to invoke 00668 * zfsctl_snapdir_inactive(), which would cause us to destroy 00669 * the sd_lock mutex held by our caller. 00670 */ 00671 ASSERT(svp->v_count == 1); 00672 gfs_vop_inactive(svp, cr, NULL); 00673 00674 kmem_free(sep->se_name, strlen(sep->se_name) + 1); 00675 kmem_free(sep, sizeof (zfs_snapentry_t)); 00676 00677 return (0); 00678 #else /* !sun */ 00679 return (dounmount(vn_mountedvfs(svp), fflags, curthread)); 00680 #endif /* !sun */ 00681 } 00682 00683 #ifdef sun 00684 static void 00685 zfsctl_rename_snap(zfsctl_snapdir_t *sdp, zfs_snapentry_t *sep, const char *nm) 00686 { 00687 avl_index_t where; 00688 vfs_t *vfsp; 00689 refstr_t *pathref; 00690 char newpath[MAXNAMELEN]; 00691 char *tail; 00692 00693 ASSERT(MUTEX_HELD(&sdp->sd_lock)); 00694 ASSERT(sep != NULL); 00695 00696 vfsp = vn_mountedvfs(sep->se_root); 00697 ASSERT(vfsp != NULL); 00698 00699 vfs_lock_wait(vfsp); 00700 00701 /* 00702 * Change the name in the AVL tree. 00703 */ 00704 avl_remove(&sdp->sd_snaps, sep); 00705 kmem_free(sep->se_name, strlen(sep->se_name) + 1); 00706 sep->se_name = kmem_alloc(strlen(nm) + 1, KM_SLEEP); 00707 (void) strcpy(sep->se_name, nm); 00708 VERIFY(avl_find(&sdp->sd_snaps, sep, &where) == NULL); 00709 avl_insert(&sdp->sd_snaps, sep, where); 00710 00711 /* 00712 * Change the current mountpoint info: 00713 * - update the tail of the mntpoint path 00714 * - update the tail of the resource path 00715 */ 00716 pathref = vfs_getmntpoint(vfsp); 00717 (void) strncpy(newpath, refstr_value(pathref), sizeof (newpath)); 00718 VERIFY((tail = strrchr(newpath, '/')) != NULL); 00719 *(tail+1) = '\0'; 00720 ASSERT3U(strlen(newpath) + strlen(nm), <, sizeof (newpath)); 00721 (void) strcat(newpath, nm); 00722 refstr_rele(pathref); 00723 vfs_setmntpoint(vfsp, newpath, 0); 00724 00725 pathref = vfs_getresource(vfsp); 00726 (void) strncpy(newpath, refstr_value(pathref), sizeof (newpath)); 00727 VERIFY((tail = strrchr(newpath, '@')) != NULL); 00728 *(tail+1) = '\0'; 00729 ASSERT3U(strlen(newpath) + strlen(nm), <, sizeof (newpath)); 00730 (void) strcat(newpath, nm); 00731 refstr_rele(pathref); 00732 vfs_setresource(vfsp, newpath, 0); 00733 00734 vfs_unlock(vfsp); 00735 } 00736 #endif /* sun */ 00737 00738 #ifdef sun 00739 /*ARGSUSED*/ 00740 static int 00741 zfsctl_snapdir_rename(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, 00742 cred_t *cr, caller_context_t *ct, int flags) 00743 { 00744 zfsctl_snapdir_t *sdp = sdvp->v_data; 00745 zfs_snapentry_t search, *sep; 00746 zfsvfs_t *zfsvfs; 00747 avl_index_t where; 00748 char from[MAXNAMELEN], to[MAXNAMELEN]; 00749 char real[MAXNAMELEN]; 00750 int err; 00751 00752 zfsvfs = sdvp->v_vfsp->vfs_data; 00753 ZFS_ENTER(zfsvfs); 00754 00755 if ((flags & FIGNORECASE) || zfsvfs->z_case == ZFS_CASE_INSENSITIVE) { 00756 err = dmu_snapshot_realname(zfsvfs->z_os, snm, real, 00757 MAXNAMELEN, NULL); 00758 if (err == 0) { 00759 snm = real; 00760 } else if (err != ENOTSUP) { 00761 ZFS_EXIT(zfsvfs); 00762 return (err); 00763 } 00764 } 00765 00766 ZFS_EXIT(zfsvfs); 00767 00768 err = zfsctl_snapshot_zname(sdvp, snm, MAXNAMELEN, from); 00769 if (!err) 00770 err = zfsctl_snapshot_zname(tdvp, tnm, MAXNAMELEN, to); 00771 if (!err) 00772 err = zfs_secpolicy_rename_perms(from, to, cr); 00773 if (err) 00774 return (err); 00775 00776 /* 00777 * Cannot move snapshots out of the snapdir. 00778 */ 00779 if (sdvp != tdvp) 00780 return (EINVAL); 00781 00782 if (strcmp(snm, tnm) == 0) 00783 return (0); 00784 00785 mutex_enter(&sdp->sd_lock); 00786 00787 search.se_name = (char *)snm; 00788 if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) == NULL) { 00789 mutex_exit(&sdp->sd_lock); 00790 return (ENOENT); 00791 } 00792 00793 err = dmu_objset_rename(from, to, 0); 00794 if (err == 0) 00795 zfsctl_rename_snap(sdp, sep, tnm); 00796 00797 mutex_exit(&sdp->sd_lock); 00798 00799 return (err); 00800 } 00801 #endif /* sun */ 00802 00803 #ifdef sun 00804 /* ARGSUSED */ 00805 static int 00806 zfsctl_snapdir_remove(vnode_t *dvp, char *name, vnode_t *cwd, cred_t *cr, 00807 caller_context_t *ct, int flags) 00808 { 00809 zfsctl_snapdir_t *sdp = dvp->v_data; 00810 zfs_snapentry_t *sep; 00811 zfs_snapentry_t search; 00812 zfsvfs_t *zfsvfs; 00813 char snapname[MAXNAMELEN]; 00814 char real[MAXNAMELEN]; 00815 int err; 00816 00817 zfsvfs = dvp->v_vfsp->vfs_data; 00818 ZFS_ENTER(zfsvfs); 00819 00820 if ((flags & FIGNORECASE) || zfsvfs->z_case == ZFS_CASE_INSENSITIVE) { 00821 00822 err = dmu_snapshot_realname(zfsvfs->z_os, name, real, 00823 MAXNAMELEN, NULL); 00824 if (err == 0) { 00825 name = real; 00826 } else if (err != ENOTSUP) { 00827 ZFS_EXIT(zfsvfs); 00828 return (err); 00829 } 00830 } 00831 00832 ZFS_EXIT(zfsvfs); 00833 00834 err = zfsctl_snapshot_zname(dvp, name, MAXNAMELEN, snapname); 00835 if (!err) 00836 err = zfs_secpolicy_destroy_perms(snapname, cr); 00837 if (err) 00838 return (err); 00839 00840 mutex_enter(&sdp->sd_lock); 00841 00842 search.se_name = name; 00843 sep = avl_find(&sdp->sd_snaps, &search, NULL); 00844 if (sep) { 00845 avl_remove(&sdp->sd_snaps, sep); 00846 err = zfsctl_unmount_snap(sep, MS_FORCE, cr); 00847 if (err) { 00848 avl_index_t where; 00849 00850 if (avl_find(&sdp->sd_snaps, sep, &where) == NULL) 00851 avl_insert(&sdp->sd_snaps, sep, where); 00852 } else 00853 err = dmu_objset_destroy(snapname, B_FALSE); 00854 } else { 00855 err = ENOENT; 00856 } 00857 00858 mutex_exit(&sdp->sd_lock); 00859 00860 return (err); 00861 } 00862 #endif /* sun */ 00863 00867 /* ARGSUSED */ 00868 static int 00869 zfsctl_snapdir_mkdir(vnode_t *dvp, char *dirname, vattr_t *vap, vnode_t **vpp, 00870 cred_t *cr, caller_context_t *cc, int flags, vsecattr_t *vsecp) 00871 { 00872 zfsvfs_t *zfsvfs = dvp->v_vfsp->vfs_data; 00873 char name[MAXNAMELEN]; 00874 int err; 00875 static enum symfollow follow = NO_FOLLOW; 00876 static enum uio_seg seg = UIO_SYSSPACE; 00877 00878 if (snapshot_namecheck(dirname, NULL, NULL) != 0) 00879 return (EILSEQ); 00880 00881 dmu_objset_name(zfsvfs->z_os, name); 00882 00883 *vpp = NULL; 00884 00885 err = zfs_secpolicy_snapshot_perms(name, cr); 00886 if (err) 00887 return (err); 00888 00889 if (err == 0) { 00890 err = dmu_objset_snapshot(name, dirname, NULL, NULL, 00891 B_FALSE, B_FALSE, -1); 00892 if (err) 00893 return (err); 00894 err = lookupnameat(dirname, seg, follow, NULL, vpp, dvp); 00895 } 00896 00897 return (err); 00898 } 00899 00900 static int 00901 zfsctl_freebsd_snapdir_mkdir(ap) 00902 struct vop_mkdir_args /* { 00903 struct vnode *a_dvp; 00904 struct vnode **a_vpp; 00905 struct componentname *a_cnp; 00906 struct vattr *a_vap; 00907 } */ *ap; 00908 { 00909 00910 ASSERT(ap->a_cnp->cn_flags & SAVENAME); 00911 00912 return (zfsctl_snapdir_mkdir(ap->a_dvp, ap->a_cnp->cn_nameptr, NULL, 00913 ap->a_vpp, ap->a_cnp->cn_cred, NULL, 0, NULL)); 00914 } 00915 00921 /* ARGSUSED */ 00922 int 00923 zfsctl_snapdir_lookup(ap) 00924 struct vop_lookup_args /* { 00925 struct vnode *a_dvp; 00926 struct vnode **a_vpp; 00927 struct componentname *a_cnp; 00928 } */ *ap; 00929 { 00930 vnode_t *dvp = ap->a_dvp; 00931 vnode_t **vpp = ap->a_vpp; 00932 struct componentname *cnp = ap->a_cnp; 00933 char nm[NAME_MAX + 1]; 00934 zfsctl_snapdir_t *sdp = dvp->v_data; 00935 objset_t *snap; 00936 char snapname[MAXNAMELEN]; 00937 char real[MAXNAMELEN]; 00938 char *mountpoint; 00939 zfs_snapentry_t *sep, search; 00940 size_t mountpoint_len; 00941 avl_index_t where; 00942 zfsvfs_t *zfsvfs = dvp->v_vfsp->vfs_data; 00943 int err; 00944 int flags = 0; 00945 00946 /* 00947 * No extended attributes allowed under .zfs 00948 */ 00949 if (flags & LOOKUP_XATTR) 00950 return (EINVAL); 00951 ASSERT(ap->a_cnp->cn_namelen < sizeof(nm)); 00952 strlcpy(nm, ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen + 1); 00953 00954 ASSERT(dvp->v_type == VDIR); 00955 00956 *vpp = NULL; 00957 00958 /* 00959 * If we get a recursive call, that means we got called 00960 * from the domount() code while it was trying to look up the 00961 * spec (which looks like a local path for zfs). We need to 00962 * add some flag to domount() to tell it not to do this lookup. 00963 */ 00964 if (MUTEX_HELD(&sdp->sd_lock)) 00965 return (ENOENT); 00966 00967 ZFS_ENTER(zfsvfs); 00968 00969 if (gfs_lookup_dot(vpp, dvp, zfsvfs->z_ctldir, nm) == 0) { 00970 ZFS_EXIT(zfsvfs); 00971 return (0); 00972 } 00973 00974 if (flags & FIGNORECASE) { 00975 boolean_t conflict = B_FALSE; 00976 00977 err = dmu_snapshot_realname(zfsvfs->z_os, nm, real, 00978 MAXNAMELEN, &conflict); 00979 if (err == 0) { 00980 strlcpy(nm, real, sizeof(nm)); 00981 } else if (err != ENOTSUP) { 00982 ZFS_EXIT(zfsvfs); 00983 return (err); 00984 } 00985 #if 0 00986 if (realpnp) 00987 (void) strlcpy(realpnp->pn_buf, nm, 00988 realpnp->pn_bufsize); 00989 if (conflict && direntflags) 00990 *direntflags = ED_CASE_CONFLICT; 00991 #endif 00992 } 00993 00994 mutex_enter(&sdp->sd_lock); 00995 search.se_name = (char *)nm; 00996 if ((sep = avl_find(&sdp->sd_snaps, &search, &where)) != NULL) { 00997 *vpp = sep->se_root; 00998 VN_HOLD(*vpp); 00999 err = traverse(vpp, LK_EXCLUSIVE | LK_RETRY); 01000 if (err) { 01001 VN_RELE(*vpp); 01002 *vpp = NULL; 01003 } else if (*vpp == sep->se_root) { 01004 /* 01005 * The snapshot was unmounted behind our backs, 01006 * try to remount it. 01007 */ 01008 VERIFY(zfsctl_snapshot_zname(dvp, nm, MAXNAMELEN, snapname) == 0); 01009 goto domount; 01010 } else { 01011 /* 01012 * VROOT was set during the traverse call. We need 01013 * to clear it since we're pretending to be part 01014 * of our parent's vfs. 01015 */ 01016 (*vpp)->v_flag &= ~VROOT; 01017 } 01018 mutex_exit(&sdp->sd_lock); 01019 ZFS_EXIT(zfsvfs); 01020 return (err); 01021 } 01022 01023 /* 01024 * The requested snapshot is not currently mounted, look it up. 01025 */ 01026 err = zfsctl_snapshot_zname(dvp, nm, MAXNAMELEN, snapname); 01027 if (err) { 01028 mutex_exit(&sdp->sd_lock); 01029 ZFS_EXIT(zfsvfs); 01030 /* 01031 * handle "ls *" or "?" in a graceful manner, 01032 * forcing EILSEQ to ENOENT. 01033 * Since shell ultimately passes "*" or "?" as name to lookup 01034 */ 01035 return (err == EILSEQ ? ENOENT : err); 01036 } 01037 if (dmu_objset_hold(snapname, FTAG, &snap) != 0) { 01038 mutex_exit(&sdp->sd_lock); 01039 /* Translate errors and add SAVENAME when needed. */ 01040 if ((cnp->cn_flags & ISLASTCN) && cnp->cn_nameiop == CREATE) { 01041 err = EJUSTRETURN; 01042 cnp->cn_flags |= SAVENAME; 01043 } else { 01044 err = ENOENT; 01045 } 01046 ZFS_EXIT(zfsvfs); 01047 return (err); 01048 } 01049 01050 sep = kmem_alloc(sizeof (zfs_snapentry_t), KM_SLEEP); 01051 sep->se_name = kmem_alloc(strlen(nm) + 1, KM_SLEEP); 01052 (void) strcpy(sep->se_name, nm); 01053 *vpp = sep->se_root = zfsctl_snapshot_mknode(dvp, dmu_objset_id(snap)); 01054 VN_HOLD(*vpp); 01055 avl_insert(&sdp->sd_snaps, sep, where); 01056 01057 dmu_objset_rele(snap, FTAG); 01058 domount: 01059 mountpoint_len = strlen(dvp->v_vfsp->mnt_stat.f_mntonname) + 01060 strlen("/" ZFS_CTLDIR_NAME "/snapshot/") + strlen(nm) + 1; 01061 mountpoint = kmem_alloc(mountpoint_len, KM_SLEEP); 01062 (void) snprintf(mountpoint, mountpoint_len, 01063 "%s/" ZFS_CTLDIR_NAME "/snapshot/%s", 01064 dvp->v_vfsp->mnt_stat.f_mntonname, nm); 01065 err = mount_snapshot(curthread, vpp, "zfs", mountpoint, snapname, 0); 01066 kmem_free(mountpoint, mountpoint_len); 01067 if (err == 0) { 01068 /* 01069 * Fix up the root vnode mounted on .zfs/snapshot/<snapname>. 01070 * 01071 * This is where we lie about our v_vfsp in order to 01072 * make .zfs/snapshot/<snapname> accessible over NFS 01073 * without requiring manual mounts of <snapname>. 01074 */ 01075 ASSERT(VTOZ(*vpp)->z_zfsvfs != zfsvfs); 01076 VTOZ(*vpp)->z_zfsvfs->z_parent = zfsvfs; 01077 } 01078 mutex_exit(&sdp->sd_lock); 01079 ZFS_EXIT(zfsvfs); 01080 if (err != 0) 01081 *vpp = NULL; 01082 return (err); 01083 } 01084 01085 /* ARGSUSED */ 01086 int 01087 zfsctl_shares_lookup(ap) 01088 struct vop_lookup_args /* { 01089 struct vnode *a_dvp; 01090 struct vnode **a_vpp; 01091 struct componentname *a_cnp; 01092 } */ *ap; 01093 { 01094 vnode_t *dvp = ap->a_dvp; 01095 vnode_t **vpp = ap->a_vpp; 01096 struct componentname *cnp = ap->a_cnp; 01097 zfsvfs_t *zfsvfs = dvp->v_vfsp->vfs_data; 01098 char nm[NAME_MAX + 1]; 01099 znode_t *dzp; 01100 int error; 01101 01102 ZFS_ENTER(zfsvfs); 01103 01104 ASSERT(cnp->cn_namelen < sizeof(nm)); 01105 strlcpy(nm, cnp->cn_nameptr, cnp->cn_namelen + 1); 01106 01107 if (gfs_lookup_dot(vpp, dvp, zfsvfs->z_ctldir, nm) == 0) { 01108 ZFS_EXIT(zfsvfs); 01109 return (0); 01110 } 01111 01112 if (zfsvfs->z_shares_dir == 0) { 01113 ZFS_EXIT(zfsvfs); 01114 return (ENOTSUP); 01115 } 01116 if ((error = zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp)) == 0) 01117 error = VOP_LOOKUP(ZTOV(dzp), vpp, cnp); 01118 01119 VN_RELE(ZTOV(dzp)); 01120 ZFS_EXIT(zfsvfs); 01121 01122 return (error); 01123 } 01124 01125 /* ARGSUSED */ 01126 static int 01127 zfsctl_snapdir_readdir_cb(vnode_t *vp, void *dp, int *eofp, 01128 offset_t *offp, offset_t *nextp, void *data, int flags) 01129 { 01130 zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data; 01131 char snapname[MAXNAMELEN]; 01132 uint64_t id, cookie; 01133 boolean_t case_conflict; 01134 int error; 01135 01136 ZFS_ENTER(zfsvfs); 01137 01138 cookie = *offp; 01139 error = dmu_snapshot_list_next(zfsvfs->z_os, MAXNAMELEN, snapname, &id, 01140 &cookie, &case_conflict); 01141 if (error) { 01142 ZFS_EXIT(zfsvfs); 01143 if (error == ENOENT) { 01144 *eofp = 1; 01145 return (0); 01146 } 01147 return (error); 01148 } 01149 01150 if (flags & V_RDDIR_ENTFLAGS) { 01151 edirent_t *eodp = dp; 01152 01153 (void) strcpy(eodp->ed_name, snapname); 01154 eodp->ed_ino = ZFSCTL_INO_SNAP(id); 01155 eodp->ed_eflags = case_conflict ? ED_CASE_CONFLICT : 0; 01156 } else { 01157 struct dirent64 *odp = dp; 01158 01159 (void) strcpy(odp->d_name, snapname); 01160 odp->d_ino = ZFSCTL_INO_SNAP(id); 01161 } 01162 *nextp = cookie; 01163 01164 ZFS_EXIT(zfsvfs); 01165 01166 return (0); 01167 } 01168 01169 /* ARGSUSED */ 01170 static int 01171 zfsctl_shares_readdir(ap) 01172 struct vop_readdir_args /* { 01173 struct vnode *a_vp; 01174 struct uio *a_uio; 01175 struct ucred *a_cred; 01176 int *a_eofflag; 01177 int *a_ncookies; 01178 u_long **a_cookies; 01179 } */ *ap; 01180 { 01181 vnode_t *vp = ap->a_vp; 01182 uio_t *uiop = ap->a_uio; 01183 cred_t *cr = ap->a_cred; 01184 int *eofp = ap->a_eofflag; 01185 zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data; 01186 znode_t *dzp; 01187 int error; 01188 01189 ZFS_ENTER(zfsvfs); 01190 01191 if (zfsvfs->z_shares_dir == 0) { 01192 ZFS_EXIT(zfsvfs); 01193 return (ENOTSUP); 01194 } 01195 if ((error = zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp)) == 0) { 01196 vn_lock(ZTOV(dzp), LK_SHARED | LK_RETRY); 01197 error = VOP_READDIR(ZTOV(dzp), uiop, cr, eofp, ap->a_ncookies, ap->a_cookies); 01198 VN_URELE(ZTOV(dzp)); 01199 } else { 01200 *eofp = 1; 01201 error = ENOENT; 01202 } 01203 01204 ZFS_EXIT(zfsvfs); 01205 return (error); 01206 } 01207 01216 vnode_t * 01217 zfsctl_mknode_snapdir(vnode_t *pvp) 01218 { 01219 vnode_t *vp; 01220 zfsctl_snapdir_t *sdp; 01221 01222 vp = gfs_dir_create(sizeof (zfsctl_snapdir_t), pvp, pvp->v_vfsp, 01223 &zfsctl_ops_snapdir, NULL, NULL, MAXNAMELEN, 01224 zfsctl_snapdir_readdir_cb, NULL); 01225 sdp = vp->v_data; 01226 sdp->sd_node.zc_id = ZFSCTL_INO_SNAPDIR; 01227 sdp->sd_node.zc_cmtime = ((zfsctl_node_t *)pvp->v_data)->zc_cmtime; 01228 mutex_init(&sdp->sd_lock, NULL, MUTEX_DEFAULT, NULL); 01229 avl_create(&sdp->sd_snaps, snapentry_compare, 01230 sizeof (zfs_snapentry_t), offsetof(zfs_snapentry_t, se_node)); 01231 VOP_UNLOCK(vp, 0); 01232 return (vp); 01233 } 01234 01235 vnode_t * 01236 zfsctl_mknode_shares(vnode_t *pvp) 01237 { 01238 vnode_t *vp; 01239 zfsctl_node_t *sdp; 01240 01241 vp = gfs_dir_create(sizeof (zfsctl_node_t), pvp, pvp->v_vfsp, 01242 &zfsctl_ops_shares, NULL, NULL, MAXNAMELEN, 01243 NULL, NULL); 01244 sdp = vp->v_data; 01245 sdp->zc_cmtime = ((zfsctl_node_t *)pvp->v_data)->zc_cmtime; 01246 VOP_UNLOCK(vp, 0); 01247 return (vp); 01248 01249 } 01250 01251 /* ARGSUSED */ 01252 static int 01253 zfsctl_shares_getattr(ap) 01254 struct vop_getattr_args /* { 01255 struct vnode *a_vp; 01256 struct vattr *a_vap; 01257 struct ucred *a_cred; 01258 struct thread *a_td; 01259 } */ *ap; 01260 { 01261 vnode_t *vp = ap->a_vp; 01262 vattr_t *vap = ap->a_vap; 01263 cred_t *cr = ap->a_cred; 01264 zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data; 01265 znode_t *dzp; 01266 int error; 01267 01268 ZFS_ENTER(zfsvfs); 01269 if (zfsvfs->z_shares_dir == 0) { 01270 ZFS_EXIT(zfsvfs); 01271 return (ENOTSUP); 01272 } 01273 if ((error = zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp)) == 0) { 01274 vn_lock(ZTOV(dzp), LK_SHARED | LK_RETRY); 01275 error = VOP_GETATTR(ZTOV(dzp), vap, cr); 01276 VN_URELE(ZTOV(dzp)); 01277 } 01278 ZFS_EXIT(zfsvfs); 01279 return (error); 01280 01281 01282 } 01283 01284 /* ARGSUSED */ 01285 static int 01286 zfsctl_snapdir_getattr(ap) 01287 struct vop_getattr_args /* { 01288 struct vnode *a_vp; 01289 struct vattr *a_vap; 01290 struct ucred *a_cred; 01291 } */ *ap; 01292 { 01293 vnode_t *vp = ap->a_vp; 01294 vattr_t *vap = ap->a_vap; 01295 zfsvfs_t *zfsvfs = vp->v_vfsp->vfs_data; 01296 zfsctl_snapdir_t *sdp = vp->v_data; 01297 01298 ZFS_ENTER(zfsvfs); 01299 zfsctl_common_getattr(vp, vap); 01300 vap->va_nodeid = gfs_file_inode(vp); 01301 vap->va_nlink = vap->va_size = avl_numnodes(&sdp->sd_snaps) + 2; 01302 vap->va_ctime = vap->va_mtime = dmu_objset_snap_cmtime(zfsvfs->z_os); 01303 vap->va_birthtime = vap->va_ctime; 01304 ZFS_EXIT(zfsvfs); 01305 01306 return (0); 01307 } 01308 01309 /* ARGSUSED */ 01310 static int 01311 zfsctl_snapdir_inactive(ap) 01312 struct vop_inactive_args /* { 01313 struct vnode *a_vp; 01314 struct thread *a_td; 01315 } */ *ap; 01316 { 01317 vnode_t *vp = ap->a_vp; 01318 zfsctl_snapdir_t *sdp = vp->v_data; 01319 zfs_snapentry_t *sep; 01320 01321 /* 01322 * On forced unmount we have to free snapshots from here. 01323 */ 01324 mutex_enter(&sdp->sd_lock); 01325 while ((sep = avl_first(&sdp->sd_snaps)) != NULL) { 01326 avl_remove(&sdp->sd_snaps, sep); 01327 kmem_free(sep->se_name, strlen(sep->se_name) + 1); 01328 kmem_free(sep, sizeof (zfs_snapentry_t)); 01329 } 01330 mutex_exit(&sdp->sd_lock); 01331 gfs_dir_inactive(vp); 01332 ASSERT(avl_numnodes(&sdp->sd_snaps) == 0); 01333 mutex_destroy(&sdp->sd_lock); 01334 avl_destroy(&sdp->sd_snaps); 01335 kmem_free(sdp, sizeof (zfsctl_snapdir_t)); 01336 01337 return (0); 01338 } 01339 01340 #ifdef sun 01341 static const fs_operation_def_t zfsctl_tops_snapdir[] = { 01342 { VOPNAME_OPEN, { .vop_open = zfsctl_common_open } }, 01343 { VOPNAME_CLOSE, { .vop_close = zfsctl_common_close } }, 01344 { VOPNAME_IOCTL, { .error = fs_inval } }, 01345 { VOPNAME_GETATTR, { .vop_getattr = zfsctl_snapdir_getattr } }, 01346 { VOPNAME_ACCESS, { .vop_access = zfsctl_common_access } }, 01347 { VOPNAME_RENAME, { .vop_rename = zfsctl_snapdir_rename } }, 01348 { VOPNAME_RMDIR, { .vop_rmdir = zfsctl_snapdir_remove } }, 01349 { VOPNAME_MKDIR, { .vop_mkdir = zfsctl_snapdir_mkdir } }, 01350 { VOPNAME_READDIR, { .vop_readdir = gfs_vop_readdir } }, 01351 { VOPNAME_LOOKUP, { .vop_lookup = zfsctl_snapdir_lookup } }, 01352 { VOPNAME_SEEK, { .vop_seek = fs_seek } }, 01353 { VOPNAME_INACTIVE, { .vop_inactive = zfsctl_snapdir_inactive } }, 01354 { VOPNAME_FID, { .vop_fid = zfsctl_common_fid } }, 01355 { NULL } 01356 }; 01357 01358 static const fs_operation_def_t zfsctl_tops_shares[] = { 01359 { VOPNAME_OPEN, { .vop_open = zfsctl_common_open } }, 01360 { VOPNAME_CLOSE, { .vop_close = zfsctl_common_close } }, 01361 { VOPNAME_IOCTL, { .error = fs_inval } }, 01362 { VOPNAME_GETATTR, { .vop_getattr = zfsctl_shares_getattr } }, 01363 { VOPNAME_ACCESS, { .vop_access = zfsctl_common_access } }, 01364 { VOPNAME_READDIR, { .vop_readdir = zfsctl_shares_readdir } }, 01365 { VOPNAME_LOOKUP, { .vop_lookup = zfsctl_shares_lookup } }, 01366 { VOPNAME_SEEK, { .vop_seek = fs_seek } }, 01367 { VOPNAME_INACTIVE, { .vop_inactive = gfs_vop_inactive } }, 01368 { VOPNAME_FID, { .vop_fid = zfsctl_shares_fid } }, 01369 { NULL } 01370 }; 01371 #else /* !sun */ 01372 static struct vop_vector zfsctl_ops_snapdir = { 01373 .vop_default = &default_vnodeops, 01374 .vop_open = zfsctl_common_open, 01375 .vop_close = zfsctl_common_close, 01376 .vop_ioctl = VOP_EINVAL, 01377 .vop_getattr = zfsctl_snapdir_getattr, 01378 .vop_access = zfsctl_common_access, 01379 .vop_mkdir = zfsctl_freebsd_snapdir_mkdir, 01380 .vop_readdir = gfs_vop_readdir, 01381 .vop_lookup = zfsctl_snapdir_lookup, 01382 .vop_inactive = zfsctl_snapdir_inactive, 01383 .vop_reclaim = zfsctl_common_reclaim, 01384 .vop_fid = zfsctl_common_fid, 01385 }; 01386 01387 static struct vop_vector zfsctl_ops_shares = { 01388 .vop_default = &default_vnodeops, 01389 .vop_open = zfsctl_common_open, 01390 .vop_close = zfsctl_common_close, 01391 .vop_ioctl = VOP_EINVAL, 01392 .vop_getattr = zfsctl_shares_getattr, 01393 .vop_access = zfsctl_common_access, 01394 .vop_readdir = zfsctl_shares_readdir, 01395 .vop_lookup = zfsctl_shares_lookup, 01396 .vop_inactive = gfs_vop_inactive, 01397 .vop_reclaim = zfsctl_common_reclaim, 01398 .vop_fid = zfsctl_shares_fid, 01399 }; 01400 #endif /* !sun */ 01401 01409 static vnode_t * 01410 zfsctl_snapshot_mknode(vnode_t *pvp, uint64_t objset) 01411 { 01412 vnode_t *vp; 01413 zfsctl_node_t *zcp; 01414 01415 vp = gfs_dir_create(sizeof (zfsctl_node_t), pvp, pvp->v_vfsp, 01416 &zfsctl_ops_snapshot, NULL, NULL, MAXNAMELEN, NULL, NULL); 01417 VN_HOLD(vp); 01418 zcp = vp->v_data; 01419 zcp->zc_id = objset; 01420 VOP_UNLOCK(vp, 0); 01421 01422 return (vp); 01423 } 01424 01425 static int 01426 zfsctl_snapshot_inactive(ap) 01427 struct vop_inactive_args /* { 01428 struct vnode *a_vp; 01429 struct thread *a_td; 01430 } */ *ap; 01431 { 01432 vnode_t *vp = ap->a_vp; 01433 cred_t *cr = ap->a_td->td_ucred; 01434 struct vop_inactive_args iap; 01435 zfsctl_snapdir_t *sdp; 01436 zfs_snapentry_t *sep, *next; 01437 int locked; 01438 vnode_t *dvp; 01439 01440 if (vp->v_count > 0) 01441 goto end; 01442 01443 VERIFY(gfs_dir_lookup(vp, "..", &dvp, cr, 0, NULL, NULL) == 0); 01444 sdp = dvp->v_data; 01445 VOP_UNLOCK(dvp, 0); 01446 01447 if (!(locked = MUTEX_HELD(&sdp->sd_lock))) 01448 mutex_enter(&sdp->sd_lock); 01449 01450 ASSERT(!vn_ismntpt(vp)); 01451 01452 sep = avl_first(&sdp->sd_snaps); 01453 while (sep != NULL) { 01454 next = AVL_NEXT(&sdp->sd_snaps, sep); 01455 01456 if (sep->se_root == vp) { 01457 avl_remove(&sdp->sd_snaps, sep); 01458 kmem_free(sep->se_name, strlen(sep->se_name) + 1); 01459 kmem_free(sep, sizeof (zfs_snapentry_t)); 01460 break; 01461 } 01462 sep = next; 01463 } 01464 ASSERT(sep != NULL); 01465 01466 if (!locked) 01467 mutex_exit(&sdp->sd_lock); 01468 VN_RELE(dvp); 01469 01470 end: 01471 /* 01472 * Dispose of the vnode for the snapshot mount point. 01473 * This is safe to do because once this entry has been removed 01474 * from the AVL tree, it can't be found again, so cannot become 01475 * "active". If we lookup the same name again we will end up 01476 * creating a new vnode. 01477 */ 01478 iap.a_vp = vp; 01479 return (gfs_vop_inactive(&iap)); 01480 } 01481 01482 static int 01483 zfsctl_traverse_begin(vnode_t **vpp, int lktype) 01484 { 01485 01486 VN_HOLD(*vpp); 01487 /* Snapshot should be already mounted, but just in case. */ 01488 if (vn_mountedvfs(*vpp) == NULL) 01489 return (ENOENT); 01490 return (traverse(vpp, lktype)); 01491 } 01492 01493 static void 01494 zfsctl_traverse_end(vnode_t *vp, int err) 01495 { 01496 01497 if (err == 0) 01498 vput(vp); 01499 else 01500 VN_RELE(vp); 01501 } 01502 01503 static int 01504 zfsctl_snapshot_getattr(ap) 01505 struct vop_getattr_args /* { 01506 struct vnode *a_vp; 01507 struct vattr *a_vap; 01508 struct ucred *a_cred; 01509 } */ *ap; 01510 { 01511 vnode_t *vp = ap->a_vp; 01512 int err; 01513 01514 err = zfsctl_traverse_begin(&vp, LK_SHARED | LK_RETRY); 01515 if (err == 0) 01516 err = VOP_GETATTR(vp, ap->a_vap, ap->a_cred); 01517 zfsctl_traverse_end(vp, err); 01518 return (err); 01519 } 01520 01521 static int 01522 zfsctl_snapshot_fid(ap) 01523 struct vop_fid_args /* { 01524 struct vnode *a_vp; 01525 struct fid *a_fid; 01526 } */ *ap; 01527 { 01528 vnode_t *vp = ap->a_vp; 01529 int err; 01530 01531 err = zfsctl_traverse_begin(&vp, LK_SHARED | LK_RETRY); 01532 if (err == 0) 01533 err = VOP_VPTOFH(vp, (void *)ap->a_fid); 01534 zfsctl_traverse_end(vp, err); 01535 return (err); 01536 } 01537 01538 static int 01539 zfsctl_snapshot_lookup(ap) 01540 struct vop_lookup_args /* { 01541 struct vnode *a_dvp; 01542 struct vnode **a_vpp; 01543 struct componentname *a_cnp; 01544 } */ *ap; 01545 { 01546 vnode_t *dvp = ap->a_dvp; 01547 vnode_t **vpp = ap->a_vpp; 01548 struct componentname *cnp = ap->a_cnp; 01549 cred_t *cr = ap->a_cnp->cn_cred; 01550 zfsvfs_t *zfsvfs = dvp->v_vfsp->vfs_data; 01551 int error; 01552 01553 if (cnp->cn_namelen != 2 || cnp->cn_nameptr[0] != '.' || 01554 cnp->cn_nameptr[1] != '.') { 01555 return (ENOENT); 01556 } 01557 01558 ASSERT(dvp->v_type == VDIR); 01559 ASSERT(zfsvfs->z_ctldir != NULL); 01560 01561 error = zfsctl_root_lookup(zfsvfs->z_ctldir, "snapshot", vpp, 01562 NULL, 0, NULL, cr, NULL, NULL, NULL); 01563 if (error == 0) 01564 vn_lock(*vpp, LK_EXCLUSIVE | LK_RETRY); 01565 return (error); 01566 } 01567 01568 static int 01569 zfsctl_snapshot_vptocnp(struct vop_vptocnp_args *ap) 01570 { 01571 zfsvfs_t *zfsvfs = ap->a_vp->v_vfsp->vfs_data; 01572 vnode_t *dvp, *vp; 01573 zfsctl_snapdir_t *sdp; 01574 zfs_snapentry_t *sep; 01575 int error; 01576 01577 ASSERT(zfsvfs->z_ctldir != NULL); 01578 error = zfsctl_root_lookup(zfsvfs->z_ctldir, "snapshot", &dvp, 01579 NULL, 0, NULL, kcred, NULL, NULL, NULL); 01580 if (error != 0) 01581 return (error); 01582 sdp = dvp->v_data; 01583 01584 mutex_enter(&sdp->sd_lock); 01585 sep = avl_first(&sdp->sd_snaps); 01586 while (sep != NULL) { 01587 vp = sep->se_root; 01588 if (vp == ap->a_vp) 01589 break; 01590 sep = AVL_NEXT(&sdp->sd_snaps, sep); 01591 } 01592 if (sep == NULL) { 01593 mutex_exit(&sdp->sd_lock); 01594 error = ENOENT; 01595 } else { 01596 size_t len; 01597 01598 len = strlen(sep->se_name); 01599 *ap->a_buflen -= len; 01600 bcopy(sep->se_name, ap->a_buf + *ap->a_buflen, len); 01601 mutex_exit(&sdp->sd_lock); 01602 vref(dvp); 01603 *ap->a_vpp = dvp; 01604 } 01605 VN_RELE(dvp); 01606 01607 return (error); 01608 } 01609 01614 static struct vop_vector zfsctl_ops_snapshot = { 01615 .vop_default = &default_vnodeops, 01616 .vop_inactive = zfsctl_snapshot_inactive, 01617 .vop_lookup = zfsctl_snapshot_lookup, 01618 .vop_reclaim = zfsctl_common_reclaim, 01619 .vop_getattr = zfsctl_snapshot_getattr, 01620 .vop_fid = zfsctl_snapshot_fid, 01621 .vop_vptocnp = zfsctl_snapshot_vptocnp, 01622 }; 01623 01624 int 01625 zfsctl_lookup_objset(vfs_t *vfsp, uint64_t objsetid, zfsvfs_t **zfsvfsp) 01626 { 01627 zfsvfs_t *zfsvfs = vfsp->vfs_data; 01628 vnode_t *dvp, *vp; 01629 zfsctl_snapdir_t *sdp; 01630 zfsctl_node_t *zcp; 01631 zfs_snapentry_t *sep; 01632 int error; 01633 01634 ASSERT(zfsvfs->z_ctldir != NULL); 01635 error = zfsctl_root_lookup(zfsvfs->z_ctldir, "snapshot", &dvp, 01636 NULL, 0, NULL, kcred, NULL, NULL, NULL); 01637 if (error != 0) 01638 return (error); 01639 sdp = dvp->v_data; 01640 01641 mutex_enter(&sdp->sd_lock); 01642 sep = avl_first(&sdp->sd_snaps); 01643 while (sep != NULL) { 01644 vp = sep->se_root; 01645 zcp = vp->v_data; 01646 if (zcp->zc_id == objsetid) 01647 break; 01648 01649 sep = AVL_NEXT(&sdp->sd_snaps, sep); 01650 } 01651 01652 if (sep != NULL) { 01653 VN_HOLD(vp); 01654 /* 01655 * Return the mounted root rather than the covered mount point. 01656 * Takes the GFS vnode at .zfs/snapshot/<snapshot objsetid> 01657 * and returns the ZFS vnode mounted on top of the GFS node. 01658 * This ZFS vnode is the root of the vfs for objset 'objsetid'. 01659 */ 01660 error = traverse(&vp, LK_SHARED | LK_RETRY); 01661 if (error == 0) { 01662 if (vp == sep->se_root) 01663 error = EINVAL; 01664 else 01665 *zfsvfsp = VTOZ(vp)->z_zfsvfs; 01666 } 01667 mutex_exit(&sdp->sd_lock); 01668 if (error == 0) 01669 VN_URELE(vp); 01670 else 01671 VN_RELE(vp); 01672 } else { 01673 error = EINVAL; 01674 mutex_exit(&sdp->sd_lock); 01675 } 01676 01677 VN_RELE(dvp); 01678 01679 return (error); 01680 } 01681 01687 int 01688 zfsctl_umount_snapshots(vfs_t *vfsp, int fflags, cred_t *cr) 01689 { 01690 zfsvfs_t *zfsvfs = vfsp->vfs_data; 01691 vnode_t *dvp; 01692 zfsctl_snapdir_t *sdp; 01693 zfs_snapentry_t *sep, *next; 01694 int error; 01695 01696 ASSERT(zfsvfs->z_ctldir != NULL); 01697 error = zfsctl_root_lookup(zfsvfs->z_ctldir, "snapshot", &dvp, 01698 NULL, 0, NULL, cr, NULL, NULL, NULL); 01699 if (error != 0) 01700 return (error); 01701 sdp = dvp->v_data; 01702 01703 mutex_enter(&sdp->sd_lock); 01704 01705 sep = avl_first(&sdp->sd_snaps); 01706 while (sep != NULL) { 01707 next = AVL_NEXT(&sdp->sd_snaps, sep); 01708 01709 /* 01710 * If this snapshot is not mounted, then it must 01711 * have just been unmounted by somebody else, and 01712 * will be cleaned up by zfsctl_snapdir_inactive(). 01713 */ 01714 if (vn_ismntpt(sep->se_root)) { 01715 error = zfsctl_unmount_snap(sep, fflags, cr); 01716 if (error) { 01717 avl_index_t where; 01718 01719 /* 01720 * Before reinserting snapshot to the tree, 01721 * check if it was actually removed. For example 01722 * when snapshot mount point is busy, we will 01723 * have an error here, but there will be no need 01724 * to reinsert snapshot. 01725 */ 01726 if (avl_find(&sdp->sd_snaps, sep, &where) == NULL) 01727 avl_insert(&sdp->sd_snaps, sep, where); 01728 break; 01729 } 01730 } 01731 sep = next; 01732 } 01733 01734 mutex_exit(&sdp->sd_lock); 01735 VN_RELE(dvp); 01736 01737 return (error); 01738 }