vfs_default.c revision 191990
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: head/sys/kern/vfs_default.c 191990 2009-05-11 15:33:26Z attilio $");
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
5865770Sbp#include <vm/vm.h>
5965770Sbp#include <vm/vm_object.h>
6065770Sbp#include <vm/vm_extern.h>
6165770Sbp#include <vm/pmap.h>
6265770Sbp#include <vm/vm_map.h>
6365770Sbp#include <vm/vm_page.h>
6465770Sbp#include <vm/vm_pager.h>
6565770Sbp#include <vm/vnode_pager.h>
6665770Sbp
6792723Salfredstatic int	vop_nolookup(struct vop_lookup_args *);
6892723Salfredstatic int	vop_nostrategy(struct vop_strategy_args *);
69189539Smarcusstatic int	get_next_dirent(struct vnode *vp, struct dirent **dpp,
70189539Smarcus				char *dirbuf, int dirbuflen, off_t *off,
71189539Smarcus				char **cpos, int *len, int *eofflag,
72189539Smarcus				struct thread *td);
73189539Smarcusstatic int	dirent_exists(struct vnode *vp, const char *dirname,
74189539Smarcus			      struct thread *td);
7530489Sphk
76189539Smarcus#define DIRENT_MINSIZE (sizeof(struct dirent) - (MAXNAMLEN+1) + 4)
77189539Smarcus
7830489Sphk/*
7930489Sphk * This vnode table stores what we want to do if the filesystem doesn't
8030489Sphk * implement a particular VOP.
8130489Sphk *
8230489Sphk * If there is no specific entry here, we will return EOPNOTSUPP.
8330489Sphk *
8430489Sphk */
8530489Sphk
86138290Sphkstruct vop_vector default_vnodeops = {
87138290Sphk	.vop_default =		NULL,
88138339Sphk	.vop_bypass =		VOP_EOPNOTSUPP,
89138339Sphk
90178243Skib	.vop_advlock =		vop_stdadvlock,
91178243Skib	.vop_advlockasync =	vop_stdadvlockasync,
92138290Sphk	.vop_bmap =		vop_stdbmap,
93138290Sphk	.vop_close =		VOP_NULL,
94138290Sphk	.vop_fsync =		VOP_NULL,
95138290Sphk	.vop_getpages =		vop_stdgetpages,
96138290Sphk	.vop_getwritemount = 	vop_stdgetwritemount,
97143494Sjeff	.vop_inactive =		VOP_NULL,
98138290Sphk	.vop_ioctl =		VOP_ENOTTY,
99147198Sssouhlal	.vop_kqfilter =		vop_stdkqfilter,
100138290Sphk	.vop_islocked =		vop_stdislocked,
101169671Skib	.vop_lock1 =		vop_stdlock,
102138290Sphk	.vop_lookup =		vop_nolookup,
103138290Sphk	.vop_open =		VOP_NULL,
104138290Sphk	.vop_pathconf =		VOP_EINVAL,
105138290Sphk	.vop_poll =		vop_nopoll,
106138290Sphk	.vop_putpages =		vop_stdputpages,
107138290Sphk	.vop_readlink =		VOP_EINVAL,
108138290Sphk	.vop_revoke =		VOP_PANIC,
109138290Sphk	.vop_strategy =		vop_nostrategy,
110138290Sphk	.vop_unlock =		vop_stdunlock,
111189539Smarcus	.vop_vptocnp =		vop_stdvptocnp,
112166774Spjd	.vop_vptofh =		vop_stdvptofh,
11330489Sphk};
11430489Sphk
11591690Seivind/*
11691690Seivind * Series of placeholder functions for various error returns for
11791690Seivind * VOPs.
11891690Seivind */
11991690Seivind
12030489Sphkint
12130492Sphkvop_eopnotsupp(struct vop_generic_args *ap)
12230489Sphk{
12330489Sphk	/*
12430492Sphk	printf("vop_notsupp[%s]\n", ap->a_desc->vdesc_name);
12530489Sphk	*/
12630489Sphk
12730489Sphk	return (EOPNOTSUPP);
12830489Sphk}
12930489Sphk
13030489Sphkint
13130492Sphkvop_ebadf(struct vop_generic_args *ap)
13230489Sphk{
13330489Sphk
13430492Sphk	return (EBADF);
13530492Sphk}
13630492Sphk
13730492Sphkint
13830492Sphkvop_enotty(struct vop_generic_args *ap)
13930492Sphk{
14030492Sphk
14130492Sphk	return (ENOTTY);
14230492Sphk}
14330492Sphk
14430492Sphkint
14530492Sphkvop_einval(struct vop_generic_args *ap)
14630492Sphk{
14730492Sphk
14830492Sphk	return (EINVAL);
14930492Sphk}
15030492Sphk
15130492Sphkint
152185956Smarcusvop_enoent(struct vop_generic_args *ap)
153185956Smarcus{
154185956Smarcus
155185956Smarcus	return (ENOENT);
156185956Smarcus}
157185956Smarcus
158185956Smarcusint
15930492Sphkvop_null(struct vop_generic_args *ap)
16030492Sphk{
16130492Sphk
16230492Sphk	return (0);
16330492Sphk}
16430492Sphk
16591690Seivind/*
16691690Seivind * Helper function to panic on some bad VOPs in some filesystems.
16791690Seivind */
16841056Speterint
16941056Spetervop_panic(struct vop_generic_args *ap)
17041056Speter{
17141056Speter
17272594Sbde	panic("filesystem goof: vop_panic[%s]", ap->a_desc->vdesc_name);
17341056Speter}
17441056Speter
17591690Seivind/*
17691690Seivind * vop_std<something> and vop_no<something> are default functions for use by
17791690Seivind * filesystems that need the "default reasonable" implementation for a
17891690Seivind * particular operation.
17991690Seivind *
18091690Seivind * The documentation for the operations they implement exists (if it exists)
18191690Seivind * in the VOP_<SOMETHING>(9) manpage (all uppercase).
18291690Seivind */
18391690Seivind
18491690Seivind/*
18591690Seivind * Default vop for filesystems that do not support name lookup
18691690Seivind */
18772594Sbdestatic int
18872594Sbdevop_nolookup(ap)
18972594Sbde	struct vop_lookup_args /* {
19072594Sbde		struct vnode *a_dvp;
19172594Sbde		struct vnode **a_vpp;
19272594Sbde		struct componentname *a_cnp;
19372594Sbde	} */ *ap;
19472594Sbde{
19572594Sbde
19672594Sbde	*ap->a_vpp = NULL;
19772594Sbde	return (ENOTDIR);
19872594Sbde}
19972594Sbde
20046349Salc/*
20146349Salc *	vop_nostrategy:
20246349Salc *
20346349Salc *	Strategy routine for VFS devices that have none.
20446349Salc *
20558934Sphk *	BIO_ERROR and B_INVAL must be cleared prior to calling any strategy
20658345Sphk *	routine.  Typically this is done for a BIO_READ strategy call.
207112067Skan *	Typically B_INVAL is assumed to already be clear prior to a write
20858345Sphk *	and should not be cleared manually unless you just made the buffer
20958934Sphk *	invalid.  BIO_ERROR should be cleared either way.
21046349Salc */
21146349Salc
21230489Sphkstatic int
21330489Sphkvop_nostrategy (struct vop_strategy_args *ap)
21430489Sphk{
21530489Sphk	printf("No strategy for buffer at %p\n", ap->a_bp);
216111842Snjl	vprint("vnode", ap->a_vp);
21758934Sphk	ap->a_bp->b_ioflags |= BIO_ERROR;
21830489Sphk	ap->a_bp->b_error = EOPNOTSUPP;
21959249Sphk	bufdone(ap->a_bp);
22030489Sphk	return (EOPNOTSUPP);
22130489Sphk}
22230492Sphk
223189539Smarcusstatic int
224189539Smarcusget_next_dirent(struct vnode *vp, struct dirent **dpp, char *dirbuf,
225189539Smarcus		int dirbuflen, off_t *off, char **cpos, int *len,
226189539Smarcus		int *eofflag, struct thread *td)
227189539Smarcus{
228189539Smarcus	int error, reclen;
229189539Smarcus	struct uio uio;
230189539Smarcus	struct iovec iov;
231189539Smarcus	struct dirent *dp;
232189539Smarcus
233189539Smarcus	KASSERT(VOP_ISLOCKED(vp), ("vp %p is not locked", vp));
234189539Smarcus	KASSERT(vp->v_type == VDIR, ("vp %p is not a directory", vp));
235189539Smarcus
236189539Smarcus	if (*len == 0) {
237189539Smarcus		iov.iov_base = dirbuf;
238189539Smarcus		iov.iov_len = dirbuflen;
239189539Smarcus
240189539Smarcus		uio.uio_iov = &iov;
241189539Smarcus		uio.uio_iovcnt = 1;
242189539Smarcus		uio.uio_offset = *off;
243189539Smarcus		uio.uio_resid = dirbuflen;
244189539Smarcus		uio.uio_segflg = UIO_SYSSPACE;
245189539Smarcus		uio.uio_rw = UIO_READ;
246189539Smarcus		uio.uio_td = td;
247189539Smarcus
248189539Smarcus		*eofflag = 0;
249189539Smarcus
250189539Smarcus#ifdef MAC
251189539Smarcus		error = mac_vnode_check_readdir(td->td_ucred, vp);
252189539Smarcus		if (error == 0)
253189539Smarcus#endif
254189539Smarcus			error = VOP_READDIR(vp, &uio, td->td_ucred, eofflag,
255189539Smarcus		    		NULL, NULL);
256189539Smarcus		if (error)
257189539Smarcus			return (error);
258189539Smarcus
259189539Smarcus		*off = uio.uio_offset;
260189539Smarcus
261189539Smarcus		*cpos = dirbuf;
262189539Smarcus		*len = (dirbuflen - uio.uio_resid);
263189539Smarcus	}
264189539Smarcus
265189539Smarcus	dp = (struct dirent *)(*cpos);
266189539Smarcus	reclen = dp->d_reclen;
267189539Smarcus	*dpp = dp;
268189539Smarcus
269189539Smarcus	/* check for malformed directory.. */
270189539Smarcus	if (reclen < DIRENT_MINSIZE)
271189539Smarcus		return (EINVAL);
272189539Smarcus
273189539Smarcus	*cpos += reclen;
274189539Smarcus	*len -= reclen;
275189539Smarcus
276189539Smarcus	return (0);
277189539Smarcus}
278189539Smarcus
27991690Seivind/*
280189539Smarcus * Check if a named file exists in a given directory vnode.
281189539Smarcus */
282189539Smarcusstatic int
283189539Smarcusdirent_exists(struct vnode *vp, const char *dirname, struct thread *td)
284189539Smarcus{
285189539Smarcus	char *dirbuf, *cpos;
286189539Smarcus	int error, eofflag, dirbuflen, len, found;
287189539Smarcus	off_t off;
288189539Smarcus	struct dirent *dp;
289189539Smarcus	struct vattr va;
290189539Smarcus
291189539Smarcus	KASSERT(VOP_ISLOCKED(vp), ("vp %p is not locked", vp));
292189539Smarcus	KASSERT(vp->v_type == VDIR, ("vp %p is not a directory", vp));
293189539Smarcus
294189539Smarcus	found = 0;
295189539Smarcus
296189539Smarcus	error = VOP_GETATTR(vp, &va, td->td_ucred);
297189539Smarcus	if (error)
298189539Smarcus		return (found);
299189539Smarcus
300189539Smarcus	dirbuflen = DEV_BSIZE;
301189539Smarcus	if (dirbuflen < va.va_blocksize)
302189539Smarcus		dirbuflen = va.va_blocksize;
303189539Smarcus	dirbuf = (char *)malloc(dirbuflen, M_TEMP, M_WAITOK);
304189539Smarcus
305189539Smarcus	off = 0;
306189539Smarcus	len = 0;
307189539Smarcus	do {
308189539Smarcus		error = get_next_dirent(vp, &dp, dirbuf, dirbuflen, &off,
309189539Smarcus					&cpos, &len, &eofflag, td);
310189539Smarcus		if (error)
311189539Smarcus			goto out;
312189539Smarcus
313189539Smarcus		if ((dp->d_type != DT_WHT) &&
314189539Smarcus		    !strcmp(dp->d_name, dirname)) {
315189539Smarcus			found = 1;
316189539Smarcus			goto out;
317189539Smarcus		}
318189539Smarcus	} while (len > 0 || !eofflag);
319189539Smarcus
320189539Smarcusout:
321189539Smarcus	free(dirbuf, M_TEMP);
322189539Smarcus	return (found);
323189539Smarcus}
324189539Smarcus
325189539Smarcus/*
326178243Skib * Advisory record locking support
327178243Skib */
328178243Skibint
329178243Skibvop_stdadvlock(struct vop_advlock_args *ap)
330178243Skib{
331182371Sattilio	struct vnode *vp;
332182371Sattilio	struct ucred *cred;
333178243Skib	struct vattr vattr;
334178243Skib	int error;
335178243Skib
336182371Sattilio	vp = ap->a_vp;
337182371Sattilio	cred = curthread->td_ucred;
338178243Skib	vn_lock(vp, LK_SHARED | LK_RETRY);
339182371Sattilio	error = VOP_GETATTR(vp, &vattr, cred);
340178243Skib	VOP_UNLOCK(vp, 0);
341178243Skib	if (error)
342178243Skib		return (error);
343178243Skib
344178243Skib	return (lf_advlock(ap, &(vp->v_lockf), vattr.va_size));
345178243Skib}
346178243Skib
347178243Skibint
348178243Skibvop_stdadvlockasync(struct vop_advlockasync_args *ap)
349178243Skib{
350182371Sattilio	struct vnode *vp;
351182371Sattilio	struct ucred *cred;
352178243Skib	struct vattr vattr;
353178243Skib	int error;
354178243Skib
355182371Sattilio	vp = ap->a_vp;
356182371Sattilio	cred = curthread->td_ucred;
357178243Skib	vn_lock(vp, LK_SHARED | LK_RETRY);
358182371Sattilio	error = VOP_GETATTR(vp, &vattr, cred);
359178243Skib	VOP_UNLOCK(vp, 0);
360178243Skib	if (error)
361178243Skib		return (error);
362178243Skib
363178243Skib	return (lf_advlockasync(ap, &(vp->v_lockf), vattr.va_size));
364178243Skib}
365178243Skib
366178243Skib/*
36791690Seivind * vop_stdpathconf:
368112067Skan *
36991690Seivind * Standard implementation of POSIX pathconf, to get information about limits
37091690Seivind * for a filesystem.
37191690Seivind * Override per filesystem for the case where the filesystem has smaller
37291690Seivind * limits.
37391690Seivind */
37430492Sphkint
37530492Sphkvop_stdpathconf(ap)
37630492Sphk	struct vop_pathconf_args /* {
37730492Sphk	struct vnode *a_vp;
37830492Sphk	int a_name;
37930492Sphk	int *a_retval;
38030492Sphk	} */ *ap;
38130492Sphk{
38230492Sphk
38330492Sphk	switch (ap->a_name) {
384149175Sphk		case _PC_NAME_MAX:
385149175Sphk			*ap->a_retval = NAME_MAX;
386149175Sphk			return (0);
387149175Sphk		case _PC_PATH_MAX:
388149175Sphk			*ap->a_retval = PATH_MAX;
389149175Sphk			return (0);
39030492Sphk		case _PC_LINK_MAX:
39130492Sphk			*ap->a_retval = LINK_MAX;
39230492Sphk			return (0);
39330492Sphk		case _PC_MAX_CANON:
39430492Sphk			*ap->a_retval = MAX_CANON;
39530492Sphk			return (0);
39630492Sphk		case _PC_MAX_INPUT:
39730492Sphk			*ap->a_retval = MAX_INPUT;
39830492Sphk			return (0);
39930492Sphk		case _PC_PIPE_BUF:
40030492Sphk			*ap->a_retval = PIPE_BUF;
40130492Sphk			return (0);
40230492Sphk		case _PC_CHOWN_RESTRICTED:
40330492Sphk			*ap->a_retval = 1;
40430492Sphk			return (0);
40530492Sphk		case _PC_VDISABLE:
40630492Sphk			*ap->a_retval = _POSIX_VDISABLE;
40730492Sphk			return (0);
40830492Sphk		default:
40930492Sphk			return (EINVAL);
41030492Sphk	}
41130492Sphk	/* NOTREACHED */
41230492Sphk}
41330513Sphk
41430513Sphk/*
41530513Sphk * Standard lock, unlock and islocked functions.
41630513Sphk */
41730513Sphkint
41830513Sphkvop_stdlock(ap)
419169671Skib	struct vop_lock1_args /* {
42030513Sphk		struct vnode *a_vp;
42130513Sphk		int a_flags;
422164248Skmacy		char *file;
423164248Skmacy		int line;
42430513Sphk	} */ *ap;
425112067Skan{
42666355Sbp	struct vnode *vp = ap->a_vp;
42730513Sphk
428176320Sattilio	return (_lockmgr_args(vp->v_vnlock, ap->a_flags, VI_MTX(vp),
429176320Sattilio	    LK_WMESG_DEFAULT, LK_PRIO_DEFAULT, LK_TIMO_DEFAULT, ap->a_file,
430175635Sattilio	    ap->a_line));
43130513Sphk}
43230513Sphk
43391690Seivind/* See above. */
43430513Sphkint
43530513Sphkvop_stdunlock(ap)
43630513Sphk	struct vop_unlock_args /* {
43730513Sphk		struct vnode *a_vp;
43830513Sphk		int a_flags;
43930513Sphk	} */ *ap;
44030513Sphk{
44166355Sbp	struct vnode *vp = ap->a_vp;
44230513Sphk
443175635Sattilio	return (lockmgr(vp->v_vnlock, ap->a_flags | LK_RELEASE, VI_MTX(vp)));
44430513Sphk}
44530513Sphk
44691690Seivind/* See above. */
44730513Sphkint
44830513Sphkvop_stdislocked(ap)
44930513Sphk	struct vop_islocked_args /* {
45030513Sphk		struct vnode *a_vp;
45130513Sphk	} */ *ap;
45230513Sphk{
45330513Sphk
454176559Sattilio	return (lockstatus(ap->a_vp->v_vnlock));
45530513Sphk}
45630513Sphk
45730743Sphk/*
45830743Sphk * Return true for select/poll.
45930743Sphk */
46030743Sphkint
46130743Sphkvop_nopoll(ap)
46230743Sphk	struct vop_poll_args /* {
46330743Sphk		struct vnode *a_vp;
46430743Sphk		int  a_events;
46530743Sphk		struct ucred *a_cred;
46683366Sjulian		struct thread *a_td;
46730743Sphk	} */ *ap;
46830743Sphk{
46931727Swollman
470189450Skib	return (poll_no_poll(ap->a_events));
47130743Sphk}
47230743Sphk
47331727Swollman/*
47431727Swollman * Implement poll for local filesystems that support it.
47531727Swollman */
47630743Sphkint
47731727Swollmanvop_stdpoll(ap)
47831727Swollman	struct vop_poll_args /* {
47931727Swollman		struct vnode *a_vp;
48031727Swollman		int  a_events;
48131727Swollman		struct ucred *a_cred;
48283366Sjulian		struct thread *a_td;
48331727Swollman	} */ *ap;
48431727Swollman{
48576578Sjlemon	if (ap->a_events & ~POLLSTANDARD)
48683366Sjulian		return (vn_pollrecord(ap->a_vp, ap->a_td, ap->a_events));
48776578Sjlemon	return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
48831727Swollman}
48931727Swollman
49030743Sphk/*
49162976Smckusick * Return our mount point, as we will take charge of the writes.
49262976Smckusick */
49362976Smckusickint
49462976Smckusickvop_stdgetwritemount(ap)
49562976Smckusick	struct vop_getwritemount_args /* {
49662976Smckusick		struct vnode *a_vp;
49762976Smckusick		struct mount **a_mpp;
49862976Smckusick	} */ *ap;
49962976Smckusick{
500157323Sjeff	struct mount *mp;
50162976Smckusick
502157323Sjeff	/*
503157323Sjeff	 * XXX Since this is called unlocked we may be recycled while
504157323Sjeff	 * attempting to ref the mount.  If this is the case or mountpoint
505157323Sjeff	 * will be set to NULL.  We only have to prevent this call from
506157323Sjeff	 * returning with a ref to an incorrect mountpoint.  It is not
507157323Sjeff	 * harmful to return with a ref to our previous mountpoint.
508157323Sjeff	 */
509157323Sjeff	mp = ap->a_vp->v_mount;
510162455Stegge	if (mp != NULL) {
511162455Stegge		vfs_ref(mp);
512162455Stegge		if (mp != ap->a_vp->v_mount) {
513162455Stegge			vfs_rel(mp);
514162455Stegge			mp = NULL;
515162455Stegge		}
516157323Sjeff	}
517157323Sjeff	*(ap->a_mpp) = mp;
51862976Smckusick	return (0);
51962976Smckusick}
52062976Smckusick
52191690Seivind/* XXX Needs good comment and VOP_BMAP(9) manpage */
52276131Sphkint
52376131Sphkvop_stdbmap(ap)
524112067Skan	struct vop_bmap_args /* {
52576131Sphk		struct vnode *a_vp;
52676131Sphk		daddr_t  a_bn;
527137726Sphk		struct bufobj **a_bop;
52876131Sphk		daddr_t *a_bnp;
52976131Sphk		int *a_runp;
53076131Sphk		int *a_runb;
53176131Sphk	} */ *ap;
53276131Sphk{
53376131Sphk
534137726Sphk	if (ap->a_bop != NULL)
535137726Sphk		*ap->a_bop = &ap->a_vp->v_bufobj;
53676131Sphk	if (ap->a_bnp != NULL)
53776131Sphk		*ap->a_bnp = ap->a_bn * btodb(ap->a_vp->v_mount->mnt_stat.f_iosize);
53876131Sphk	if (ap->a_runp != NULL)
53976131Sphk		*ap->a_runp = 0;
54076131Sphk	if (ap->a_runb != NULL)
54176131Sphk		*ap->a_runb = 0;
54276131Sphk	return (0);
54376131Sphk}
54476131Sphk
545110584Sjeffint
546110584Sjeffvop_stdfsync(ap)
547110584Sjeff	struct vop_fsync_args /* {
548110584Sjeff		struct vnode *a_vp;
549110584Sjeff		struct ucred *a_cred;
550110584Sjeff		int a_waitfor;
551110584Sjeff		struct thread *a_td;
552110584Sjeff	} */ *ap;
553110584Sjeff{
554110584Sjeff	struct vnode *vp = ap->a_vp;
555110584Sjeff	struct buf *bp;
556136751Sphk	struct bufobj *bo;
557110584Sjeff	struct buf *nbp;
558145732Sjeff	int error = 0;
559144584Sjeff	int maxretry = 1000;     /* large, arbitrarily chosen */
560110584Sjeff
561177493Sjeff	bo = &vp->v_bufobj;
562177493Sjeff	BO_LOCK(bo);
563110584Sjeffloop1:
564110584Sjeff	/*
565110584Sjeff	 * MARK/SCAN initialization to avoid infinite loops.
566110584Sjeff	 */
567177493Sjeff        TAILQ_FOREACH(bp, &bo->bo_dirty.bv_hd, b_bobufs) {
568110584Sjeff                bp->b_vflags &= ~BV_SCANNED;
569110584Sjeff		bp->b_error = 0;
570110584Sjeff	}
571110584Sjeff
572110584Sjeff	/*
573144584Sjeff	 * Flush all dirty buffers associated with a vnode.
574110584Sjeff	 */
575110584Sjeffloop2:
576177493Sjeff	TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) {
577110584Sjeff		if ((bp->b_vflags & BV_SCANNED) != 0)
578110584Sjeff			continue;
579110584Sjeff		bp->b_vflags |= BV_SCANNED;
580111463Sjeff		if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL))
581110584Sjeff			continue;
582177493Sjeff		BO_UNLOCK(bo);
583177493Sjeff		KASSERT(bp->b_bufobj == bo,
584147388Sjeff		    ("bp %p wrong b_bufobj %p should be %p",
585177493Sjeff		    bp, bp->b_bufobj, bo));
586110584Sjeff		if ((bp->b_flags & B_DELWRI) == 0)
587110588Sjeff			panic("fsync: not dirty");
588140734Sphk		if ((vp->v_object != NULL) && (bp->b_flags & B_CLUSTEROK)) {
589110584Sjeff			vfs_bio_awrite(bp);
590110584Sjeff		} else {
591110584Sjeff			bremfree(bp);
592110584Sjeff			bawrite(bp);
593110584Sjeff		}
594177493Sjeff		BO_LOCK(bo);
595110584Sjeff		goto loop2;
596110584Sjeff	}
597110584Sjeff
598110584Sjeff	/*
599110584Sjeff	 * If synchronous the caller expects us to completely resolve all
600110584Sjeff	 * dirty buffers in the system.  Wait for in-progress I/O to
601110584Sjeff	 * complete (which could include background bitmap writes), then
602110584Sjeff	 * retry if dirty blocks still exist.
603110584Sjeff	 */
604110584Sjeff	if (ap->a_waitfor == MNT_WAIT) {
605136751Sphk		bufobj_wwait(bo, 0, 0);
606136751Sphk		if (bo->bo_dirty.bv_cnt > 0) {
607110584Sjeff			/*
608110584Sjeff			 * If we are unable to write any of these buffers
609110584Sjeff			 * then we fail now rather than trying endlessly
610110584Sjeff			 * to write them out.
611110584Sjeff			 */
612136751Sphk			TAILQ_FOREACH(bp, &bo->bo_dirty.bv_hd, b_bobufs)
613110584Sjeff				if ((error = bp->b_error) == 0)
614110584Sjeff					continue;
615145732Sjeff			if (error == 0 && --maxretry >= 0)
616110584Sjeff				goto loop1;
617110584Sjeff			error = EAGAIN;
618110584Sjeff		}
619110584Sjeff	}
620177493Sjeff	BO_UNLOCK(bo);
621144584Sjeff	if (error == EAGAIN)
622144584Sjeff		vprint("fsync: giving up on dirty", vp);
623112067Skan
624110584Sjeff	return (error);
625110584Sjeff}
626112067Skan
62791690Seivind/* XXX Needs good comment and more info in the manpage (VOP_GETPAGES(9)). */
62876167Sphkint
62976167Sphkvop_stdgetpages(ap)
63076167Sphk	struct vop_getpages_args /* {
63176167Sphk		struct vnode *a_vp;
63276167Sphk		vm_page_t *a_m;
63376167Sphk		int a_count;
63476167Sphk		int a_reqpage;
63576167Sphk		vm_ooffset_t a_offset;
63676167Sphk	} */ *ap;
63776167Sphk{
63876131Sphk
63976167Sphk	return vnode_pager_generic_getpages(ap->a_vp, ap->a_m,
64076167Sphk	    ap->a_count, ap->a_reqpage);
64176167Sphk}
64276167Sphk
643147198Sssouhlalint
644147198Sssouhlalvop_stdkqfilter(struct vop_kqfilter_args *ap)
645147198Sssouhlal{
646147198Sssouhlal	return vfs_kqfilter(ap);
647147198Sssouhlal}
648147198Sssouhlal
64991690Seivind/* XXX Needs good comment and more info in the manpage (VOP_PUTPAGES(9)). */
65076319Sphkint
65176167Sphkvop_stdputpages(ap)
65276167Sphk	struct vop_putpages_args /* {
65376167Sphk		struct vnode *a_vp;
65476167Sphk		vm_page_t *a_m;
65576167Sphk		int a_count;
65676167Sphk		int a_sync;
65776167Sphk		int *a_rtvals;
65876167Sphk		vm_ooffset_t a_offset;
65976167Sphk	} */ *ap;
66076167Sphk{
66176167Sphk
66276319Sphk	return vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count,
66376167Sphk	     ap->a_sync, ap->a_rtvals);
66476167Sphk}
66576167Sphk
666166774Spjdint
667166774Spjdvop_stdvptofh(struct vop_vptofh_args *ap)
668166774Spjd{
669166795Spjd	return (EOPNOTSUPP);
670166774Spjd}
671166774Spjd
672189539Smarcusint
673189539Smarcusvop_stdvptocnp(struct vop_vptocnp_args *ap)
674189539Smarcus{
675189539Smarcus	struct vnode *vp = ap->a_vp;
676189539Smarcus	struct vnode **dvp = ap->a_vpp;
677189539Smarcus	char *buf = ap->a_buf;
678189539Smarcus	int *buflen = ap->a_buflen;
679189539Smarcus	char *dirbuf, *cpos;
680189539Smarcus	int i, error, eofflag, dirbuflen, flags, locked, len, covered;
681189539Smarcus	off_t off;
682189539Smarcus	ino_t fileno;
683189539Smarcus	struct vattr va;
684189539Smarcus	struct nameidata nd;
685189539Smarcus	struct thread *td;
686189539Smarcus	struct dirent *dp;
687189539Smarcus	struct vnode *mvp;
688189539Smarcus
689189539Smarcus	i = *buflen;
690189539Smarcus	error = 0;
691189539Smarcus	covered = 0;
692189539Smarcus	td = curthread;
693189539Smarcus
694189539Smarcus	if (vp->v_type != VDIR)
695189539Smarcus		return (ENOENT);
696189539Smarcus
697189539Smarcus	error = VOP_GETATTR(vp, &va, td->td_ucred);
698189539Smarcus	if (error)
699189539Smarcus		return (error);
700189539Smarcus
701189539Smarcus	VREF(vp);
702189539Smarcus	locked = VOP_ISLOCKED(vp);
703189539Smarcus	VOP_UNLOCK(vp, 0);
704189539Smarcus	NDINIT_ATVP(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
705189539Smarcus	    "..", vp, td);
706189539Smarcus	flags = FREAD;
707189539Smarcus	error = vn_open(&nd, &flags, 0, NULL);
708189539Smarcus	if (error) {
709189539Smarcus		vn_lock(vp, locked | LK_RETRY);
710189539Smarcus		return (error);
711189539Smarcus	}
712189539Smarcus	NDFREE(&nd, NDF_ONLY_PNBUF);
713189539Smarcus
714189539Smarcus	mvp = *dvp = nd.ni_vp;
715189539Smarcus
716189539Smarcus	if (vp->v_mount != (*dvp)->v_mount &&
717189539Smarcus	    ((*dvp)->v_vflag & VV_ROOT) &&
718189539Smarcus	    ((*dvp)->v_mount->mnt_flag & MNT_UNION)) {
719189539Smarcus		*dvp = (*dvp)->v_mount->mnt_vnodecovered;
720189539Smarcus		VREF(mvp);
721189539Smarcus		VOP_UNLOCK(mvp, 0);
722189539Smarcus		vn_close(mvp, FREAD, td->td_ucred, td);
723189539Smarcus		VREF(*dvp);
724189539Smarcus		vn_lock(*dvp, LK_EXCLUSIVE | LK_RETRY);
725189539Smarcus		covered = 1;
726189539Smarcus	}
727189539Smarcus
728189539Smarcus	fileno = va.va_fileid;
729189539Smarcus
730189539Smarcus	dirbuflen = DEV_BSIZE;
731189539Smarcus	if (dirbuflen < va.va_blocksize)
732189539Smarcus		dirbuflen = va.va_blocksize;
733189539Smarcus	dirbuf = (char *)malloc(dirbuflen, M_TEMP, M_WAITOK);
734189539Smarcus
735189539Smarcus	if ((*dvp)->v_type != VDIR) {
736189539Smarcus		error = ENOENT;
737189539Smarcus		goto out;
738189539Smarcus	}
739189539Smarcus
740189539Smarcus	off = 0;
741189539Smarcus	len = 0;
742189539Smarcus	do {
743189539Smarcus		/* call VOP_READDIR of parent */
744189539Smarcus		error = get_next_dirent(*dvp, &dp, dirbuf, dirbuflen, &off,
745189539Smarcus					&cpos, &len, &eofflag, td);
746189539Smarcus		if (error)
747189539Smarcus			goto out;
748189539Smarcus
749189539Smarcus		if ((dp->d_type != DT_WHT) &&
750189539Smarcus		    (dp->d_fileno == fileno)) {
751189539Smarcus			if (covered) {
752189539Smarcus				VOP_UNLOCK(*dvp, 0);
753189539Smarcus				vn_lock(mvp, LK_EXCLUSIVE | LK_RETRY);
754189539Smarcus				if (dirent_exists(mvp, dp->d_name, td)) {
755189539Smarcus					error = ENOENT;
756189539Smarcus					VOP_UNLOCK(mvp, 0);
757189539Smarcus					vn_lock(*dvp, LK_EXCLUSIVE | LK_RETRY);
758189539Smarcus					goto out;
759189539Smarcus				}
760189539Smarcus				VOP_UNLOCK(mvp, 0);
761189539Smarcus				vn_lock(*dvp, LK_EXCLUSIVE | LK_RETRY);
762189539Smarcus			}
763189539Smarcus			i -= dp->d_namlen;
764189539Smarcus
765189539Smarcus			if (i < 0) {
766189539Smarcus				error = ENOMEM;
767189539Smarcus				goto out;
768189539Smarcus			}
769189539Smarcus			bcopy(dp->d_name, buf + i, dp->d_namlen);
770189539Smarcus			error = 0;
771189539Smarcus			goto out;
772189539Smarcus		}
773189539Smarcus	} while (len > 0 || !eofflag);
774189539Smarcus	error = ENOENT;
775189539Smarcus
776189539Smarcusout:
777189539Smarcus	free(dirbuf, M_TEMP);
778189539Smarcus	if (!error) {
779189539Smarcus		*buflen = i;
780189539Smarcus		vhold(*dvp);
781189539Smarcus	}
782189539Smarcus	if (covered) {
783189539Smarcus		vput(*dvp);
784189539Smarcus		vrele(mvp);
785189539Smarcus	} else {
786189539Smarcus		VOP_UNLOCK(mvp, 0);
787189539Smarcus		vn_close(mvp, FREAD, td->td_ucred, td);
788189539Smarcus	}
789189539Smarcus	vn_lock(vp, locked | LK_RETRY);
790189539Smarcus	return (error);
791189539Smarcus}
792189539Smarcus
793112067Skan/*
79451068Salfred * vfs default ops
79591690Seivind * used to fill the vfs function table to get reasonable default return values.
79651068Salfred */
79791690Seivindint
798191990Sattiliovfs_stdroot (mp, flags, vpp)
79951068Salfred	struct mount *mp;
800144054Sjeff	int flags;
80151068Salfred	struct vnode **vpp;
80251068Salfred{
803131734Salfred
80451068Salfred	return (EOPNOTSUPP);
80551068Salfred}
80651068Salfred
80791690Seivindint
808191990Sattiliovfs_stdstatfs (mp, sbp)
80951068Salfred	struct mount *mp;
81051068Salfred	struct statfs *sbp;
81151068Salfred{
812131734Salfred
81351068Salfred	return (EOPNOTSUPP);
81451068Salfred}
81551068Salfred
81651068Salfredint
817191990Sattiliovfs_stdquotactl (mp, cmds, uid, arg)
81851068Salfred	struct mount *mp;
81951068Salfred	int cmds;
82051068Salfred	uid_t uid;
821153400Sdes	void *arg;
82251068Salfred{
823131734Salfred
82451068Salfred	return (EOPNOTSUPP);
82551068Salfred}
82651068Salfred
827112067Skanint
828191990Sattiliovfs_stdsync(mp, waitfor)
82951068Salfred	struct mount *mp;
83051068Salfred	int waitfor;
83151068Salfred{
832154152Stegge	struct vnode *vp, *mvp;
833191990Sattilio	struct thread *td;
834112119Skan	int error, lockreq, allerror = 0;
835112119Skan
836191990Sattilio	td = curthread;
837112119Skan	lockreq = LK_EXCLUSIVE | LK_INTERLOCK;
838112119Skan	if (waitfor != MNT_WAIT)
839112119Skan		lockreq |= LK_NOWAIT;
840112119Skan	/*
841112119Skan	 * Force stale buffer cache information to be flushed.
842112119Skan	 */
843122091Skan	MNT_ILOCK(mp);
844112119Skanloop:
845154152Stegge	MNT_VNODE_FOREACH(vp, mp, mvp) {
846177493Sjeff		/* bv_cnt is an acceptable race here. */
847177493Sjeff		if (vp->v_bufobj.bo_dirty.bv_cnt == 0)
848177493Sjeff			continue;
849112119Skan		VI_LOCK(vp);
850122091Skan		MNT_IUNLOCK(mp);
851112119Skan		if ((error = vget(vp, lockreq, td)) != 0) {
852122091Skan			MNT_ILOCK(mp);
853154152Stegge			if (error == ENOENT) {
854154152Stegge				MNT_VNODE_FOREACH_ABORT_ILOCKED(mp, mvp);
855112119Skan				goto loop;
856154152Stegge			}
857112119Skan			continue;
858112119Skan		}
859140048Sphk		error = VOP_FSYNC(vp, waitfor, td);
860112119Skan		if (error)
861112119Skan			allerror = error;
862112119Skan
863155032Sjeff		/* Do not turn this into vput.  td is not always curthread. */
864175294Sattilio		VOP_UNLOCK(vp, 0);
865121874Skan		vrele(vp);
866122091Skan		MNT_ILOCK(mp);
867112119Skan	}
868122091Skan	MNT_IUNLOCK(mp);
869112119Skan	return (allerror);
870112119Skan}
871112119Skan
872112119Skanint
873191990Sattiliovfs_stdnosync (mp, waitfor)
874112119Skan	struct mount *mp;
875112119Skan	int waitfor;
876112119Skan{
877131734Salfred
87851068Salfred	return (0);
87951068Salfred}
88051068Salfred
881112067Skanint
88292462Smckusickvfs_stdvget (mp, ino, flags, vpp)
88351068Salfred	struct mount *mp;
88451068Salfred	ino_t ino;
88592462Smckusick	int flags;
88651068Salfred	struct vnode **vpp;
88751068Salfred{
888131734Salfred
88951068Salfred	return (EOPNOTSUPP);
89051068Salfred}
89151068Salfred
892112067Skanint
89351138Salfredvfs_stdfhtovp (mp, fhp, vpp)
89451068Salfred	struct mount *mp;
89551068Salfred	struct fid *fhp;
89651138Salfred	struct vnode **vpp;
89751138Salfred{
898131734Salfred
89951138Salfred	return (EOPNOTSUPP);
90051138Salfred}
90151138Salfred
90251068Salfredint
903112067Skanvfs_stdinit (vfsp)
90451068Salfred	struct vfsconf *vfsp;
90551068Salfred{
906131734Salfred
90751068Salfred	return (0);
90851068Salfred}
90951068Salfred
91051068Salfredint
91151068Salfredvfs_stduninit (vfsp)
91251068Salfred	struct vfsconf *vfsp;
91351068Salfred{
914131734Salfred
91551068Salfred	return(0);
91651068Salfred}
91751068Salfred
91854803Srwatsonint
919191990Sattiliovfs_stdextattrctl(mp, cmd, filename_vp, attrnamespace, attrname)
92054803Srwatson	struct mount *mp;
92154803Srwatson	int cmd;
92274273Srwatson	struct vnode *filename_vp;
92374437Srwatson	int attrnamespace;
92456272Srwatson	const char *attrname;
92554803Srwatson{
926131734Salfred
927101786Sphk	if (filename_vp != NULL)
928175294Sattilio		VOP_UNLOCK(filename_vp, 0);
929131734Salfred	return (EOPNOTSUPP);
93054803Srwatson}
93154803Srwatson
932131733Salfredint
933131733Salfredvfs_stdsysctl(mp, op, req)
934131733Salfred	struct mount *mp;
935131733Salfred	fsctlop_t op;
936131733Salfred	struct sysctl_req *req;
937131733Salfred{
938131733Salfred
939131733Salfred	return (EOPNOTSUPP);
940131733Salfred}
941131733Salfred
94251068Salfred/* end of vfs default ops */
943