vfs_default.c revision 276192
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 276192 2014-12-24 22:58:08Z rmacklem $");
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>
50189539Smarcus#include <sys/namei.h>
51248084Sattilio#include <sys/rwlock.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
81241025Skibstatic int vop_stdis_text(struct vop_is_text_args *ap);
82241025Skibstatic int vop_stdset_text(struct vop_set_text_args *ap);
83241025Skibstatic int vop_stdunset_text(struct vop_unset_text_args *ap);
84242476Skibstatic int vop_stdget_writecount(struct vop_get_writecount_args *ap);
85242476Skibstatic int vop_stdadd_writecount(struct vop_add_writecount_args *ap);
86274914Sglebiusstatic int vop_stdgetpages_async(struct vop_getpages_async_args *ap);
87241025Skib
8830489Sphk/*
8930489Sphk * This vnode table stores what we want to do if the filesystem doesn't
9030489Sphk * implement a particular VOP.
9130489Sphk *
9230489Sphk * If there is no specific entry here, we will return EOPNOTSUPP.
9330489Sphk *
94197680Strasz * Note that every filesystem has to implement either vop_access
95197680Strasz * or vop_accessx; failing to do so will result in immediate crash
96197680Strasz * due to stack overflow, as vop_stdaccess() calls vop_stdaccessx(),
97197680Strasz * which calls vop_stdaccess() etc.
9830489Sphk */
9930489Sphk
100138290Sphkstruct vop_vector default_vnodeops = {
101138290Sphk	.vop_default =		NULL,
102138339Sphk	.vop_bypass =		VOP_EOPNOTSUPP,
103138339Sphk
104197680Strasz	.vop_access =		vop_stdaccess,
105193092Strasz	.vop_accessx =		vop_stdaccessx,
106227070Sjhb	.vop_advise =		vop_stdadvise,
107178243Skib	.vop_advlock =		vop_stdadvlock,
108178243Skib	.vop_advlockasync =	vop_stdadvlockasync,
109208003Szml	.vop_advlockpurge =	vop_stdadvlockpurge,
110220791Smdf	.vop_allocate =		vop_stdallocate,
111138290Sphk	.vop_bmap =		vop_stdbmap,
112138290Sphk	.vop_close =		VOP_NULL,
113138290Sphk	.vop_fsync =		VOP_NULL,
114138290Sphk	.vop_getpages =		vop_stdgetpages,
115274914Sglebius	.vop_getpages_async =	vop_stdgetpages_async,
116138290Sphk	.vop_getwritemount = 	vop_stdgetwritemount,
117143494Sjeff	.vop_inactive =		VOP_NULL,
118138290Sphk	.vop_ioctl =		VOP_ENOTTY,
119147198Sssouhlal	.vop_kqfilter =		vop_stdkqfilter,
120138290Sphk	.vop_islocked =		vop_stdislocked,
121169671Skib	.vop_lock1 =		vop_stdlock,
122138290Sphk	.vop_lookup =		vop_nolookup,
123138290Sphk	.vop_open =		VOP_NULL,
124138290Sphk	.vop_pathconf =		VOP_EINVAL,
125138290Sphk	.vop_poll =		vop_nopoll,
126138290Sphk	.vop_putpages =		vop_stdputpages,
127138290Sphk	.vop_readlink =		VOP_EINVAL,
128206094Skib	.vop_rename =		vop_norename,
129138290Sphk	.vop_revoke =		VOP_PANIC,
130138290Sphk	.vop_strategy =		vop_nostrategy,
131138290Sphk	.vop_unlock =		vop_stdunlock,
132189539Smarcus	.vop_vptocnp =		vop_stdvptocnp,
133166774Spjd	.vop_vptofh =		vop_stdvptofh,
134232317Strociny	.vop_unp_bind =		vop_stdunp_bind,
135232317Strociny	.vop_unp_connect =	vop_stdunp_connect,
136232317Strociny	.vop_unp_detach =	vop_stdunp_detach,
137241025Skib	.vop_is_text =		vop_stdis_text,
138241025Skib	.vop_set_text =		vop_stdset_text,
139241025Skib	.vop_unset_text =	vop_stdunset_text,
140242476Skib	.vop_get_writecount =	vop_stdget_writecount,
141242476Skib	.vop_add_writecount =	vop_stdadd_writecount,
14230489Sphk};
14330489Sphk
14491690Seivind/*
14591690Seivind * Series of placeholder functions for various error returns for
14691690Seivind * VOPs.
14791690Seivind */
14891690Seivind
14930489Sphkint
15030492Sphkvop_eopnotsupp(struct vop_generic_args *ap)
15130489Sphk{
15230489Sphk	/*
15330492Sphk	printf("vop_notsupp[%s]\n", ap->a_desc->vdesc_name);
15430489Sphk	*/
15530489Sphk
15630489Sphk	return (EOPNOTSUPP);
15730489Sphk}
15830489Sphk
15930489Sphkint
16030492Sphkvop_ebadf(struct vop_generic_args *ap)
16130489Sphk{
16230489Sphk
16330492Sphk	return (EBADF);
16430492Sphk}
16530492Sphk
16630492Sphkint
16730492Sphkvop_enotty(struct vop_generic_args *ap)
16830492Sphk{
16930492Sphk
17030492Sphk	return (ENOTTY);
17130492Sphk}
17230492Sphk
17330492Sphkint
17430492Sphkvop_einval(struct vop_generic_args *ap)
17530492Sphk{
17630492Sphk
17730492Sphk	return (EINVAL);
17830492Sphk}
17930492Sphk
18030492Sphkint
181185956Smarcusvop_enoent(struct vop_generic_args *ap)
182185956Smarcus{
183185956Smarcus
184185956Smarcus	return (ENOENT);
185185956Smarcus}
186185956Smarcus
187185956Smarcusint
18830492Sphkvop_null(struct vop_generic_args *ap)
18930492Sphk{
19030492Sphk
19130492Sphk	return (0);
19230492Sphk}
19330492Sphk
19491690Seivind/*
19591690Seivind * Helper function to panic on some bad VOPs in some filesystems.
19691690Seivind */
19741056Speterint
19841056Spetervop_panic(struct vop_generic_args *ap)
19941056Speter{
20041056Speter
20172594Sbde	panic("filesystem goof: vop_panic[%s]", ap->a_desc->vdesc_name);
20241056Speter}
20341056Speter
20491690Seivind/*
20591690Seivind * vop_std<something> and vop_no<something> are default functions for use by
20691690Seivind * filesystems that need the "default reasonable" implementation for a
20791690Seivind * particular operation.
20891690Seivind *
20991690Seivind * The documentation for the operations they implement exists (if it exists)
21091690Seivind * in the VOP_<SOMETHING>(9) manpage (all uppercase).
21191690Seivind */
21291690Seivind
21391690Seivind/*
21491690Seivind * Default vop for filesystems that do not support name lookup
21591690Seivind */
21672594Sbdestatic int
21772594Sbdevop_nolookup(ap)
21872594Sbde	struct vop_lookup_args /* {
21972594Sbde		struct vnode *a_dvp;
22072594Sbde		struct vnode **a_vpp;
22172594Sbde		struct componentname *a_cnp;
22272594Sbde	} */ *ap;
22372594Sbde{
22472594Sbde
22572594Sbde	*ap->a_vpp = NULL;
22672594Sbde	return (ENOTDIR);
22772594Sbde}
22872594Sbde
22946349Salc/*
230206094Skib * vop_norename:
231206094Skib *
232206094Skib * Handle unlock and reference counting for arguments of vop_rename
233206094Skib * for filesystems that do not implement rename operation.
234206094Skib */
235206094Skibstatic int
236206094Skibvop_norename(struct vop_rename_args *ap)
237206094Skib{
238206094Skib
239206094Skib	vop_rename_fail(ap);
240206094Skib	return (EOPNOTSUPP);
241206094Skib}
242206094Skib
243206094Skib/*
24446349Salc *	vop_nostrategy:
24546349Salc *
24646349Salc *	Strategy routine for VFS devices that have none.
24746349Salc *
24858934Sphk *	BIO_ERROR and B_INVAL must be cleared prior to calling any strategy
24958345Sphk *	routine.  Typically this is done for a BIO_READ strategy call.
250112067Skan *	Typically B_INVAL is assumed to already be clear prior to a write
25158345Sphk *	and should not be cleared manually unless you just made the buffer
25258934Sphk *	invalid.  BIO_ERROR should be cleared either way.
25346349Salc */
25446349Salc
25530489Sphkstatic int
25630489Sphkvop_nostrategy (struct vop_strategy_args *ap)
25730489Sphk{
25830489Sphk	printf("No strategy for buffer at %p\n", ap->a_bp);
259111842Snjl	vprint("vnode", ap->a_vp);
26058934Sphk	ap->a_bp->b_ioflags |= BIO_ERROR;
26130489Sphk	ap->a_bp->b_error = EOPNOTSUPP;
26259249Sphk	bufdone(ap->a_bp);
26330489Sphk	return (EOPNOTSUPP);
26430489Sphk}
26530492Sphk
266189539Smarcusstatic int
267189539Smarcusget_next_dirent(struct vnode *vp, struct dirent **dpp, char *dirbuf,
268189539Smarcus		int dirbuflen, off_t *off, char **cpos, int *len,
269189539Smarcus		int *eofflag, struct thread *td)
270189539Smarcus{
271189539Smarcus	int error, reclen;
272189539Smarcus	struct uio uio;
273189539Smarcus	struct iovec iov;
274189539Smarcus	struct dirent *dp;
275189539Smarcus
276189539Smarcus	KASSERT(VOP_ISLOCKED(vp), ("vp %p is not locked", vp));
277189539Smarcus	KASSERT(vp->v_type == VDIR, ("vp %p is not a directory", vp));
278189539Smarcus
279189539Smarcus	if (*len == 0) {
280189539Smarcus		iov.iov_base = dirbuf;
281189539Smarcus		iov.iov_len = dirbuflen;
282189539Smarcus
283189539Smarcus		uio.uio_iov = &iov;
284189539Smarcus		uio.uio_iovcnt = 1;
285189539Smarcus		uio.uio_offset = *off;
286189539Smarcus		uio.uio_resid = dirbuflen;
287189539Smarcus		uio.uio_segflg = UIO_SYSSPACE;
288189539Smarcus		uio.uio_rw = UIO_READ;
289189539Smarcus		uio.uio_td = td;
290189539Smarcus
291189539Smarcus		*eofflag = 0;
292189539Smarcus
293189539Smarcus#ifdef MAC
294189539Smarcus		error = mac_vnode_check_readdir(td->td_ucred, vp);
295189539Smarcus		if (error == 0)
296189539Smarcus#endif
297189539Smarcus			error = VOP_READDIR(vp, &uio, td->td_ucred, eofflag,
298189539Smarcus		    		NULL, NULL);
299189539Smarcus		if (error)
300189539Smarcus			return (error);
301189539Smarcus
302211818Sbrian		*off = uio.uio_offset;
303211818Sbrian
304211684Sbrian		*cpos = dirbuf;
305211818Sbrian		*len = (dirbuflen - uio.uio_resid);
306211818Sbrian
307211818Sbrian		if (*len == 0)
308211818Sbrian			return (ENOENT);
309189539Smarcus	}
310189539Smarcus
311189539Smarcus	dp = (struct dirent *)(*cpos);
312189539Smarcus	reclen = dp->d_reclen;
313189539Smarcus	*dpp = dp;
314189539Smarcus
315189539Smarcus	/* check for malformed directory.. */
316189539Smarcus	if (reclen < DIRENT_MINSIZE)
317189539Smarcus		return (EINVAL);
318189539Smarcus
319189539Smarcus	*cpos += reclen;
320189539Smarcus	*len -= reclen;
321189539Smarcus
322189539Smarcus	return (0);
323189539Smarcus}
324189539Smarcus
32591690Seivind/*
326189539Smarcus * Check if a named file exists in a given directory vnode.
327189539Smarcus */
328189539Smarcusstatic int
329189539Smarcusdirent_exists(struct vnode *vp, const char *dirname, struct thread *td)
330189539Smarcus{
331189539Smarcus	char *dirbuf, *cpos;
332189539Smarcus	int error, eofflag, dirbuflen, len, found;
333189539Smarcus	off_t off;
334189539Smarcus	struct dirent *dp;
335189539Smarcus	struct vattr va;
336189539Smarcus
337189539Smarcus	KASSERT(VOP_ISLOCKED(vp), ("vp %p is not locked", vp));
338189539Smarcus	KASSERT(vp->v_type == VDIR, ("vp %p is not a directory", vp));
339189539Smarcus
340189539Smarcus	found = 0;
341189539Smarcus
342189539Smarcus	error = VOP_GETATTR(vp, &va, td->td_ucred);
343189539Smarcus	if (error)
344189539Smarcus		return (found);
345189539Smarcus
346189539Smarcus	dirbuflen = DEV_BSIZE;
347189539Smarcus	if (dirbuflen < va.va_blocksize)
348189539Smarcus		dirbuflen = va.va_blocksize;
349189539Smarcus	dirbuf = (char *)malloc(dirbuflen, M_TEMP, M_WAITOK);
350189539Smarcus
351189539Smarcus	off = 0;
352189539Smarcus	len = 0;
353189539Smarcus	do {
354189539Smarcus		error = get_next_dirent(vp, &dp, dirbuf, dirbuflen, &off,
355189539Smarcus					&cpos, &len, &eofflag, td);
356189539Smarcus		if (error)
357189539Smarcus			goto out;
358189539Smarcus
359235503Sgleb		if (dp->d_type != DT_WHT && dp->d_fileno != 0 &&
360235503Sgleb		    strcmp(dp->d_name, dirname) == 0) {
361189539Smarcus			found = 1;
362189539Smarcus			goto out;
363189539Smarcus		}
364189539Smarcus	} while (len > 0 || !eofflag);
365189539Smarcus
366189539Smarcusout:
367189539Smarcus	free(dirbuf, M_TEMP);
368189539Smarcus	return (found);
369189539Smarcus}
370189539Smarcus
371193092Straszint
372197680Straszvop_stdaccess(struct vop_access_args *ap)
373197680Strasz{
374197680Strasz
375197680Strasz	KASSERT((ap->a_accmode & ~(VEXEC | VWRITE | VREAD | VADMIN |
376197680Strasz	    VAPPEND)) == 0, ("invalid bit in accmode"));
377197680Strasz
378197680Strasz	return (VOP_ACCESSX(ap->a_vp, ap->a_accmode, ap->a_cred, ap->a_td));
379197680Strasz}
380197680Strasz
381197680Straszint
382193092Straszvop_stdaccessx(struct vop_accessx_args *ap)
383193092Strasz{
384193092Strasz	int error;
385193092Strasz	accmode_t accmode = ap->a_accmode;
386193092Strasz
387193092Strasz	error = vfs_unixify_accmode(&accmode);
388193092Strasz	if (error != 0)
389193092Strasz		return (error);
390193092Strasz
391193092Strasz	if (accmode == 0)
392193092Strasz		return (0);
393193092Strasz
394193092Strasz	return (VOP_ACCESS(ap->a_vp, accmode, ap->a_cred, ap->a_td));
395193092Strasz}
396193092Strasz
397189539Smarcus/*
398178243Skib * Advisory record locking support
399178243Skib */
400178243Skibint
401178243Skibvop_stdadvlock(struct vop_advlock_args *ap)
402178243Skib{
403182371Sattilio	struct vnode *vp;
404178243Skib	struct vattr vattr;
405178243Skib	int error;
406178243Skib
407182371Sattilio	vp = ap->a_vp;
408276192Srmacklem	if (ap->a_fl->l_whence == SEEK_END) {
409276192Srmacklem		/*
410276192Srmacklem		 * The NFSv4 server will LOR/deadlock if a vn_lock() call
411276192Srmacklem		 * is done on vp. Fortunately, vattr.va_size is only
412276192Srmacklem		 * needed for SEEK_END and the NFSv4 server only uses SEEK_SET.
413276192Srmacklem		 */
414276192Srmacklem		vn_lock(vp, LK_SHARED | LK_RETRY);
415276192Srmacklem		error = VOP_GETATTR(vp, &vattr, curthread->td_ucred);
416276192Srmacklem		VOP_UNLOCK(vp, 0);
417276192Srmacklem		if (error)
418276192Srmacklem			return (error);
419276192Srmacklem	} else
420276192Srmacklem		vattr.va_size = 0;
421178243Skib
422178243Skib	return (lf_advlock(ap, &(vp->v_lockf), vattr.va_size));
423178243Skib}
424178243Skib
425178243Skibint
426178243Skibvop_stdadvlockasync(struct vop_advlockasync_args *ap)
427178243Skib{
428182371Sattilio	struct vnode *vp;
429178243Skib	struct vattr vattr;
430178243Skib	int error;
431178243Skib
432182371Sattilio	vp = ap->a_vp;
433276192Srmacklem	if (ap->a_fl->l_whence == SEEK_END) {
434276192Srmacklem		/* The size argument is only needed for SEEK_END. */
435276192Srmacklem		vn_lock(vp, LK_SHARED | LK_RETRY);
436276192Srmacklem		error = VOP_GETATTR(vp, &vattr, curthread->td_ucred);
437276192Srmacklem		VOP_UNLOCK(vp, 0);
438276192Srmacklem		if (error)
439276192Srmacklem			return (error);
440276192Srmacklem	} else
441276192Srmacklem		vattr.va_size = 0;
442178243Skib
443178243Skib	return (lf_advlockasync(ap, &(vp->v_lockf), vattr.va_size));
444178243Skib}
445178243Skib
446208003Szmlint
447208003Szmlvop_stdadvlockpurge(struct vop_advlockpurge_args *ap)
448208003Szml{
449208003Szml	struct vnode *vp;
450208003Szml
451208003Szml	vp = ap->a_vp;
452208003Szml	lf_purgelocks(vp, &vp->v_lockf);
453208003Szml	return (0);
454208003Szml}
455208003Szml
456178243Skib/*
45791690Seivind * vop_stdpathconf:
458112067Skan *
45991690Seivind * Standard implementation of POSIX pathconf, to get information about limits
46091690Seivind * for a filesystem.
46191690Seivind * Override per filesystem for the case where the filesystem has smaller
46291690Seivind * limits.
46391690Seivind */
46430492Sphkint
46530492Sphkvop_stdpathconf(ap)
46630492Sphk	struct vop_pathconf_args /* {
46730492Sphk	struct vnode *a_vp;
46830492Sphk	int a_name;
46930492Sphk	int *a_retval;
47030492Sphk	} */ *ap;
47130492Sphk{
47230492Sphk
47330492Sphk	switch (ap->a_name) {
474149175Sphk		case _PC_NAME_MAX:
475149175Sphk			*ap->a_retval = NAME_MAX;
476149175Sphk			return (0);
477149175Sphk		case _PC_PATH_MAX:
478149175Sphk			*ap->a_retval = PATH_MAX;
479149175Sphk			return (0);
48030492Sphk		case _PC_LINK_MAX:
48130492Sphk			*ap->a_retval = LINK_MAX;
48230492Sphk			return (0);
48330492Sphk		case _PC_MAX_CANON:
48430492Sphk			*ap->a_retval = MAX_CANON;
48530492Sphk			return (0);
48630492Sphk		case _PC_MAX_INPUT:
48730492Sphk			*ap->a_retval = MAX_INPUT;
48830492Sphk			return (0);
48930492Sphk		case _PC_PIPE_BUF:
49030492Sphk			*ap->a_retval = PIPE_BUF;
49130492Sphk			return (0);
49230492Sphk		case _PC_CHOWN_RESTRICTED:
49330492Sphk			*ap->a_retval = 1;
49430492Sphk			return (0);
49530492Sphk		case _PC_VDISABLE:
49630492Sphk			*ap->a_retval = _POSIX_VDISABLE;
49730492Sphk			return (0);
49830492Sphk		default:
49930492Sphk			return (EINVAL);
50030492Sphk	}
50130492Sphk	/* NOTREACHED */
50230492Sphk}
50330513Sphk
50430513Sphk/*
50530513Sphk * Standard lock, unlock and islocked functions.
50630513Sphk */
50730513Sphkint
50830513Sphkvop_stdlock(ap)
509169671Skib	struct vop_lock1_args /* {
51030513Sphk		struct vnode *a_vp;
51130513Sphk		int a_flags;
512164248Skmacy		char *file;
513164248Skmacy		int line;
51430513Sphk	} */ *ap;
515112067Skan{
51666355Sbp	struct vnode *vp = ap->a_vp;
51730513Sphk
518176320Sattilio	return (_lockmgr_args(vp->v_vnlock, ap->a_flags, VI_MTX(vp),
519176320Sattilio	    LK_WMESG_DEFAULT, LK_PRIO_DEFAULT, LK_TIMO_DEFAULT, ap->a_file,
520175635Sattilio	    ap->a_line));
52130513Sphk}
52230513Sphk
52391690Seivind/* See above. */
52430513Sphkint
52530513Sphkvop_stdunlock(ap)
52630513Sphk	struct vop_unlock_args /* {
52730513Sphk		struct vnode *a_vp;
52830513Sphk		int a_flags;
52930513Sphk	} */ *ap;
53030513Sphk{
53166355Sbp	struct vnode *vp = ap->a_vp;
53230513Sphk
533175635Sattilio	return (lockmgr(vp->v_vnlock, ap->a_flags | LK_RELEASE, VI_MTX(vp)));
53430513Sphk}
53530513Sphk
53691690Seivind/* See above. */
53730513Sphkint
53830513Sphkvop_stdislocked(ap)
53930513Sphk	struct vop_islocked_args /* {
54030513Sphk		struct vnode *a_vp;
54130513Sphk	} */ *ap;
54230513Sphk{
54330513Sphk
544176559Sattilio	return (lockstatus(ap->a_vp->v_vnlock));
54530513Sphk}
54630513Sphk
54730743Sphk/*
54830743Sphk * Return true for select/poll.
54930743Sphk */
55030743Sphkint
55130743Sphkvop_nopoll(ap)
55230743Sphk	struct vop_poll_args /* {
55330743Sphk		struct vnode *a_vp;
55430743Sphk		int  a_events;
55530743Sphk		struct ucred *a_cred;
55683366Sjulian		struct thread *a_td;
55730743Sphk	} */ *ap;
55830743Sphk{
55931727Swollman
560189450Skib	return (poll_no_poll(ap->a_events));
56130743Sphk}
56230743Sphk
56331727Swollman/*
56431727Swollman * Implement poll for local filesystems that support it.
56531727Swollman */
56630743Sphkint
56731727Swollmanvop_stdpoll(ap)
56831727Swollman	struct vop_poll_args /* {
56931727Swollman		struct vnode *a_vp;
57031727Swollman		int  a_events;
57131727Swollman		struct ucred *a_cred;
57283366Sjulian		struct thread *a_td;
57331727Swollman	} */ *ap;
57431727Swollman{
57576578Sjlemon	if (ap->a_events & ~POLLSTANDARD)
57683366Sjulian		return (vn_pollrecord(ap->a_vp, ap->a_td, ap->a_events));
57776578Sjlemon	return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
57831727Swollman}
57931727Swollman
58030743Sphk/*
58162976Smckusick * Return our mount point, as we will take charge of the writes.
58262976Smckusick */
58362976Smckusickint
58462976Smckusickvop_stdgetwritemount(ap)
58562976Smckusick	struct vop_getwritemount_args /* {
58662976Smckusick		struct vnode *a_vp;
58762976Smckusick		struct mount **a_mpp;
58862976Smckusick	} */ *ap;
58962976Smckusick{
590157323Sjeff	struct mount *mp;
59162976Smckusick
592157323Sjeff	/*
593157323Sjeff	 * XXX Since this is called unlocked we may be recycled while
594157323Sjeff	 * attempting to ref the mount.  If this is the case or mountpoint
595157323Sjeff	 * will be set to NULL.  We only have to prevent this call from
596157323Sjeff	 * returning with a ref to an incorrect mountpoint.  It is not
597157323Sjeff	 * harmful to return with a ref to our previous mountpoint.
598157323Sjeff	 */
599157323Sjeff	mp = ap->a_vp->v_mount;
600162455Stegge	if (mp != NULL) {
601162455Stegge		vfs_ref(mp);
602162455Stegge		if (mp != ap->a_vp->v_mount) {
603162455Stegge			vfs_rel(mp);
604162455Stegge			mp = NULL;
605162455Stegge		}
606157323Sjeff	}
607157323Sjeff	*(ap->a_mpp) = mp;
60862976Smckusick	return (0);
60962976Smckusick}
61062976Smckusick
61191690Seivind/* XXX Needs good comment and VOP_BMAP(9) manpage */
61276131Sphkint
61376131Sphkvop_stdbmap(ap)
614112067Skan	struct vop_bmap_args /* {
61576131Sphk		struct vnode *a_vp;
61676131Sphk		daddr_t  a_bn;
617137726Sphk		struct bufobj **a_bop;
61876131Sphk		daddr_t *a_bnp;
61976131Sphk		int *a_runp;
62076131Sphk		int *a_runb;
62176131Sphk	} */ *ap;
62276131Sphk{
62376131Sphk
624137726Sphk	if (ap->a_bop != NULL)
625137726Sphk		*ap->a_bop = &ap->a_vp->v_bufobj;
62676131Sphk	if (ap->a_bnp != NULL)
62776131Sphk		*ap->a_bnp = ap->a_bn * btodb(ap->a_vp->v_mount->mnt_stat.f_iosize);
62876131Sphk	if (ap->a_runp != NULL)
62976131Sphk		*ap->a_runp = 0;
63076131Sphk	if (ap->a_runb != NULL)
63176131Sphk		*ap->a_runb = 0;
63276131Sphk	return (0);
63376131Sphk}
63476131Sphk
635110584Sjeffint
636110584Sjeffvop_stdfsync(ap)
637110584Sjeff	struct vop_fsync_args /* {
638110584Sjeff		struct vnode *a_vp;
639110584Sjeff		struct ucred *a_cred;
640110584Sjeff		int a_waitfor;
641110584Sjeff		struct thread *a_td;
642110584Sjeff	} */ *ap;
643110584Sjeff{
644110584Sjeff	struct vnode *vp = ap->a_vp;
645110584Sjeff	struct buf *bp;
646136751Sphk	struct bufobj *bo;
647110584Sjeff	struct buf *nbp;
648145732Sjeff	int error = 0;
649144584Sjeff	int maxretry = 1000;     /* large, arbitrarily chosen */
650110584Sjeff
651177493Sjeff	bo = &vp->v_bufobj;
652177493Sjeff	BO_LOCK(bo);
653110584Sjeffloop1:
654110584Sjeff	/*
655110584Sjeff	 * MARK/SCAN initialization to avoid infinite loops.
656110584Sjeff	 */
657177493Sjeff        TAILQ_FOREACH(bp, &bo->bo_dirty.bv_hd, b_bobufs) {
658110584Sjeff                bp->b_vflags &= ~BV_SCANNED;
659110584Sjeff		bp->b_error = 0;
660110584Sjeff	}
661110584Sjeff
662110584Sjeff	/*
663144584Sjeff	 * Flush all dirty buffers associated with a vnode.
664110584Sjeff	 */
665110584Sjeffloop2:
666177493Sjeff	TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) {
667110584Sjeff		if ((bp->b_vflags & BV_SCANNED) != 0)
668110584Sjeff			continue;
669110584Sjeff		bp->b_vflags |= BV_SCANNED;
670236825Smckusick		if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) {
671236825Smckusick			if (ap->a_waitfor != MNT_WAIT)
672236825Smckusick				continue;
673236825Smckusick			if (BUF_LOCK(bp,
674236825Smckusick			    LK_EXCLUSIVE | LK_INTERLOCK | LK_SLEEPFAIL,
675251171Sjeff			    BO_LOCKPTR(bo)) != 0) {
676236825Smckusick				BO_LOCK(bo);
677236825Smckusick				goto loop1;
678236825Smckusick			}
679236825Smckusick			BO_LOCK(bo);
680236825Smckusick		}
681177493Sjeff		BO_UNLOCK(bo);
682177493Sjeff		KASSERT(bp->b_bufobj == bo,
683147388Sjeff		    ("bp %p wrong b_bufobj %p should be %p",
684177493Sjeff		    bp, bp->b_bufobj, bo));
685110584Sjeff		if ((bp->b_flags & B_DELWRI) == 0)
686110588Sjeff			panic("fsync: not dirty");
687140734Sphk		if ((vp->v_object != NULL) && (bp->b_flags & B_CLUSTEROK)) {
688110584Sjeff			vfs_bio_awrite(bp);
689110584Sjeff		} else {
690110584Sjeff			bremfree(bp);
691110584Sjeff			bawrite(bp);
692110584Sjeff		}
693177493Sjeff		BO_LOCK(bo);
694110584Sjeff		goto loop2;
695110584Sjeff	}
696110584Sjeff
697110584Sjeff	/*
698110584Sjeff	 * If synchronous the caller expects us to completely resolve all
699110584Sjeff	 * dirty buffers in the system.  Wait for in-progress I/O to
700110584Sjeff	 * complete (which could include background bitmap writes), then
701110584Sjeff	 * retry if dirty blocks still exist.
702110584Sjeff	 */
703110584Sjeff	if (ap->a_waitfor == MNT_WAIT) {
704136751Sphk		bufobj_wwait(bo, 0, 0);
705136751Sphk		if (bo->bo_dirty.bv_cnt > 0) {
706110584Sjeff			/*
707110584Sjeff			 * If we are unable to write any of these buffers
708110584Sjeff			 * then we fail now rather than trying endlessly
709110584Sjeff			 * to write them out.
710110584Sjeff			 */
711136751Sphk			TAILQ_FOREACH(bp, &bo->bo_dirty.bv_hd, b_bobufs)
712110584Sjeff				if ((error = bp->b_error) == 0)
713110584Sjeff					continue;
714145732Sjeff			if (error == 0 && --maxretry >= 0)
715110584Sjeff				goto loop1;
716110584Sjeff			error = EAGAIN;
717110584Sjeff		}
718110584Sjeff	}
719177493Sjeff	BO_UNLOCK(bo);
720144584Sjeff	if (error == EAGAIN)
721144584Sjeff		vprint("fsync: giving up on dirty", vp);
722112067Skan
723110584Sjeff	return (error);
724110584Sjeff}
725112067Skan
72691690Seivind/* XXX Needs good comment and more info in the manpage (VOP_GETPAGES(9)). */
72776167Sphkint
72876167Sphkvop_stdgetpages(ap)
72976167Sphk	struct vop_getpages_args /* {
73076167Sphk		struct vnode *a_vp;
73176167Sphk		vm_page_t *a_m;
73276167Sphk		int a_count;
73376167Sphk		int a_reqpage;
73476167Sphk	} */ *ap;
73576167Sphk{
73676131Sphk
73776167Sphk	return vnode_pager_generic_getpages(ap->a_vp, ap->a_m,
738274914Sglebius	    ap->a_count, ap->a_reqpage, NULL, NULL);
73976167Sphk}
74076167Sphk
741274914Sglebiusstatic int
742274914Sglebiusvop_stdgetpages_async(struct vop_getpages_async_args *ap)
743274914Sglebius{
744274914Sglebius	int error;
745274914Sglebius
746274914Sglebius	error = VOP_GETPAGES(ap->a_vp, ap->a_m, ap->a_count, ap->a_reqpage);
747274914Sglebius	ap->a_iodone(ap->a_arg, ap->a_m, ap->a_reqpage, error);
748274914Sglebius	return (error);
749274914Sglebius}
750274914Sglebius
751147198Sssouhlalint
752147198Sssouhlalvop_stdkqfilter(struct vop_kqfilter_args *ap)
753147198Sssouhlal{
754147198Sssouhlal	return vfs_kqfilter(ap);
755147198Sssouhlal}
756147198Sssouhlal
75791690Seivind/* XXX Needs good comment and more info in the manpage (VOP_PUTPAGES(9)). */
75876319Sphkint
75976167Sphkvop_stdputpages(ap)
76076167Sphk	struct vop_putpages_args /* {
76176167Sphk		struct vnode *a_vp;
76276167Sphk		vm_page_t *a_m;
76376167Sphk		int a_count;
76476167Sphk		int a_sync;
76576167Sphk		int *a_rtvals;
76676167Sphk	} */ *ap;
76776167Sphk{
76876167Sphk
76976319Sphk	return vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count,
77076167Sphk	     ap->a_sync, ap->a_rtvals);
77176167Sphk}
77276167Sphk
773166774Spjdint
774166774Spjdvop_stdvptofh(struct vop_vptofh_args *ap)
775166774Spjd{
776166795Spjd	return (EOPNOTSUPP);
777166774Spjd}
778166774Spjd
779189539Smarcusint
780189539Smarcusvop_stdvptocnp(struct vop_vptocnp_args *ap)
781189539Smarcus{
782189539Smarcus	struct vnode *vp = ap->a_vp;
783189539Smarcus	struct vnode **dvp = ap->a_vpp;
784194601Skib	struct ucred *cred = ap->a_cred;
785189539Smarcus	char *buf = ap->a_buf;
786189539Smarcus	int *buflen = ap->a_buflen;
787189539Smarcus	char *dirbuf, *cpos;
788189539Smarcus	int i, error, eofflag, dirbuflen, flags, locked, len, covered;
789189539Smarcus	off_t off;
790189539Smarcus	ino_t fileno;
791189539Smarcus	struct vattr va;
792189539Smarcus	struct nameidata nd;
793189539Smarcus	struct thread *td;
794189539Smarcus	struct dirent *dp;
795189539Smarcus	struct vnode *mvp;
796189539Smarcus
797189539Smarcus	i = *buflen;
798189539Smarcus	error = 0;
799189539Smarcus	covered = 0;
800189539Smarcus	td = curthread;
801189539Smarcus
802189539Smarcus	if (vp->v_type != VDIR)
803189539Smarcus		return (ENOENT);
804189539Smarcus
805194601Skib	error = VOP_GETATTR(vp, &va, cred);
806189539Smarcus	if (error)
807189539Smarcus		return (error);
808189539Smarcus
809189539Smarcus	VREF(vp);
810189539Smarcus	locked = VOP_ISLOCKED(vp);
811189539Smarcus	VOP_UNLOCK(vp, 0);
812189539Smarcus	NDINIT_ATVP(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE,
813189539Smarcus	    "..", vp, td);
814189539Smarcus	flags = FREAD;
815194601Skib	error = vn_open_cred(&nd, &flags, 0, VN_OPEN_NOAUDIT, cred, NULL);
816189539Smarcus	if (error) {
817189539Smarcus		vn_lock(vp, locked | LK_RETRY);
818189539Smarcus		return (error);
819189539Smarcus	}
820189539Smarcus	NDFREE(&nd, NDF_ONLY_PNBUF);
821189539Smarcus
822189539Smarcus	mvp = *dvp = nd.ni_vp;
823189539Smarcus
824189539Smarcus	if (vp->v_mount != (*dvp)->v_mount &&
825189539Smarcus	    ((*dvp)->v_vflag & VV_ROOT) &&
826189539Smarcus	    ((*dvp)->v_mount->mnt_flag & MNT_UNION)) {
827189539Smarcus		*dvp = (*dvp)->v_mount->mnt_vnodecovered;
828189539Smarcus		VREF(mvp);
829189539Smarcus		VOP_UNLOCK(mvp, 0);
830194601Skib		vn_close(mvp, FREAD, cred, td);
831189539Smarcus		VREF(*dvp);
832189539Smarcus		vn_lock(*dvp, LK_EXCLUSIVE | LK_RETRY);
833189539Smarcus		covered = 1;
834189539Smarcus	}
835189539Smarcus
836189539Smarcus	fileno = va.va_fileid;
837189539Smarcus
838189539Smarcus	dirbuflen = DEV_BSIZE;
839189539Smarcus	if (dirbuflen < va.va_blocksize)
840189539Smarcus		dirbuflen = va.va_blocksize;
841189539Smarcus	dirbuf = (char *)malloc(dirbuflen, M_TEMP, M_WAITOK);
842189539Smarcus
843189539Smarcus	if ((*dvp)->v_type != VDIR) {
844189539Smarcus		error = ENOENT;
845189539Smarcus		goto out;
846189539Smarcus	}
847189539Smarcus
848189539Smarcus	off = 0;
849189539Smarcus	len = 0;
850189539Smarcus	do {
851189539Smarcus		/* call VOP_READDIR of parent */
852189539Smarcus		error = get_next_dirent(*dvp, &dp, dirbuf, dirbuflen, &off,
853189539Smarcus					&cpos, &len, &eofflag, td);
854189539Smarcus		if (error)
855189539Smarcus			goto out;
856189539Smarcus
857189539Smarcus		if ((dp->d_type != DT_WHT) &&
858189539Smarcus		    (dp->d_fileno == fileno)) {
859189539Smarcus			if (covered) {
860189539Smarcus				VOP_UNLOCK(*dvp, 0);
861189539Smarcus				vn_lock(mvp, LK_EXCLUSIVE | LK_RETRY);
862189539Smarcus				if (dirent_exists(mvp, dp->d_name, td)) {
863189539Smarcus					error = ENOENT;
864189539Smarcus					VOP_UNLOCK(mvp, 0);
865189539Smarcus					vn_lock(*dvp, LK_EXCLUSIVE | LK_RETRY);
866189539Smarcus					goto out;
867189539Smarcus				}
868189539Smarcus				VOP_UNLOCK(mvp, 0);
869189539Smarcus				vn_lock(*dvp, LK_EXCLUSIVE | LK_RETRY);
870189539Smarcus			}
871189539Smarcus			i -= dp->d_namlen;
872189539Smarcus
873189539Smarcus			if (i < 0) {
874189539Smarcus				error = ENOMEM;
875189539Smarcus				goto out;
876189539Smarcus			}
877247560Skib			if (dp->d_namlen == 1 && dp->d_name[0] == '.') {
878247560Skib				error = ENOENT;
879247560Skib			} else {
880247560Skib				bcopy(dp->d_name, buf + i, dp->d_namlen);
881247560Skib				error = 0;
882247560Skib			}
883189539Smarcus			goto out;
884189539Smarcus		}
885189539Smarcus	} while (len > 0 || !eofflag);
886189539Smarcus	error = ENOENT;
887189539Smarcus
888189539Smarcusout:
889189539Smarcus	free(dirbuf, M_TEMP);
890189539Smarcus	if (!error) {
891189539Smarcus		*buflen = i;
892227697Skib		vref(*dvp);
893189539Smarcus	}
894189539Smarcus	if (covered) {
895189539Smarcus		vput(*dvp);
896189539Smarcus		vrele(mvp);
897189539Smarcus	} else {
898189539Smarcus		VOP_UNLOCK(mvp, 0);
899194601Skib		vn_close(mvp, FREAD, cred, td);
900189539Smarcus	}
901189539Smarcus	vn_lock(vp, locked | LK_RETRY);
902189539Smarcus	return (error);
903189539Smarcus}
904189539Smarcus
905220791Smdfint
906220791Smdfvop_stdallocate(struct vop_allocate_args *ap)
907220791Smdf{
908220791Smdf#ifdef __notyet__
909220791Smdf	struct statfs sfs;
910220791Smdf#endif
911220791Smdf	struct iovec aiov;
912220791Smdf	struct vattr vattr, *vap;
913220791Smdf	struct uio auio;
914220846Smdf	off_t fsize, len, cur, offset;
915220791Smdf	uint8_t *buf;
916220791Smdf	struct thread *td;
917220791Smdf	struct vnode *vp;
918220791Smdf	size_t iosize;
919220846Smdf	int error;
920220791Smdf
921220791Smdf	buf = NULL;
922220791Smdf	error = 0;
923220791Smdf	td = curthread;
924220791Smdf	vap = &vattr;
925220791Smdf	vp = ap->a_vp;
926220846Smdf	len = *ap->a_len;
927220846Smdf	offset = *ap->a_offset;
928220791Smdf
929220791Smdf	error = VOP_GETATTR(vp, vap, td->td_ucred);
930220791Smdf	if (error != 0)
931220791Smdf		goto out;
932220846Smdf	fsize = vap->va_size;
933220791Smdf	iosize = vap->va_blocksize;
934220791Smdf	if (iosize == 0)
935220791Smdf		iosize = BLKDEV_IOSIZE;
936220791Smdf	if (iosize > MAXPHYS)
937220791Smdf		iosize = MAXPHYS;
938220791Smdf	buf = malloc(iosize, M_TEMP, M_WAITOK);
939220791Smdf
940220791Smdf#ifdef __notyet__
941220791Smdf	/*
942220791Smdf	 * Check if the filesystem sets f_maxfilesize; if not use
943220791Smdf	 * VOP_SETATTR to perform the check.
944220791Smdf	 */
945220791Smdf	error = VFS_STATFS(vp->v_mount, &sfs, td);
946220791Smdf	if (error != 0)
947220791Smdf		goto out;
948220791Smdf	if (sfs.f_maxfilesize) {
949220791Smdf		if (offset > sfs.f_maxfilesize || len > sfs.f_maxfilesize ||
950220791Smdf		    offset + len > sfs.f_maxfilesize) {
951220791Smdf			error = EFBIG;
952220791Smdf			goto out;
953220791Smdf		}
954220791Smdf	} else
955220791Smdf#endif
956220791Smdf	if (offset + len > vap->va_size) {
957220846Smdf		/*
958220846Smdf		 * Test offset + len against the filesystem's maxfilesize.
959220846Smdf		 */
960220791Smdf		VATTR_NULL(vap);
961220791Smdf		vap->va_size = offset + len;
962220791Smdf		error = VOP_SETATTR(vp, vap, td->td_ucred);
963220791Smdf		if (error != 0)
964220791Smdf			goto out;
965220846Smdf		VATTR_NULL(vap);
966220846Smdf		vap->va_size = fsize;
967220846Smdf		error = VOP_SETATTR(vp, vap, td->td_ucred);
968220846Smdf		if (error != 0)
969220846Smdf			goto out;
970220791Smdf	}
971220791Smdf
972220846Smdf	for (;;) {
973220791Smdf		/*
974220791Smdf		 * Read and write back anything below the nominal file
975220791Smdf		 * size.  There's currently no way outside the filesystem
976220791Smdf		 * to know whether this area is sparse or not.
977220791Smdf		 */
978220791Smdf		cur = iosize;
979220791Smdf		if ((offset % iosize) != 0)
980220791Smdf			cur -= (offset % iosize);
981220791Smdf		if (cur > len)
982220791Smdf			cur = len;
983220846Smdf		if (offset < fsize) {
984220791Smdf			aiov.iov_base = buf;
985220791Smdf			aiov.iov_len = cur;
986220791Smdf			auio.uio_iov = &aiov;
987220791Smdf			auio.uio_iovcnt = 1;
988220791Smdf			auio.uio_offset = offset;
989220791Smdf			auio.uio_resid = cur;
990220791Smdf			auio.uio_segflg = UIO_SYSSPACE;
991220791Smdf			auio.uio_rw = UIO_READ;
992220791Smdf			auio.uio_td = td;
993220791Smdf			error = VOP_READ(vp, &auio, 0, td->td_ucred);
994220791Smdf			if (error != 0)
995220791Smdf				break;
996220791Smdf			if (auio.uio_resid > 0) {
997220791Smdf				bzero(buf + cur - auio.uio_resid,
998220791Smdf				    auio.uio_resid);
999220791Smdf			}
1000220791Smdf		} else {
1001220791Smdf			bzero(buf, cur);
1002220791Smdf		}
1003220791Smdf
1004220791Smdf		aiov.iov_base = buf;
1005220791Smdf		aiov.iov_len = cur;
1006220791Smdf		auio.uio_iov = &aiov;
1007220791Smdf		auio.uio_iovcnt = 1;
1008220791Smdf		auio.uio_offset = offset;
1009220791Smdf		auio.uio_resid = cur;
1010220791Smdf		auio.uio_segflg = UIO_SYSSPACE;
1011220791Smdf		auio.uio_rw = UIO_WRITE;
1012220791Smdf		auio.uio_td = td;
1013220791Smdf
1014220791Smdf		error = VOP_WRITE(vp, &auio, 0, td->td_ucred);
1015220791Smdf		if (error != 0)
1016220791Smdf			break;
1017220791Smdf
1018220791Smdf		len -= cur;
1019220791Smdf		offset += cur;
1020220846Smdf		if (len == 0)
1021220846Smdf			break;
1022220846Smdf		if (should_yield())
1023220846Smdf			break;
1024220791Smdf	}
1025220791Smdf
1026220791Smdf out:
1027220846Smdf	*ap->a_len = len;
1028220846Smdf	*ap->a_offset = offset;
1029220791Smdf	free(buf, M_TEMP);
1030220791Smdf	return (error);
1031220791Smdf}
1032220791Smdf
1033227070Sjhbint
1034227070Sjhbvop_stdadvise(struct vop_advise_args *ap)
1035227070Sjhb{
1036227070Sjhb	struct vnode *vp;
1037227070Sjhb	off_t start, end;
1038241896Skib	int error;
1039227070Sjhb
1040227070Sjhb	vp = ap->a_vp;
1041227070Sjhb	switch (ap->a_advice) {
1042227070Sjhb	case POSIX_FADV_WILLNEED:
1043227070Sjhb		/*
1044227070Sjhb		 * Do nothing for now.  Filesystems should provide a
1045227070Sjhb		 * custom method which starts an asynchronous read of
1046227070Sjhb		 * the requested region.
1047227070Sjhb		 */
1048227070Sjhb		error = 0;
1049227070Sjhb		break;
1050227070Sjhb	case POSIX_FADV_DONTNEED:
1051227070Sjhb		/*
1052227070Sjhb		 * Flush any open FS buffers and then remove pages
1053227070Sjhb		 * from the backing VM object.  Using vinvalbuf() here
1054227070Sjhb		 * is a bit heavy-handed as it flushes all buffers for
1055227070Sjhb		 * the given vnode, not just the buffers covering the
1056227070Sjhb		 * requested range.
1057227070Sjhb		 */
1058227070Sjhb		error = 0;
1059227070Sjhb		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1060227070Sjhb		if (vp->v_iflag & VI_DOOMED) {
1061227070Sjhb			VOP_UNLOCK(vp, 0);
1062227070Sjhb			break;
1063227070Sjhb		}
1064227070Sjhb		vinvalbuf(vp, V_CLEANONLY, 0, 0);
1065227070Sjhb		if (vp->v_object != NULL) {
1066227070Sjhb			start = trunc_page(ap->a_start);
1067227070Sjhb			end = round_page(ap->a_end);
1068248084Sattilio			VM_OBJECT_WLOCK(vp->v_object);
1069227070Sjhb			vm_object_page_cache(vp->v_object, OFF_TO_IDX(start),
1070227070Sjhb			    OFF_TO_IDX(end));
1071248084Sattilio			VM_OBJECT_WUNLOCK(vp->v_object);
1072227070Sjhb		}
1073227070Sjhb		VOP_UNLOCK(vp, 0);
1074227070Sjhb		break;
1075227070Sjhb	default:
1076227070Sjhb		error = EINVAL;
1077227070Sjhb		break;
1078227070Sjhb	}
1079227070Sjhb	return (error);
1080227070Sjhb}
1081227070Sjhb
1082232317Strocinyint
1083232317Strocinyvop_stdunp_bind(struct vop_unp_bind_args *ap)
1084232317Strociny{
1085232317Strociny
1086232317Strociny	ap->a_vp->v_socket = ap->a_socket;
1087232317Strociny	return (0);
1088232317Strociny}
1089232317Strociny
1090232317Strocinyint
1091232317Strocinyvop_stdunp_connect(struct vop_unp_connect_args *ap)
1092232317Strociny{
1093232317Strociny
1094232317Strociny	*ap->a_socket = ap->a_vp->v_socket;
1095232317Strociny	return (0);
1096232317Strociny}
1097232317Strociny
1098232317Strocinyint
1099232317Strocinyvop_stdunp_detach(struct vop_unp_detach_args *ap)
1100232317Strociny{
1101232317Strociny
1102232317Strociny	ap->a_vp->v_socket = NULL;
1103232317Strociny	return (0);
1104232317Strociny}
1105232317Strociny
1106241025Skibstatic int
1107241025Skibvop_stdis_text(struct vop_is_text_args *ap)
1108241025Skib{
1109241025Skib
1110241025Skib	return ((ap->a_vp->v_vflag & VV_TEXT) != 0);
1111241025Skib}
1112241025Skib
1113241025Skibstatic int
1114241025Skibvop_stdset_text(struct vop_set_text_args *ap)
1115241025Skib{
1116241025Skib
1117241025Skib	ap->a_vp->v_vflag |= VV_TEXT;
1118241025Skib	return (0);
1119241025Skib}
1120241025Skib
1121241025Skibstatic int
1122241025Skibvop_stdunset_text(struct vop_unset_text_args *ap)
1123241025Skib{
1124241025Skib
1125241025Skib	ap->a_vp->v_vflag &= ~VV_TEXT;
1126241025Skib	return (0);
1127241025Skib}
1128241025Skib
1129242476Skibstatic int
1130242476Skibvop_stdget_writecount(struct vop_get_writecount_args *ap)
1131242476Skib{
1132242476Skib
1133242476Skib	*ap->a_writecount = ap->a_vp->v_writecount;
1134242476Skib	return (0);
1135242476Skib}
1136242476Skib
1137242476Skibstatic int
1138242476Skibvop_stdadd_writecount(struct vop_add_writecount_args *ap)
1139242476Skib{
1140242476Skib
1141242476Skib	ap->a_vp->v_writecount += ap->a_inc;
1142242476Skib	return (0);
1143242476Skib}
1144242476Skib
1145112067Skan/*
114651068Salfred * vfs default ops
114791690Seivind * used to fill the vfs function table to get reasonable default return values.
114851068Salfred */
114991690Seivindint
1150191990Sattiliovfs_stdroot (mp, flags, vpp)
115151068Salfred	struct mount *mp;
1152144054Sjeff	int flags;
115351068Salfred	struct vnode **vpp;
115451068Salfred{
1155131734Salfred
115651068Salfred	return (EOPNOTSUPP);
115751068Salfred}
115851068Salfred
115991690Seivindint
1160191990Sattiliovfs_stdstatfs (mp, sbp)
116151068Salfred	struct mount *mp;
116251068Salfred	struct statfs *sbp;
116351068Salfred{
1164131734Salfred
116551068Salfred	return (EOPNOTSUPP);
116651068Salfred}
116751068Salfred
116851068Salfredint
1169191990Sattiliovfs_stdquotactl (mp, cmds, uid, arg)
117051068Salfred	struct mount *mp;
117151068Salfred	int cmds;
117251068Salfred	uid_t uid;
1173153400Sdes	void *arg;
117451068Salfred{
1175131734Salfred
117651068Salfred	return (EOPNOTSUPP);
117751068Salfred}
117851068Salfred
1179112067Skanint
1180191990Sattiliovfs_stdsync(mp, waitfor)
118151068Salfred	struct mount *mp;
118251068Salfred	int waitfor;
118351068Salfred{
1184154152Stegge	struct vnode *vp, *mvp;
1185191990Sattilio	struct thread *td;
1186112119Skan	int error, lockreq, allerror = 0;
1187112119Skan
1188191990Sattilio	td = curthread;
1189112119Skan	lockreq = LK_EXCLUSIVE | LK_INTERLOCK;
1190112119Skan	if (waitfor != MNT_WAIT)
1191112119Skan		lockreq |= LK_NOWAIT;
1192112119Skan	/*
1193112119Skan	 * Force stale buffer cache information to be flushed.
1194112119Skan	 */
1195112119Skanloop:
1196234386Smckusick	MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
1197234386Smckusick		if (vp->v_bufobj.bo_dirty.bv_cnt == 0) {
1198234386Smckusick			VI_UNLOCK(vp);
1199177493Sjeff			continue;
1200234386Smckusick		}
1201112119Skan		if ((error = vget(vp, lockreq, td)) != 0) {
1202154152Stegge			if (error == ENOENT) {
1203234386Smckusick				MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp);
1204112119Skan				goto loop;
1205154152Stegge			}
1206112119Skan			continue;
1207112119Skan		}
1208140048Sphk		error = VOP_FSYNC(vp, waitfor, td);
1209112119Skan		if (error)
1210112119Skan			allerror = error;
1211204065Spjd		vput(vp);
1212112119Skan	}
1213112119Skan	return (allerror);
1214112119Skan}
1215112119Skan
1216112119Skanint
1217191990Sattiliovfs_stdnosync (mp, waitfor)
1218112119Skan	struct mount *mp;
1219112119Skan	int waitfor;
1220112119Skan{
1221131734Salfred
122251068Salfred	return (0);
122351068Salfred}
122451068Salfred
1225112067Skanint
122692462Smckusickvfs_stdvget (mp, ino, flags, vpp)
122751068Salfred	struct mount *mp;
122851068Salfred	ino_t ino;
122992462Smckusick	int flags;
123051068Salfred	struct vnode **vpp;
123151068Salfred{
1232131734Salfred
123351068Salfred	return (EOPNOTSUPP);
123451068Salfred}
123551068Salfred
1236112067Skanint
1237222167Srmacklemvfs_stdfhtovp (mp, fhp, flags, vpp)
123851068Salfred	struct mount *mp;
123951068Salfred	struct fid *fhp;
1240222167Srmacklem	int flags;
124151138Salfred	struct vnode **vpp;
124251138Salfred{
1243131734Salfred
124451138Salfred	return (EOPNOTSUPP);
124551138Salfred}
124651138Salfred
124751068Salfredint
1248112067Skanvfs_stdinit (vfsp)
124951068Salfred	struct vfsconf *vfsp;
125051068Salfred{
1251131734Salfred
125251068Salfred	return (0);
125351068Salfred}
125451068Salfred
125551068Salfredint
125651068Salfredvfs_stduninit (vfsp)
125751068Salfred	struct vfsconf *vfsp;
125851068Salfred{
1259131734Salfred
126051068Salfred	return(0);
126151068Salfred}
126251068Salfred
126354803Srwatsonint
1264191990Sattiliovfs_stdextattrctl(mp, cmd, filename_vp, attrnamespace, attrname)
126554803Srwatson	struct mount *mp;
126654803Srwatson	int cmd;
126774273Srwatson	struct vnode *filename_vp;
126874437Srwatson	int attrnamespace;
126956272Srwatson	const char *attrname;
127054803Srwatson{
1271131734Salfred
1272101786Sphk	if (filename_vp != NULL)
1273175294Sattilio		VOP_UNLOCK(filename_vp, 0);
1274131734Salfred	return (EOPNOTSUPP);
127554803Srwatson}
127654803Srwatson
1277131733Salfredint
1278131733Salfredvfs_stdsysctl(mp, op, req)
1279131733Salfred	struct mount *mp;
1280131733Salfred	fsctlop_t op;
1281131733Salfred	struct sysctl_req *req;
1282131733Salfred{
1283131733Salfred
1284131733Salfred	return (EOPNOTSUPP);
1285131733Salfred}
1286131733Salfred
128751068Salfred/* end of vfs default ops */
1288