1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*
28 * Portions Copyright 2007-2013 Apple Inc.
29 */
30
31#pragma ident	"@(#)auto_vnops.c	1.70	05/12/19 SMI"
32
33#include <mach/mach_types.h>
34#include <mach/machine/boolean.h>
35#include <mach/host_priv.h>
36#include <mach/host_special_ports.h>
37#include <mach/vm_map.h>
38#include <vm/vm_map.h>
39#include <vm/vm_kern.h>
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/kernel.h>
44#include <sys/file.h>
45#include <sys/stat.h>
46#include <sys/buf.h>
47#include <sys/proc.h>
48#include <sys/conf.h>
49#include <sys/mount.h>
50#include <sys/vnode.h>
51#include <sys/malloc.h>
52#include <sys/dirent.h>
53#include <sys/namei.h>
54#include <sys/kauth.h>
55#include <sys/attr.h>
56#include <sys/vnode_if.h>
57#include <sys/vfs_context.h>
58#include <sys/vm.h>
59#include <sys/errno.h>
60#include <vfs/vfs_support.h>
61#include <sys/uio.h>
62
63#include <kern/assert.h>
64#include <kern/host.h>
65
66#include <IOKit/IOLib.h>
67
68#include "autofs.h"
69#include "triggers.h"
70#include "triggers_priv.h"
71#include "autofs_kern.h"
72#include "autofs_protUser.h"
73
74/*
75 *  Vnode ops for autofs
76 */
77static int auto_getattr(struct vnop_getattr_args *);
78static int auto_setattr(struct vnop_setattr_args *);
79static int auto_lookup(struct vnop_lookup_args *);
80static int auto_readdir(struct vnop_readdir_args *);
81static int auto_readlink(struct vnop_readlink_args *);
82static int auto_pathconf(struct vnop_pathconf_args *);
83static int auto_fsctl(struct vnop_ioctl_args *);
84static int auto_getxattr(struct vnop_getxattr_args *);
85static int auto_listxattr(struct vnop_listxattr_args *);
86static int auto_inactive(struct vnop_inactive_args *);
87static int auto_reclaim(struct vnop_reclaim_args *);
88
89int (**autofs_vnodeop_p)(void *);
90
91#define VOPFUNC int (*)(void *)
92
93struct vnodeopv_entry_desc autofs_vnodeop_entries[] = {
94	{&vnop_default_desc, (VOPFUNC)vn_default_error},
95	{&vnop_lookup_desc, (VOPFUNC)auto_lookup},		/* lookup */
96	{&vnop_open_desc, (VOPFUNC)nop_open},			/* open	- NOP */
97	{&vnop_close_desc, (VOPFUNC)nop_close},			/* close - NOP */
98	{&vnop_getattr_desc, (VOPFUNC)auto_getattr},		/* getattr */
99	{&vnop_setattr_desc, (VOPFUNC)auto_setattr},		/* setattr */
100	{&vnop_fsync_desc, (VOPFUNC)nop_fsync},			/* fsync - NOP */
101	{&vnop_readdir_desc, (VOPFUNC)auto_readdir},		/* readdir */
102	{&vnop_readlink_desc, (VOPFUNC)auto_readlink},		/* readlink */
103	{&vnop_pathconf_desc, (VOPFUNC)auto_pathconf},		/* pathconf */
104	{&vnop_ioctl_desc, (VOPFUNC)auto_fsctl},		/* ioctl (really fsctl) */
105	{&vnop_getxattr_desc, (VOPFUNC)auto_getxattr},		/* getxattr */
106	{&vnop_listxattr_desc, (VOPFUNC)auto_listxattr},	/* listxattr */
107	{&vnop_inactive_desc, (VOPFUNC)auto_inactive},		/* inactive */
108	{&vnop_reclaim_desc, (VOPFUNC)auto_reclaim},		/* reclaim */
109	{NULL, NULL}
110};
111
112struct vnodeopv_desc autofsfs_vnodeop_opv_desc =
113	{ &autofs_vnodeop_p, autofs_vnodeop_entries };
114
115static int autofs_nobrowse = 0;
116
117/*
118 * Returns 1 if a readdir on the vnode will only return names for the
119 * vnodes we have, 0 otherwise.
120 *
121 * XXX - come up with a better name.
122 */
123int
124auto_nobrowse(vnode_t vp)
125{
126	fnnode_t *fnp = vntofn(vp);
127	fninfo_t *fnip = vfstofni(vnode_mount(vp));
128
129	if (fnp == vntofn(fnip->fi_rootvp)) {
130		/*
131		 * This is the root directory of the mount, so a
132		 * readdir on the vnode will only return names for
133		 * the vnodes we already have if we've globally
134		 * disabled browsing or the map was mounted with
135		 * "nobrowse".
136		 */
137		return (autofs_nobrowse ||
138		    (fnip->fi_mntflags & AUTOFS_MNT_NOBROWSE));
139	} else {
140		/*
141		 * This is a subdirectory of the mount; a readdir
142		 * on the vnode will always make an upcall, as
143		 * we need to enumerate all the subdirectories
144		 * generated by the submounts.
145		 */
146		return (0);
147	}
148}
149
150static int
151auto_getattr(ap)
152	struct vnop_getattr_args /* {
153		struct vnodeop_desc *a_desc;
154		vnode_t a_vp;
155		struct vnode_attr *a_vap;
156		vfs_context_t a_context;
157	} */ *ap;
158{
159	vnode_t vp = ap->a_vp;
160	struct vnode_attr *vap = ap->a_vap;
161
162	AUTOFS_DPRINT((4, "auto_getattr vp %p\n", (void *)vp));
163
164	/* XXX - lock the fnnode? */
165
166	auto_get_attributes(vp, vap);
167
168	return (0);
169}
170
171void
172auto_get_attributes(vnode_t vp, struct vnode_attr *vap)
173{
174	fnnode_t *fnp = vntofn(vp);
175
176	VATTR_RETURN(vap, va_rdev, 0);
177	switch (vnode_vtype(vp)) {
178	case VDIR:
179		/*
180		 * fn_linkcnt doesn't count the "." link, as we're using it
181		 * as a count of references to the fnnode from other vnnodes
182		 * (so that if it goes to 0, we know no other fnnode refers
183		 * to it).
184		 */
185		VATTR_RETURN(vap, va_nlink, fnp->fn_linkcnt + 1);
186
187		/*
188		 * The "size" of a directory is the number of entries
189		 * in its list of directory entries, plus 1.
190		 * (Solaris added 1 for some reason.)
191		 */
192		VATTR_RETURN(vap, va_data_size, fnp->fn_direntcnt + 1);
193		break;
194	case VLNK:
195		VATTR_RETURN(vap, va_nlink, fnp->fn_linkcnt);
196		VATTR_RETURN(vap, va_data_size, fnp->fn_symlinklen);
197		break;
198	default:
199		VATTR_RETURN(vap, va_nlink, fnp->fn_linkcnt);
200		VATTR_RETURN(vap, va_data_size, 0);
201		break;
202	}
203	VATTR_RETURN(vap, va_total_size, roundup(vap->va_data_size, AUTOFS_BLOCKSIZE));
204	VATTR_RETURN(vap, va_iosize, AUTOFS_BLOCKSIZE);
205
206	VATTR_RETURN(vap, va_uid, fnp->fn_uid);
207	VATTR_RETURN(vap, va_gid, 0);
208	VATTR_RETURN(vap, va_mode, fnp->fn_mode);
209	/*
210	 * Does our caller want the BSD flags?
211	 */
212	if (VATTR_IS_ACTIVE(vap, va_flags)) {
213		/*
214		 * If this is the root of a mount, and if the "hide this
215		 * from the Finder" mount option is set on that mount,
216		 * return the hidden bit, so the Finder won't show it.
217		 */
218		if (vnode_isvroot(vp)) {
219			fninfo_t *fnip = vfstofni(vnode_mount(vp));
220
221			if (fnip->fi_mntflags & AUTOFS_MNT_HIDEFROMFINDER)
222				VATTR_RETURN(vap, va_flags, UF_HIDDEN);
223			else
224				VATTR_RETURN(vap, va_flags, 0);
225		} else
226			VATTR_RETURN(vap, va_flags, 0);
227	}
228	vap->va_access_time.tv_sec = fnp->fn_atime.tv_sec;
229	vap->va_access_time.tv_nsec = fnp->fn_atime.tv_usec * 1000;
230	VATTR_SET_SUPPORTED(vap, va_access_time);
231	vap->va_modify_time.tv_sec = fnp->fn_mtime.tv_sec;
232	vap->va_modify_time.tv_nsec = fnp->fn_mtime.tv_usec * 1000;
233	VATTR_SET_SUPPORTED(vap, va_modify_time);
234	vap->va_change_time.tv_sec = fnp->fn_ctime.tv_sec;
235	vap->va_change_time.tv_nsec = fnp->fn_ctime.tv_usec * 1000;
236	VATTR_SET_SUPPORTED(vap, va_change_time);
237	VATTR_RETURN(vap, va_fileid, fnp->fn_nodeid);
238	VATTR_RETURN(vap, va_fsid, vfs_statfs(vnode_mount(vp))->f_fsid.val[0]);
239	VATTR_RETURN(vap, va_filerev, 0);
240	VATTR_RETURN(vap, va_type, vnode_vtype(vp));
241}
242
243static int
244auto_setattr(ap)
245	struct vnop_setattr_args /* {
246		struct vnodeop_desc *a_desc;
247		vnode_t a_vp;
248		struct vnode_attr *a_vap;
249		vfs_context_t a_context;
250	} */ *ap;
251{
252	vnode_t vp = ap->a_vp;
253	struct vnode_attr *vap = ap->a_vap;
254	fnnode_t *fnp = vntofn(vp);
255
256	AUTOFS_DPRINT((4, "auto_setattr vp %p\n", (void *)vp));
257
258	/*
259	 * Only root can change the attributes.
260	 */
261	if (!kauth_cred_issuser(vfs_context_ucred(ap->a_context)))
262		return (EPERM);
263
264	/*
265	 * All you can set are the UID and the permissions; that's to
266	 * allow the automounter to give the mount point to the user
267	 * on whose behalf we're doing the mount, and make it writable
268	 * by them, so we can do AFP and SMB mounts as that user (so
269	 * the connection can be authenticated as them).
270	 *
271	 * We pretend to allow the GID to be set, but we don't actually
272	 * set it.
273	 */
274	VATTR_SET_SUPPORTED(vap, va_uid);
275	if (VATTR_IS_ACTIVE(vap, va_uid))
276		fnp->fn_uid = vap->va_uid;
277	VATTR_SET_SUPPORTED(vap, va_gid);
278	VATTR_SET_SUPPORTED(vap, va_mode);
279	if (VATTR_IS_ACTIVE(vap, va_mode))
280		fnp->fn_mode = vap->va_mode & ALLPERMS;
281	return (0);
282}
283
284#include <sys/syslog.h>
285static int
286auto_lookup(ap)
287	struct vnop_lookup_args /* {
288		struct vnodeop_desc *a_desc;
289		vnode_t a_dvp;
290		vnode_t *a_vpp;
291		struct componentname *a_cnp;
292		vfs_context_t a_context;
293	} */ *ap;
294{
295	vnode_t dvp = ap->a_dvp;
296	vnode_t *vpp = ap->a_vpp;
297	struct componentname *cnp = ap->a_cnp;
298	u_long nameiop = cnp->cn_nameiop;
299	u_long flags = cnp->cn_flags;
300	int namelen = cnp->cn_namelen;
301	vfs_context_t context = ap->a_context;
302	int pid = vfs_context_pid(context);
303	int error = 0;
304	fninfo_t *dfnip;
305	fnnode_t *dfnp = NULL;
306	fnnode_t *fnp = NULL;
307	vnode_t vp;
308	uint32_t vid;
309	char *searchnm;
310	int searchnmlen;
311	int do_notify = 0;
312	struct vnode_attr vattr;
313	int node_type;
314        boolean_t have_lock = 0;
315	int retry_count = 0;
316
317	dfnip = vfstofni(vnode_mount(dvp));
318	AUTOFS_DPRINT((3, "auto_lookup: dvp=%p (%s) name=%.*s\n",
319	    (void *)dvp, dfnip->fi_map, namelen, cnp->cn_nameptr));
320
321	/* This must be a directory. */
322	if (!vnode_isdir(dvp))
323		return (ENOTDIR);
324
325	/*
326	 * XXX - is this necessary?
327	 */
328	if (namelen == 0) {
329		error = vnode_get(dvp);
330		if (error)
331			return (error);
332		*vpp = dvp;
333		return (0);
334	}
335
336	/* first check for "." and ".." */
337	if (cnp->cn_nameptr[0] == '.') {
338		if (namelen == 1) {
339			/*
340			 * "." requested
341			 */
342
343			/*
344			 * Thou shalt not rename ".".
345			 * (No, the VFS layer doesn't catch this for us.)
346			 */
347			if ((nameiop == RENAME) && (flags & WANTPARENT) &&
348			    (flags & ISLASTCN))
349				return (EISDIR);
350
351			error = vnode_get(dvp);
352			if (error)
353				return (error);
354			*vpp = dvp;
355			return (0);
356		} else if ((namelen == 2) && (cnp->cn_nameptr[1] == '.')) {
357			fnnode_t *pdfnp;
358
359			pdfnp = (vntofn(dvp))->fn_parent;
360			assert(pdfnp != NULL);
361
362			/*
363			 * Since it is legitimate to have the VROOT flag set for the
364			 * subdirectories of the indirect map in autofs filesystem,
365			 * rootfnnodep is checked against fnnode of dvp instead of
366			 * just checking whether VROOT flag is set in dvp
367			 */
368
369#if 0
370			if (pdfnp == pdfnp->fn_globals->fng_rootfnnodep) {
371				vnode_t vp;
372
373				vfs_lock_wait(vnode_mount(dvp));
374				if (vnode_mount(dvp)->vfs_flag & VFS_UNMOUNTED) {
375					vfs_unlock(vnode_mount(dvp));
376					return (EIO);
377				}
378				vp = vnode_mount(dvp)->mnt_vnodecovered;
379				error = vnode_get(vp);	/* XXX - what if it fails? */
380				vfs_unlock(vnode_mount(dvp));
381				error = VNOP_LOOKUP(vp, nm, vpp, pnp, flags, rdir, cred);
382				vnode_put(vp);
383				return (error);
384			} else {
385#else
386			{
387#endif
388				*vpp = fntovn(pdfnp);
389				return (vnode_get(*vpp));
390			}
391		}
392	}
393
394	dfnp = vntofn(dvp);
395	searchnm = cnp->cn_nameptr;
396	searchnmlen = namelen;
397
398	AUTOFS_DPRINT((3, "auto_lookup: dvp=%p dfnp=%p\n", (void *)dvp,
399	    (void *)dfnp));
400
401	have_lock = auto_fninfo_lock_shared(dfnip, pid);
402
403top:
404	/*
405	 * If this vnode is a trigger, then something should
406	 * be mounted atop it, and there should be nothing
407	 * in this file system below it.  (We shouldn't
408	 * normally get here, as we should have resolved
409	 * the trigger. It's possible we've hit a retrigger
410	 * window.  Send the system call back to restart.
411	 */
412	if (dfnp->fn_trigger_info != NULL) {
413		auto_fninfo_unlock_shared(dfnip, have_lock);
414		if (dfnp->fn_restart_cnt++ > 3) {
415			dfnp->fn_restart_cnt = 0;
416                        return ENOENT;
417                }
418                log(LOG_ALERT, "auto_lookup called with trigger dir\n");
419		return ERESTART;
420	}
421	dfnp->fn_restart_cnt = 0;
422
423	/*
424	 * See if we have done something with this name already, so we
425	 * already have it.
426	 */
427	lck_rw_lock_shared(dfnp->fn_rwlock);
428	fnp = auto_search(dfnp, cnp->cn_nameptr, cnp->cn_namelen);
429	if (fnp == NULL) {
430		/*
431		 * No, we don't, so we need to make an upcall to see
432		 * if something with that name should exist.
433		 *
434		 * Drop the writer lock on the directory, so
435		 * that we don't block reclaims of autofs
436		 * vnodes in that directory while we're
437		 * waiting for automountd to respond
438		 * (automountd, or some process on which
439		 * it depends, might be doing something
440		 * that requires the allocation of a
441		 * vnode, and that might involve reclaiming
442		 * an autofs vnode) or while we're trying
443		 * to allocate a vnode for the file or
444		 * directory we're looking up.
445		 */
446		lck_rw_unlock_shared(dfnp->fn_rwlock);
447
448		/*
449		 * Check whether this map is in the process of being
450		 * unmounted.  If so, return ENOENT; see auto_control_ioctl()
451		 * for the reason why this is done.
452		 */
453		if (dfnip->fi_flags & MF_UNMOUNTING) {
454			error = ENOENT;
455			goto fail;
456		}
457
458		/*
459		 * Ask automountd whether something with this
460		 * name exists.
461		 */
462		error = auto_lookup_aux(dfnip, dfnp, searchnm,
463		    searchnmlen, context, &node_type);
464		if (error != 0)
465			goto fail;	/* nope */
466
467		/*
468		 * OK, it exists.  We need to create the
469		 * fnnode for it, and enter it into the
470		 * directory.
471		 *
472		 * Create the fnnode first, as we must
473		 * not grab the writer lock on the
474		 * directory, as per the above.
475		 */
476		error = auto_makefnnode(&fnp, node_type,
477		    vnode_mount(dvp), cnp, NULL, dvp, 0,
478		    dfnp->fn_globals);
479		if (error)
480			goto fail;
481
482		/*
483		 * Now enter the fnnode in the directory.
484		 *
485		 * Note that somebody might have created the
486		 * name while we weren't holding the lock;
487		 * if so, then auto_enter() will return
488		 * EEXIST, and will have discarded the
489		 * vnode we created and handed us back
490		 * an fnnode referring to what they'd
491		 * already created.
492		 */
493		error = auto_enter(dfnp, cnp, &fnp);
494		if (error) {
495			if (error == EEXIST) {
496				/*
497				 * We found the name.  Act as if
498				 * the auto_search() above succeeded.
499				 */
500				error = 0;
501			} else if (error == EJUSTRETURN) {
502				/*
503				 * We could not acquire either
504				 * a) an iocount on the existing vnode and the
505				 * autofs mount point is getting unmounted.
506				 * or
507				 * b) a reference on the parent directory.
508				 *
509				 * In either case we no longer have an iocount
510				 * on the vnode we created. EJUSTRETURN is used
511				 * as a subsitute for ENOMORERETRIES.
512				 *
513				 * This should ideally redrive the lookup
514				 * instead i.e we should be able to return
515				 * ERECYCLE and have namei do a limited number
516				 * retries but ERECYCLE is not exported and
517				 * namei does not impose a limit on the number
518				 * of retries it will do.
519				 *
520				 * We'll just return ENOENT which may have the
521				 * unfortunate side effect of getting transient
522				 * ENOENT's in a unmount->retrigger window.
523				 */
524				error = ENOENT;
525				goto fail;
526			} else {
527				/*
528				 * We found the name, but couldn't
529				 * get an iocount on the vnode for
530				 * its fnnode.  That's probably
531				 * because it was in the process
532				 * of being recycled.  if we havn't already done
533				 * it 3 times, Redo the search, as the
534				 * directory might have changed.
535				 */
536				if (++retry_count >= 3) {
537					error = ENOENT;
538					goto fail;
539				}
540				error = 0;
541				goto top;
542			}
543		} else {
544			/*
545			 * We added an entry to the directory,
546			 * so we might want to notify
547			 * interested parties about that.
548			 * XXX
549			 */
550			do_notify = 1;
551		}
552	} else {
553		/*
554		 * Yes, we did.
555		 *
556		 * We're holding a read lock on that directory, so this
557		 * won't be released out from under us.  We'll have to
558		 * drop the read lock when we do a vnode_getwithvid() to
559		 * allow in-progress reclaims to finish, but that means
560		 * such a reclaim could free the fnnode.
561		 *
562		 * We get the vnode for the fnnode - which will remain
563		 * a vnode even if it's reclaimed - and the vnode ID it
564		 * had when we created the fnnode.
565		 */
566		vp = fntovn(fnp);
567		vid = fnp->fn_vid;
568
569		/*
570		 * Now we can, and must, drop the rwlock to allow
571		 * in-progress reclaims to finish.
572		 */
573		lck_rw_unlock_shared(dfnp->fn_rwlock);
574
575	    	/*
576	    	 * Now let's try to get an iocount on the fnnode, so it
577		 * doesn't vanish out from under us; this also checks
578		 * whether the vnode has been reclaimed out from under
579		 * us, and, thus, whether the fnnode has already vanished
580		 * out from under us.
581	    	 */
582		if (vnode_getwithvid(vp, vid) != 0) {
583			/*
584			 * We failed; the vnode was reclaimed.  The fnnode
585			 * is gone; redo the search.
586			 */
587			error = 0;
588			goto top;
589		}
590
591		/*
592		 * OK, that succeeded, and the vnode is still what it
593		 * was when we created the fnnode, so the fnnode is
594		 * still there - and, as we're holding an iocount
595		 * on the vnode, it's not going away.
596		 */
597	}
598
599fail:
600	auto_fninfo_unlock_shared(dfnip, have_lock);
601
602	if (error) {
603		/*
604		 * If this is a CREATE operation, and this is the last
605		 * component, and the error is ENOENT, make it ENOTSUP,
606		 * instead, so that somebody trying to create a file or
607		 * directory gets told "sorry, we don't support that".
608		 * Do the same for RENAME operations, so somebody trying
609		 * to rename a file or directory gets told that.
610		 */
611		if (error == ENOENT &&
612		    (nameiop == CREATE || nameiop == RENAME) &&
613		    (flags & ISLASTCN))
614			error = ENOTSUP;
615		goto done;
616	}
617
618	/*
619	 * We now have the actual fnnode we're interested in.
620	 */
621	*vpp = fntovn(fnp);
622
623	/*
624	 * If the directory in which we created this is one on which a
625	 * readdir will only return names corresponding to the vnodes
626	 * we have for it, and somebody cares whether something was
627	 * created in it, notify them.
628	 *
629	 * XXX - defer until we trigger a mount atop it?
630	 */
631	if (do_notify && vnode_ismonitored(dvp) && auto_nobrowse(dvp)) {
632		vfs_get_notify_attributes(&vattr);
633		auto_get_attributes(dvp, &vattr);
634		vnode_notify(dvp, VNODE_EVENT_WRITE, &vattr);
635	}
636
637done:
638	AUTOFS_DPRINT((5, "auto_lookup: name=%s *vpp=%p return=%d\n",
639	    cnp->cn_nameptr, (void *)*vpp, error));
640
641	return (error);
642}
643
644/*
645#% readdir	vp	L L L
646#
647vnop_readdir {
648	IN vnode_t vp;
649	INOUT struct uio *uio;
650	INOUT int *eofflag;
651	OUT int *ncookies;
652	INOUT u_long **cookies;
653	IN vfs_context_t context;
654*/
655
656#define MAXDIRBUFSIZE	65536
657
658/*
659 * "Transient" fnnodes are fnnodes that don't have anything mounted on
660 * them and don't have subdirectories.
661 * Those are subject to evaporating in the near term, so we don't
662 * return them from a readdir - and don't filter them out from names
663 * we get from automountd.
664 */
665#define IS_TRANSIENT(fnp) \
666	 (!vnode_mountedhere(fntovn(fnp)) && (fnp)->fn_direntcnt == 0)
667
668int
669auto_readdir(ap)
670	struct vnop_readdir_args /* {
671		vnode_t a_vp;
672		struct uio *a_uio;
673		int a_flags;
674		int *a_eofflag;
675		int *a_numdirent;
676		vfs_context_t a_context;
677	} */ *ap;
678{
679	vnode_t vp = ap->a_vp;
680	struct uio *uiop = ap->a_uio;
681	int pid = vfs_context_pid(ap->a_context);
682	int64_t return_offset;
683	boolean_t return_eof;
684	byte_buffer return_buffer;
685	mach_msg_type_number_t return_bufcount;
686	vm_map_offset_t map_data;
687	vm_offset_t data;
688	fnnode_t *fnp = vntofn(vp);
689	fnnode_t *cfnp, *nfnp;
690	struct dirent *dp;
691	off_t offset;
692	u_int outcount = 0;
693	mach_msg_type_number_t count;
694        void *outbuf;
695	user_ssize_t user_alloc_count;
696	u_int alloc_count;
697	fninfo_t *fnip = vfstofni(vnode_mount(vp));
698	kern_return_t ret;
699	int error = 0;
700	int reached_max = 0;
701	int myeof = 0;
702	u_int this_reclen;
703        boolean_t have_lock = 0;
704
705        AUTOFS_DPRINT((4, "auto_readdir vp=%p offset=%lld\n",
706            (void *)vp, uio_offset(uiop)));
707
708	if (ap->a_numdirent != NULL)
709		*ap->a_numdirent = 0;
710
711	if (ap->a_flags & (VNODE_READDIR_EXTENDED | VNODE_READDIR_REQSEEKOFF))
712		return (EINVAL);
713
714	if (ap->a_eofflag != NULL)
715		*ap->a_eofflag = 0;
716
717	user_alloc_count = uio_resid(uiop);
718	/*
719	 * Reject too-small user requests.
720	 */
721	if (user_alloc_count < (user_ssize_t) DIRENT_RECLEN(1))
722		return (EINVAL);
723	/*
724	 * Trim too-large user requests.
725	 */
726	if (user_alloc_count > (user_ssize_t) MAXDIRBUFSIZE)
727		user_alloc_count = MAXDIRBUFSIZE;
728	alloc_count = (u_int)user_alloc_count;
729
730	/*
731	 * Make sure the mounted map won't change out from under us.
732	 */
733	have_lock = auto_fninfo_lock_shared(fnip, pid);
734
735	/*
736	 * Make sure the directory we're reading won't change out from
737	 * under us while we're scanning it.
738	 */
739	lck_rw_lock_shared(fnp->fn_rwlock);
740
741	if (uio_offset(uiop) >= AUTOFS_DAEMONCOOKIE) {
742		/*
743		 * If we're in the middle of unmounting the map, we won't
744		 * create anything under it in a lookup, so we should
745		 * only return directory entries for things that are
746		 * already there.
747		 */
748		if (fnip->fi_flags & MF_UNMOUNTING) {
749			myeof = 1;
750			if (ap->a_eofflag != NULL)
751				*ap->a_eofflag = 1;
752			goto done;
753		}
754
755again:
756		/*
757		 * Do readdir of daemon contents only
758		 * Drop readers lock and reacquire after reply.
759		 */
760		lck_rw_unlock_shared(fnp->fn_rwlock);
761
762		count = 0;
763		error = auto_readdir_aux(fnip, fnp,
764		    uio_offset(uiop), alloc_count,
765		    &return_offset, &return_eof, &return_buffer,
766		    &return_bufcount);
767
768		/*
769		 * reacquire previously dropped lock
770		 */
771		lck_rw_lock_shared(fnp->fn_rwlock);
772
773		if (error)
774			goto done;
775
776		ret = vm_map_copyout(kernel_map, &map_data,
777		    (vm_map_copy_t)return_buffer);
778		if (ret != KERN_SUCCESS) {
779			IOLog("autofs: vm_map_copyout failed, status 0x%08x\n",
780			    ret);
781			/* XXX - deal with Mach errors */
782			error = EIO;
783			goto done;
784		}
785		data = CAST_DOWN(vm_offset_t, map_data);
786
787		if (return_bufcount != 0) {
788			struct dirent *odp;	/* next in output buffer */
789			struct dirent *cdp;	/* current examined entry */
790
791			/*
792			 * Check for duplicates of entries that have
793			 * fnnodes, and for illegal values (".", "..",
794			 * and anything with a "/" in it), here.
795			 */
796			dp = (struct dirent *)data;
797			odp = dp;
798			cdp = dp;
799			do {
800				this_reclen = RECLEN(cdp);
801				cfnp = auto_search(fnp, cdp->d_name,
802				    cdp->d_namlen);
803				if (cfnp == NULL || IS_TRANSIENT(cfnp)) {
804					/*
805					 * entry not found in kernel list,
806					 * or found but is transient, so
807					 * include it in readdir output.
808					 *
809					 * If we are skipping entries. then
810					 * we need to copy this entry to the
811					 * correct position in the buffer
812					 * to be copied out.
813					 */
814					if (cdp != odp)
815						bcopy(cdp, odp,
816						    (size_t)this_reclen);
817					odp = nextdp(odp);
818					outcount += this_reclen;
819					if (ap->a_numdirent)
820						++(*ap->a_numdirent);
821				} else {
822					/*
823					 * Entry was found in the kernel
824					 * list. If it is the first entry
825					 * in this buffer, then just skip it
826					 */
827					if (odp == dp) {
828						dp = nextdp(dp);
829						odp = dp;
830					}
831				}
832				count += this_reclen;
833				cdp = (struct dirent *)
834				    ((char *)cdp + this_reclen);
835			} while (count < return_bufcount);
836
837			if (outcount)
838				error = uiomove((caddr_t)dp, outcount, uiop);
839			uio_setoffset(uiop, return_offset);
840		} else {
841			if (return_eof == 0) {
842				/*
843				 * alloc_count not large enough for one
844				 * directory entry
845				 */
846				error = EINVAL;
847			}
848		}
849		vm_deallocate(kernel_map, data, return_bufcount);
850		if (return_eof && !error) {
851			myeof = 1;
852			if (ap->a_eofflag != NULL)
853				*ap->a_eofflag = 1;
854		}
855		if (!error && !myeof && outcount == 0) {
856			/*
857			 * call daemon with new cookie, all previous
858			 * elements happened to be duplicates
859			 */
860			goto again;
861		}
862		goto done;
863	}
864
865	/*
866	 * Not past the "magic" offset, so we return only the entries
867	 * we get without talking to the daemon.
868	 */
869	MALLOC(outbuf, void *, alloc_count, M_AUTOFS, M_WAITOK);
870	dp = outbuf;
871	if (uio_offset(uiop) == 0) {
872		/*
873		 * first time: so fudge the . and ..
874		 */
875		this_reclen = DIRENT_RECLEN(1);
876		if (alloc_count < this_reclen) {
877			error = EINVAL;
878			goto done;
879		}
880		dp->d_ino = (ino_t)fnp->fn_nodeid;
881		dp->d_reclen = (uint16_t)this_reclen;
882#if 0
883		dp->d_type = DT_DIR;
884#else
885		dp->d_type = DT_UNKNOWN;
886#endif
887		dp->d_namlen = 1;
888
889		/* use strncpy() to zero out uninitialized bytes */
890
891		(void) strncpy(dp->d_name, ".", DIRENT_NAMELEN(this_reclen));
892		outcount += dp->d_reclen;
893		dp = nextdp(dp);
894
895		if (ap->a_numdirent)
896			++(*ap->a_numdirent);
897
898		this_reclen = DIRENT_RECLEN(2);
899		if (alloc_count < outcount + this_reclen) {
900			error = EINVAL;
901			FREE(outbuf, M_AUTOFS);
902			goto done;
903		}
904		dp->d_reclen = (uint16_t)this_reclen;
905		dp->d_ino = (ino_t)fnp->fn_parent->fn_nodeid;
906#if 0
907		dp->d_type = DT_DIR;
908#else
909		dp->d_type = DT_UNKNOWN;
910#endif
911		dp->d_namlen = 2;
912
913		/* use strncpy() to zero out uninitialized bytes */
914
915		(void) strncpy(dp->d_name, "..",
916		    DIRENT_NAMELEN(this_reclen));
917		outcount += dp->d_reclen;
918		dp = nextdp(dp);
919
920		if (ap->a_numdirent)
921			++(*ap->a_numdirent);
922	}
923
924	offset = 2;
925	cfnp = fnp->fn_dirents;
926	while (cfnp != NULL) {
927		nfnp = cfnp->fn_next;
928		offset = cfnp->fn_offset;
929		/*
930		 * XXX - what is this lock protecting against?  We're
931		 * holding a read lock on the directory we're reading,
932		 * which should keep its fn_dirents list from changing
933		 * and thus keep fnnodes in that list from being freed.
934		 */
935		lck_rw_lock_shared(cfnp->fn_rwlock);
936		if ((offset >= uio_offset(uiop)) && !IS_TRANSIENT(cfnp)) {
937			int reclen;
938
939			lck_rw_unlock_shared(cfnp->fn_rwlock);
940
941			/*
942			 * include node only if its offset is greater or
943			 * equal to the one required and isn't
944			 * transient
945			 */
946			reclen = (int)DIRENT_RECLEN(cfnp->fn_namelen);
947			if (outcount + reclen > alloc_count) {
948				reached_max = 1;
949				break;
950			}
951			dp->d_reclen = (uint16_t)reclen;
952			dp->d_ino = (ino_t)cfnp->fn_nodeid;
953#if 0
954			dp->d_type = vnode_isdir(fntovn(cfnp)) ? DT_DIR : DT_LNK;
955#else
956			dp->d_type = DT_UNKNOWN;
957#endif
958			dp->d_namlen = cfnp->fn_namelen;
959
960			/* use strncpy() to zero out uninitialized bytes */
961
962			(void) strncpy(dp->d_name, cfnp->fn_name,
963			    DIRENT_NAMELEN(reclen));
964			outcount += dp->d_reclen;
965			dp = nextdp(dp);
966
967			if (ap->a_numdirent)
968				++(*ap->a_numdirent);
969		} else
970			lck_rw_unlock_shared(cfnp->fn_rwlock);
971		cfnp = nfnp;
972	}
973
974	if (outcount)
975		error = uiomove(outbuf, outcount, uiop);
976	if (!error) {
977		if (reached_max) {
978			/*
979			 * This entry did not get added to the buffer on this,
980			 * call. We need to add it on the next call therefore
981			 * set uio_offset to this entry's offset.  If there
982			 * wasn't enough space for one dirent, return EINVAL.
983			 */
984			uio_setoffset(uiop, offset);
985			if (outcount == 0)
986				error = EINVAL;
987		} else if (auto_nobrowse(vp)) {
988			/*
989			 * done reading directory entries
990			 */
991			uio_setoffset(uiop, offset + 1);
992			if (ap->a_eofflag != NULL)
993				*ap->a_eofflag = 1;
994		} else {
995			/*
996			 * Need to get the rest of the entries from the daemon.
997			 */
998			uio_setoffset(uiop, AUTOFS_DAEMONCOOKIE);
999		}
1000	}
1001	FREE(outbuf, M_AUTOFS);
1002
1003done:
1004	lck_rw_unlock_shared(fnp->fn_rwlock);
1005	auto_fninfo_unlock_shared(fnip, have_lock);
1006	AUTOFS_DPRINT((5, "auto_readdir vp=%p offset=%lld eof=%d\n",
1007	    (void *)vp, uio_offset(uiop), myeof));
1008	return (error);
1009}
1010
1011static int
1012auto_readlink(ap)
1013	struct vnop_readlink_args /* {
1014		struct vnodeop_desc *a_desc;
1015		vnode_t a_vp;
1016		struct uio *a_uio;
1017		vfs_context_t a_context;
1018	} */ *ap;
1019{
1020	vnode_t vp = ap->a_vp;
1021	uio_t uiop = ap->a_uio;
1022	fnnode_t *fnp = vntofn(vp);
1023	struct timeval now;
1024	int error;
1025
1026	AUTOFS_DPRINT((4, "auto_readlink: vp=%p\n", (void *)vp));
1027
1028	if (!vnode_islnk(vp))
1029		error = EINVAL;
1030	else {
1031		microtime(&now);
1032		fnp->fn_atime = now;
1033		error = uiomove(fnp->fn_symlink, MIN(fnp->fn_symlinklen,
1034		    (int)uio_resid(uiop)), uiop);
1035	}
1036
1037	AUTOFS_DPRINT((5, "auto_readlink: error=%d\n", error));
1038	return (error);
1039}
1040
1041static int
1042auto_pathconf(ap)
1043	struct vnop_pathconf_args /* {
1044		struct vnode *a_vp;
1045		int a_name;
1046		int *a_retval;
1047		vfs_context_t a_context;
1048	} */ *ap;
1049{
1050	switch (ap->a_name) {
1051	case _PC_LINK_MAX:
1052		/* arbitrary limit matching HFS; autofs has no hard limit */
1053		*ap->a_retval = 32767;
1054		break;
1055	case _PC_NAME_MAX:
1056		*ap->a_retval = NAME_MAX;
1057		break;
1058	case _PC_PATH_MAX:
1059		*ap->a_retval = PATH_MAX;
1060		break;
1061	case _PC_CHOWN_RESTRICTED:
1062		*ap->a_retval = 200112;		/* _POSIX_CHOWN_RESTRICTED */
1063		break;
1064	case _PC_NO_TRUNC:
1065		*ap->a_retval = 0;
1066		break;
1067	case _PC_CASE_SENSITIVE:
1068		*ap->a_retval = 1;
1069		break;
1070	case _PC_CASE_PRESERVING:
1071		*ap->a_retval = 1;
1072		break;
1073	default:
1074		return (EINVAL);
1075	}
1076
1077	return (0);
1078}
1079
1080static int
1081auto_fsctl(ap)
1082	struct vnop_ioctl_args /* {
1083		struct vnodeop_desc *a_desc;
1084		vnode_t a_vp;
1085		int32_t a_command;
1086		caddr_t a_data;
1087		int32_t a_fflag;
1088		vfs_context_t a_context;
1089	}; */ *ap;
1090{
1091	vnode_t vp = ap->a_vp;
1092
1093	/*
1094	 * The only operation we support is "mark this as having a home
1095	 * directory mount in progress".
1096	 */
1097	if (ap->a_command != IOCBASECMD(AUTOFS_MARK_HOMEDIRMOUNT))
1098		return (EINVAL);
1099
1100        /*
1101         * <13595777> homedirmounter getting ready to do a mount so we
1102         * want to take the mutex
1103         */
1104	return (auto_mark_vnode_homedirmount(vp,
1105                                             vfs_context_pid(ap->a_context),
1106                                             1));
1107}
1108
1109static int
1110auto_getxattr(ap)
1111 	struct vnop_getxattr_args /* {
1112		struct vnodeop_desc *a_desc;
1113		vnode_t a_vp;
1114		char * a_name;
1115		uio_t a_uio;
1116		size_t *a_size;
1117		int a_options;
1118		vfs_context_t a_context;
1119	}; */ *ap;
1120{
1121	struct uio *uio = ap->a_uio;
1122
1123	/* do not support position argument */
1124	if (uio_offset(uio) != 0)
1125		return (EINVAL);
1126
1127	/*
1128	 * We don't actually offer any extended attributes; we just say
1129	 * we do, so that nobody wastes our time - or any server's time,
1130	 * with wildcard maps - looking for ._ files.
1131	 */
1132	return (ENOATTR);
1133}
1134
1135static int
1136auto_listxattr(ap)
1137	struct vnop_listxattr_args /* {
1138		struct vnodeop_desc *a_desc;
1139		vnode_t a_vp;
1140		uio_t a_uio;
1141		size_t *a_size;
1142		int a_options;
1143		vfs_context_t a_context;
1144	}; */ *ap;
1145{
1146	*ap->a_size = 0;
1147
1148	/* we have no extended attributes, so just return 0 */
1149	return (0);
1150}
1151
1152/*
1153 * Called when the I/O count (in-progress vnops) is 0, and either
1154 * the use count (long-term references) is 0 or the vnode is being
1155 * forcibly disconnected from us (e.g., on a forced unmount, in which
1156 * case the vnode will be reassociated with deadfs).
1157 *
1158 * We just recycle the vnode, which encourages its reclamation; we
1159 * can't disconnect it until it's actually reclaimed.
1160 */
1161static int
1162auto_inactive(ap)
1163	struct vnop_inactive_args /* {
1164		struct vnodeop_desc *a_desc;
1165		vnode_t a_vp;
1166		vfs_context_t a_context;
1167	} */ *ap;
1168{
1169	AUTOFS_DPRINT((4, "auto_inactive: vp=%p\n", (void *)vp));
1170
1171	vnode_recycle(ap->a_vp);
1172
1173	AUTOFS_DPRINT((5, "auto_inactive: (exit) vp=%p\n", (void *)vp));
1174	return (0);
1175}
1176
1177static int
1178auto_reclaim(ap)
1179	struct vnop_reclaim_args /* {
1180		struct vnodeop_desc *a_desc;
1181		vnode_t a_vp;
1182		vfs_context_t a_context;
1183	} */ *ap;
1184{
1185	vnode_t vp = ap->a_vp;
1186	fnnode_t *fnp = vntofn(vp);
1187	vnode_t pvp = fnp->fn_parentvp;
1188	int is_symlink = (vnode_vtype(vp) == VLNK) ? 1 : 0;
1189
1190	AUTOFS_DPRINT((4, "auto_reclaim: vp=%p fn_link=%d\n",
1191	    (void *)vp, fnp->fn_linkcnt));
1192
1193	/*
1194	 * There are no filesystem calls in progress on this vnode, and
1195	 * none will be made until we're done.
1196	 *
1197	 * Thus, it's safe to disconnect this from its parent directory,
1198	 * if it has one.
1199	 */
1200	fnnode_t *dfnp = fnp->fn_parent;
1201	if (dfnp != NULL) {
1202		int	needs_put = 0;
1203
1204		if (pvp && pvp != vp) {
1205			if (vnode_getwithvid(pvp, fnp->fn_parentvid)) {
1206				/*
1207				 * parent has been reclaimed, just release the
1208				 * reference acquired in auto_lookup.
1209				 */
1210				fnp->fn_parent = NULL;
1211				fnp->fn_parentvp = NULL;
1212				vnode_rele(pvp);
1213				goto free_node;
1214			}
1215			needs_put = 1;
1216		}
1217
1218		lck_rw_lock_exclusive(dfnp->fn_rwlock);
1219		/*
1220		 * If there's only one link to this, namely the link to it
1221		 * from its parent, get rid of it by removing it from
1222		 * its parent's list of child fnnodes and recycle it;
1223		 * a subsequent reference to it will recreate it if
1224		 * the name is still there in the map.
1225		 *
1226		 * However, even if there is more than 1 link and we are in
1227		 * reclaim it just means that the parent is getting reclaimed
1228		 * before the child. This can happen and autofs can't prevent
1229		 * it because vflush with FORCECLOSE has already happened
1230		 * by the time autofs gets to say that it doesn't support
1231		 * forced unmounts in auto_unmount. The > 1 case is that case
1232		 * and we have to disconnect ourselves from the parent in that
1233		 * case as well.
1234		 */
1235		if (fnp->fn_linkcnt >= 1) {
1236			/*
1237			 * This will drop the write lock on dfnp.
1238			 */
1239			auto_disconnect(dfnp, fnp);
1240		} else if (fnp->fn_linkcnt == 0) {
1241			/*
1242			 * Root vnode; we've already removed it from the
1243			 * "parent" (the master node for all autofs file
1244			 * systems) - just null out the parent pointer, so
1245			 * that we don't trip any assertions
1246			 * in auto_freefnnode().
1247			 */
1248			fnp->fn_parent = NULL;
1249			fnp->fn_parentvp = NULL;
1250			lck_rw_unlock_exclusive(dfnp->fn_rwlock);
1251		}
1252
1253		if (needs_put) {
1254			vnode_put(pvp);
1255		}
1256	}
1257free_node:
1258	auto_freefnnode(fnp, is_symlink);
1259	vnode_clearfsnode(vp);
1260	AUTOFS_DPRINT((5, "auto_reclaim: (exit) vp=%p freed\n",
1261	    (void *)vp));
1262	return (0);
1263}
1264