vfs_default.c revision 285135
1214077Sgibbs/*- 2223059Sgibbs * Copyright (c) 1989, 1993 3181643Skmacy * The Regents of the University of California. All rights reserved. 4181643Skmacy * 5214077Sgibbs * This code is derived from software contributed 6214077Sgibbs * to Berkeley by John Heidemann of the UCLA Ficus project. 7181643Skmacy * 8214077Sgibbs * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project 9214077Sgibbs * 10214077Sgibbs * Redistribution and use in source and binary forms, with or without 11214077Sgibbs * modification, are permitted provided that the following conditions 12214077Sgibbs * are met: 13214077Sgibbs * 1. Redistributions of source code must retain the above copyright 14214077Sgibbs * notice, this list of conditions and the following disclaimer. 15214077Sgibbs * 2. Redistributions in binary form must reproduce the above copyright 16181643Skmacy * notice, this list of conditions and the following disclaimer in the 17214077Sgibbs * documentation and/or other materials provided with the distribution. 18214077Sgibbs * 4. Neither the name of the University nor the names of its contributors 19214077Sgibbs * may be used to endorse or promote products derived from this software 20214077Sgibbs * without specific prior written permission. 21214077Sgibbs * 22214077Sgibbs * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23214077Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24214077Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25214077Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26214077Sgibbs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27214077Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28214077Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29181643Skmacy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30214077Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31214077Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32181643Skmacy * SUCH DAMAGE. 33181643Skmacy */ 34181643Skmacy 35181643Skmacy#include <sys/cdefs.h> 36214077Sgibbs__FBSDID("$FreeBSD: head/sys/kern/vfs_default.c 285135 2015-07-04 15:46:39Z mjg $"); 37214077Sgibbs 38214077Sgibbs#include <sys/param.h> 39214077Sgibbs#include <sys/systm.h> 40214077Sgibbs#include <sys/bio.h> 41214077Sgibbs#include <sys/buf.h> 42214077Sgibbs#include <sys/conf.h> 43231743Sgibbs#include <sys/event.h> 44231743Sgibbs#include <sys/kernel.h> 45181643Skmacy#include <sys/limits.h> 46181643Skmacy#include <sys/lock.h> 47214077Sgibbs#include <sys/lockf.h> 48181643Skmacy#include <sys/malloc.h> 49214077Sgibbs#include <sys/mount.h> 50214077Sgibbs#include <sys/namei.h> 51214077Sgibbs#include <sys/rwlock.h> 52214077Sgibbs#include <sys/fcntl.h> 53214077Sgibbs#include <sys/unistd.h> 54214077Sgibbs#include <sys/vnode.h> 55214077Sgibbs#include <sys/dirent.h> 56214077Sgibbs#include <sys/poll.h> 57214077Sgibbs 58214077Sgibbs#include <security/mac/mac_framework.h> 59181643Skmacy 60181643Skmacy#include <vm/vm.h> 61214077Sgibbs#include <vm/vm_object.h> 62214077Sgibbs#include <vm/vm_extern.h> 63214077Sgibbs#include <vm/pmap.h> 64181643Skmacy#include <vm/vm_map.h> 65214077Sgibbs#include <vm/vm_page.h> 66223059Sgibbs#include <vm/vm_pager.h> 67223059Sgibbs#include <vm/vnode_pager.h> 68231743Sgibbs 69181643Skmacystatic int vop_nolookup(struct vop_lookup_args *); 70181643Skmacystatic int vop_norename(struct vop_rename_args *); 71181643Skmacystatic int vop_nostrategy(struct vop_strategy_args *); 72214077Sgibbsstatic int get_next_dirent(struct vnode *vp, struct dirent **dpp, 73214077Sgibbs char *dirbuf, int dirbuflen, off_t *off, 74214077Sgibbs char **cpos, int *len, int *eofflag, 75181643Skmacy struct thread *td); 76181643Skmacystatic int dirent_exists(struct vnode *vp, const char *dirname, 77181643Skmacy struct thread *td); 78255040Sgibbs 79214077Sgibbs#define DIRENT_MINSIZE (sizeof(struct dirent) - (MAXNAMLEN+1) + 4) 80214077Sgibbs 81214077Sgibbsstatic int vop_stdis_text(struct vop_is_text_args *ap); 82181643Skmacystatic int vop_stdset_text(struct vop_set_text_args *ap); 83214077Sgibbsstatic int vop_stdunset_text(struct vop_unset_text_args *ap); 84214077Sgibbsstatic int vop_stdget_writecount(struct vop_get_writecount_args *ap); 85181643Skmacystatic int vop_stdadd_writecount(struct vop_add_writecount_args *ap); 86214077Sgibbsstatic int vop_stdgetpages_async(struct vop_getpages_async_args *ap); 87214077Sgibbs 88214077Sgibbs/* 89214077Sgibbs * This vnode table stores what we want to do if the filesystem doesn't 90214077Sgibbs * implement a particular VOP. 91214077Sgibbs * 92214077Sgibbs * If there is no specific entry here, we will return EOPNOTSUPP. 93214077Sgibbs * 94214077Sgibbs * Note that every filesystem has to implement either vop_access 95214077Sgibbs * or vop_accessx; failing to do so will result in immediate crash 96214077Sgibbs * due to stack overflow, as vop_stdaccess() calls vop_stdaccessx(), 97214077Sgibbs * which calls vop_stdaccess() etc. 98214077Sgibbs */ 99214077Sgibbs 100214077Sgibbsstruct vop_vector default_vnodeops = { 101214077Sgibbs .vop_default = NULL, 102214077Sgibbs .vop_bypass = VOP_EOPNOTSUPP, 103214077Sgibbs 104214077Sgibbs .vop_access = vop_stdaccess, 105214077Sgibbs .vop_accessx = vop_stdaccessx, 106214077Sgibbs .vop_advise = vop_stdadvise, 107214077Sgibbs .vop_advlock = vop_stdadvlock, 108214077Sgibbs .vop_advlockasync = vop_stdadvlockasync, 109214077Sgibbs .vop_advlockpurge = vop_stdadvlockpurge, 110214077Sgibbs .vop_allocate = vop_stdallocate, 111214077Sgibbs .vop_bmap = vop_stdbmap, 112214077Sgibbs .vop_close = VOP_NULL, 113214077Sgibbs .vop_fsync = VOP_NULL, 114214077Sgibbs .vop_getpages = vop_stdgetpages, 115214077Sgibbs .vop_getpages_async = vop_stdgetpages_async, 116214077Sgibbs .vop_getwritemount = vop_stdgetwritemount, 117214077Sgibbs .vop_inactive = VOP_NULL, 118214077Sgibbs .vop_ioctl = VOP_ENOTTY, 119214077Sgibbs .vop_kqfilter = vop_stdkqfilter, 120214077Sgibbs .vop_islocked = vop_stdislocked, 121214077Sgibbs .vop_lock1 = vop_stdlock, 122214077Sgibbs .vop_lookup = vop_nolookup, 123214077Sgibbs .vop_open = VOP_NULL, 124214077Sgibbs .vop_pathconf = VOP_EINVAL, 125214077Sgibbs .vop_poll = vop_nopoll, 126227293Sed .vop_putpages = vop_stdputpages, 127214077Sgibbs .vop_readlink = VOP_EINVAL, 128214077Sgibbs .vop_rename = vop_norename, 129231743Sgibbs .vop_revoke = VOP_PANIC, 130214077Sgibbs .vop_strategy = vop_nostrategy, 131181643Skmacy .vop_unlock = vop_stdunlock, 132214077Sgibbs .vop_vptocnp = vop_stdvptocnp, 133181643Skmacy .vop_vptofh = vop_stdvptofh, 134181643Skmacy .vop_unp_bind = vop_stdunp_bind, 135214077Sgibbs .vop_unp_connect = vop_stdunp_connect, 136214077Sgibbs .vop_unp_detach = vop_stdunp_detach, 137214077Sgibbs .vop_is_text = vop_stdis_text, 138214077Sgibbs .vop_set_text = vop_stdset_text, 139231743Sgibbs .vop_unset_text = vop_stdunset_text, 140214077Sgibbs .vop_get_writecount = vop_stdget_writecount, 141181643Skmacy .vop_add_writecount = vop_stdadd_writecount, 142214077Sgibbs}; 143214077Sgibbs 144214077Sgibbs/* 145214077Sgibbs * Series of placeholder functions for various error returns for 146214077Sgibbs * VOPs. 147231743Sgibbs */ 148231743Sgibbs 149231743Sgibbsint 150214077Sgibbsvop_eopnotsupp(struct vop_generic_args *ap) 151181643Skmacy{ 152214077Sgibbs /* 153214077Sgibbs printf("vop_notsupp[%s]\n", ap->a_desc->vdesc_name); 154214077Sgibbs */ 155214077Sgibbs 156214077Sgibbs return (EOPNOTSUPP); 157214077Sgibbs} 158214077Sgibbs 159214077Sgibbsint 160223059Sgibbsvop_ebadf(struct vop_generic_args *ap) 161223059Sgibbs{ 162223059Sgibbs 163223059Sgibbs return (EBADF); 164223059Sgibbs} 165223059Sgibbs 166223059Sgibbsint 167223059Sgibbsvop_enotty(struct vop_generic_args *ap) 168223059Sgibbs{ 169214077Sgibbs 170214077Sgibbs return (ENOTTY); 171214077Sgibbs} 172223059Sgibbs 173214077Sgibbsint 174214077Sgibbsvop_einval(struct vop_generic_args *ap) 175214077Sgibbs{ 176214077Sgibbs 177214077Sgibbs return (EINVAL); 178214077Sgibbs} 179214077Sgibbs 180214077Sgibbsint 181223059Sgibbsvop_enoent(struct vop_generic_args *ap) 182223059Sgibbs{ 183223059Sgibbs 184223059Sgibbs return (ENOENT); 185223059Sgibbs} 186223059Sgibbs 187223059Sgibbsint 188223059Sgibbsvop_null(struct vop_generic_args *ap) 189214077Sgibbs{ 190214077Sgibbs 191214077Sgibbs return (0); 192214077Sgibbs} 193214077Sgibbs 194214077Sgibbs/* 195214077Sgibbs * Helper function to panic on some bad VOPs in some filesystems. 196223059Sgibbs */ 197214077Sgibbsint 198223059Sgibbsvop_panic(struct vop_generic_args *ap) 199214077Sgibbs{ 200214077Sgibbs 201223059Sgibbs panic("filesystem goof: vop_panic[%s]", ap->a_desc->vdesc_name); 202223059Sgibbs} 203223059Sgibbs 204223059Sgibbs/* 205223059Sgibbs * vop_std<something> and vop_no<something> are default functions for use by 206223059Sgibbs * filesystems that need the "default reasonable" implementation for a 207223059Sgibbs * particular operation. 208223059Sgibbs * 209223059Sgibbs * The documentation for the operations they implement exists (if it exists) 210223059Sgibbs * in the VOP_<SOMETHING>(9) manpage (all uppercase). 211223059Sgibbs */ 212223059Sgibbs 213223059Sgibbs/* 214223059Sgibbs * Default vop for filesystems that do not support name lookup 215223059Sgibbs */ 216223059Sgibbsstatic int 217223059Sgibbsvop_nolookup(ap) 218223059Sgibbs struct vop_lookup_args /* { 219223059Sgibbs struct vnode *a_dvp; 220223059Sgibbs struct vnode **a_vpp; 221223059Sgibbs struct componentname *a_cnp; 222223059Sgibbs } */ *ap; 223223059Sgibbs{ 224223059Sgibbs 225223059Sgibbs *ap->a_vpp = NULL; 226223059Sgibbs return (ENOTDIR); 227223059Sgibbs} 228223059Sgibbs 229223059Sgibbs/* 230223059Sgibbs * vop_norename: 231223059Sgibbs * 232223059Sgibbs * Handle unlock and reference counting for arguments of vop_rename 233255218Sgibbs * for filesystems that do not implement rename operation. 234223059Sgibbs */ 235223059Sgibbsstatic int 236223059Sgibbsvop_norename(struct vop_rename_args *ap) 237223059Sgibbs{ 238223059Sgibbs 239223059Sgibbs vop_rename_fail(ap); 240223059Sgibbs return (EOPNOTSUPP); 241223059Sgibbs} 242223059Sgibbs 243223059Sgibbs/* 244223059Sgibbs * vop_nostrategy: 245223059Sgibbs * 246223059Sgibbs * Strategy routine for VFS devices that have none. 247223059Sgibbs * 248214077Sgibbs * BIO_ERROR and B_INVAL must be cleared prior to calling any strategy 249223059Sgibbs * routine. Typically this is done for a BIO_READ strategy call. 250214077Sgibbs * Typically B_INVAL is assumed to already be clear prior to a write 251214077Sgibbs * and should not be cleared manually unless you just made the buffer 252214077Sgibbs * invalid. BIO_ERROR should be cleared either way. 253214077Sgibbs */ 254223059Sgibbs 255223059Sgibbsstatic int 256223059Sgibbsvop_nostrategy (struct vop_strategy_args *ap) 257223059Sgibbs{ 258223059Sgibbs printf("No strategy for buffer at %p\n", ap->a_bp); 259223059Sgibbs vprint("vnode", ap->a_vp); 260223059Sgibbs ap->a_bp->b_ioflags |= BIO_ERROR; 261214077Sgibbs ap->a_bp->b_error = EOPNOTSUPP; 262214077Sgibbs bufdone(ap->a_bp); 263214077Sgibbs return (EOPNOTSUPP); 264214077Sgibbs} 265214077Sgibbs 266214077Sgibbsstatic int 267214077Sgibbsget_next_dirent(struct vnode *vp, struct dirent **dpp, char *dirbuf, 268214077Sgibbs int dirbuflen, off_t *off, char **cpos, int *len, 269214077Sgibbs int *eofflag, struct thread *td) 270223059Sgibbs{ 271214077Sgibbs int error, reclen; 272223059Sgibbs struct uio uio; 273214077Sgibbs struct iovec iov; 274214077Sgibbs struct dirent *dp; 275223059Sgibbs 276223059Sgibbs KASSERT(VOP_ISLOCKED(vp), ("vp %p is not locked", vp)); 277223059Sgibbs KASSERT(vp->v_type == VDIR, ("vp %p is not a directory", vp)); 278223059Sgibbs 279223059Sgibbs if (*len == 0) { 280223059Sgibbs iov.iov_base = dirbuf; 281223059Sgibbs iov.iov_len = dirbuflen; 282223059Sgibbs 283223059Sgibbs uio.uio_iov = &iov; 284223059Sgibbs uio.uio_iovcnt = 1; 285223059Sgibbs uio.uio_offset = *off; 286223059Sgibbs uio.uio_resid = dirbuflen; 287223059Sgibbs uio.uio_segflg = UIO_SYSSPACE; 288223059Sgibbs uio.uio_rw = UIO_READ; 289223059Sgibbs uio.uio_td = td; 290223059Sgibbs 291223059Sgibbs *eofflag = 0; 292223059Sgibbs 293223059Sgibbs#ifdef MAC 294223059Sgibbs error = mac_vnode_check_readdir(td->td_ucred, vp); 295223059Sgibbs if (error == 0) 296223059Sgibbs#endif 297223059Sgibbs error = VOP_READDIR(vp, &uio, td->td_ucred, eofflag, 298223059Sgibbs NULL, NULL); 299223059Sgibbs if (error) 300223059Sgibbs return (error); 301223059Sgibbs 302223059Sgibbs *off = uio.uio_offset; 303223059Sgibbs 304223059Sgibbs *cpos = dirbuf; 305223059Sgibbs *len = (dirbuflen - uio.uio_resid); 306223059Sgibbs 307223059Sgibbs if (*len == 0) 308223059Sgibbs return (ENOENT); 309223059Sgibbs } 310223059Sgibbs 311223059Sgibbs dp = (struct dirent *)(*cpos); 312223059Sgibbs reclen = dp->d_reclen; 313223059Sgibbs *dpp = dp; 314223059Sgibbs 315223059Sgibbs /* check for malformed directory.. */ 316223059Sgibbs if (reclen < DIRENT_MINSIZE) 317223059Sgibbs return (EINVAL); 318223059Sgibbs 319223059Sgibbs *cpos += reclen; 320214077Sgibbs *len -= reclen; 321214077Sgibbs 322223059Sgibbs return (0); 323214077Sgibbs} 324214077Sgibbs 325214077Sgibbs/* 326214077Sgibbs * Check if a named file exists in a given directory vnode. 327223059Sgibbs */ 328214077Sgibbsstatic int 329214077Sgibbsdirent_exists(struct vnode *vp, const char *dirname, struct thread *td) 330214077Sgibbs{ 331214077Sgibbs char *dirbuf, *cpos; 332223059Sgibbs int error, eofflag, dirbuflen, len, found; 333214077Sgibbs off_t off; 334214077Sgibbs struct dirent *dp; 335223059Sgibbs struct vattr va; 336214077Sgibbs 337223059Sgibbs KASSERT(VOP_ISLOCKED(vp), ("vp %p is not locked", vp)); 338214077Sgibbs KASSERT(vp->v_type == VDIR, ("vp %p is not a directory", vp)); 339214077Sgibbs 340223059Sgibbs found = 0; 341214077Sgibbs 342223059Sgibbs error = VOP_GETATTR(vp, &va, td->td_ucred); 343214077Sgibbs if (error) 344214077Sgibbs return (found); 345223059Sgibbs 346214077Sgibbs dirbuflen = DEV_BSIZE; 347223059Sgibbs if (dirbuflen < va.va_blocksize) 348214077Sgibbs dirbuflen = va.va_blocksize; 349214077Sgibbs dirbuf = (char *)malloc(dirbuflen, M_TEMP, M_WAITOK); 350214077Sgibbs 351214077Sgibbs off = 0; 352214077Sgibbs len = 0; 353214077Sgibbs do { 354214077Sgibbs error = get_next_dirent(vp, &dp, dirbuf, dirbuflen, &off, 355223059Sgibbs &cpos, &len, &eofflag, td); 356214077Sgibbs if (error) 357223059Sgibbs goto out; 358181643Skmacy 359214077Sgibbs if (dp->d_type != DT_WHT && dp->d_fileno != 0 && 360181643Skmacy strcmp(dp->d_name, dirname) == 0) { 361214077Sgibbs found = 1; 362214077Sgibbs goto out; 363214077Sgibbs } 364214077Sgibbs } while (len > 0 || !eofflag); 365214077Sgibbs 366214077Sgibbsout: 367214077Sgibbs free(dirbuf, M_TEMP); 368214077Sgibbs return (found); 369181643Skmacy} 370214077Sgibbs 371214077Sgibbsint 372181643Skmacyvop_stdaccess(struct vop_access_args *ap) 373214077Sgibbs{ 374214077Sgibbs 375214077Sgibbs KASSERT((ap->a_accmode & ~(VEXEC | VWRITE | VREAD | VADMIN | 376214077Sgibbs VAPPEND)) == 0, ("invalid bit in accmode")); 377214077Sgibbs 378214077Sgibbs return (VOP_ACCESSX(ap->a_vp, ap->a_accmode, ap->a_cred, ap->a_td)); 379181643Skmacy} 380214077Sgibbs 381214077Sgibbsint 382214077Sgibbsvop_stdaccessx(struct vop_accessx_args *ap) 383214077Sgibbs{ 384214077Sgibbs int error; 385214077Sgibbs accmode_t accmode = ap->a_accmode; 386181643Skmacy 387214077Sgibbs error = vfs_unixify_accmode(&accmode); 388214077Sgibbs if (error != 0) 389181643Skmacy return (error); 390214077Sgibbs 391214077Sgibbs if (accmode == 0) 392214077Sgibbs return (0); 393214077Sgibbs 394214077Sgibbs return (VOP_ACCESS(ap->a_vp, accmode, ap->a_cred, ap->a_td)); 395214077Sgibbs} 396181643Skmacy 397214077Sgibbs/* 398214077Sgibbs * Advisory record locking support 399214077Sgibbs */ 400181643Skmacyint 401214077Sgibbsvop_stdadvlock(struct vop_advlock_args *ap) 402214077Sgibbs{ 403214077Sgibbs struct vnode *vp; 404214077Sgibbs struct vattr vattr; 405214077Sgibbs int error; 406214077Sgibbs 407214077Sgibbs vp = ap->a_vp; 408214077Sgibbs if (ap->a_fl->l_whence == SEEK_END) { 409214077Sgibbs /* 410214077Sgibbs * The NFSv4 server must avoid doing a vn_lock() here, since it 411214077Sgibbs * can deadlock the nfsd threads, due to a LOR. Fortunately 412214077Sgibbs * the NFSv4 server always uses SEEK_SET and this code is 413214077Sgibbs * only required for the SEEK_END case. 414214077Sgibbs */ 415214077Sgibbs vn_lock(vp, LK_SHARED | LK_RETRY); 416214077Sgibbs error = VOP_GETATTR(vp, &vattr, curthread->td_ucred); 417214077Sgibbs VOP_UNLOCK(vp, 0); 418214077Sgibbs if (error) 419214077Sgibbs return (error); 420214077Sgibbs } else 421214077Sgibbs vattr.va_size = 0; 422223059Sgibbs 423223059Sgibbs return (lf_advlock(ap, &(vp->v_lockf), vattr.va_size)); 424223059Sgibbs} 425223059Sgibbs 426214077Sgibbsint 427214077Sgibbsvop_stdadvlockasync(struct vop_advlockasync_args *ap) 428214077Sgibbs{ 429214077Sgibbs struct vnode *vp; 430214077Sgibbs struct vattr vattr; 431214077Sgibbs int error; 432214077Sgibbs 433214077Sgibbs vp = ap->a_vp; 434214077Sgibbs if (ap->a_fl->l_whence == SEEK_END) { 435214077Sgibbs /* The size argument is only needed for SEEK_END. */ 436214077Sgibbs vn_lock(vp, LK_SHARED | LK_RETRY); 437214077Sgibbs error = VOP_GETATTR(vp, &vattr, curthread->td_ucred); 438214077Sgibbs VOP_UNLOCK(vp, 0); 439214077Sgibbs if (error) 440214077Sgibbs return (error); 441214077Sgibbs } else 442214077Sgibbs vattr.va_size = 0; 443214077Sgibbs 444214077Sgibbs return (lf_advlockasync(ap, &(vp->v_lockf), vattr.va_size)); 445214077Sgibbs} 446214077Sgibbs 447214077Sgibbsint 448214077Sgibbsvop_stdadvlockpurge(struct vop_advlockpurge_args *ap) 449214077Sgibbs{ 450214077Sgibbs struct vnode *vp; 451214077Sgibbs 452214077Sgibbs vp = ap->a_vp; 453214077Sgibbs lf_purgelocks(vp, &vp->v_lockf); 454214077Sgibbs return (0); 455214077Sgibbs} 456214077Sgibbs 457214077Sgibbs/* 458214077Sgibbs * vop_stdpathconf: 459214077Sgibbs * 460214077Sgibbs * Standard implementation of POSIX pathconf, to get information about limits 461214077Sgibbs * for a filesystem. 462214077Sgibbs * Override per filesystem for the case where the filesystem has smaller 463214077Sgibbs * limits. 464214077Sgibbs */ 465214077Sgibbsint 466214077Sgibbsvop_stdpathconf(ap) 467214077Sgibbs struct vop_pathconf_args /* { 468214077Sgibbs struct vnode *a_vp; 469214077Sgibbs int a_name; 470214077Sgibbs int *a_retval; 471214077Sgibbs } */ *ap; 472214077Sgibbs{ 473214077Sgibbs 474214077Sgibbs switch (ap->a_name) { 475214077Sgibbs case _PC_NAME_MAX: 476214077Sgibbs *ap->a_retval = NAME_MAX; 477214077Sgibbs return (0); 478214077Sgibbs case _PC_PATH_MAX: 479214077Sgibbs *ap->a_retval = PATH_MAX; 480214077Sgibbs return (0); 481214077Sgibbs case _PC_LINK_MAX: 482214077Sgibbs *ap->a_retval = LINK_MAX; 483214077Sgibbs return (0); 484181643Skmacy case _PC_MAX_CANON: 485181643Skmacy *ap->a_retval = MAX_CANON; 486214077Sgibbs return (0); 487214077Sgibbs case _PC_MAX_INPUT: 488214077Sgibbs *ap->a_retval = MAX_INPUT; 489181643Skmacy return (0); 490214077Sgibbs case _PC_PIPE_BUF: 491214077Sgibbs *ap->a_retval = PIPE_BUF; 492214077Sgibbs return (0); 493214077Sgibbs case _PC_CHOWN_RESTRICTED: 494214077Sgibbs *ap->a_retval = 1; 495214077Sgibbs return (0); 496181643Skmacy case _PC_VDISABLE: 497214077Sgibbs *ap->a_retval = _POSIX_VDISABLE; 498214077Sgibbs return (0); 499214077Sgibbs default: 500214077Sgibbs return (EINVAL); 501214077Sgibbs } 502214077Sgibbs /* NOTREACHED */ 503223059Sgibbs} 504214077Sgibbs 505181643Skmacy/* 506214077Sgibbs * Standard lock, unlock and islocked functions. 507214077Sgibbs */ 508214077Sgibbsint 509214077Sgibbsvop_stdlock(ap) 510214077Sgibbs struct vop_lock1_args /* { 511214077Sgibbs struct vnode *a_vp; 512214077Sgibbs int a_flags; 513214077Sgibbs char *file; 514214077Sgibbs int line; 515223059Sgibbs } */ *ap; 516214077Sgibbs{ 517214077Sgibbs struct vnode *vp = ap->a_vp; 518214077Sgibbs 519214077Sgibbs return (_lockmgr_args(vp->v_vnlock, ap->a_flags, VI_MTX(vp), 520214077Sgibbs LK_WMESG_DEFAULT, LK_PRIO_DEFAULT, LK_TIMO_DEFAULT, ap->a_file, 521214077Sgibbs ap->a_line)); 522214077Sgibbs} 523214077Sgibbs 524214077Sgibbs/* See above. */ 525214077Sgibbsint 526223059Sgibbsvop_stdunlock(ap) 527214077Sgibbs struct vop_unlock_args /* { 528214077Sgibbs struct vnode *a_vp; 529214077Sgibbs int a_flags; 530214077Sgibbs } */ *ap; 531214077Sgibbs{ 532181643Skmacy struct vnode *vp = ap->a_vp; 533214077Sgibbs 534214077Sgibbs return (lockmgr(vp->v_vnlock, ap->a_flags | LK_RELEASE, VI_MTX(vp))); 535214077Sgibbs} 536214077Sgibbs 537181643Skmacy/* See above. */ 538214077Sgibbsint 539214077Sgibbsvop_stdislocked(ap) 540214077Sgibbs struct vop_islocked_args /* { 541223059Sgibbs struct vnode *a_vp; 542223059Sgibbs } */ *ap; 543223059Sgibbs{ 544181643Skmacy 545214077Sgibbs return (lockstatus(ap->a_vp->v_vnlock)); 546214077Sgibbs} 547181643Skmacy 548214077Sgibbs/* 549181643Skmacy * Return true for select/poll. 550214077Sgibbs */ 551214077Sgibbsint 552214077Sgibbsvop_nopoll(ap) 553214077Sgibbs struct vop_poll_args /* { 554181643Skmacy struct vnode *a_vp; 555214077Sgibbs int a_events; 556214077Sgibbs struct ucred *a_cred; 557214077Sgibbs struct thread *a_td; 558214077Sgibbs } */ *ap; 559214077Sgibbs{ 560181643Skmacy 561214077Sgibbs return (poll_no_poll(ap->a_events)); 562214077Sgibbs} 563181643Skmacy 564214077Sgibbs/* 565214077Sgibbs * Implement poll for local filesystems that support it. 566181643Skmacy */ 567214077Sgibbsint 568214077Sgibbsvop_stdpoll(ap) 569181643Skmacy struct vop_poll_args /* { 570214077Sgibbs struct vnode *a_vp; 571223059Sgibbs int a_events; 572181643Skmacy struct ucred *a_cred; 573214077Sgibbs struct thread *a_td; 574223059Sgibbs } */ *ap; 575181643Skmacy{ 576214077Sgibbs if (ap->a_events & ~POLLSTANDARD) 577214077Sgibbs return (vn_pollrecord(ap->a_vp, ap->a_td, ap->a_events)); 578181643Skmacy return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)); 579223059Sgibbs} 580223059Sgibbs 581223059Sgibbs/* 582223059Sgibbs * Return our mount point, as we will take charge of the writes. 583223059Sgibbs */ 584223059Sgibbsint 585223059Sgibbsvop_stdgetwritemount(ap) 586223059Sgibbs struct vop_getwritemount_args /* { 587223059Sgibbs struct vnode *a_vp; 588214077Sgibbs struct mount **a_mpp; 589214077Sgibbs } */ *ap; 590214077Sgibbs{ 591214077Sgibbs struct mount *mp; 592214077Sgibbs 593181643Skmacy /* 594214077Sgibbs * XXX Since this is called unlocked we may be recycled while 595214077Sgibbs * attempting to ref the mount. If this is the case or mountpoint 596181643Skmacy * will be set to NULL. We only have to prevent this call from 597214077Sgibbs * returning with a ref to an incorrect mountpoint. It is not 598214077Sgibbs * harmful to return with a ref to our previous mountpoint. 599181643Skmacy */ 600223059Sgibbs mp = ap->a_vp->v_mount; 601223059Sgibbs if (mp != NULL) { 602223059Sgibbs vfs_ref(mp); 603223059Sgibbs if (mp != ap->a_vp->v_mount) { 604223059Sgibbs vfs_rel(mp); 605223059Sgibbs mp = NULL; 606223059Sgibbs } 607223059Sgibbs } 608223059Sgibbs *(ap->a_mpp) = mp; 609214077Sgibbs return (0); 610214077Sgibbs} 611214077Sgibbs 612214077Sgibbs/* XXX Needs good comment and VOP_BMAP(9) manpage */ 613214077Sgibbsint 614214077Sgibbsvop_stdbmap(ap) 615214077Sgibbs struct vop_bmap_args /* { 616214077Sgibbs struct vnode *a_vp; 617181643Skmacy daddr_t a_bn; 618214077Sgibbs struct bufobj **a_bop; 619214077Sgibbs daddr_t *a_bnp; 620214077Sgibbs int *a_runp; 621214077Sgibbs int *a_runb; 622214077Sgibbs } */ *ap; 623214077Sgibbs{ 624214077Sgibbs 625214077Sgibbs if (ap->a_bop != NULL) 626214077Sgibbs *ap->a_bop = &ap->a_vp->v_bufobj; 627214077Sgibbs if (ap->a_bnp != NULL) 628181643Skmacy *ap->a_bnp = ap->a_bn * btodb(ap->a_vp->v_mount->mnt_stat.f_iosize); 629214077Sgibbs if (ap->a_runp != NULL) 630223059Sgibbs *ap->a_runp = 0; 631223059Sgibbs if (ap->a_runb != NULL) 632214077Sgibbs *ap->a_runb = 0; 633214077Sgibbs return (0); 634214077Sgibbs} 635223059Sgibbs 636181643Skmacyint 637214077Sgibbsvop_stdfsync(ap) 638214077Sgibbs struct vop_fsync_args /* { 639214077Sgibbs struct vnode *a_vp; 640214077Sgibbs struct ucred *a_cred; 641214077Sgibbs int a_waitfor; 642214077Sgibbs struct thread *a_td; 643223059Sgibbs } */ *ap; 644181643Skmacy{ 645214077Sgibbs struct vnode *vp = ap->a_vp; 646223059Sgibbs struct buf *bp; 647223059Sgibbs struct bufobj *bo; 648223059Sgibbs struct buf *nbp; 649223059Sgibbs int error = 0; 650223059Sgibbs int maxretry = 1000; /* large, arbitrarily chosen */ 651223059Sgibbs 652223059Sgibbs bo = &vp->v_bufobj; 653223059Sgibbs BO_LOCK(bo); 654214077Sgibbsloop1: 655214077Sgibbs /* 656214077Sgibbs * MARK/SCAN initialization to avoid infinite loops. 657214077Sgibbs */ 658214077Sgibbs TAILQ_FOREACH(bp, &bo->bo_dirty.bv_hd, b_bobufs) { 659223059Sgibbs bp->b_vflags &= ~BV_SCANNED; 660181643Skmacy bp->b_error = 0; 661223059Sgibbs } 662223059Sgibbs 663223059Sgibbs /* 664223059Sgibbs * Flush all dirty buffers associated with a vnode. 665223059Sgibbs */ 666223059Sgibbsloop2: 667214077Sgibbs TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) { 668214077Sgibbs if ((bp->b_vflags & BV_SCANNED) != 0) 669181643Skmacy continue; 670214077Sgibbs bp->b_vflags |= BV_SCANNED; 671214077Sgibbs if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) { 672181643Skmacy if (ap->a_waitfor != MNT_WAIT) 673214077Sgibbs continue; 674214077Sgibbs if (BUF_LOCK(bp, 675181643Skmacy LK_EXCLUSIVE | LK_INTERLOCK | LK_SLEEPFAIL, 676214077Sgibbs BO_LOCKPTR(bo)) != 0) { 677255040Sgibbs BO_LOCK(bo); 678181643Skmacy goto loop1; 679214077Sgibbs } 680214077Sgibbs BO_LOCK(bo); 681214077Sgibbs } 682214077Sgibbs BO_UNLOCK(bo); 683214077Sgibbs KASSERT(bp->b_bufobj == bo, 684214077Sgibbs ("bp %p wrong b_bufobj %p should be %p", 685181643Skmacy bp, bp->b_bufobj, bo)); 686214077Sgibbs if ((bp->b_flags & B_DELWRI) == 0) 687214077Sgibbs panic("fsync: not dirty"); 688214077Sgibbs if ((vp->v_object != NULL) && (bp->b_flags & B_CLUSTEROK)) { 689214077Sgibbs vfs_bio_awrite(bp); 690214077Sgibbs } else { 691214077Sgibbs bremfree(bp); 692214077Sgibbs bawrite(bp); 693181643Skmacy } 694214077Sgibbs BO_LOCK(bo); 695214077Sgibbs goto loop2; 696214077Sgibbs } 697214077Sgibbs 698214077Sgibbs /* 699214077Sgibbs * If synchronous the caller expects us to completely resolve all 700214077Sgibbs * dirty buffers in the system. Wait for in-progress I/O to 701214077Sgibbs * complete (which could include background bitmap writes), then 702181643Skmacy * retry if dirty blocks still exist. 703214077Sgibbs */ 704214077Sgibbs if (ap->a_waitfor == MNT_WAIT) { 705214077Sgibbs bufobj_wwait(bo, 0, 0); 706214077Sgibbs if (bo->bo_dirty.bv_cnt > 0) { 707214077Sgibbs /* 708181643Skmacy * If we are unable to write any of these buffers 709214077Sgibbs * then we fail now rather than trying endlessly 710223059Sgibbs * to write them out. 711214077Sgibbs */ 712214077Sgibbs TAILQ_FOREACH(bp, &bo->bo_dirty.bv_hd, b_bobufs) 713181643Skmacy if ((error = bp->b_error) == 0) 714214077Sgibbs continue; 715214077Sgibbs if (error == 0 && --maxretry >= 0) 716181643Skmacy goto loop1; 717214077Sgibbs error = EAGAIN; 718214077Sgibbs } 719214077Sgibbs } 720214077Sgibbs BO_UNLOCK(bo); 721214077Sgibbs if (error == EAGAIN) 722214077Sgibbs vprint("fsync: giving up on dirty", vp); 723214077Sgibbs 724214077Sgibbs return (error); 725214077Sgibbs} 726214077Sgibbs 727214077Sgibbs/* XXX Needs good comment and more info in the manpage (VOP_GETPAGES(9)). */ 728214077Sgibbsint 729214077Sgibbsvop_stdgetpages(ap) 730214077Sgibbs struct vop_getpages_args /* { 731214077Sgibbs struct vnode *a_vp; 732214077Sgibbs vm_page_t *a_m; 733214077Sgibbs int a_count; 734214077Sgibbs int a_reqpage; 735223059Sgibbs } */ *ap; 736214077Sgibbs{ 737223059Sgibbs 738223059Sgibbs return vnode_pager_generic_getpages(ap->a_vp, ap->a_m, 739223059Sgibbs ap->a_count, ap->a_reqpage, NULL, NULL); 740223059Sgibbs} 741223059Sgibbs 742223059Sgibbsstatic int 743223059Sgibbsvop_stdgetpages_async(struct vop_getpages_async_args *ap) 744214077Sgibbs{ 745214077Sgibbs int error; 746214077Sgibbs 747214077Sgibbs error = VOP_GETPAGES(ap->a_vp, ap->a_m, ap->a_count, ap->a_reqpage); 748214077Sgibbs ap->a_iodone(ap->a_arg, ap->a_m, ap->a_reqpage, error); 749214077Sgibbs return (error); 750214077Sgibbs} 751214077Sgibbs 752214077Sgibbsint 753214077Sgibbsvop_stdkqfilter(struct vop_kqfilter_args *ap) 754214077Sgibbs{ 755214077Sgibbs return vfs_kqfilter(ap); 756214077Sgibbs} 757214077Sgibbs 758223059Sgibbs/* XXX Needs good comment and more info in the manpage (VOP_PUTPAGES(9)). */ 759223059Sgibbsint 760223059Sgibbsvop_stdputpages(ap) 761223059Sgibbs struct vop_putpages_args /* { 762214077Sgibbs struct vnode *a_vp; 763223059Sgibbs vm_page_t *a_m; 764223059Sgibbs int a_count; 765223059Sgibbs int a_sync; 766223059Sgibbs int *a_rtvals; 767223059Sgibbs } */ *ap; 768223059Sgibbs{ 769223059Sgibbs 770223059Sgibbs return vnode_pager_generic_putpages(ap->a_vp, ap->a_m, ap->a_count, 771223059Sgibbs ap->a_sync, ap->a_rtvals); 772223059Sgibbs} 773223059Sgibbs 774223059Sgibbsint 775223059Sgibbsvop_stdvptofh(struct vop_vptofh_args *ap) 776223059Sgibbs{ 777223059Sgibbs return (EOPNOTSUPP); 778223059Sgibbs} 779223059Sgibbs 780223059Sgibbsint 781223059Sgibbsvop_stdvptocnp(struct vop_vptocnp_args *ap) 782223059Sgibbs{ 783223059Sgibbs struct vnode *vp = ap->a_vp; 784223059Sgibbs struct vnode **dvp = ap->a_vpp; 785223059Sgibbs struct ucred *cred = ap->a_cred; 786223059Sgibbs char *buf = ap->a_buf; 787223059Sgibbs int *buflen = ap->a_buflen; 788223059Sgibbs char *dirbuf, *cpos; 789223059Sgibbs int i, error, eofflag, dirbuflen, flags, locked, len, covered; 790223059Sgibbs off_t off; 791223059Sgibbs ino_t fileno; 792223059Sgibbs struct vattr va; 793223059Sgibbs struct nameidata nd; 794223059Sgibbs struct thread *td; 795223059Sgibbs struct dirent *dp; 796223059Sgibbs struct vnode *mvp; 797223059Sgibbs 798223059Sgibbs i = *buflen; 799223059Sgibbs error = 0; 800223059Sgibbs covered = 0; 801223059Sgibbs td = curthread; 802223059Sgibbs 803214077Sgibbs if (vp->v_type != VDIR) 804214077Sgibbs return (ENOENT); 805214077Sgibbs 806214077Sgibbs error = VOP_GETATTR(vp, &va, cred); 807214077Sgibbs if (error) 808214077Sgibbs return (error); 809214077Sgibbs 810214077Sgibbs VREF(vp); 811214077Sgibbs locked = VOP_ISLOCKED(vp); 812214077Sgibbs VOP_UNLOCK(vp, 0); 813214077Sgibbs NDINIT_ATVP(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF, UIO_SYSSPACE, 814214077Sgibbs "..", vp, td); 815214077Sgibbs flags = FREAD; 816181643Skmacy error = vn_open_cred(&nd, &flags, 0, VN_OPEN_NOAUDIT, cred, NULL); 817214077Sgibbs if (error) { 818181643Skmacy vn_lock(vp, locked | LK_RETRY); 819214077Sgibbs return (error); 820214077Sgibbs } 821223059Sgibbs NDFREE(&nd, NDF_ONLY_PNBUF); 822223059Sgibbs 823223059Sgibbs mvp = *dvp = nd.ni_vp; 824223059Sgibbs 825223059Sgibbs if (vp->v_mount != (*dvp)->v_mount && 826181643Skmacy ((*dvp)->v_vflag & VV_ROOT) && 827223059Sgibbs ((*dvp)->v_mount->mnt_flag & MNT_UNION)) { 828214077Sgibbs *dvp = (*dvp)->v_mount->mnt_vnodecovered; 829181643Skmacy VREF(mvp); 830181643Skmacy VOP_UNLOCK(mvp, 0); 831214077Sgibbs vn_close(mvp, FREAD, cred, td); 832214077Sgibbs VREF(*dvp); 833214077Sgibbs vn_lock(*dvp, LK_SHARED | LK_RETRY); 834214077Sgibbs covered = 1; 835214077Sgibbs } 836214077Sgibbs 837214077Sgibbs fileno = va.va_fileid; 838214077Sgibbs 839181643Skmacy dirbuflen = DEV_BSIZE; 840223059Sgibbs if (dirbuflen < va.va_blocksize) 841181643Skmacy dirbuflen = va.va_blocksize; 842223059Sgibbs dirbuf = (char *)malloc(dirbuflen, M_TEMP, M_WAITOK); 843214077Sgibbs 844181643Skmacy if ((*dvp)->v_type != VDIR) { 845223059Sgibbs error = ENOENT; 846223059Sgibbs goto out; 847223059Sgibbs } 848181643Skmacy 849223059Sgibbs off = 0; 850223059Sgibbs len = 0; 851223059Sgibbs do { 852223059Sgibbs /* call VOP_READDIR of parent */ 853223059Sgibbs error = get_next_dirent(*dvp, &dp, dirbuf, dirbuflen, &off, 854223059Sgibbs &cpos, &len, &eofflag, td); 855223059Sgibbs if (error) 856223059Sgibbs goto out; 857223059Sgibbs 858223059Sgibbs if ((dp->d_type != DT_WHT) && 859223059Sgibbs (dp->d_fileno == fileno)) { 860223059Sgibbs if (covered) { 861223059Sgibbs VOP_UNLOCK(*dvp, 0); 862223059Sgibbs vn_lock(mvp, LK_SHARED | LK_RETRY); 863223059Sgibbs if (dirent_exists(mvp, dp->d_name, td)) { 864223059Sgibbs error = ENOENT; 865223059Sgibbs VOP_UNLOCK(mvp, 0); 866223059Sgibbs vn_lock(*dvp, LK_SHARED | LK_RETRY); 867214077Sgibbs goto out; 868181643Skmacy } 869214077Sgibbs VOP_UNLOCK(mvp, 0); 870214077Sgibbs vn_lock(*dvp, LK_SHARED | LK_RETRY); 871214077Sgibbs } 872214077Sgibbs i -= dp->d_namlen; 873223059Sgibbs 874214077Sgibbs if (i < 0) { 875214077Sgibbs error = ENOMEM; 876214077Sgibbs goto out; 877214077Sgibbs } 878214077Sgibbs if (dp->d_namlen == 1 && dp->d_name[0] == '.') { 879214077Sgibbs error = ENOENT; 880214077Sgibbs } else { 881223059Sgibbs bcopy(dp->d_name, buf + i, dp->d_namlen); 882214077Sgibbs error = 0; 883223059Sgibbs } 884214077Sgibbs goto out; 885181643Skmacy } 886214077Sgibbs } while (len > 0 || !eofflag); 887214077Sgibbs error = ENOENT; 888214077Sgibbs 889214077Sgibbsout: 890214077Sgibbs free(dirbuf, M_TEMP); 891223059Sgibbs if (!error) { 892214077Sgibbs *buflen = i; 893214077Sgibbs vref(*dvp); 894214077Sgibbs } 895214077Sgibbs if (covered) { 896214077Sgibbs vput(*dvp); 897214077Sgibbs vrele(mvp); 898214077Sgibbs } else { 899223059Sgibbs VOP_UNLOCK(mvp, 0); 900214077Sgibbs vn_close(mvp, FREAD, cred, td); 901223059Sgibbs } 902181643Skmacy vn_lock(vp, locked | LK_RETRY); 903214077Sgibbs return (error); 904181643Skmacy} 905214077Sgibbs 906214077Sgibbsint 907214077Sgibbsvop_stdallocate(struct vop_allocate_args *ap) 908214077Sgibbs{ 909214077Sgibbs#ifdef __notyet__ 910223059Sgibbs struct statfs sfs; 911214077Sgibbs#endif 912214077Sgibbs struct iovec aiov; 913214077Sgibbs struct vattr vattr, *vap; 914214077Sgibbs struct uio auio; 915214077Sgibbs off_t fsize, len, cur, offset; 916214077Sgibbs uint8_t *buf; 917214077Sgibbs struct thread *td; 918214077Sgibbs struct vnode *vp; 919214077Sgibbs size_t iosize; 920214077Sgibbs int error; 921214077Sgibbs 922223059Sgibbs buf = NULL; 923181643Skmacy error = 0; 924214077Sgibbs td = curthread; 925223059Sgibbs vap = &vattr; 926214077Sgibbs vp = ap->a_vp; 927223059Sgibbs len = *ap->a_len; 928214077Sgibbs offset = *ap->a_offset; 929181643Skmacy 930181643Skmacy error = VOP_GETATTR(vp, vap, td->td_ucred); 931214077Sgibbs if (error != 0) 932214077Sgibbs goto out; 933214077Sgibbs fsize = vap->va_size; 934214077Sgibbs iosize = vap->va_blocksize; 935214077Sgibbs if (iosize == 0) 936223059Sgibbs iosize = BLKDEV_IOSIZE; 937214077Sgibbs if (iosize > MAXPHYS) 938214077Sgibbs iosize = MAXPHYS; 939214077Sgibbs buf = malloc(iosize, M_TEMP, M_WAITOK); 940214077Sgibbs 941214077Sgibbs#ifdef __notyet__ 942214077Sgibbs /* 943214077Sgibbs * Check if the filesystem sets f_maxfilesize; if not use 944214077Sgibbs * VOP_SETATTR to perform the check. 945214077Sgibbs */ 946214077Sgibbs error = VFS_STATFS(vp->v_mount, &sfs, td); 947214077Sgibbs if (error != 0) 948214077Sgibbs goto out; 949223059Sgibbs if (sfs.f_maxfilesize) { 950181643Skmacy if (offset > sfs.f_maxfilesize || len > sfs.f_maxfilesize || 951223059Sgibbs offset + len > sfs.f_maxfilesize) { 952223059Sgibbs error = EFBIG; 953223059Sgibbs goto out; 954223059Sgibbs } 955223059Sgibbs } else 956223059Sgibbs#endif 957223059Sgibbs if (offset + len > vap->va_size) { 958181643Skmacy /* 959181643Skmacy * Test offset + len against the filesystem's maxfilesize. 960214077Sgibbs */ 961223059Sgibbs VATTR_NULL(vap); 962223059Sgibbs vap->va_size = offset + len; 963223059Sgibbs error = VOP_SETATTR(vp, vap, td->td_ucred); 964223059Sgibbs if (error != 0) 965223059Sgibbs goto out; 966223059Sgibbs VATTR_NULL(vap); 967223059Sgibbs vap->va_size = fsize; 968223059Sgibbs error = VOP_SETATTR(vp, vap, td->td_ucred); 969223059Sgibbs if (error != 0) 970223059Sgibbs goto out; 971223059Sgibbs } 972223059Sgibbs 973223059Sgibbs for (;;) { 974223059Sgibbs /* 975223059Sgibbs * Read and write back anything below the nominal file 976223059Sgibbs * size. There's currently no way outside the filesystem 977223059Sgibbs * to know whether this area is sparse or not. 978231743Sgibbs */ 979231743Sgibbs cur = iosize; 980223059Sgibbs if ((offset % iosize) != 0) 981231743Sgibbs cur -= (offset % iosize); 982223059Sgibbs if (cur > len) 983223059Sgibbs cur = len; 984223059Sgibbs if (offset < fsize) { 985223059Sgibbs aiov.iov_base = buf; 986223059Sgibbs aiov.iov_len = cur; 987223059Sgibbs auio.uio_iov = &aiov; 988223059Sgibbs auio.uio_iovcnt = 1; 989223059Sgibbs auio.uio_offset = offset; 990223059Sgibbs auio.uio_resid = cur; 991223059Sgibbs auio.uio_segflg = UIO_SYSSPACE; 992223059Sgibbs auio.uio_rw = UIO_READ; 993223059Sgibbs auio.uio_td = td; 994223059Sgibbs error = VOP_READ(vp, &auio, 0, td->td_ucred); 995223059Sgibbs if (error != 0) 996223059Sgibbs break; 997223059Sgibbs if (auio.uio_resid > 0) { 998223059Sgibbs bzero(buf + cur - auio.uio_resid, 999223059Sgibbs auio.uio_resid); 1000223059Sgibbs } 1001223059Sgibbs } else { 1002223059Sgibbs bzero(buf, cur); 1003223059Sgibbs } 1004223059Sgibbs 1005223059Sgibbs aiov.iov_base = buf; 1006223059Sgibbs aiov.iov_len = cur; 1007223059Sgibbs auio.uio_iov = &aiov; 1008223059Sgibbs auio.uio_iovcnt = 1; 1009223059Sgibbs auio.uio_offset = offset; 1010223059Sgibbs auio.uio_resid = cur; 1011223059Sgibbs auio.uio_segflg = UIO_SYSSPACE; 1012223059Sgibbs auio.uio_rw = UIO_WRITE; 1013223059Sgibbs auio.uio_td = td; 1014223059Sgibbs 1015223059Sgibbs error = VOP_WRITE(vp, &auio, 0, td->td_ucred); 1016223059Sgibbs if (error != 0) 1017223059Sgibbs break; 1018223059Sgibbs 1019223059Sgibbs len -= cur; 1020223059Sgibbs offset += cur; 1021223059Sgibbs if (len == 0) 1022223059Sgibbs break; 1023223059Sgibbs if (should_yield()) 1024223059Sgibbs break; 1025223059Sgibbs } 1026223059Sgibbs 1027223059Sgibbs out: 1028223059Sgibbs *ap->a_len = len; 1029223059Sgibbs *ap->a_offset = offset; 1030223059Sgibbs free(buf, M_TEMP); 1031223059Sgibbs return (error); 1032223059Sgibbs} 1033223059Sgibbs 1034223059Sgibbsint 1035223059Sgibbsvop_stdadvise(struct vop_advise_args *ap) 1036223059Sgibbs{ 1037223059Sgibbs struct vnode *vp; 1038223059Sgibbs off_t start, end; 1039223059Sgibbs int error; 1040223059Sgibbs 1041223059Sgibbs vp = ap->a_vp; 1042223059Sgibbs switch (ap->a_advice) { 1043223059Sgibbs case POSIX_FADV_WILLNEED: 1044223059Sgibbs /* 1045223059Sgibbs * Do nothing for now. Filesystems should provide a 1046223059Sgibbs * custom method which starts an asynchronous read of 1047223059Sgibbs * the requested region. 1048223059Sgibbs */ 1049223059Sgibbs error = 0; 1050223059Sgibbs break; 1051223059Sgibbs case POSIX_FADV_DONTNEED: 1052223059Sgibbs /* 1053223059Sgibbs * Flush any open FS buffers and then remove pages 1054223059Sgibbs * from the backing VM object. Using vinvalbuf() here 1055223059Sgibbs * is a bit heavy-handed as it flushes all buffers for 1056223059Sgibbs * the given vnode, not just the buffers covering the 1057223059Sgibbs * requested range. 1058223059Sgibbs */ 1059223059Sgibbs error = 0; 1060223059Sgibbs vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 1061223059Sgibbs if (vp->v_iflag & VI_DOOMED) { 1062223059Sgibbs VOP_UNLOCK(vp, 0); 1063223059Sgibbs break; 1064223059Sgibbs } 1065223059Sgibbs vinvalbuf(vp, V_CLEANONLY, 0, 0); 1066223059Sgibbs if (vp->v_object != NULL) { 1067223059Sgibbs start = trunc_page(ap->a_start); 1068223059Sgibbs end = round_page(ap->a_end); 1069223059Sgibbs VM_OBJECT_WLOCK(vp->v_object); 1070223059Sgibbs vm_object_page_cache(vp->v_object, OFF_TO_IDX(start), 1071223059Sgibbs OFF_TO_IDX(end)); 1072223059Sgibbs VM_OBJECT_WUNLOCK(vp->v_object); 1073214077Sgibbs } 1074214077Sgibbs VOP_UNLOCK(vp, 0); 1075214077Sgibbs break; 1076214077Sgibbs default: 1077214077Sgibbs error = EINVAL; 1078223059Sgibbs break; 1079181643Skmacy } 1080223059Sgibbs return (error); 1081214077Sgibbs} 1082214077Sgibbs 1083214077Sgibbsint 1084181643Skmacyvop_stdunp_bind(struct vop_unp_bind_args *ap) 1085214077Sgibbs{ 1086223059Sgibbs 1087181643Skmacy ap->a_vp->v_socket = ap->a_socket; 1088223059Sgibbs return (0); 1089214077Sgibbs} 1090214077Sgibbs 1091223059Sgibbsint 1092214077Sgibbsvop_stdunp_connect(struct vop_unp_connect_args *ap) 1093223059Sgibbs{ 1094223059Sgibbs 1095214077Sgibbs *ap->a_socket = ap->a_vp->v_socket; 1096181643Skmacy return (0); 1097181643Skmacy} 1098214077Sgibbs 1099214077Sgibbsint 1100214077Sgibbsvop_stdunp_detach(struct vop_unp_detach_args *ap) 1101181643Skmacy{ 1102181643Skmacy 1103214077Sgibbs ap->a_vp->v_socket = NULL; 1104223059Sgibbs return (0); 1105223059Sgibbs} 1106223059Sgibbs 1107223059Sgibbsstatic int 1108223059Sgibbsvop_stdis_text(struct vop_is_text_args *ap) 1109223059Sgibbs{ 1110223059Sgibbs 1111223059Sgibbs return ((ap->a_vp->v_vflag & VV_TEXT) != 0); 1112223059Sgibbs} 1113223059Sgibbs 1114223059Sgibbsstatic int 1115223059Sgibbsvop_stdset_text(struct vop_set_text_args *ap) 1116223059Sgibbs{ 1117223059Sgibbs 1118223059Sgibbs ap->a_vp->v_vflag |= VV_TEXT; 1119223059Sgibbs return (0); 1120223059Sgibbs} 1121223059Sgibbs 1122223059Sgibbsstatic int 1123223059Sgibbsvop_stdunset_text(struct vop_unset_text_args *ap) 1124223059Sgibbs{ 1125223059Sgibbs 1126223059Sgibbs ap->a_vp->v_vflag &= ~VV_TEXT; 1127223059Sgibbs return (0); 1128223059Sgibbs} 1129223059Sgibbs 1130223059Sgibbsstatic int 1131223059Sgibbsvop_stdget_writecount(struct vop_get_writecount_args *ap) 1132223059Sgibbs{ 1133223059Sgibbs 1134223059Sgibbs *ap->a_writecount = ap->a_vp->v_writecount; 1135223059Sgibbs return (0); 1136223059Sgibbs} 1137223059Sgibbs 1138223059Sgibbsstatic int 1139223059Sgibbsvop_stdadd_writecount(struct vop_add_writecount_args *ap) 1140223059Sgibbs{ 1141223059Sgibbs 1142223059Sgibbs ap->a_vp->v_writecount += ap->a_inc; 1143223059Sgibbs return (0); 1144223059Sgibbs} 1145223059Sgibbs 1146223059Sgibbs/* 1147223059Sgibbs * vfs default ops 1148223059Sgibbs * used to fill the vfs function table to get reasonable default return values. 1149223059Sgibbs */ 1150223059Sgibbsint 1151223059Sgibbsvfs_stdroot (mp, flags, vpp) 1152223059Sgibbs struct mount *mp; 1153223059Sgibbs int flags; 1154223059Sgibbs struct vnode **vpp; 1155223059Sgibbs{ 1156223059Sgibbs 1157223059Sgibbs return (EOPNOTSUPP); 1158223059Sgibbs} 1159223059Sgibbs 1160223059Sgibbsint 1161223059Sgibbsvfs_stdstatfs (mp, sbp) 1162223059Sgibbs struct mount *mp; 1163223059Sgibbs struct statfs *sbp; 1164223059Sgibbs{ 1165223059Sgibbs 1166223059Sgibbs return (EOPNOTSUPP); 1167223059Sgibbs} 1168223059Sgibbs 1169223059Sgibbsint 1170223059Sgibbsvfs_stdquotactl (mp, cmds, uid, arg) 1171223059Sgibbs struct mount *mp; 1172223059Sgibbs int cmds; 1173223059Sgibbs uid_t uid; 1174223059Sgibbs void *arg; 1175223059Sgibbs{ 1176223059Sgibbs 1177223059Sgibbs return (EOPNOTSUPP); 1178223059Sgibbs} 1179223059Sgibbs 1180223059Sgibbsint 1181223059Sgibbsvfs_stdsync(mp, waitfor) 1182223059Sgibbs struct mount *mp; 1183223059Sgibbs int waitfor; 1184223059Sgibbs{ 1185223059Sgibbs struct vnode *vp, *mvp; 1186223059Sgibbs struct thread *td; 1187223059Sgibbs int error, lockreq, allerror = 0; 1188223059Sgibbs 1189223059Sgibbs td = curthread; 1190223059Sgibbs lockreq = LK_EXCLUSIVE | LK_INTERLOCK; 1191223059Sgibbs if (waitfor != MNT_WAIT) 1192223059Sgibbs lockreq |= LK_NOWAIT; 1193223059Sgibbs /* 1194223059Sgibbs * Force stale buffer cache information to be flushed. 1195223059Sgibbs */ 1196223059Sgibbsloop: 1197223059Sgibbs MNT_VNODE_FOREACH_ALL(vp, mp, mvp) { 1198223059Sgibbs if (vp->v_bufobj.bo_dirty.bv_cnt == 0) { 1199223059Sgibbs VI_UNLOCK(vp); 1200223059Sgibbs continue; 1201223059Sgibbs } 1202223059Sgibbs if ((error = vget(vp, lockreq, td)) != 0) { 1203223059Sgibbs if (error == ENOENT) { 1204223059Sgibbs MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp); 1205223059Sgibbs goto loop; 1206223059Sgibbs } 1207223059Sgibbs continue; 1208223059Sgibbs } 1209223059Sgibbs error = VOP_FSYNC(vp, waitfor, td); 1210223059Sgibbs if (error) 1211223059Sgibbs allerror = error; 1212223059Sgibbs vput(vp); 1213223059Sgibbs } 1214223059Sgibbs return (allerror); 1215223059Sgibbs} 1216223059Sgibbs 1217223059Sgibbsint 1218223059Sgibbsvfs_stdnosync (mp, waitfor) 1219223059Sgibbs struct mount *mp; 1220223059Sgibbs int waitfor; 1221223059Sgibbs{ 1222223059Sgibbs 1223223059Sgibbs return (0); 1224223059Sgibbs} 1225223059Sgibbs 1226223059Sgibbsint 1227223059Sgibbsvfs_stdvget (mp, ino, flags, vpp) 1228223059Sgibbs struct mount *mp; 1229223059Sgibbs ino_t ino; 1230223059Sgibbs int flags; 1231223059Sgibbs struct vnode **vpp; 1232223059Sgibbs{ 1233223059Sgibbs 1234223059Sgibbs return (EOPNOTSUPP); 1235255179Sgibbs} 1236255218Sgibbs 1237223059Sgibbsint 1238223059Sgibbsvfs_stdfhtovp (mp, fhp, flags, vpp) 1239223059Sgibbs struct mount *mp; 1240223059Sgibbs struct fid *fhp; 1241223059Sgibbs int flags; 1242223059Sgibbs struct vnode **vpp; 1243223059Sgibbs{ 1244223059Sgibbs 1245223059Sgibbs return (EOPNOTSUPP); 1246223059Sgibbs} 1247223059Sgibbs 1248223059Sgibbsint 1249223059Sgibbsvfs_stdinit (vfsp) 1250223059Sgibbs struct vfsconf *vfsp; 1251223059Sgibbs{ 1252223059Sgibbs 1253223059Sgibbs return (0); 1254223059Sgibbs} 1255223059Sgibbs 1256223059Sgibbsint 1257223059Sgibbsvfs_stduninit (vfsp) 1258223059Sgibbs struct vfsconf *vfsp; 1259223059Sgibbs{ 1260223059Sgibbs 1261223059Sgibbs return(0); 1262223059Sgibbs} 1263223059Sgibbs 1264223059Sgibbsint 1265223059Sgibbsvfs_stdextattrctl(mp, cmd, filename_vp, attrnamespace, attrname) 1266223059Sgibbs struct mount *mp; 1267223059Sgibbs int cmd; 1268223059Sgibbs struct vnode *filename_vp; 1269223059Sgibbs int attrnamespace; 1270223059Sgibbs const char *attrname; 1271223059Sgibbs{ 1272223059Sgibbs 1273223059Sgibbs if (filename_vp != NULL) 1274223059Sgibbs VOP_UNLOCK(filename_vp, 0); 1275214077Sgibbs return (EOPNOTSUPP); 1276214077Sgibbs} 1277214077Sgibbs 1278214077Sgibbsint 1279214077Sgibbsvfs_stdsysctl(mp, op, req) 1280214077Sgibbs struct mount *mp; 1281214077Sgibbs fsctlop_t op; 1282181643Skmacy struct sysctl_req *req; 1283214077Sgibbs{ 1284181643Skmacy 1285181643Skmacy return (EOPNOTSUPP); 1286214077Sgibbs} 1287214077Sgibbs 1288181643Skmacy/* end of vfs default ops */ 1289214077Sgibbs