xref: /onnv-gate/usr/src/uts/common/fs/zfs/zfs_ctldir.c (revision 5331:3047ad28a67b)
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