1139804Simp/*-
230489Sphk * Copyright (c) 1989, 1993
330489Sphk *	The Regents of the University of California.  All rights reserved.
430489Sphk *
530489Sphk * This code is derived from software contributed
630489Sphk * to Berkeley by John Heidemann of the UCLA Ficus project.
730489Sphk *
830489Sphk * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project
930489Sphk *
1030489Sphk * Redistribution and use in source and binary forms, with or without
1130489Sphk * modification, are permitted provided that the following conditions
1230489Sphk * are met:
1330489Sphk * 1. Redistributions of source code must retain the above copyright
1430489Sphk *    notice, this list of conditions and the following disclaimer.
1530489Sphk * 2. Redistributions in binary form must reproduce the above copyright
1630489Sphk *    notice, this list of conditions and the following disclaimer in the
1730489Sphk *    documentation and/or other materials provided with the distribution.
1830489Sphk * 4. Neither the name of the University nor the names of its contributors
1930489Sphk *    may be used to endorse or promote products derived from this software
2030489Sphk *    without specific prior written permission.
2130489Sphk *
2230489Sphk * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2330489Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2430489Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2530489Sphk * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2630489Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2730489Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2830489Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2930489Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3030489Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3130489Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3230489Sphk * SUCH DAMAGE.
3330489Sphk */
3430489Sphk
35116182Sobrien#include <sys/cdefs.h>
36116182Sobrien__FBSDID("$FreeBSD$");
37116182Sobrien
3830489Sphk#include <sys/param.h>
3930489Sphk#include <sys/systm.h>
4060041Sphk#include <sys/bio.h>
4144272Sbde#include <sys/buf.h>
4265770Sbp#include <sys/conf.h>
43147198Sssouhlal#include <sys/event.h>
4430489Sphk#include <sys/kernel.h>
45114216Skan#include <sys/limits.h>
4631561Sbde#include <sys/lock.h>
47178243Skib#include <sys/lockf.h>
4830743Sphk#include <sys/malloc.h>
4951068Salfred#include <sys/mount.h>
5067365Sjhb#include <sys/mutex.h>
51189539Smarcus#include <sys/namei.h>
52189539Smarcus#include <sys/fcntl.h>
5330492Sphk#include <sys/unistd.h>
5430489Sphk#include <sys/vnode.h>
55189539Smarcus#include <sys/dirent.h>
5630743Sphk#include <sys/poll.h>
5730489Sphk
58193508Srwatson#include <security/mac/mac_framework.h>
59193508Srwatson
6065770Sbp#include <vm/vm.h>
6165770Sbp#include <vm/vm_object.h>
6265770Sbp#include <vm/vm_extern.h>
6365770Sbp#include <vm/pmap.h>
6465770Sbp#include <vm/vm_map.h>
6565770Sbp#include <vm/vm_page.h>
6665770Sbp#include <vm/vm_pager.h>
6765770Sbp#include <vm/vnode_pager.h>
6865770Sbp
6992723Salfredstatic int	vop_nolookup(struct vop_lookup_args *);
70206094Skibstatic int	vop_norename(struct vop_rename_args *);
7192723Salfredstatic int	vop_nostrategy(struct vop_strategy_args *);
72189539Smarcusstatic int	get_next_dirent(struct vnode *vp, struct dirent **dpp,
73189539Smarcus				char *dirbuf, int dirbuflen, off_t *off,
74189539Smarcus				char **cpos, int *len, int *eofflag,
75189539Smarcus				struct thread *td);
76189539Smarcusstatic int	dirent_exists(struct vnode *vp, const char *dirname,
77189539Smarcus			      struct thread *td);
7830489Sphk
79189539Smarcus#define DIRENT_MINSIZE (sizeof(struct dirent) - (MAXNAMLEN+1) + 4)
80189539Smarcus
81244658Skibstatic int vop_stdis_text(struct vop_is_text_args *ap);
82244658Skibstatic int vop_stdset_text(struct vop_set_text_args *ap);
83244658Skibstatic int vop_stdunset_text(struct vop_unset_text_args *ap);
84244660Skibstatic int vop_stdget_writecount(struct vop_get_writecount_args *ap);
85244660Skibstatic int vop_stdadd_writecount(struct vop_add_writecount_args *ap);
86244658Skib
8730489Sphk/*
8830489Sphk * This vnode table stores what we want to do if the filesystem doesn't
8930489Sphk * implement a particular VOP.
9030489Sphk *
9130489Sphk * If there is no specific entry here, we will return EOPNOTSUPP.
9230489Sphk *
93197680Strasz * Note that every filesystem has to implement either vop_access
94197680Strasz * or vop_accessx; failing to do so will result in immediate crash
95197680Strasz * due to stack overflow, as vop_stdaccess() calls vop_stdaccessx(),
96197680Strasz * which calls vop_stdaccess() etc.
9730489Sphk */
9830489Sphk
99138290Sphkstruct vop_vector default_vnodeops = {
100138290Sphk	.vop_default =		NULL,
101138339Sphk	.vop_bypass =		VOP_EOPNOTSUPP,
102138339Sphk
103197680Strasz	.vop_access =		vop_stdaccess,
104193092Strasz	.vop_accessx =		vop_stdaccessx,
105229723Sjhb	.vop_advise =		vop_stdadvise,
106178243Skib	.vop_advlock =		vop_stdadvlock,
107178243Skib	.vop_advlockasync =	vop_stdadvlockasync,
108208003Szml	.vop_advlockpurge =	vop_stdadvlockpurge,
109220791Smdf	.vop_allocate =		vop_stdallocate,
110138290Sphk	.vop_bmap =		vop_stdbmap,
111138290Sphk	.vop_close =		VOP_NULL,
112138290Sphk	.vop_fsync =		VOP_NULL,
113138290Sphk	.vop_getpages =		vop_stdgetpages,
114138290Sphk	.vop_getwritemount = 	vop_stdgetwritemount,
115143494Sjeff	.vop_inactive =		VOP_NULL,
116138290Sphk	.vop_ioctl =		VOP_ENOTTY,
117147198Sssouhlal	.vop_kqfilter =		vop_stdkqfilter,
118138290Sphk	.vop_islocked =		vop_stdislocked,
119169671Skib	.vop_lock1 =		vop_stdlock,
120138290Sphk	.vop_lookup =		vop_nolookup,
121138290Sphk	.vop_open =		VOP_NULL,
122138290Sphk	.vop_pathconf =		VOP_EINVAL,
123138290Sphk	.vop_poll =		vop_nopoll,
124138290Sphk	.vop_putpages =		vop_stdputpages,
125138290Sphk	.vop_readlink =		VOP_EINVAL,
126206094Skib	.vop_rename =		vop_norename,
127138290Sphk	.vop_revoke =		VOP_PANIC,
128138290Sphk	.vop_strategy =		vop_nostrategy,
129138290Sphk	.vop_unlock =		vop_stdunlock,
130189539Smarcus	.vop_vptocnp =		vop_stdvptocnp,
131166774Spjd	.vop_vptofh =		vop_stdvptofh,
132234660Strociny	.vop_unp_bind =		vop_stdunp_bind,
133234660Strociny	.vop_unp_connect =	vop_stdunp_connect,
134234660Strociny	.vop_unp_detach =	vop_stdunp_detach,
135244658Skib	.vop_is_text =		vop_stdis_text,
136244658Skib	.vop_set_text =		vop_stdset_text,
137244658Skib	.vop_unset_text =	vop_stdunset_text,
138244660Skib	.vop_get_writecount =	vop_stdget_writecount,
139244660Skib	.vop_add_writecount =	vop_stdadd_writecount,
14030489Sphk};
14130489Sphk
14291690Seivind/*
14391690Seivind * Series of placeholder functions for various error returns for
14491690Seivind * VOPs.
14591690Seivind */
14691690Seivind
14730489Sphkint
14830492Sphkvop_eopnotsupp(struct vop_generic_args *ap)
14930489Sphk{
15030489Sphk	/*
15130492Sphk	printf("vop_notsupp[%s]\n", ap->a_desc->vdesc_name);
15230489Sphk	*/
15330489Sphk
15430489Sphk	return (EOPNOTSUPP);
15530489Sphk}
15630489Sphk
15730489Sphkint
15830492Sphkvop_ebadf(struct vop_generic_args *ap)
15930489Sphk{
16030489Sphk
16130492Sphk	return (EBADF);
16230492Sphk}
16330492Sphk
16430492Sphkint
16530492Sphkvop_enotty(struct vop_generic_args *ap)
16630492Sphk{
16730492Sphk
16830492Sphk	return (ENOTTY);
16930492Sphk}
17030492Sphk
17130492Sphkint
17230492Sphkvop_einval(struct vop_generic_args *ap)
17330492Sphk{
17430492Sphk
17530492Sphk	return (EINVAL);
17630492Sphk}
17730492Sphk
17830492Sphkint
179185956Smarcusvop_enoent(struct vop_generic_args *ap)
180185956Smarcus{
181185956Smarcus
182185956Smarcus	return (ENOENT);
183185956Smarcus}
184185956Smarcus
185185956Smarcusint
18630492Sphkvop_null(struct vop_generic_args *ap)
18730492Sphk{
18830492Sphk
18930492Sphk	return (0);
19030492Sphk}
19130492Sphk
19291690Seivind/*
19391690Seivind * Helper function to panic on some bad VOPs in some filesystems.
19491690Seivind */
19541056Speterint
19641056Spetervop_panic(struct vop_generic_args *ap)
19741056Speter{
19841056Speter
19972594Sbde	panic("filesystem goof: vop_panic[%s]", ap->a_desc->vdesc_name);
20041056Speter}
20141056Speter
20291690Seivind/*
20391690Seivind * vop_std<something> and vop_no<something> are default functions for use by
20491690Seivind * filesystems that need the "default reasonable" implementation for a
20591690Seivind * particular operation.
20691690Seivind *
20791690Seivind * The documentation for the operations they implement exists (if it exists)
20891690Seivind * in the VOP_<SOMETHING>(9) manpage (all uppercase).
20991690Seivind */
21091690Seivind
21191690Seivind/*
21291690Seivind * Default vop for filesystems that do not support name lookup
21391690Seivind */
21472594Sbdestatic int
21572594Sbdevop_nolookup(ap)
21672594Sbde	struct vop_lookup_args /* {
21772594Sbde		struct vnode *a_dvp;
21872594Sbde		struct vnode **a_vpp;
21972594Sbde		struct componentname *a_cnp;
22072594Sbde	} */ *ap;
22172594Sbde{
22272594Sbde
22372594Sbde	*ap->a_vpp = NULL;
22472594Sbde	return (ENOTDIR);
22572594Sbde}
22672594Sbde
22746349Salc/*
228206094Skib * vop_norename:
229206094Skib *
230206094Skib * Handle unlock and reference counting for arguments of vop_rename
231206094Skib * for filesystems that do not implement rename operation.
232206094Skib */
233206094Skibstatic int
234206094Skibvop_norename(struct vop_rename_args *ap)
235206094Skib{
236206094Skib
237206094Skib	vop_rename_fail(ap);
238206094Skib	return (EOPNOTSUPP);
239206094Skib}
240206094Skib
241206094Skib/*
24246349Salc *	vop_nostrategy:
24346349Salc *
24446349Salc *	Strategy routine for VFS devices that have none.
24546349Salc *
24658934Sphk *	BIO_ERROR and B_INVAL must be cleared prior to calling any strategy
24758345Sphk *	routine.  Typically this is done for a BIO_READ strategy call.
248112067Skan *	Typically B_INVAL is assumed to already be clear prior to a write
24958345Sphk *	and should not be cleared manually unless you just made the buffer
25058934Sphk *	invalid.  BIO_ERROR should be cleared either way.
25146349Salc */
25246349Salc
25330489Sphkstatic int
25430489Sphkvop_nostrategy (struct vop_strategy_args *ap)
25530489Sphk{
25630489Sphk	printf("No strategy for buffer at %p\n", ap->a_bp);
257111842Snjl	vprint("vnode", ap->a_vp);
25858934Sphk	ap->a_bp->b_ioflags |= BIO_ERROR;
25930489Sphk	ap->a_bp->b_error = EOPNOTSUPP;
26059249Sphk	bufdone(ap->a_bp);
26130489Sphk	return (EOPNOTSUPP);
26230489Sphk}
26330492Sphk
264189539Smarcusstatic int
265189539Smarcusget_next_dirent(struct vnode *vp, struct dirent **dpp, char *dirbuf,
266189539Smarcus		int dirbuflen, off_t *off, char **cpos, int *len,
267189539Smarcus		int *eofflag, struct thread *td)
268189539Smarcus{
269189539Smarcus	int error, reclen;
270189539Smarcus	struct uio uio;
271189539Smarcus	struct iovec iov;
272189539Smarcus	struct dirent *dp;
273189539Smarcus
274189539Smarcus	KASSERT(VOP_ISLOCKED(vp), ("vp %p is not locked", vp));
275189539Smarcus	KASSERT(vp->v_type == VDIR, ("vp %p is not a directory", vp));
276189539Smarcus
277189539Smarcus	if (*len == 0) {
278189539Smarcus		iov.iov_base = dirbuf;
279189539Smarcus		iov.iov_len = dirbuflen;
280189539Smarcus
281189539Smarcus		uio.uio_iov = &iov;
282189539Smarcus		uio.uio_iovcnt = 1;
283189539Smarcus		uio.uio_offset = *off;
284189539Smarcus		uio.uio_resid = dirbuflen;
285189539Smarcus		uio.uio_segflg = UIO_SYSSPACE;
286189539Smarcus		uio.uio_rw = UIO_READ;
287189539Smarcus		uio.uio_td = td;
288189539Smarcus
289189539Smarcus		*eofflag = 0;
290189539Smarcus
291189539Smarcus#ifdef MAC
292189539Smarcus		error = mac_vnode_check_readdir(td->td_ucred, vp);
293189539Smarcus		if (error == 0)
294189539Smarcus#endif
295189539Smarcus			error = VOP_READDIR(vp, &uio, td->td_ucred, eofflag,
296189539Smarcus		    		NULL, NULL);
297189539Smarcus		if (error)
298189539Smarcus			return (error);
299189539Smarcus
300211818Sbrian		*off = uio.uio_offset;
301211818Sbrian
302211684Sbrian		*cpos = dirbuf;
303211818Sbrian		*len = (dirbuflen - uio.uio_resid);
304211818Sbrian
305211818Sbrian		if (*len == 0)
306211818Sbrian			return (ENOENT);
307189539Smarcus	}
308189539Smarcus
309189539Smarcus	dp = (struct dirent *)(*cpos);
310189539Smarcus	reclen = dp->d_reclen;
311189539Smarcus	*dpp = dp;
312189539Smarcus
313189539Smarcus	/* check for malformed directory.. */
314189539Smarcus	if (reclen < DIRENT_MINSIZE)
315189539Smarcus		return (EINVAL);
316189539Smarcus
317189539Smarcus	*cpos += reclen;
318189539Smarcus	*len -= reclen;
319189539Smarcus
320189539Smarcus	return (0);
321189539Smarcus}
322189539Smarcus
32391690Seivind/*
324189539Smarcus * Check if a named file exists in a given directory vnode.
325189539Smarcus */
326189539Smarcusstatic int
327189539Smarcusdirent_exists(struct vnode *vp, const char *dirname, struct thread *td)
328189539Smarcus{
329189539Smarcus	char *dirbuf, *cpos;
330189539Smarcus	int error, eofflag, dirbuflen, len, found;
331189539Smarcus	off_t off;
332189539Smarcus	struct dirent *dp;
333189539Smarcus	struct vattr va;
334189539Smarcus
335189539Smarcus	KASSERT(VOP_ISLOCKED(vp), ("vp %p is not locked", vp));
336189539Smarcus	KASSERT(vp->v_type == VDIR, ("vp %p is not a directory", vp));
337189539Smarcus
338189539Smarcus	found = 0;
339189539Smarcus
340189539Smarcus	error = VOP_GETATTR(vp, &va, td->td_ucred);
341189539Smarcus	if (error)
342189539Smarcus		return (found);
343189539Smarcus
344189539Smarcus	dirbuflen = DEV_BSIZE;
345189539Smarcus	if (dirbuflen < va.va_blocksize)
346189539Smarcus		dirbuflen = va.va_blocksize;
347189539Smarcus	dirbuf = (char *)malloc(dirbuflen, M_TEMP, M_WAITOK);
348189539Smarcus
349189539Smarcus	off = 0;
350189539Smarcus	len = 0;
351189539Smarcus	do {
352189539Smarcus		error = get_next_dirent(vp, &dp, dirbuf, dirbuflen, &off,
353189539Smarcus					&cpos, &len, &eofflag, td);
354189539Smarcus		if (error)
355189539Smarcus			goto out;
356189539Smarcus
357189539Smarcus		if ((dp->d_type != DT_WHT) &&
358189539Smarcus		    !strcmp(dp->d_name, dirname)) {
359189539Smarcus			found = 1;
360189539Smarcus			goto out;
361189539Smarcus		}
362189539Smarcus	} while (len > 0 || !eofflag);
363189539Smarcus
364189539Smarcusout:
365189539Smarcus	free(dirbuf, M_TEMP);
366189539Smarcus	return (found);
367189539Smarcus}
368189539Smarcus
369193092Straszint
370197680Straszvop_stdaccess(struct vop_access_args *ap)
371197680Strasz{
372197680Strasz
373197680Strasz	KASSERT((ap->a_accmode & ~(VEXEC | VWRITE | VREAD | VADMIN |
374197680Strasz	    VAPPEND)) == 0, ("invalid bit in accmode"));
375197680Strasz
376197680Strasz	return (VOP_ACCESSX(ap->a_vp, ap->a_accmode, ap->a_cred, ap->a_td));
377197680Strasz}
378197680Strasz
379197680Straszint
380193092Straszvop_stdaccessx(struct vop_accessx_args *ap)
381193092Strasz{
382193092Strasz	int error;
383193092Strasz	accmode_t accmode = ap->a_accmode;
384193092Strasz
385193092Strasz	error = vfs_unixify_accmode(&accmode);
386193092Strasz	if (error != 0)
387193092Strasz		return (error);
388193092Strasz
389193092Strasz	if (accmode == 0)
390193092Strasz		return (0);
391193092Strasz
392193092Strasz	return (VOP_ACCESS(ap->a_vp, accmode, ap->a_cred, ap->a_td));
393193092Strasz}
394193092Strasz
395189539Smarcus/*
396178243Skib * Advisory record locking support
397178243Skib */
398178243Skibint
399178243Skibvop_stdadvlock(struct vop_advlock_args *ap)
400178243Skib{
401182371Sattilio	struct vnode *vp;
402182371Sattilio	struct ucred *cred;
403178243Skib	struct vattr vattr;
404178243Skib	int error;
405178243Skib
406182371Sattilio	vp = ap->a_vp;
407182371Sattilio	cred = curthread->td_ucred;
408178243Skib	vn_lock(vp, LK_SHARED | LK_RETRY);
409182371Sattilio	error = VOP_GETATTR(vp, &vattr, cred);
410178243Skib	VOP_UNLOCK(vp, 0);
411178243Skib	if (error)
412178243Skib		return (error);
413178243Skib
414178243Skib	return (lf_advlock(ap, &(vp->v_lockf), vattr.va_size));
415178243Skib}
416178243Skib
417178243Skibint
418178243Skibvop_stdadvlockasync(struct vop_advlockasync_args *ap)
419178243Skib{
420182371Sattilio	struct vnode *vp;
421182371Sattilio	struct ucred *cred;
422178243Skib	struct vattr vattr;
423178243Skib	int error;
424178243Skib
425182371Sattilio	vp = ap->a_vp;
426182371Sattilio	cred = curthread->td_ucred;
427178243Skib	vn_lock(vp, LK_SHARED | LK_RETRY);
428182371Sattilio	error = VOP_GETATTR(vp, &vattr, cred);
429178243Skib	VOP_UNLOCK(vp, 0);
430178243Skib	if (error)
431178243Skib		return (error);
432178243Skib
433178243Skib	return (lf_advlockasync(ap, &(vp->v_lockf), vattr.va_size));
434178243Skib}
435178243Skib
436208003Szmlint
437208003Szmlvop_stdadvlockpurge(struct vop_advlockpurge_args *ap)
438208003Szml{
439208003Szml	struct vnode *vp;
440208003Szml
441208003Szml	vp = ap->a_vp;
442208003Szml	lf_purgelocks(vp, &vp->v_lockf);
443208003Szml	return (0);
444208003Szml}
445208003Szml
446178243Skib/*
44791690Seivind * vop_stdpathconf:
448112067Skan *
44991690Seivind * Standard implementation of POSIX pathconf, to get information about limits
45091690Seivind * for a filesystem.
45191690Seivind * Override per filesystem for the case where the filesystem has smaller
45291690Seivind * limits.
45391690Seivind */
45430492Sphkint
45530492Sphkvop_stdpathconf(ap)
45630492Sphk	struct vop_pathconf_args /* {
45730492Sphk	struct vnode *a_vp;
45830492Sphk	int a_name;
45930492Sphk	int *a_retval;
46030492Sphk	} */ *ap;
46130492Sphk{
46230492Sphk
46330492Sphk	switch (ap->a_name) {
464149175Sphk		case _PC_NAME_MAX:
465149175Sphk			*ap->a_retval = NAME_MAX;
466149175Sphk			return (0);
467149175Sphk		case _PC_PATH_MAX:
468149175Sphk			*ap->a_retval = PATH_MAX;
469149175Sphk			return (0);
47030492Sphk		case _PC_LINK_MAX:
47130492Sphk			*ap->a_retval = LINK_MAX;
47230492Sphk			return (0);
47330492Sphk		case _PC_MAX_CANON:
47430492Sphk			*ap->a_retval = MAX_CANON;
47530492Sphk			return (0);
47630492Sphk		case _PC_MAX_INPUT:
47730492Sphk			*ap->a_retval = MAX_INPUT;
47830492Sphk			return (0);
47930492Sphk		case _PC_PIPE_BUF:
48030492Sphk			*ap->a_retval = PIPE_BUF;
48130492Sphk			return (0);
48230492Sphk		case _PC_CHOWN_RESTRICTED:
48330492Sphk			*ap->a_retval = 1;
48430492Sphk			return (0);
48530492Sphk		case _PC_VDISABLE:
48630492Sphk			*ap->a_retval = _POSIX_VDISABLE;
48730492Sphk			return (0);
48830492Sphk		default:
48930492Sphk			return (EINVAL);
49030492Sphk	}
49130492Sphk	/* NOTREACHED */
49230492Sphk}
49330513Sphk
49430513Sphk/*
49530513Sphk * Standard lock, unlock and islocked functions.
49630513Sphk */
49730513Sphkint
49830513Sphkvop_stdlock(ap)
499169671Skib	struct vop_lock1_args /* {
50030513Sphk		struct vnode *a_vp;
50130513Sphk		int a_flags;
502164248Skmacy		char *file;
503164248Skmacy		int line;
50430513Sphk	} */ *ap;
505112067Skan{
50666355Sbp	struct vnode *vp = ap->a_vp;
50730513Sphk
508176320Sattilio	return (_lockmgr_args(vp->v_vnlock, ap->a_flags, VI_MTX(vp),
509176320Sattilio	    LK_WMESG_DEFAULT, LK_PRIO_DEFAULT, LK_TIMO_DEFAULT, ap->a_file,
510175635Sattilio	    ap->a_line));
51130513Sphk}
51230513Sphk
51391690Seivind/* See above. */
51430513Sphkint
51530513Sphkvop_stdunlock(ap)
51630513Sphk	struct vop_unlock_args /* {
51730513Sphk		struct vnode *a_vp;
51830513Sphk		int a_flags;
51930513Sphk	} */ *ap;
52030513Sphk{
52166355Sbp	struct vnode *vp = ap->a_vp;
52230513Sphk
523175635Sattilio	return (lockmgr(vp->v_vnlock, ap->a_flags | LK_RELEASE, VI_MTX(vp)));
52430513Sphk}
52530513Sphk
52691690Seivind/* See above. */
52730513Sphkint
52830513Sphkvop_stdislocked(ap)
52930513Sphk	struct vop_islocked_args /* {
53030513Sphk		struct vnode *a_vp;
53130513Sphk	} */ *ap;
53230513Sphk{
53330513Sphk
534176559Sattilio	return (lockstatus(ap->a_vp->v_vnlock));
53530513Sphk}
53630513Sphk
53730743Sphk/*
53830743Sphk * Return true for select/poll.
53930743Sphk */
54030743Sphkint
54130743Sphkvop_nopoll(ap)
54230743Sphk	struct vop_poll_args /* {
54330743Sphk		struct vnode *a_vp;
54430743Sphk		int  a_events;
54530743Sphk		struct ucred *a_cred;
54683366Sjulian		struct thread *a_td;
54730743Sphk	} */ *ap;
54830743Sphk{
54931727Swollman
550189450Skib	return (poll_no_poll(ap->a_events));
55130743Sphk}
55230743Sphk
55331727Swollman/*
55431727Swollman * Implement poll for local filesystems that support it.
55531727Swollman */
55630743Sphkint
55731727Swollmanvop_stdpoll(ap)
55831727Swollman	struct vop_poll_args /* {
55931727Swollman		struct vnode *a_vp;
56031727Swollman		int  a_events;
56131727Swollman		struct ucred *a_cred;
56283366Sjulian		struct thread *a_td;
56331727Swollman	} */ *ap;
56431727Swollman{
56576578Sjlemon	if (ap->a_events & ~POLLSTANDARD)
56683366Sjulian		return (vn_pollrecord(ap->a_vp, ap->a_td, ap->a_events));
56776578Sjlemon	return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
56831727Swollman}
56931727Swollman
57030743Sphk/*
57162976Smckusick * Return our mount point, as we will take charge of the writes.
57262976Smckusick */
57362976Smckusickint
57462976Smckusickvop_stdgetwritemount(ap)
57562976Smckusick	struct vop_getwritemount_args /* {
57662976Smckusick		struct vnode *a_vp;
57762976Smckusick		struct mount **a_mpp;
57862976Smckusick	} */ *ap;
57962976Smckusick{
580157323Sjeff	struct mount *mp;
58162976Smckusick
582157323Sjeff	/*
583157323Sjeff	 * XXX Since this is called unlocked we may be recycled while
584157323Sjeff	 * attempting to ref the mount.  If this is the case or mountpoint
585157323Sjeff	 * will be set to NULL.  We only have to prevent this call from
586157323Sjeff	 * returning with a ref to an incorrect mountpoint.  It is not
587157323Sjeff	 * harmful to return with a ref to our previous mountpoint.
588157323Sjeff	 */
589157323Sjeff	mp = ap->a_vp->v_mount;
590162455Stegge	if (mp != NULL) {
591162455Stegge		vfs_ref(mp);
592162455Stegge		if (mp != ap->a_vp->v_mount) {
593162455Stegge			vfs_rel(mp);
594162455Stegge			mp = NULL;
595162455Stegge		}
596157323Sjeff	}
597157323Sjeff	*(ap->a_mpp) = mp;
59862976Smckusick	return (0);
59962976Smckusick}
60062976Smckusick
60191690Seivind/* XXX Needs good comment and VOP_BMAP(9) manpage */
60276131Sphkint
60376131Sphkvop_stdbmap(ap)
604112067Skan	struct vop_bmap_args /* {
60576131Sphk		struct vnode *a_vp;
60676131Sphk		daddr_t  a_bn;
607137726Sphk		struct bufobj **a_bop;
60876131Sphk		daddr_t *a_bnp;
60976131Sphk		int *a_runp;
61076131Sphk		int *a_runb;
61176131Sphk	} */ *ap;
61276131Sphk{
61376131Sphk
614137726Sphk	if (ap->a_bop != NULL)
615137726Sphk		*ap->a_bop = &ap->a_vp->v_bufobj;
61676131Sphk	if (ap->a_bnp != NULL)
61776131Sphk		*ap->a_bnp = ap->a_bn * btodb(ap->a_vp->v_mount->mnt_stat.f_iosize);
61876131Sphk	if (ap->a_runp != NULL)
61976131Sphk		*ap->a_runp = 0;
62076131Sphk	if (ap->a_runb != NULL)
62176131Sphk		*ap->a_runb = 0;
62276131Sphk	return (0);
62376131Sphk}
62476131Sphk
625110584Sjeffint
626110584Sjeffvop_stdfsync(ap)
627110584Sjeff	struct vop_fsync_args /* {
628110584Sjeff		struct vnode *a_vp;
629110584Sjeff		struct ucred *a_cred;
630110584Sjeff		int a_waitfor;
631110584Sjeff		struct thread *a_td;
632110584Sjeff	} */ *ap;
633110584Sjeff{
634110584Sjeff	struct vnode *vp = ap->a_vp;
635110584Sjeff	struct buf *bp;
636136751Sphk	struct bufobj *bo;
637110584Sjeff	struct buf *nbp;
638145732Sjeff	int error = 0;
639144584Sjeff	int maxretry = 1000;     /* large, arbitrarily chosen */
640110584Sjeff
641177493Sjeff	bo = &vp->v_bufobj;
642177493Sjeff	BO_LOCK(bo);
643110584Sjeffloop1:
644110584Sjeff	/*
645110584Sjeff	 * MARK/SCAN initialization to avoid infinite loops.
646110584Sjeff	 */
647177493Sjeff        TAILQ_FOREACH(bp, &bo->bo_dirty.bv_hd, b_bobufs) {
648110584Sjeff                bp->b_vflags &= ~BV_SCANNED;
649110584Sjeff		bp->b_error = 0;
650110584Sjeff	}
651110584Sjeff
652110584Sjeff	/*
653144584Sjeff	 * Flush all dirty buffers associated with a vnode.
654110584Sjeff	 */
655110584Sjeffloop2:
656177493Sjeff	TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) {
657110584Sjeff		if ((bp->b_vflags & BV_SCANNED) != 0)
658110584Sjeff			continue;
659110584Sjeff		bp->b_vflags |= BV_SCANNED;
660237351Smckusick		if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) {
661237351Smckusick			if (ap->a_waitfor != MNT_WAIT)
662237351Smckusick				continue;
663237351Smckusick			if (BUF_LOCK(bp,
664237351Smckusick			    LK_EXCLUSIVE | LK_INTERLOCK | LK_SLEEPFAIL,
665237351Smckusick			    BO_MTX(bo)) != 0) {
666237351Smckusick				BO_LOCK(bo);
667237351Smckusick				goto loop1;
668237351Smckusick			}
669237351Smckusick			BO_LOCK(bo);
670237351Smckusick		}
671177493Sjeff		BO_UNLOCK(bo);
672177493Sjeff		KASSERT(bp->b_bufobj == bo,
673147388Sjeff		    ("bp %p wrong b_bufobj %p should be %p",
674177493Sjeff		    bp, bp->b_bufobj, bo));
675110584Sjeff		if ((bp->b_flags & B_DELWRI) == 0)
676110588Sjeff			panic("fsync: not dirty");
677140734Sphk		if ((vp->v_object != NULL) && (bp->b_flags & B_CLUSTEROK)) {
678110584Sjeff			vfs_bio_awrite(bp);
679110584Sjeff		} else {
680110584Sjeff			bremfree(bp);
681110584Sjeff			bawrite(bp);
682110584Sjeff		}
683177493Sjeff		BO_LOCK(bo);
684110584Sjeff		goto loop2;
685110584Sjeff	}
686110584Sjeff
687110584Sjeff	/*
688110584Sjeff	 * If synchronous the caller expects us to completely resolve all
689110584Sjeff	 * dirty buffers in the system.  Wait for in-progress I/O to
690110584Sjeff	 * complete (which could include background bitmap writes), then
691110584Sjeff	 * retry if dirty blocks still exist.
692110584Sjeff	 */
693110584Sjeff	if (ap->a_waitfor == MNT_WAIT) {
694136751Sphk		bufobj_wwait(bo, 0, 0);
695136751Sphk		if (bo->bo_dirty.bv_cnt > 0) {
696110584Sjeff			/*
697110584Sjeff			 * If we are unable to write any of these buffers
698110584Sjeff			 * then we fail now rather than trying endlessly
699110584Sjeff			 * to write them out.
700110584Sjeff			 */
701136751Sphk			TAILQ_FOREACH(bp, &bo->bo_dirty.bv_hd, b_bobufs)
702110584Sjeff				if ((error = bp->b_error) == 0)
703110584Sjeff					continue;
704145732Sjeff			if (error == 0 && --maxretry >= 0)
705110584Sjeff				goto loop1;
706110584Sjeff			error = EAGAIN;
707110584Sjeff		}
708110584Sjeff	}
709177493Sjeff	BO_UNLOCK(bo);
710144584Sjeff	if (error == EAGAIN)
711144584Sjeff		vprint("fsync: giving up on dirty", vp);
712112067Skan
713110584Sjeff	return (error);
714110584Sjeff}
715112067Skan
71691690Seivind/* XXX Needs good comment and more info in the manpage (VOP_GETPAGES(9)). */
71776167Sphkint
71876167Sphkvop_stdgetpages(ap)
71976167Sphk	struct vop_getpages_args /* {
72076167Sphk		struct vnode *a_vp;
72176167Sphk		vm_page_t *a_m;
72276167Sphk		int a_count;
72376167Sphk		int a_reqpage;
72476167Sphk		vm_ooffset_t a_offset;
72576167Sphk	} */ *ap;
72676167Sphk{
72776131Sphk
72876167Sphk	return vnode_pager_generic_getpages(ap->a_vp, ap->a_m,
72976167Sphk	    ap->a_count, ap->a_reqpage);
73076167Sphk}
73176167Sphk
732147198Sssouhlalint
733147198Sssouhlalvop_stdkqfilter(struct vop_kqfilter_args *ap)
734147198Sssouhlal{
735147198Sssouhlal	return vfs_kqfilter(ap);
736147198Sssouhlal}
737147198Sssouhlal
73891690Seivind/* XXX Needs good comment and more info in the manpage (VOP_PUTPAGES(9)). */
73976319Sphkint
74076167Sphkvop_stdputpages(ap)
74176167Sphk	struct vop_putpages_args /* {
74276167Sphk		struct vnode *a_vp;
74376167Sphk		vm_page_t *a_m;
74476167Sphk		int a_count;
74576167Sphk		int a_sync;
74676167Sphk		int *a_rtvals;
74776167Sphk		vm_ooffset_t a_offset;
74876167Sphk	} */ *ap;
74976167Sphk{
75076167Sphk
75176319Sphk	return vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count,
75276167Sphk	     ap->a_sync, ap->a_rtvals);
75376167Sphk}
75476167Sphk
755166774Spjdint
756166774Spjdvop_stdvptofh(struct vop_vptofh_args *ap)
757166774Spjd{
758166795Spjd	return (EOPNOTSUPP);
759166774Spjd}
760166774Spjd
761189539Smarcusint
762189539Smarcusvop_stdvptocnp(struct vop_vptocnp_args *ap)
763189539Smarcus{
764189539Smarcus	struct vnode *vp = ap->a_vp;
765189539Smarcus	struct vnode **dvp = ap->a_vpp;
766194601Skib	struct ucred *cred = ap->a_cred;
767189539Smarcus	char *buf = ap->a_buf;
768189539Smarcus	int *buflen = ap->a_buflen;
769189539Smarcus	char *dirbuf, *cpos;
770189539Smarcus	int i, error, eofflag, dirbuflen, flags, locked, len, covered;
771189539Smarcus	off_t off;
772189539Smarcus	ino_t fileno;
773189539Smarcus	struct vattr va;
774189539Smarcus	struct nameidata nd;
775189539Smarcus	struct thread *td;
776189539Smarcus	struct dirent *dp;
777189539Smarcus	struct vnode *mvp;
778189539Smarcus
779189539Smarcus	i = *buflen;
780189539Smarcus	error = 0;
781189539Smarcus	covered = 0;
782189539Smarcus	td = curthread;
783189539Smarcus
784189539Smarcus	if (vp->v_type != VDIR)
785189539Smarcus		return (ENOENT);
786189539Smarcus
787194601Skib	error = VOP_GETATTR(vp, &va, cred);
788189539Smarcus	if (error)
789189539Smarcus		return (error);
790189539Smarcus
791189539Smarcus	VREF(vp);
792189539Smarcus	locked = VOP_ISLOCKED(vp);
793189539Smarcus	VOP_UNLOCK(vp, 0);
794189539Smarcus	NDINIT_ATVP(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
795189539Smarcus	    "..", vp, td);
796189539Smarcus	flags = FREAD;
797194601Skib	error = vn_open_cred(&nd, &flags, 0, VN_OPEN_NOAUDIT, cred, NULL);
798189539Smarcus	if (error) {
799189539Smarcus		vn_lock(vp, locked | LK_RETRY);
800189539Smarcus		return (error);
801189539Smarcus	}
802189539Smarcus	NDFREE(&nd, NDF_ONLY_PNBUF);
803189539Smarcus
804189539Smarcus	mvp = *dvp = nd.ni_vp;
805189539Smarcus
806189539Smarcus	if (vp->v_mount != (*dvp)->v_mount &&
807189539Smarcus	    ((*dvp)->v_vflag & VV_ROOT) &&
808189539Smarcus	    ((*dvp)->v_mount->mnt_flag & MNT_UNION)) {
809189539Smarcus		*dvp = (*dvp)->v_mount->mnt_vnodecovered;
810189539Smarcus		VREF(mvp);
811189539Smarcus		VOP_UNLOCK(mvp, 0);
812194601Skib		vn_close(mvp, FREAD, cred, td);
813189539Smarcus		VREF(*dvp);
814189539Smarcus		vn_lock(*dvp, LK_EXCLUSIVE | LK_RETRY);
815189539Smarcus		covered = 1;
816189539Smarcus	}
817189539Smarcus
818189539Smarcus	fileno = va.va_fileid;
819189539Smarcus
820189539Smarcus	dirbuflen = DEV_BSIZE;
821189539Smarcus	if (dirbuflen < va.va_blocksize)
822189539Smarcus		dirbuflen = va.va_blocksize;
823189539Smarcus	dirbuf = (char *)malloc(dirbuflen, M_TEMP, M_WAITOK);
824189539Smarcus
825189539Smarcus	if ((*dvp)->v_type != VDIR) {
826189539Smarcus		error = ENOENT;
827189539Smarcus		goto out;
828189539Smarcus	}
829189539Smarcus
830189539Smarcus	off = 0;
831189539Smarcus	len = 0;
832189539Smarcus	do {
833189539Smarcus		/* call VOP_READDIR of parent */
834189539Smarcus		error = get_next_dirent(*dvp, &dp, dirbuf, dirbuflen, &off,
835189539Smarcus					&cpos, &len, &eofflag, td);
836189539Smarcus		if (error)
837189539Smarcus			goto out;
838189539Smarcus
839189539Smarcus		if ((dp->d_type != DT_WHT) &&
840189539Smarcus		    (dp->d_fileno == fileno)) {
841189539Smarcus			if (covered) {
842189539Smarcus				VOP_UNLOCK(*dvp, 0);
843189539Smarcus				vn_lock(mvp, LK_EXCLUSIVE | LK_RETRY);
844189539Smarcus				if (dirent_exists(mvp, dp->d_name, td)) {
845189539Smarcus					error = ENOENT;
846189539Smarcus					VOP_UNLOCK(mvp, 0);
847189539Smarcus					vn_lock(*dvp, LK_EXCLUSIVE | LK_RETRY);
848189539Smarcus					goto out;
849189539Smarcus				}
850189539Smarcus				VOP_UNLOCK(mvp, 0);
851189539Smarcus				vn_lock(*dvp, LK_EXCLUSIVE | LK_RETRY);
852189539Smarcus			}
853189539Smarcus			i -= dp->d_namlen;
854189539Smarcus
855189539Smarcus			if (i < 0) {
856189539Smarcus				error = ENOMEM;
857189539Smarcus				goto out;
858189539Smarcus			}
859248029Skib			if (dp->d_namlen == 1 && dp->d_name[0] == '.') {
860248029Skib				error = ENOENT;
861248029Skib			} else {
862248029Skib				bcopy(dp->d_name, buf + i, dp->d_namlen);
863248029Skib				error = 0;
864248029Skib			}
865189539Smarcus			goto out;
866189539Smarcus		}
867189539Smarcus	} while (len > 0 || !eofflag);
868189539Smarcus	error = ENOENT;
869189539Smarcus
870189539Smarcusout:
871189539Smarcus	free(dirbuf, M_TEMP);
872189539Smarcus	if (!error) {
873189539Smarcus		*buflen = i;
874229703Skib		vref(*dvp);
875189539Smarcus	}
876189539Smarcus	if (covered) {
877189539Smarcus		vput(*dvp);
878189539Smarcus		vrele(mvp);
879189539Smarcus	} else {
880189539Smarcus		VOP_UNLOCK(mvp, 0);
881194601Skib		vn_close(mvp, FREAD, cred, td);
882189539Smarcus	}
883189539Smarcus	vn_lock(vp, locked | LK_RETRY);
884189539Smarcus	return (error);
885189539Smarcus}
886189539Smarcus
887220791Smdfint
888220791Smdfvop_stdallocate(struct vop_allocate_args *ap)
889220791Smdf{
890220791Smdf#ifdef __notyet__
891220791Smdf	struct statfs sfs;
892220791Smdf#endif
893220791Smdf	struct iovec aiov;
894220791Smdf	struct vattr vattr, *vap;
895220791Smdf	struct uio auio;
896220846Smdf	off_t fsize, len, cur, offset;
897220791Smdf	uint8_t *buf;
898220791Smdf	struct thread *td;
899220791Smdf	struct vnode *vp;
900220791Smdf	size_t iosize;
901220846Smdf	int error;
902220791Smdf
903220791Smdf	buf = NULL;
904220791Smdf	error = 0;
905220791Smdf	td = curthread;
906220791Smdf	vap = &vattr;
907220791Smdf	vp = ap->a_vp;
908220846Smdf	len = *ap->a_len;
909220846Smdf	offset = *ap->a_offset;
910220791Smdf
911220791Smdf	error = VOP_GETATTR(vp, vap, td->td_ucred);
912220791Smdf	if (error != 0)
913220791Smdf		goto out;
914220846Smdf	fsize = vap->va_size;
915220791Smdf	iosize = vap->va_blocksize;
916220791Smdf	if (iosize == 0)
917220791Smdf		iosize = BLKDEV_IOSIZE;
918220791Smdf	if (iosize > MAXPHYS)
919220791Smdf		iosize = MAXPHYS;
920220791Smdf	buf = malloc(iosize, M_TEMP, M_WAITOK);
921220791Smdf
922220791Smdf#ifdef __notyet__
923220791Smdf	/*
924220791Smdf	 * Check if the filesystem sets f_maxfilesize; if not use
925220791Smdf	 * VOP_SETATTR to perform the check.
926220791Smdf	 */
927220791Smdf	error = VFS_STATFS(vp->v_mount, &sfs, td);
928220791Smdf	if (error != 0)
929220791Smdf		goto out;
930220791Smdf	if (sfs.f_maxfilesize) {
931220791Smdf		if (offset > sfs.f_maxfilesize || len > sfs.f_maxfilesize ||
932220791Smdf		    offset + len > sfs.f_maxfilesize) {
933220791Smdf			error = EFBIG;
934220791Smdf			goto out;
935220791Smdf		}
936220791Smdf	} else
937220791Smdf#endif
938220791Smdf	if (offset + len > vap->va_size) {
939220846Smdf		/*
940220846Smdf		 * Test offset + len against the filesystem's maxfilesize.
941220846Smdf		 */
942220791Smdf		VATTR_NULL(vap);
943220791Smdf		vap->va_size = offset + len;
944220791Smdf		error = VOP_SETATTR(vp, vap, td->td_ucred);
945220791Smdf		if (error != 0)
946220791Smdf			goto out;
947220846Smdf		VATTR_NULL(vap);
948220846Smdf		vap->va_size = fsize;
949220846Smdf		error = VOP_SETATTR(vp, vap, td->td_ucred);
950220846Smdf		if (error != 0)
951220846Smdf			goto out;
952220791Smdf	}
953220791Smdf
954220846Smdf	for (;;) {
955220791Smdf		/*
956220791Smdf		 * Read and write back anything below the nominal file
957220791Smdf		 * size.  There's currently no way outside the filesystem
958220791Smdf		 * to know whether this area is sparse or not.
959220791Smdf		 */
960220791Smdf		cur = iosize;
961220791Smdf		if ((offset % iosize) != 0)
962220791Smdf			cur -= (offset % iosize);
963220791Smdf		if (cur > len)
964220791Smdf			cur = len;
965220846Smdf		if (offset < fsize) {
966220791Smdf			aiov.iov_base = buf;
967220791Smdf			aiov.iov_len = cur;
968220791Smdf			auio.uio_iov = &aiov;
969220791Smdf			auio.uio_iovcnt = 1;
970220791Smdf			auio.uio_offset = offset;
971220791Smdf			auio.uio_resid = cur;
972220791Smdf			auio.uio_segflg = UIO_SYSSPACE;
973220791Smdf			auio.uio_rw = UIO_READ;
974220791Smdf			auio.uio_td = td;
975220791Smdf			error = VOP_READ(vp, &auio, 0, td->td_ucred);
976220791Smdf			if (error != 0)
977220791Smdf				break;
978220791Smdf			if (auio.uio_resid > 0) {
979220791Smdf				bzero(buf + cur - auio.uio_resid,
980220791Smdf				    auio.uio_resid);
981220791Smdf			}
982220791Smdf		} else {
983220791Smdf			bzero(buf, cur);
984220791Smdf		}
985220791Smdf
986220791Smdf		aiov.iov_base = buf;
987220791Smdf		aiov.iov_len = cur;
988220791Smdf		auio.uio_iov = &aiov;
989220791Smdf		auio.uio_iovcnt = 1;
990220791Smdf		auio.uio_offset = offset;
991220791Smdf		auio.uio_resid = cur;
992220791Smdf		auio.uio_segflg = UIO_SYSSPACE;
993220791Smdf		auio.uio_rw = UIO_WRITE;
994220791Smdf		auio.uio_td = td;
995220791Smdf
996220791Smdf		error = VOP_WRITE(vp, &auio, 0, td->td_ucred);
997220791Smdf		if (error != 0)
998220791Smdf			break;
999220791Smdf
1000220791Smdf		len -= cur;
1001220791Smdf		offset += cur;
1002220846Smdf		if (len == 0)
1003220846Smdf			break;
1004220846Smdf		if (should_yield())
1005220846Smdf			break;
1006220791Smdf	}
1007220791Smdf
1008220791Smdf out:
1009220846Smdf	*ap->a_len = len;
1010220846Smdf	*ap->a_offset = offset;
1011220791Smdf	free(buf, M_TEMP);
1012220791Smdf	return (error);
1013220791Smdf}
1014220791Smdf
1015229723Sjhbint
1016229723Sjhbvop_stdadvise(struct vop_advise_args *ap)
1017229723Sjhb{
1018229723Sjhb	struct vnode *vp;
1019229723Sjhb	off_t start, end;
1020229723Sjhb	int error, vfslocked;
1021229723Sjhb
1022229723Sjhb	vp = ap->a_vp;
1023229723Sjhb	switch (ap->a_advice) {
1024229723Sjhb	case POSIX_FADV_WILLNEED:
1025229723Sjhb		/*
1026229723Sjhb		 * Do nothing for now.  Filesystems should provide a
1027229723Sjhb		 * custom method which starts an asynchronous read of
1028229723Sjhb		 * the requested region.
1029229723Sjhb		 */
1030229723Sjhb		error = 0;
1031229723Sjhb		break;
1032229723Sjhb	case POSIX_FADV_DONTNEED:
1033229723Sjhb		/*
1034229723Sjhb		 * Flush any open FS buffers and then remove pages
1035229723Sjhb		 * from the backing VM object.  Using vinvalbuf() here
1036229723Sjhb		 * is a bit heavy-handed as it flushes all buffers for
1037229723Sjhb		 * the given vnode, not just the buffers covering the
1038229723Sjhb		 * requested range.
1039229723Sjhb		 */
1040229723Sjhb		error = 0;
1041229723Sjhb		vfslocked = VFS_LOCK_GIANT(vp->v_mount);
1042229723Sjhb		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1043229723Sjhb		if (vp->v_iflag & VI_DOOMED) {
1044229723Sjhb			VOP_UNLOCK(vp, 0);
1045229723Sjhb			VFS_UNLOCK_GIANT(vfslocked);
1046229723Sjhb			break;
1047229723Sjhb		}
1048229723Sjhb		vinvalbuf(vp, V_CLEANONLY, 0, 0);
1049229723Sjhb		if (vp->v_object != NULL) {
1050229723Sjhb			start = trunc_page(ap->a_start);
1051229723Sjhb			end = round_page(ap->a_end);
1052229723Sjhb			VM_OBJECT_LOCK(vp->v_object);
1053229723Sjhb			vm_object_page_cache(vp->v_object, OFF_TO_IDX(start),
1054229723Sjhb			    OFF_TO_IDX(end));
1055229723Sjhb			VM_OBJECT_UNLOCK(vp->v_object);
1056229723Sjhb		}
1057229723Sjhb		VOP_UNLOCK(vp, 0);
1058229723Sjhb		VFS_UNLOCK_GIANT(vfslocked);
1059229723Sjhb		break;
1060229723Sjhb	default:
1061229723Sjhb		error = EINVAL;
1062229723Sjhb		break;
1063229723Sjhb	}
1064229723Sjhb	return (error);
1065229723Sjhb}
1066229723Sjhb
1067234660Strocinyint
1068234660Strocinyvop_stdunp_bind(struct vop_unp_bind_args *ap)
1069234660Strociny{
1070234660Strociny
1071234660Strociny	ap->a_vp->v_socket = ap->a_socket;
1072234660Strociny	return (0);
1073234660Strociny}
1074234660Strociny
1075234660Strocinyint
1076234660Strocinyvop_stdunp_connect(struct vop_unp_connect_args *ap)
1077234660Strociny{
1078234660Strociny
1079234660Strociny	*ap->a_socket = ap->a_vp->v_socket;
1080234660Strociny	return (0);
1081234660Strociny}
1082234660Strociny
1083234660Strocinyint
1084234660Strocinyvop_stdunp_detach(struct vop_unp_detach_args *ap)
1085234660Strociny{
1086234660Strociny
1087234660Strociny	ap->a_vp->v_socket = NULL;
1088234660Strociny	return (0);
1089234660Strociny}
1090234660Strociny
1091244658Skibstatic int
1092244658Skibvop_stdis_text(struct vop_is_text_args *ap)
1093244658Skib{
1094244658Skib
1095244658Skib	return ((ap->a_vp->v_vflag & VV_TEXT) != 0);
1096244658Skib}
1097244658Skib
1098244658Skibstatic int
1099244658Skibvop_stdset_text(struct vop_set_text_args *ap)
1100244658Skib{
1101244658Skib
1102244658Skib	ap->a_vp->v_vflag |= VV_TEXT;
1103244658Skib	return (0);
1104244658Skib}
1105244658Skib
1106244658Skibstatic int
1107244658Skibvop_stdunset_text(struct vop_unset_text_args *ap)
1108244658Skib{
1109244658Skib
1110244658Skib	ap->a_vp->v_vflag &= ~VV_TEXT;
1111244658Skib	return (0);
1112244658Skib}
1113244658Skib
1114244660Skibstatic int
1115244660Skibvop_stdget_writecount(struct vop_get_writecount_args *ap)
1116244660Skib{
1117244660Skib
1118244660Skib	*ap->a_writecount = ap->a_vp->v_writecount;
1119244660Skib	return (0);
1120244660Skib}
1121244660Skib
1122244660Skibstatic int
1123244660Skibvop_stdadd_writecount(struct vop_add_writecount_args *ap)
1124244660Skib{
1125244660Skib
1126244660Skib	ap->a_vp->v_writecount += ap->a_inc;
1127244660Skib	return (0);
1128244660Skib}
1129244660Skib
1130112067Skan/*
113151068Salfred * vfs default ops
113291690Seivind * used to fill the vfs function table to get reasonable default return values.
113351068Salfred */
113491690Seivindint
1135191990Sattiliovfs_stdroot (mp, flags, vpp)
113651068Salfred	struct mount *mp;
1137144054Sjeff	int flags;
113851068Salfred	struct vnode **vpp;
113951068Salfred{
1140131734Salfred
114151068Salfred	return (EOPNOTSUPP);
114251068Salfred}
114351068Salfred
114491690Seivindint
1145191990Sattiliovfs_stdstatfs (mp, sbp)
114651068Salfred	struct mount *mp;
114751068Salfred	struct statfs *sbp;
114851068Salfred{
1149131734Salfred
115051068Salfred	return (EOPNOTSUPP);
115151068Salfred}
115251068Salfred
115351068Salfredint
1154191990Sattiliovfs_stdquotactl (mp, cmds, uid, arg)
115551068Salfred	struct mount *mp;
115651068Salfred	int cmds;
115751068Salfred	uid_t uid;
1158153400Sdes	void *arg;
115951068Salfred{
1160131734Salfred
116151068Salfred	return (EOPNOTSUPP);
116251068Salfred}
116351068Salfred
1164112067Skanint
1165191990Sattiliovfs_stdsync(mp, waitfor)
116651068Salfred	struct mount *mp;
116751068Salfred	int waitfor;
116851068Salfred{
1169154152Stegge	struct vnode *vp, *mvp;
1170191990Sattilio	struct thread *td;
1171112119Skan	int error, lockreq, allerror = 0;
1172112119Skan
1173191990Sattilio	td = curthread;
1174112119Skan	lockreq = LK_EXCLUSIVE | LK_INTERLOCK;
1175112119Skan	if (waitfor != MNT_WAIT)
1176112119Skan		lockreq |= LK_NOWAIT;
1177112119Skan	/*
1178112119Skan	 * Force stale buffer cache information to be flushed.
1179112119Skan	 */
1180112119Skanloop:
1181235626Smckusick	MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
1182235626Smckusick		if (vp->v_bufobj.bo_dirty.bv_cnt == 0) {
1183235626Smckusick			VI_UNLOCK(vp);
1184177493Sjeff			continue;
1185235626Smckusick		}
1186112119Skan		if ((error = vget(vp, lockreq, td)) != 0) {
1187154152Stegge			if (error == ENOENT) {
1188235626Smckusick				MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
1189112119Skan				goto loop;
1190154152Stegge			}
1191112119Skan			continue;
1192112119Skan		}
1193140048Sphk		error = VOP_FSYNC(vp, waitfor, td);
1194112119Skan		if (error)
1195112119Skan			allerror = error;
1196204065Spjd		vput(vp);
1197112119Skan	}
1198112119Skan	return (allerror);
1199112119Skan}
1200112119Skan
1201112119Skanint
1202191990Sattiliovfs_stdnosync (mp, waitfor)
1203112119Skan	struct mount *mp;
1204112119Skan	int waitfor;
1205112119Skan{
1206131734Salfred
120751068Salfred	return (0);
120851068Salfred}
120951068Salfred
1210112067Skanint
121192462Smckusickvfs_stdvget (mp, ino, flags, vpp)
121251068Salfred	struct mount *mp;
121351068Salfred	ino_t ino;
121492462Smckusick	int flags;
121551068Salfred	struct vnode **vpp;
121651068Salfred{
1217131734Salfred
121851068Salfred	return (EOPNOTSUPP);
121951068Salfred}
122051068Salfred
1221112067Skanint
1222222167Srmacklemvfs_stdfhtovp (mp, fhp, flags, vpp)
122351068Salfred	struct mount *mp;
122451068Salfred	struct fid *fhp;
1225222167Srmacklem	int flags;
122651138Salfred	struct vnode **vpp;
122751138Salfred{
1228131734Salfred
122951138Salfred	return (EOPNOTSUPP);
123051138Salfred}
123151138Salfred
123251068Salfredint
1233112067Skanvfs_stdinit (vfsp)
123451068Salfred	struct vfsconf *vfsp;
123551068Salfred{
1236131734Salfred
123751068Salfred	return (0);
123851068Salfred}
123951068Salfred
124051068Salfredint
124151068Salfredvfs_stduninit (vfsp)
124251068Salfred	struct vfsconf *vfsp;
124351068Salfred{
1244131734Salfred
124551068Salfred	return(0);
124651068Salfred}
124751068Salfred
124854803Srwatsonint
1249191990Sattiliovfs_stdextattrctl(mp, cmd, filename_vp, attrnamespace, attrname)
125054803Srwatson	struct mount *mp;
125154803Srwatson	int cmd;
125274273Srwatson	struct vnode *filename_vp;
125374437Srwatson	int attrnamespace;
125456272Srwatson	const char *attrname;
125554803Srwatson{
1256131734Salfred
1257101786Sphk	if (filename_vp != NULL)
1258175294Sattilio		VOP_UNLOCK(filename_vp, 0);
1259131734Salfred	return (EOPNOTSUPP);
126054803Srwatson}
126154803Srwatson
1262131733Salfredint
1263131733Salfredvfs_stdsysctl(mp, op, req)
1264131733Salfred	struct mount *mp;
1265131733Salfred	fsctlop_t op;
1266131733Salfred	struct sysctl_req *req;
1267131733Salfred{
1268131733Salfred
1269131733Salfred	return (EOPNOTSUPP);
1270131733Salfred}
1271131733Salfred
127251068Salfred/* end of vfs default ops */
1273