nfs_clvnops.c revision 306659
1279315Strasz/*- 2279315Strasz * Copyright (c) 1989, 1993 3279315Strasz * The Regents of the University of California. All rights reserved. 4279315Strasz * 5279315Strasz * This code is derived from software contributed to Berkeley by 6279315Strasz * Rick Macklem at The University of Guelph. 7279315Strasz * 8279315Strasz * Redistribution and use in source and binary forms, with or without 9279315Strasz * modification, are permitted provided that the following conditions 10279315Strasz * are met: 11279315Strasz * 1. Redistributions of source code must retain the above copyright 12279315Strasz * notice, this list of conditions and the following disclaimer. 13279315Strasz * 2. Redistributions in binary form must reproduce the above copyright 14279315Strasz * notice, this list of conditions and the following disclaimer in the 15279315Strasz * documentation and/or other materials provided with the distribution. 16279315Strasz * 4. Neither the name of the University nor the names of its contributors 17279315Strasz * may be used to endorse or promote products derived from this software 18279315Strasz * without specific prior written permission. 19279315Strasz * 20279315Strasz * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21279315Strasz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22279315Strasz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23279315Strasz * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24279315Strasz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25279315Strasz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26279315Strasz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27279315Strasz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28279315Strasz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29279315Strasz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30279315Strasz * SUCH DAMAGE. 31279315Strasz * 32279315Strasz * from nfs_vnops.c 8.16 (Berkeley) 5/27/95 33279315Strasz */ 34279315Strasz 35279315Strasz#include <sys/cdefs.h> 36279315Strasz__FBSDID("$FreeBSD: stable/10/sys/fs/nfsclient/nfs_clvnops.c 306659 2016-10-03 22:11:45Z rmacklem $"); 37279315Strasz 38279315Strasz/* 39279315Strasz * vnode op calls for Sun NFS version 2, 3 and 4 40279315Strasz */ 41279315Strasz 42279315Strasz#include "opt_kdtrace.h" 43279315Strasz#include "opt_inet.h" 44279315Strasz 45279315Strasz#include <sys/param.h> 46279315Strasz#include <sys/kernel.h> 47279315Strasz#include <sys/systm.h> 48279315Strasz#include <sys/resourcevar.h> 49279315Strasz#include <sys/proc.h> 50279315Strasz#include <sys/mount.h> 51279315Strasz#include <sys/bio.h> 52279315Strasz#include <sys/buf.h> 53279315Strasz#include <sys/jail.h> 54279315Strasz#include <sys/malloc.h> 55279315Strasz#include <sys/mbuf.h> 56279315Strasz#include <sys/namei.h> 57279315Strasz#include <sys/socket.h> 58279315Strasz#include <sys/vnode.h> 59279315Strasz#include <sys/dirent.h> 60279315Strasz#include <sys/fcntl.h> 61279315Strasz#include <sys/lockf.h> 62279315Strasz#include <sys/stat.h> 63279315Strasz#include <sys/sysctl.h> 64279315Strasz#include <sys/signalvar.h> 65279315Strasz 66279315Strasz#include <vm/vm.h> 67279315Strasz#include <vm/vm_extern.h> 68279315Strasz#include <vm/vm_object.h> 69279315Strasz 70279315Strasz#include <fs/nfs/nfsport.h> 71279315Strasz#include <fs/nfsclient/nfsnode.h> 72279315Strasz#include <fs/nfsclient/nfsmount.h> 73279315Strasz#include <fs/nfsclient/nfs.h> 74279315Strasz#include <fs/nfsclient/nfs_kdtrace.h> 75279315Strasz 76279315Strasz#include <net/if.h> 77279315Strasz#include <netinet/in.h> 78279315Strasz#include <netinet/in_var.h> 79279315Strasz 80279315Strasz#include <nfs/nfs_lock.h> 81279315Strasz 82279315Strasz#ifdef KDTRACE_HOOKS 83279315Strasz#include <sys/dtrace_bsd.h> 84279315Strasz 85279315Straszdtrace_nfsclient_accesscache_flush_probe_func_t 86279315Strasz dtrace_nfscl_accesscache_flush_done_probe; 87279315Straszuint32_t nfscl_accesscache_flush_done_id; 88279315Strasz 89279315Straszdtrace_nfsclient_accesscache_get_probe_func_t 90279315Strasz dtrace_nfscl_accesscache_get_hit_probe, 91279315Strasz dtrace_nfscl_accesscache_get_miss_probe; 92279315Straszuint32_t nfscl_accesscache_get_hit_id; 93279315Straszuint32_t nfscl_accesscache_get_miss_id; 94279315Strasz 95279315Straszdtrace_nfsclient_accesscache_load_probe_func_t 96279315Strasz dtrace_nfscl_accesscache_load_done_probe; 97279315Straszuint32_t nfscl_accesscache_load_done_id; 98279315Strasz#endif /* !KDTRACE_HOOKS */ 99279315Strasz 100279315Strasz/* Defs */ 101279315Strasz#define TRUE 1 102279315Strasz#define FALSE 0 103279315Strasz 104279315Straszextern struct nfsstatsv1 nfsstatsv1; 105279315Straszextern int nfsrv_useacl; 106279315Straszextern int nfscl_debuglevel; 107279315StraszMALLOC_DECLARE(M_NEWNFSREQ); 108279315Strasz 109279315Strasz/* 110279315Strasz * Ifdef for FreeBSD-current merged buffer cache. It is unfortunate that these 111279315Strasz * calls are not in getblk() and brelse() so that they would not be necessary 112279315Strasz * here. 113279315Strasz */ 114279315Strasz#ifndef B_VMIO 115279315Strasz#define vfs_busy_pages(bp, f) 116279315Strasz#endif 117279315Strasz 118279315Straszstatic vop_read_t nfsfifo_read; 119279315Straszstatic vop_write_t nfsfifo_write; 120279315Straszstatic vop_close_t nfsfifo_close; 121279315Straszstatic int nfs_setattrrpc(struct vnode *, struct vattr *, struct ucred *, 122279315Strasz struct thread *); 123279315Straszstatic vop_lookup_t nfs_lookup; 124279315Straszstatic vop_create_t nfs_create; 125279315Straszstatic vop_mknod_t nfs_mknod; 126279315Straszstatic vop_open_t nfs_open; 127279315Straszstatic vop_pathconf_t nfs_pathconf; 128279315Straszstatic vop_close_t nfs_close; 129279315Straszstatic vop_access_t nfs_access; 130279315Straszstatic vop_getattr_t nfs_getattr; 131279315Straszstatic vop_setattr_t nfs_setattr; 132279315Straszstatic vop_read_t nfs_read; 133279315Straszstatic vop_fsync_t nfs_fsync; 134279315Straszstatic vop_remove_t nfs_remove; 135279315Straszstatic vop_link_t nfs_link; 136279315Straszstatic vop_rename_t nfs_rename; 137279315Straszstatic vop_mkdir_t nfs_mkdir; 138279315Straszstatic vop_rmdir_t nfs_rmdir; 139279315Straszstatic vop_symlink_t nfs_symlink; 140279315Straszstatic vop_readdir_t nfs_readdir; 141279315Straszstatic vop_strategy_t nfs_strategy; 142279315Straszstatic int nfs_lookitup(struct vnode *, char *, int, 143279315Strasz struct ucred *, struct thread *, struct nfsnode **); 144279315Straszstatic int nfs_sillyrename(struct vnode *, struct vnode *, 145279315Strasz struct componentname *); 146279315Straszstatic vop_access_t nfsspec_access; 147279315Straszstatic vop_readlink_t nfs_readlink; 148279315Straszstatic vop_print_t nfs_print; 149279315Straszstatic vop_advlock_t nfs_advlock; 150279315Straszstatic vop_advlockasync_t nfs_advlockasync; 151279315Straszstatic vop_getacl_t nfs_getacl; 152279315Straszstatic vop_setacl_t nfs_setacl; 153279315Strasz 154279315Strasz/* 155279315Strasz * Global vfs data structures for nfs 156279315Strasz */ 157279315Straszstruct vop_vector newnfs_vnodeops = { 158279315Strasz .vop_default = &default_vnodeops, 159279315Strasz .vop_access = nfs_access, 160279315Strasz .vop_advlock = nfs_advlock, 161279315Strasz .vop_advlockasync = nfs_advlockasync, 162279315Strasz .vop_close = nfs_close, 163279315Strasz .vop_create = nfs_create, 164279315Strasz .vop_fsync = nfs_fsync, 165279315Strasz .vop_getattr = nfs_getattr, 166279315Strasz .vop_getpages = ncl_getpages, 167279315Strasz .vop_putpages = ncl_putpages, 168279315Strasz .vop_inactive = ncl_inactive, 169279315Strasz .vop_link = nfs_link, 170279315Strasz .vop_lookup = nfs_lookup, 171279315Strasz .vop_mkdir = nfs_mkdir, 172279315Strasz .vop_mknod = nfs_mknod, 173279315Strasz .vop_open = nfs_open, 174279315Strasz .vop_pathconf = nfs_pathconf, 175279315Strasz .vop_print = nfs_print, 176279315Strasz .vop_read = nfs_read, 177279315Strasz .vop_readdir = nfs_readdir, 178279315Strasz .vop_readlink = nfs_readlink, 179279315Strasz .vop_reclaim = ncl_reclaim, 180279315Strasz .vop_remove = nfs_remove, 181279315Strasz .vop_rename = nfs_rename, 182279315Strasz .vop_rmdir = nfs_rmdir, 183279315Strasz .vop_setattr = nfs_setattr, 184279315Strasz .vop_strategy = nfs_strategy, 185279315Strasz .vop_symlink = nfs_symlink, 186279315Strasz .vop_write = ncl_write, 187279315Strasz .vop_getacl = nfs_getacl, 188279315Strasz .vop_setacl = nfs_setacl, 189279315Strasz}; 190279315Strasz 191279315Straszstruct vop_vector newnfs_fifoops = { 192279315Strasz .vop_default = &fifo_specops, 193279315Strasz .vop_access = nfsspec_access, 194279315Strasz .vop_close = nfsfifo_close, 195279315Strasz .vop_fsync = nfs_fsync, 196279315Strasz .vop_getattr = nfs_getattr, 197279315Strasz .vop_inactive = ncl_inactive, 198279315Strasz .vop_print = nfs_print, 199279315Strasz .vop_read = nfsfifo_read, 200279315Strasz .vop_reclaim = ncl_reclaim, 201279315Strasz .vop_setattr = nfs_setattr, 202279315Strasz .vop_write = nfsfifo_write, 203279315Strasz}; 204279315Strasz 205279315Straszstatic int nfs_mknodrpc(struct vnode *dvp, struct vnode **vpp, 206279315Strasz struct componentname *cnp, struct vattr *vap); 207279315Straszstatic int nfs_removerpc(struct vnode *dvp, struct vnode *vp, char *name, 208279315Strasz int namelen, struct ucred *cred, struct thread *td); 209279315Straszstatic int nfs_renamerpc(struct vnode *fdvp, struct vnode *fvp, 210279315Strasz char *fnameptr, int fnamelen, struct vnode *tdvp, struct vnode *tvp, 211279315Strasz char *tnameptr, int tnamelen, struct ucred *cred, struct thread *td); 212279315Straszstatic int nfs_renameit(struct vnode *sdvp, struct vnode *svp, 213279315Strasz struct componentname *scnp, struct sillyrename *sp); 214279315Strasz 215279315Strasz/* 216279315Strasz * Global variables 217279315Strasz */ 218279315Strasz#define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1)) 219279315Strasz 220279315StraszSYSCTL_DECL(_vfs_nfs); 221279315Strasz 222279315Straszstatic int nfsaccess_cache_timeout = NFS_MAXATTRTIMO; 223279315StraszSYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_timeout, CTLFLAG_RW, 224279315Strasz &nfsaccess_cache_timeout, 0, "NFS ACCESS cache timeout"); 225279315Strasz 226279315Straszstatic int nfs_prime_access_cache = 0; 227279315StraszSYSCTL_INT(_vfs_nfs, OID_AUTO, prime_access_cache, CTLFLAG_RW, 228279315Strasz &nfs_prime_access_cache, 0, 229279315Strasz "Prime NFS ACCESS cache when fetching attributes"); 230279315Strasz 231279315Straszstatic int newnfs_commit_on_close = 0; 232279315StraszSYSCTL_INT(_vfs_nfs, OID_AUTO, commit_on_close, CTLFLAG_RW, 233279315Strasz &newnfs_commit_on_close, 0, "write+commit on close, else only write"); 234279315Strasz 235279315Straszstatic int nfs_clean_pages_on_close = 1; 236279315StraszSYSCTL_INT(_vfs_nfs, OID_AUTO, clean_pages_on_close, CTLFLAG_RW, 237279315Strasz &nfs_clean_pages_on_close, 0, "NFS clean dirty pages on close"); 238279315Strasz 239279315Straszint newnfs_directio_enable = 0; 240279315StraszSYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_directio_enable, CTLFLAG_RW, 241279315Strasz &newnfs_directio_enable, 0, "Enable NFS directio"); 242279315Strasz 243279315Straszint nfs_keep_dirty_on_error; 244279315StraszSYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_keep_dirty_on_error, CTLFLAG_RW, 245279315Strasz &nfs_keep_dirty_on_error, 0, "Retry pageout if error returned"); 246279315Strasz 247279315Strasz/* 248279315Strasz * This sysctl allows other processes to mmap a file that has been opened 249279315Strasz * O_DIRECT by a process. In general, having processes mmap the file while 250279315Strasz * Direct IO is in progress can lead to Data Inconsistencies. But, we allow 251279315Strasz * this by default to prevent DoS attacks - to prevent a malicious user from 252279315Strasz * opening up files O_DIRECT preventing other users from mmap'ing these 253279315Strasz * files. "Protected" environments where stricter consistency guarantees are 254279315Strasz * required can disable this knob. The process that opened the file O_DIRECT 255279315Strasz * cannot mmap() the file, because mmap'ed IO on an O_DIRECT open() is not 256279315Strasz * meaningful. 257279315Strasz */ 258279315Straszint newnfs_directio_allow_mmap = 1; 259279315StraszSYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_directio_allow_mmap, CTLFLAG_RW, 260279315Strasz &newnfs_directio_allow_mmap, 0, "Enable mmaped IO on file with O_DIRECT opens"); 261279315Strasz 262279315Strasz#define NFSACCESS_ALL (NFSACCESS_READ | NFSACCESS_MODIFY \ 263279315Strasz | NFSACCESS_EXTEND | NFSACCESS_EXECUTE \ 264279315Strasz | NFSACCESS_DELETE | NFSACCESS_LOOKUP) 265279315Strasz 266279315Strasz/* 267279315Strasz * SMP Locking Note : 268279315Strasz * The list of locks after the description of the lock is the ordering 269279315Strasz * of other locks acquired with the lock held. 270279315Strasz * np->n_mtx : Protects the fields in the nfsnode. 271279315Strasz VM Object Lock 272279315Strasz VI_MTX (acquired indirectly) 273279315Strasz * nmp->nm_mtx : Protects the fields in the nfsmount. 274279315Strasz rep->r_mtx 275279315Strasz * ncl_iod_mutex : Global lock, protects shared nfsiod state. 276279315Strasz * nfs_reqq_mtx : Global lock, protects the nfs_reqq list. 277279315Strasz nmp->nm_mtx 278279315Strasz rep->r_mtx 279279315Strasz * rep->r_mtx : Protects the fields in an nfsreq. 280279315Strasz */ 281279315Strasz 282279315Straszstatic int 283279315Strasznfs34_access_otw(struct vnode *vp, int wmode, struct thread *td, 284279315Strasz struct ucred *cred, u_int32_t *retmode) 285279315Strasz{ 286279315Strasz int error = 0, attrflag, i, lrupos; 287279315Strasz u_int32_t rmode; 288279315Strasz struct nfsnode *np = VTONFS(vp); 289279315Strasz struct nfsvattr nfsva; 290279315Strasz 291279315Strasz error = nfsrpc_accessrpc(vp, wmode, cred, td, &nfsva, &attrflag, 292279315Strasz &rmode, NULL); 293279315Strasz if (attrflag) 294279315Strasz (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1); 295279315Strasz if (!error) { 296279315Strasz lrupos = 0; 297279315Strasz mtx_lock(&np->n_mtx); 298279315Strasz for (i = 0; i < NFS_ACCESSCACHESIZE; i++) { 299279315Strasz if (np->n_accesscache[i].uid == cred->cr_uid) { 300279315Strasz np->n_accesscache[i].mode = rmode; 301279315Strasz np->n_accesscache[i].stamp = time_second; 302279315Strasz break; 303279315Strasz } 304279315Strasz if (i > 0 && np->n_accesscache[i].stamp < 305279315Strasz np->n_accesscache[lrupos].stamp) 306279315Strasz lrupos = i; 307279315Strasz } 308279315Strasz if (i == NFS_ACCESSCACHESIZE) { 309279315Strasz np->n_accesscache[lrupos].uid = cred->cr_uid; 310279315Strasz np->n_accesscache[lrupos].mode = rmode; 311279315Strasz np->n_accesscache[lrupos].stamp = time_second; 312279315Strasz } 313279315Strasz mtx_unlock(&np->n_mtx); 314279315Strasz if (retmode != NULL) 315279315Strasz *retmode = rmode; 316279315Strasz KDTRACE_NFS_ACCESSCACHE_LOAD_DONE(vp, cred->cr_uid, rmode, 0); 317279315Strasz } else if (NFS_ISV4(vp)) { 318279315Strasz error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0); 319279315Strasz } 320279315Strasz#ifdef KDTRACE_HOOKS 321279315Strasz if (error != 0) 322279315Strasz KDTRACE_NFS_ACCESSCACHE_LOAD_DONE(vp, cred->cr_uid, 0, 323279315Strasz error); 324279315Strasz#endif 325279315Strasz return (error); 326279315Strasz} 327279315Strasz 328279315Strasz/* 329279315Strasz * nfs access vnode op. 330279315Strasz * For nfs version 2, just return ok. File accesses may fail later. 331279315Strasz * For nfs version 3, use the access rpc to check accessibility. If file modes 332279315Strasz * are changed on the server, accesses might still fail later. 333279315Strasz */ 334279315Straszstatic int 335279315Strasznfs_access(struct vop_access_args *ap) 336279315Strasz{ 337279315Strasz struct vnode *vp = ap->a_vp; 338279315Strasz int error = 0, i, gotahit; 339279315Strasz u_int32_t mode, wmode, rmode; 340279315Strasz int v34 = NFS_ISV34(vp); 341279315Strasz struct nfsnode *np = VTONFS(vp); 342279315Strasz 343279315Strasz /* 344279315Strasz * Disallow write attempts on filesystems mounted read-only; 345279315Strasz * unless the file is a socket, fifo, or a block or character 346279315Strasz * device resident on the filesystem. 347279315Strasz */ 348279315Strasz if ((ap->a_accmode & (VWRITE | VAPPEND | VWRITE_NAMED_ATTRS | 349279315Strasz VDELETE_CHILD | VWRITE_ATTRIBUTES | VDELETE | VWRITE_ACL | 350279315Strasz VWRITE_OWNER)) != 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) != 0) { 351279315Strasz switch (vp->v_type) { 352279315Strasz case VREG: 353279315Strasz case VDIR: 354279315Strasz case VLNK: 355279315Strasz return (EROFS); 356279315Strasz default: 357279315Strasz break; 358279315Strasz } 359279315Strasz } 360279315Strasz /* 361279315Strasz * For nfs v3 or v4, check to see if we have done this recently, and if 362279315Strasz * so return our cached result instead of making an ACCESS call. 363279315Strasz * If not, do an access rpc, otherwise you are stuck emulating 364279315Strasz * ufs_access() locally using the vattr. This may not be correct, 365279315Strasz * since the server may apply other access criteria such as 366279315Strasz * client uid-->server uid mapping that we do not know about. 367279315Strasz */ 368279315Strasz if (v34) { 369279315Strasz if (ap->a_accmode & VREAD) 370279315Strasz mode = NFSACCESS_READ; 371279315Strasz else 372279315Strasz mode = 0; 373279315Strasz if (vp->v_type != VDIR) { 374279315Strasz if (ap->a_accmode & VWRITE) 375279315Strasz mode |= (NFSACCESS_MODIFY | NFSACCESS_EXTEND); 376279315Strasz if (ap->a_accmode & VAPPEND) 377279315Strasz mode |= NFSACCESS_EXTEND; 378279315Strasz if (ap->a_accmode & VEXEC) 379279315Strasz mode |= NFSACCESS_EXECUTE; 380279315Strasz if (ap->a_accmode & VDELETE) 381279315Strasz mode |= NFSACCESS_DELETE; 382279315Strasz } else { 383279315Strasz if (ap->a_accmode & VWRITE) 384279315Strasz mode |= (NFSACCESS_MODIFY | NFSACCESS_EXTEND); 385279315Strasz if (ap->a_accmode & VAPPEND) 386279315Strasz mode |= NFSACCESS_EXTEND; 387279315Strasz if (ap->a_accmode & VEXEC) 388279315Strasz mode |= NFSACCESS_LOOKUP; 389279315Strasz if (ap->a_accmode & VDELETE) 390279315Strasz mode |= NFSACCESS_DELETE; 391279315Strasz if (ap->a_accmode & VDELETE_CHILD) 392279315Strasz mode |= NFSACCESS_MODIFY; 393279315Strasz } 394279315Strasz /* XXX safety belt, only make blanket request if caching */ 395279315Strasz if (nfsaccess_cache_timeout > 0) { 396279315Strasz wmode = NFSACCESS_READ | NFSACCESS_MODIFY | 397279315Strasz NFSACCESS_EXTEND | NFSACCESS_EXECUTE | 398279315Strasz NFSACCESS_DELETE | NFSACCESS_LOOKUP; 399279315Strasz } else { 400279315Strasz wmode = mode; 401279315Strasz } 402279315Strasz 403279315Strasz /* 404279315Strasz * Does our cached result allow us to give a definite yes to 405279315Strasz * this request? 406279315Strasz */ 407279315Strasz gotahit = 0; 408279315Strasz mtx_lock(&np->n_mtx); 409279315Strasz for (i = 0; i < NFS_ACCESSCACHESIZE; i++) { 410279315Strasz if (ap->a_cred->cr_uid == np->n_accesscache[i].uid) { 411279315Strasz if (time_second < (np->n_accesscache[i].stamp 412279315Strasz + nfsaccess_cache_timeout) && 413279315Strasz (np->n_accesscache[i].mode & mode) == mode) { 414279315Strasz NFSINCRGLOBAL(nfsstatsv1.accesscache_hits); 415279315Strasz gotahit = 1; 416279315Strasz } 417279315Strasz break; 418279315Strasz } 419279315Strasz } 420279315Strasz mtx_unlock(&np->n_mtx); 421279315Strasz#ifdef KDTRACE_HOOKS 422279315Strasz if (gotahit != 0) 423279315Strasz KDTRACE_NFS_ACCESSCACHE_GET_HIT(vp, 424279315Strasz ap->a_cred->cr_uid, mode); 425279315Strasz else 426 KDTRACE_NFS_ACCESSCACHE_GET_MISS(vp, 427 ap->a_cred->cr_uid, mode); 428#endif 429 if (gotahit == 0) { 430 /* 431 * Either a no, or a don't know. Go to the wire. 432 */ 433 NFSINCRGLOBAL(nfsstatsv1.accesscache_misses); 434 error = nfs34_access_otw(vp, wmode, ap->a_td, 435 ap->a_cred, &rmode); 436 if (!error && 437 (rmode & mode) != mode) 438 error = EACCES; 439 } 440 return (error); 441 } else { 442 if ((error = nfsspec_access(ap)) != 0) { 443 return (error); 444 } 445 /* 446 * Attempt to prevent a mapped root from accessing a file 447 * which it shouldn't. We try to read a byte from the file 448 * if the user is root and the file is not zero length. 449 * After calling nfsspec_access, we should have the correct 450 * file size cached. 451 */ 452 mtx_lock(&np->n_mtx); 453 if (ap->a_cred->cr_uid == 0 && (ap->a_accmode & VREAD) 454 && VTONFS(vp)->n_size > 0) { 455 struct iovec aiov; 456 struct uio auio; 457 char buf[1]; 458 459 mtx_unlock(&np->n_mtx); 460 aiov.iov_base = buf; 461 aiov.iov_len = 1; 462 auio.uio_iov = &aiov; 463 auio.uio_iovcnt = 1; 464 auio.uio_offset = 0; 465 auio.uio_resid = 1; 466 auio.uio_segflg = UIO_SYSSPACE; 467 auio.uio_rw = UIO_READ; 468 auio.uio_td = ap->a_td; 469 470 if (vp->v_type == VREG) 471 error = ncl_readrpc(vp, &auio, ap->a_cred); 472 else if (vp->v_type == VDIR) { 473 char* bp; 474 bp = malloc(NFS_DIRBLKSIZ, M_TEMP, M_WAITOK); 475 aiov.iov_base = bp; 476 aiov.iov_len = auio.uio_resid = NFS_DIRBLKSIZ; 477 error = ncl_readdirrpc(vp, &auio, ap->a_cred, 478 ap->a_td); 479 free(bp, M_TEMP); 480 } else if (vp->v_type == VLNK) 481 error = ncl_readlinkrpc(vp, &auio, ap->a_cred); 482 else 483 error = EACCES; 484 } else 485 mtx_unlock(&np->n_mtx); 486 return (error); 487 } 488} 489 490 491/* 492 * nfs open vnode op 493 * Check to see if the type is ok 494 * and that deletion is not in progress. 495 * For paged in text files, you will need to flush the page cache 496 * if consistency is lost. 497 */ 498/* ARGSUSED */ 499static int 500nfs_open(struct vop_open_args *ap) 501{ 502 struct vnode *vp = ap->a_vp; 503 struct nfsnode *np = VTONFS(vp); 504 struct vattr vattr; 505 int error; 506 int fmode = ap->a_mode; 507 struct ucred *cred; 508 509 if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) 510 return (EOPNOTSUPP); 511 512 /* 513 * For NFSv4, we need to do the Open Op before cache validation, 514 * so that we conform to RFC3530 Sec. 9.3.1. 515 */ 516 if (NFS_ISV4(vp)) { 517 error = nfsrpc_open(vp, fmode, ap->a_cred, ap->a_td); 518 if (error) { 519 error = nfscl_maperr(ap->a_td, error, (uid_t)0, 520 (gid_t)0); 521 return (error); 522 } 523 } 524 525 /* 526 * Now, if this Open will be doing reading, re-validate/flush the 527 * cache, so that Close/Open coherency is maintained. 528 */ 529 mtx_lock(&np->n_mtx); 530 if (np->n_flag & NMODIFIED) { 531 mtx_unlock(&np->n_mtx); 532 error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1); 533 if (error == EINTR || error == EIO) { 534 if (NFS_ISV4(vp)) 535 (void) nfsrpc_close(vp, 0, ap->a_td); 536 return (error); 537 } 538 mtx_lock(&np->n_mtx); 539 np->n_attrstamp = 0; 540 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); 541 if (vp->v_type == VDIR) 542 np->n_direofoffset = 0; 543 mtx_unlock(&np->n_mtx); 544 error = VOP_GETATTR(vp, &vattr, ap->a_cred); 545 if (error) { 546 if (NFS_ISV4(vp)) 547 (void) nfsrpc_close(vp, 0, ap->a_td); 548 return (error); 549 } 550 mtx_lock(&np->n_mtx); 551 np->n_mtime = vattr.va_mtime; 552 if (NFS_ISV4(vp)) 553 np->n_change = vattr.va_filerev; 554 } else { 555 mtx_unlock(&np->n_mtx); 556 error = VOP_GETATTR(vp, &vattr, ap->a_cred); 557 if (error) { 558 if (NFS_ISV4(vp)) 559 (void) nfsrpc_close(vp, 0, ap->a_td); 560 return (error); 561 } 562 mtx_lock(&np->n_mtx); 563 if ((NFS_ISV4(vp) && np->n_change != vattr.va_filerev) || 564 NFS_TIMESPEC_COMPARE(&np->n_mtime, &vattr.va_mtime)) { 565 if (vp->v_type == VDIR) 566 np->n_direofoffset = 0; 567 mtx_unlock(&np->n_mtx); 568 error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1); 569 if (error == EINTR || error == EIO) { 570 if (NFS_ISV4(vp)) 571 (void) nfsrpc_close(vp, 0, ap->a_td); 572 return (error); 573 } 574 mtx_lock(&np->n_mtx); 575 np->n_mtime = vattr.va_mtime; 576 if (NFS_ISV4(vp)) 577 np->n_change = vattr.va_filerev; 578 } 579 } 580 581 /* 582 * If the object has >= 1 O_DIRECT active opens, we disable caching. 583 */ 584 if (newnfs_directio_enable && (fmode & O_DIRECT) && 585 (vp->v_type == VREG)) { 586 if (np->n_directio_opens == 0) { 587 mtx_unlock(&np->n_mtx); 588 error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1); 589 if (error) { 590 if (NFS_ISV4(vp)) 591 (void) nfsrpc_close(vp, 0, ap->a_td); 592 return (error); 593 } 594 mtx_lock(&np->n_mtx); 595 np->n_flag |= NNONCACHE; 596 } 597 np->n_directio_opens++; 598 } 599 600 /* If opened for writing via NFSv4.1 or later, mark that for pNFS. */ 601 if (NFSHASPNFS(VFSTONFS(vp->v_mount)) && (fmode & FWRITE) != 0) 602 np->n_flag |= NWRITEOPENED; 603 604 /* 605 * If this is an open for writing, capture a reference to the 606 * credentials, so they can be used by ncl_putpages(). Using 607 * these write credentials is preferable to the credentials of 608 * whatever thread happens to be doing the VOP_PUTPAGES() since 609 * the write RPCs are less likely to fail with EACCES. 610 */ 611 if ((fmode & FWRITE) != 0) { 612 cred = np->n_writecred; 613 np->n_writecred = crhold(ap->a_cred); 614 } else 615 cred = NULL; 616 mtx_unlock(&np->n_mtx); 617 618 if (cred != NULL) 619 crfree(cred); 620 vnode_create_vobject(vp, vattr.va_size, ap->a_td); 621 return (0); 622} 623 624/* 625 * nfs close vnode op 626 * What an NFS client should do upon close after writing is a debatable issue. 627 * Most NFS clients push delayed writes to the server upon close, basically for 628 * two reasons: 629 * 1 - So that any write errors may be reported back to the client process 630 * doing the close system call. By far the two most likely errors are 631 * NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure. 632 * 2 - To put a worst case upper bound on cache inconsistency between 633 * multiple clients for the file. 634 * There is also a consistency problem for Version 2 of the protocol w.r.t. 635 * not being able to tell if other clients are writing a file concurrently, 636 * since there is no way of knowing if the changed modify time in the reply 637 * is only due to the write for this client. 638 * (NFS Version 3 provides weak cache consistency data in the reply that 639 * should be sufficient to detect and handle this case.) 640 * 641 * The current code does the following: 642 * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers 643 * for NFS Version 3 - flush dirty buffers to the server but don't invalidate 644 * or commit them (this satisfies 1 and 2 except for the 645 * case where the server crashes after this close but 646 * before the commit RPC, which is felt to be "good 647 * enough". Changing the last argument to ncl_flush() to 648 * a 1 would force a commit operation, if it is felt a 649 * commit is necessary now. 650 * for NFS Version 4 - flush the dirty buffers and commit them, if 651 * nfscl_mustflush() says this is necessary. 652 * It is necessary if there is no write delegation held, 653 * in order to satisfy open/close coherency. 654 * If the file isn't cached on local stable storage, 655 * it may be necessary in order to detect "out of space" 656 * errors from the server, if the write delegation 657 * issued by the server doesn't allow the file to grow. 658 */ 659/* ARGSUSED */ 660static int 661nfs_close(struct vop_close_args *ap) 662{ 663 struct vnode *vp = ap->a_vp; 664 struct nfsnode *np = VTONFS(vp); 665 struct nfsvattr nfsva; 666 struct ucred *cred; 667 int error = 0, ret, localcred = 0; 668 int fmode = ap->a_fflag; 669 670 if ((vp->v_mount->mnt_kern_flag & MNTK_UNMOUNTF)) 671 return (0); 672 /* 673 * During shutdown, a_cred isn't valid, so just use root. 674 */ 675 if (ap->a_cred == NOCRED) { 676 cred = newnfs_getcred(); 677 localcred = 1; 678 } else { 679 cred = ap->a_cred; 680 } 681 if (vp->v_type == VREG) { 682 /* 683 * Examine and clean dirty pages, regardless of NMODIFIED. 684 * This closes a major hole in close-to-open consistency. 685 * We want to push out all dirty pages (and buffers) on 686 * close, regardless of whether they were dirtied by 687 * mmap'ed writes or via write(). 688 */ 689 if (nfs_clean_pages_on_close && vp->v_object) { 690 VM_OBJECT_WLOCK(vp->v_object); 691 vm_object_page_clean(vp->v_object, 0, 0, 0); 692 VM_OBJECT_WUNLOCK(vp->v_object); 693 } 694 mtx_lock(&np->n_mtx); 695 if (np->n_flag & NMODIFIED) { 696 mtx_unlock(&np->n_mtx); 697 if (NFS_ISV3(vp)) { 698 /* 699 * Under NFSv3 we have dirty buffers to dispose of. We 700 * must flush them to the NFS server. We have the option 701 * of waiting all the way through the commit rpc or just 702 * waiting for the initial write. The default is to only 703 * wait through the initial write so the data is in the 704 * server's cache, which is roughly similar to the state 705 * a standard disk subsystem leaves the file in on close(). 706 * 707 * We cannot clear the NMODIFIED bit in np->n_flag due to 708 * potential races with other processes, and certainly 709 * cannot clear it if we don't commit. 710 * These races occur when there is no longer the old 711 * traditional vnode locking implemented for Vnode Ops. 712 */ 713 int cm = newnfs_commit_on_close ? 1 : 0; 714 error = ncl_flush(vp, MNT_WAIT, cred, ap->a_td, cm, 0); 715 /* np->n_flag &= ~NMODIFIED; */ 716 } else if (NFS_ISV4(vp)) { 717 if (nfscl_mustflush(vp) != 0) { 718 int cm = newnfs_commit_on_close ? 1 : 0; 719 error = ncl_flush(vp, MNT_WAIT, cred, ap->a_td, 720 cm, 0); 721 /* 722 * as above w.r.t races when clearing 723 * NMODIFIED. 724 * np->n_flag &= ~NMODIFIED; 725 */ 726 } 727 } else 728 error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1); 729 mtx_lock(&np->n_mtx); 730 } 731 /* 732 * Invalidate the attribute cache in all cases. 733 * An open is going to fetch fresh attrs any way, other procs 734 * on this node that have file open will be forced to do an 735 * otw attr fetch, but this is safe. 736 * --> A user found that their RPC count dropped by 20% when 737 * this was commented out and I can't see any requirement 738 * for it, so I've disabled it when negative lookups are 739 * enabled. (What does this have to do with negative lookup 740 * caching? Well nothing, except it was reported by the 741 * same user that needed negative lookup caching and I wanted 742 * there to be a way to disable it to see if it 743 * is the cause of some caching/coherency issue that might 744 * crop up.) 745 */ 746 if (VFSTONFS(vp->v_mount)->nm_negnametimeo == 0) { 747 np->n_attrstamp = 0; 748 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); 749 } 750 if (np->n_flag & NWRITEERR) { 751 np->n_flag &= ~NWRITEERR; 752 error = np->n_error; 753 } 754 mtx_unlock(&np->n_mtx); 755 } 756 757 if (NFS_ISV4(vp)) { 758 /* 759 * Get attributes so "change" is up to date. 760 */ 761 if (error == 0 && nfscl_mustflush(vp) != 0 && 762 vp->v_type == VREG && 763 (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NOCTO) == 0) { 764 ret = nfsrpc_getattr(vp, cred, ap->a_td, &nfsva, 765 NULL); 766 if (!ret) { 767 np->n_change = nfsva.na_filerev; 768 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, 769 NULL, 0, 0); 770 } 771 } 772 773 /* 774 * and do the close. 775 */ 776 ret = nfsrpc_close(vp, 0, ap->a_td); 777 if (!error && ret) 778 error = ret; 779 if (error) 780 error = nfscl_maperr(ap->a_td, error, (uid_t)0, 781 (gid_t)0); 782 } 783 if (newnfs_directio_enable) 784 KASSERT((np->n_directio_asyncwr == 0), 785 ("nfs_close: dirty unflushed (%d) directio buffers\n", 786 np->n_directio_asyncwr)); 787 if (newnfs_directio_enable && (fmode & O_DIRECT) && (vp->v_type == VREG)) { 788 mtx_lock(&np->n_mtx); 789 KASSERT((np->n_directio_opens > 0), 790 ("nfs_close: unexpectedly value (0) of n_directio_opens\n")); 791 np->n_directio_opens--; 792 if (np->n_directio_opens == 0) 793 np->n_flag &= ~NNONCACHE; 794 mtx_unlock(&np->n_mtx); 795 } 796 if (localcred) 797 NFSFREECRED(cred); 798 return (error); 799} 800 801/* 802 * nfs getattr call from vfs. 803 */ 804static int 805nfs_getattr(struct vop_getattr_args *ap) 806{ 807 struct vnode *vp = ap->a_vp; 808 struct thread *td = curthread; /* XXX */ 809 struct nfsnode *np = VTONFS(vp); 810 int error = 0; 811 struct nfsvattr nfsva; 812 struct vattr *vap = ap->a_vap; 813 struct vattr vattr; 814 815 /* 816 * Update local times for special files. 817 */ 818 mtx_lock(&np->n_mtx); 819 if (np->n_flag & (NACC | NUPD)) 820 np->n_flag |= NCHG; 821 mtx_unlock(&np->n_mtx); 822 /* 823 * First look in the cache. 824 */ 825 if (ncl_getattrcache(vp, &vattr) == 0) { 826 vap->va_type = vattr.va_type; 827 vap->va_mode = vattr.va_mode; 828 vap->va_nlink = vattr.va_nlink; 829 vap->va_uid = vattr.va_uid; 830 vap->va_gid = vattr.va_gid; 831 vap->va_fsid = vattr.va_fsid; 832 vap->va_fileid = vattr.va_fileid; 833 vap->va_size = vattr.va_size; 834 vap->va_blocksize = vattr.va_blocksize; 835 vap->va_atime = vattr.va_atime; 836 vap->va_mtime = vattr.va_mtime; 837 vap->va_ctime = vattr.va_ctime; 838 vap->va_gen = vattr.va_gen; 839 vap->va_flags = vattr.va_flags; 840 vap->va_rdev = vattr.va_rdev; 841 vap->va_bytes = vattr.va_bytes; 842 vap->va_filerev = vattr.va_filerev; 843 /* 844 * Get the local modify time for the case of a write 845 * delegation. 846 */ 847 nfscl_deleggetmodtime(vp, &vap->va_mtime); 848 return (0); 849 } 850 851 if (NFS_ISV34(vp) && nfs_prime_access_cache && 852 nfsaccess_cache_timeout > 0) { 853 NFSINCRGLOBAL(nfsstatsv1.accesscache_misses); 854 nfs34_access_otw(vp, NFSACCESS_ALL, td, ap->a_cred, NULL); 855 if (ncl_getattrcache(vp, ap->a_vap) == 0) { 856 nfscl_deleggetmodtime(vp, &ap->a_vap->va_mtime); 857 return (0); 858 } 859 } 860 error = nfsrpc_getattr(vp, ap->a_cred, td, &nfsva, NULL); 861 if (!error) 862 error = nfscl_loadattrcache(&vp, &nfsva, vap, NULL, 0, 0); 863 if (!error) { 864 /* 865 * Get the local modify time for the case of a write 866 * delegation. 867 */ 868 nfscl_deleggetmodtime(vp, &vap->va_mtime); 869 } else if (NFS_ISV4(vp)) { 870 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0); 871 } 872 return (error); 873} 874 875/* 876 * nfs setattr call. 877 */ 878static int 879nfs_setattr(struct vop_setattr_args *ap) 880{ 881 struct vnode *vp = ap->a_vp; 882 struct nfsnode *np = VTONFS(vp); 883 struct thread *td = curthread; /* XXX */ 884 struct vattr *vap = ap->a_vap; 885 int error = 0; 886 u_quad_t tsize; 887 888#ifndef nolint 889 tsize = (u_quad_t)0; 890#endif 891 892 /* 893 * Setting of flags and marking of atimes are not supported. 894 */ 895 if (vap->va_flags != VNOVAL) 896 return (EOPNOTSUPP); 897 898 /* 899 * Disallow write attempts if the filesystem is mounted read-only. 900 */ 901 if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || 902 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 903 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) && 904 (vp->v_mount->mnt_flag & MNT_RDONLY)) 905 return (EROFS); 906 if (vap->va_size != VNOVAL) { 907 switch (vp->v_type) { 908 case VDIR: 909 return (EISDIR); 910 case VCHR: 911 case VBLK: 912 case VSOCK: 913 case VFIFO: 914 if (vap->va_mtime.tv_sec == VNOVAL && 915 vap->va_atime.tv_sec == VNOVAL && 916 vap->va_mode == (mode_t)VNOVAL && 917 vap->va_uid == (uid_t)VNOVAL && 918 vap->va_gid == (gid_t)VNOVAL) 919 return (0); 920 vap->va_size = VNOVAL; 921 break; 922 default: 923 /* 924 * Disallow write attempts if the filesystem is 925 * mounted read-only. 926 */ 927 if (vp->v_mount->mnt_flag & MNT_RDONLY) 928 return (EROFS); 929 /* 930 * We run vnode_pager_setsize() early (why?), 931 * we must set np->n_size now to avoid vinvalbuf 932 * V_SAVE races that might setsize a lower 933 * value. 934 */ 935 mtx_lock(&np->n_mtx); 936 tsize = np->n_size; 937 mtx_unlock(&np->n_mtx); 938 error = ncl_meta_setsize(vp, ap->a_cred, td, 939 vap->va_size); 940 mtx_lock(&np->n_mtx); 941 if (np->n_flag & NMODIFIED) { 942 tsize = np->n_size; 943 mtx_unlock(&np->n_mtx); 944 if (vap->va_size == 0) 945 error = ncl_vinvalbuf(vp, 0, td, 1); 946 else 947 error = ncl_vinvalbuf(vp, V_SAVE, td, 1); 948 if (error) { 949 vnode_pager_setsize(vp, tsize); 950 return (error); 951 } 952 /* 953 * Call nfscl_delegmodtime() to set the modify time 954 * locally, as required. 955 */ 956 nfscl_delegmodtime(vp); 957 } else 958 mtx_unlock(&np->n_mtx); 959 /* 960 * np->n_size has already been set to vap->va_size 961 * in ncl_meta_setsize(). We must set it again since 962 * nfs_loadattrcache() could be called through 963 * ncl_meta_setsize() and could modify np->n_size. 964 */ 965 mtx_lock(&np->n_mtx); 966 np->n_vattr.na_size = np->n_size = vap->va_size; 967 mtx_unlock(&np->n_mtx); 968 }; 969 } else { 970 mtx_lock(&np->n_mtx); 971 if ((vap->va_mtime.tv_sec != VNOVAL || vap->va_atime.tv_sec != VNOVAL) && 972 (np->n_flag & NMODIFIED) && vp->v_type == VREG) { 973 mtx_unlock(&np->n_mtx); 974 if ((error = ncl_vinvalbuf(vp, V_SAVE, td, 1)) != 0 && 975 (error == EINTR || error == EIO)) 976 return (error); 977 } else 978 mtx_unlock(&np->n_mtx); 979 } 980 error = nfs_setattrrpc(vp, vap, ap->a_cred, td); 981 if (error && vap->va_size != VNOVAL) { 982 mtx_lock(&np->n_mtx); 983 np->n_size = np->n_vattr.na_size = tsize; 984 vnode_pager_setsize(vp, tsize); 985 mtx_unlock(&np->n_mtx); 986 } 987 return (error); 988} 989 990/* 991 * Do an nfs setattr rpc. 992 */ 993static int 994nfs_setattrrpc(struct vnode *vp, struct vattr *vap, struct ucred *cred, 995 struct thread *td) 996{ 997 struct nfsnode *np = VTONFS(vp); 998 int error, ret, attrflag, i; 999 struct nfsvattr nfsva; 1000 1001 if (NFS_ISV34(vp)) { 1002 mtx_lock(&np->n_mtx); 1003 for (i = 0; i < NFS_ACCESSCACHESIZE; i++) 1004 np->n_accesscache[i].stamp = 0; 1005 np->n_flag |= NDELEGMOD; 1006 mtx_unlock(&np->n_mtx); 1007 KDTRACE_NFS_ACCESSCACHE_FLUSH_DONE(vp); 1008 } 1009 error = nfsrpc_setattr(vp, vap, NULL, cred, td, &nfsva, &attrflag, 1010 NULL); 1011 if (attrflag) { 1012 ret = nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1); 1013 if (ret && !error) 1014 error = ret; 1015 } 1016 if (error && NFS_ISV4(vp)) 1017 error = nfscl_maperr(td, error, vap->va_uid, vap->va_gid); 1018 return (error); 1019} 1020 1021/* 1022 * nfs lookup call, one step at a time... 1023 * First look in cache 1024 * If not found, unlock the directory nfsnode and do the rpc 1025 */ 1026static int 1027nfs_lookup(struct vop_lookup_args *ap) 1028{ 1029 struct componentname *cnp = ap->a_cnp; 1030 struct vnode *dvp = ap->a_dvp; 1031 struct vnode **vpp = ap->a_vpp; 1032 struct mount *mp = dvp->v_mount; 1033 int flags = cnp->cn_flags; 1034 struct vnode *newvp; 1035 struct nfsmount *nmp; 1036 struct nfsnode *np, *newnp; 1037 int error = 0, attrflag, dattrflag, ltype, ncticks; 1038 struct thread *td = cnp->cn_thread; 1039 struct nfsfh *nfhp; 1040 struct nfsvattr dnfsva, nfsva; 1041 struct vattr vattr; 1042 struct timespec nctime; 1043 1044 *vpp = NULLVP; 1045 if ((flags & ISLASTCN) && (mp->mnt_flag & MNT_RDONLY) && 1046 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) 1047 return (EROFS); 1048 if (dvp->v_type != VDIR) 1049 return (ENOTDIR); 1050 nmp = VFSTONFS(mp); 1051 np = VTONFS(dvp); 1052 1053 /* For NFSv4, wait until any remove is done. */ 1054 mtx_lock(&np->n_mtx); 1055 while (NFSHASNFSV4(nmp) && (np->n_flag & NREMOVEINPROG)) { 1056 np->n_flag |= NREMOVEWANT; 1057 (void) msleep((caddr_t)np, &np->n_mtx, PZERO, "nfslkup", 0); 1058 } 1059 mtx_unlock(&np->n_mtx); 1060 1061 if ((error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td)) != 0) 1062 return (error); 1063 error = cache_lookup(dvp, vpp, cnp, &nctime, &ncticks); 1064 if (error > 0 && error != ENOENT) 1065 return (error); 1066 if (error == -1) { 1067 /* 1068 * Lookups of "." are special and always return the 1069 * current directory. cache_lookup() already handles 1070 * associated locking bookkeeping, etc. 1071 */ 1072 if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') { 1073 /* XXX: Is this really correct? */ 1074 if (cnp->cn_nameiop != LOOKUP && 1075 (flags & ISLASTCN)) 1076 cnp->cn_flags |= SAVENAME; 1077 return (0); 1078 } 1079 1080 /* 1081 * We only accept a positive hit in the cache if the 1082 * change time of the file matches our cached copy. 1083 * Otherwise, we discard the cache entry and fallback 1084 * to doing a lookup RPC. We also only trust cache 1085 * entries for less than nm_nametimeo seconds. 1086 * 1087 * To better handle stale file handles and attributes, 1088 * clear the attribute cache of this node if it is a 1089 * leaf component, part of an open() call, and not 1090 * locally modified before fetching the attributes. 1091 * This should allow stale file handles to be detected 1092 * here where we can fall back to a LOOKUP RPC to 1093 * recover rather than having nfs_open() detect the 1094 * stale file handle and failing open(2) with ESTALE. 1095 */ 1096 newvp = *vpp; 1097 newnp = VTONFS(newvp); 1098 if (!(nmp->nm_flag & NFSMNT_NOCTO) && 1099 (flags & (ISLASTCN | ISOPEN)) == (ISLASTCN | ISOPEN) && 1100 !(newnp->n_flag & NMODIFIED)) { 1101 mtx_lock(&newnp->n_mtx); 1102 newnp->n_attrstamp = 0; 1103 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(newvp); 1104 mtx_unlock(&newnp->n_mtx); 1105 } 1106 if (nfscl_nodeleg(newvp, 0) == 0 || 1107 ((u_int)(ticks - ncticks) < (nmp->nm_nametimeo * hz) && 1108 VOP_GETATTR(newvp, &vattr, cnp->cn_cred) == 0 && 1109 timespeccmp(&vattr.va_ctime, &nctime, ==))) { 1110 NFSINCRGLOBAL(nfsstatsv1.lookupcache_hits); 1111 if (cnp->cn_nameiop != LOOKUP && 1112 (flags & ISLASTCN)) 1113 cnp->cn_flags |= SAVENAME; 1114 return (0); 1115 } 1116 cache_purge(newvp); 1117 if (dvp != newvp) 1118 vput(newvp); 1119 else 1120 vrele(newvp); 1121 *vpp = NULLVP; 1122 } else if (error == ENOENT) { 1123 if (dvp->v_iflag & VI_DOOMED) 1124 return (ENOENT); 1125 /* 1126 * We only accept a negative hit in the cache if the 1127 * modification time of the parent directory matches 1128 * the cached copy in the name cache entry. 1129 * Otherwise, we discard all of the negative cache 1130 * entries for this directory. We also only trust 1131 * negative cache entries for up to nm_negnametimeo 1132 * seconds. 1133 */ 1134 if ((u_int)(ticks - ncticks) < (nmp->nm_negnametimeo * hz) && 1135 VOP_GETATTR(dvp, &vattr, cnp->cn_cred) == 0 && 1136 timespeccmp(&vattr.va_mtime, &nctime, ==)) { 1137 NFSINCRGLOBAL(nfsstatsv1.lookupcache_hits); 1138 return (ENOENT); 1139 } 1140 cache_purge_negative(dvp); 1141 } 1142 1143 error = 0; 1144 newvp = NULLVP; 1145 NFSINCRGLOBAL(nfsstatsv1.lookupcache_misses); 1146 error = nfsrpc_lookup(dvp, cnp->cn_nameptr, cnp->cn_namelen, 1147 cnp->cn_cred, td, &dnfsva, &nfsva, &nfhp, &attrflag, &dattrflag, 1148 NULL); 1149 if (dattrflag) 1150 (void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1); 1151 if (error) { 1152 if (newvp != NULLVP) { 1153 vput(newvp); 1154 *vpp = NULLVP; 1155 } 1156 1157 if (error != ENOENT) { 1158 if (NFS_ISV4(dvp)) 1159 error = nfscl_maperr(td, error, (uid_t)0, 1160 (gid_t)0); 1161 return (error); 1162 } 1163 1164 /* The requested file was not found. */ 1165 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) && 1166 (flags & ISLASTCN)) { 1167 /* 1168 * XXX: UFS does a full VOP_ACCESS(dvp, 1169 * VWRITE) here instead of just checking 1170 * MNT_RDONLY. 1171 */ 1172 if (mp->mnt_flag & MNT_RDONLY) 1173 return (EROFS); 1174 cnp->cn_flags |= SAVENAME; 1175 return (EJUSTRETURN); 1176 } 1177 1178 if ((cnp->cn_flags & MAKEENTRY) != 0 && dattrflag) { 1179 /* 1180 * Cache the modification time of the parent 1181 * directory from the post-op attributes in 1182 * the name cache entry. The negative cache 1183 * entry will be ignored once the directory 1184 * has changed. Don't bother adding the entry 1185 * if the directory has already changed. 1186 */ 1187 mtx_lock(&np->n_mtx); 1188 if (timespeccmp(&np->n_vattr.na_mtime, 1189 &dnfsva.na_mtime, ==)) { 1190 mtx_unlock(&np->n_mtx); 1191 cache_enter_time(dvp, NULL, cnp, 1192 &dnfsva.na_mtime, NULL); 1193 } else 1194 mtx_unlock(&np->n_mtx); 1195 } 1196 return (ENOENT); 1197 } 1198 1199 /* 1200 * Handle RENAME case... 1201 */ 1202 if (cnp->cn_nameiop == RENAME && (flags & ISLASTCN)) { 1203 if (NFS_CMPFH(np, nfhp->nfh_fh, nfhp->nfh_len)) { 1204 FREE((caddr_t)nfhp, M_NFSFH); 1205 return (EISDIR); 1206 } 1207 error = nfscl_nget(mp, dvp, nfhp, cnp, td, &np, NULL, 1208 LK_EXCLUSIVE); 1209 if (error) 1210 return (error); 1211 newvp = NFSTOV(np); 1212 if (attrflag) 1213 (void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL, 1214 0, 1); 1215 *vpp = newvp; 1216 cnp->cn_flags |= SAVENAME; 1217 return (0); 1218 } 1219 1220 if (flags & ISDOTDOT) { 1221 ltype = NFSVOPISLOCKED(dvp); 1222 error = vfs_busy(mp, MBF_NOWAIT); 1223 if (error != 0) { 1224 vfs_ref(mp); 1225 NFSVOPUNLOCK(dvp, 0); 1226 error = vfs_busy(mp, 0); 1227 NFSVOPLOCK(dvp, ltype | LK_RETRY); 1228 vfs_rel(mp); 1229 if (error == 0 && (dvp->v_iflag & VI_DOOMED)) { 1230 vfs_unbusy(mp); 1231 error = ENOENT; 1232 } 1233 if (error != 0) 1234 return (error); 1235 } 1236 NFSVOPUNLOCK(dvp, 0); 1237 error = nfscl_nget(mp, dvp, nfhp, cnp, td, &np, NULL, 1238 cnp->cn_lkflags); 1239 if (error == 0) 1240 newvp = NFSTOV(np); 1241 vfs_unbusy(mp); 1242 if (newvp != dvp) 1243 NFSVOPLOCK(dvp, ltype | LK_RETRY); 1244 if (dvp->v_iflag & VI_DOOMED) { 1245 if (error == 0) { 1246 if (newvp == dvp) 1247 vrele(newvp); 1248 else 1249 vput(newvp); 1250 } 1251 error = ENOENT; 1252 } 1253 if (error != 0) 1254 return (error); 1255 if (attrflag) 1256 (void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL, 1257 0, 1); 1258 } else if (NFS_CMPFH(np, nfhp->nfh_fh, nfhp->nfh_len)) { 1259 FREE((caddr_t)nfhp, M_NFSFH); 1260 VREF(dvp); 1261 newvp = dvp; 1262 if (attrflag) 1263 (void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL, 1264 0, 1); 1265 } else { 1266 error = nfscl_nget(mp, dvp, nfhp, cnp, td, &np, NULL, 1267 cnp->cn_lkflags); 1268 if (error) 1269 return (error); 1270 newvp = NFSTOV(np); 1271 if (attrflag) 1272 (void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL, 1273 0, 1); 1274 else if ((flags & (ISLASTCN | ISOPEN)) == (ISLASTCN | ISOPEN) && 1275 !(np->n_flag & NMODIFIED)) { 1276 /* 1277 * Flush the attribute cache when opening a 1278 * leaf node to ensure that fresh attributes 1279 * are fetched in nfs_open() since we did not 1280 * fetch attributes from the LOOKUP reply. 1281 */ 1282 mtx_lock(&np->n_mtx); 1283 np->n_attrstamp = 0; 1284 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(newvp); 1285 mtx_unlock(&np->n_mtx); 1286 } 1287 } 1288 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 1289 cnp->cn_flags |= SAVENAME; 1290 if ((cnp->cn_flags & MAKEENTRY) && 1291 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN)) && 1292 attrflag != 0 && (newvp->v_type != VDIR || dattrflag != 0)) 1293 cache_enter_time(dvp, newvp, cnp, &nfsva.na_ctime, 1294 newvp->v_type != VDIR ? NULL : &dnfsva.na_ctime); 1295 *vpp = newvp; 1296 return (0); 1297} 1298 1299/* 1300 * nfs read call. 1301 * Just call ncl_bioread() to do the work. 1302 */ 1303static int 1304nfs_read(struct vop_read_args *ap) 1305{ 1306 struct vnode *vp = ap->a_vp; 1307 1308 switch (vp->v_type) { 1309 case VREG: 1310 return (ncl_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred)); 1311 case VDIR: 1312 return (EISDIR); 1313 default: 1314 return (EOPNOTSUPP); 1315 } 1316} 1317 1318/* 1319 * nfs readlink call 1320 */ 1321static int 1322nfs_readlink(struct vop_readlink_args *ap) 1323{ 1324 struct vnode *vp = ap->a_vp; 1325 1326 if (vp->v_type != VLNK) 1327 return (EINVAL); 1328 return (ncl_bioread(vp, ap->a_uio, 0, ap->a_cred)); 1329} 1330 1331/* 1332 * Do a readlink rpc. 1333 * Called by ncl_doio() from below the buffer cache. 1334 */ 1335int 1336ncl_readlinkrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred) 1337{ 1338 int error, ret, attrflag; 1339 struct nfsvattr nfsva; 1340 1341 error = nfsrpc_readlink(vp, uiop, cred, uiop->uio_td, &nfsva, 1342 &attrflag, NULL); 1343 if (attrflag) { 1344 ret = nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1); 1345 if (ret && !error) 1346 error = ret; 1347 } 1348 if (error && NFS_ISV4(vp)) 1349 error = nfscl_maperr(uiop->uio_td, error, (uid_t)0, (gid_t)0); 1350 return (error); 1351} 1352 1353/* 1354 * nfs read rpc call 1355 * Ditto above 1356 */ 1357int 1358ncl_readrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred) 1359{ 1360 int error, ret, attrflag; 1361 struct nfsvattr nfsva; 1362 struct nfsmount *nmp; 1363 1364 nmp = VFSTONFS(vnode_mount(vp)); 1365 error = EIO; 1366 attrflag = 0; 1367 if (NFSHASPNFS(nmp)) 1368 error = nfscl_doiods(vp, uiop, NULL, NULL, 1369 NFSV4OPEN_ACCESSREAD, cred, uiop->uio_td); 1370 NFSCL_DEBUG(4, "readrpc: aft doiods=%d\n", error); 1371 if (error != 0) 1372 error = nfsrpc_read(vp, uiop, cred, uiop->uio_td, &nfsva, 1373 &attrflag, NULL); 1374 if (attrflag) { 1375 ret = nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1); 1376 if (ret && !error) 1377 error = ret; 1378 } 1379 if (error && NFS_ISV4(vp)) 1380 error = nfscl_maperr(uiop->uio_td, error, (uid_t)0, (gid_t)0); 1381 return (error); 1382} 1383 1384/* 1385 * nfs write call 1386 */ 1387int 1388ncl_writerpc(struct vnode *vp, struct uio *uiop, struct ucred *cred, 1389 int *iomode, int *must_commit, int called_from_strategy) 1390{ 1391 struct nfsvattr nfsva; 1392 int error, attrflag, ret; 1393 struct nfsmount *nmp; 1394 1395 nmp = VFSTONFS(vnode_mount(vp)); 1396 error = EIO; 1397 attrflag = 0; 1398 if (NFSHASPNFS(nmp)) 1399 error = nfscl_doiods(vp, uiop, iomode, must_commit, 1400 NFSV4OPEN_ACCESSWRITE, cred, uiop->uio_td); 1401 NFSCL_DEBUG(4, "writerpc: aft doiods=%d\n", error); 1402 if (error != 0) 1403 error = nfsrpc_write(vp, uiop, iomode, must_commit, cred, 1404 uiop->uio_td, &nfsva, &attrflag, NULL, 1405 called_from_strategy); 1406 if (attrflag) { 1407 if (VTONFS(vp)->n_flag & ND_NFSV4) 1408 ret = nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 1, 1409 1); 1410 else 1411 ret = nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1412 1); 1413 if (ret && !error) 1414 error = ret; 1415 } 1416 if (DOINGASYNC(vp)) 1417 *iomode = NFSWRITE_FILESYNC; 1418 if (error && NFS_ISV4(vp)) 1419 error = nfscl_maperr(uiop->uio_td, error, (uid_t)0, (gid_t)0); 1420 return (error); 1421} 1422 1423/* 1424 * nfs mknod rpc 1425 * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the 1426 * mode set to specify the file type and the size field for rdev. 1427 */ 1428static int 1429nfs_mknodrpc(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp, 1430 struct vattr *vap) 1431{ 1432 struct nfsvattr nfsva, dnfsva; 1433 struct vnode *newvp = NULL; 1434 struct nfsnode *np = NULL, *dnp; 1435 struct nfsfh *nfhp; 1436 struct vattr vattr; 1437 int error = 0, attrflag, dattrflag; 1438 u_int32_t rdev; 1439 1440 if (vap->va_type == VCHR || vap->va_type == VBLK) 1441 rdev = vap->va_rdev; 1442 else if (vap->va_type == VFIFO || vap->va_type == VSOCK) 1443 rdev = 0xffffffff; 1444 else 1445 return (EOPNOTSUPP); 1446 if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred))) 1447 return (error); 1448 error = nfsrpc_mknod(dvp, cnp->cn_nameptr, cnp->cn_namelen, vap, 1449 rdev, vap->va_type, cnp->cn_cred, cnp->cn_thread, &dnfsva, 1450 &nfsva, &nfhp, &attrflag, &dattrflag, NULL); 1451 if (!error) { 1452 if (!nfhp) 1453 (void) nfsrpc_lookup(dvp, cnp->cn_nameptr, 1454 cnp->cn_namelen, cnp->cn_cred, cnp->cn_thread, 1455 &dnfsva, &nfsva, &nfhp, &attrflag, &dattrflag, 1456 NULL); 1457 if (nfhp) 1458 error = nfscl_nget(dvp->v_mount, dvp, nfhp, cnp, 1459 cnp->cn_thread, &np, NULL, LK_EXCLUSIVE); 1460 } 1461 if (dattrflag) 1462 (void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1); 1463 if (!error) { 1464 newvp = NFSTOV(np); 1465 if (attrflag != 0) { 1466 error = nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL, 1467 0, 1); 1468 if (error != 0) 1469 vput(newvp); 1470 } 1471 } 1472 if (!error) { 1473 *vpp = newvp; 1474 } else if (NFS_ISV4(dvp)) { 1475 error = nfscl_maperr(cnp->cn_thread, error, vap->va_uid, 1476 vap->va_gid); 1477 } 1478 dnp = VTONFS(dvp); 1479 mtx_lock(&dnp->n_mtx); 1480 dnp->n_flag |= NMODIFIED; 1481 if (!dattrflag) { 1482 dnp->n_attrstamp = 0; 1483 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp); 1484 } 1485 mtx_unlock(&dnp->n_mtx); 1486 return (error); 1487} 1488 1489/* 1490 * nfs mknod vop 1491 * just call nfs_mknodrpc() to do the work. 1492 */ 1493/* ARGSUSED */ 1494static int 1495nfs_mknod(struct vop_mknod_args *ap) 1496{ 1497 return (nfs_mknodrpc(ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap)); 1498} 1499 1500static struct mtx nfs_cverf_mtx; 1501MTX_SYSINIT(nfs_cverf_mtx, &nfs_cverf_mtx, "NFS create verifier mutex", 1502 MTX_DEF); 1503 1504static nfsquad_t 1505nfs_get_cverf(void) 1506{ 1507 static nfsquad_t cverf; 1508 nfsquad_t ret; 1509 static int cverf_initialized = 0; 1510 1511 mtx_lock(&nfs_cverf_mtx); 1512 if (cverf_initialized == 0) { 1513 cverf.lval[0] = arc4random(); 1514 cverf.lval[1] = arc4random(); 1515 cverf_initialized = 1; 1516 } else 1517 cverf.qval++; 1518 ret = cverf; 1519 mtx_unlock(&nfs_cverf_mtx); 1520 1521 return (ret); 1522} 1523 1524/* 1525 * nfs file create call 1526 */ 1527static int 1528nfs_create(struct vop_create_args *ap) 1529{ 1530 struct vnode *dvp = ap->a_dvp; 1531 struct vattr *vap = ap->a_vap; 1532 struct componentname *cnp = ap->a_cnp; 1533 struct nfsnode *np = NULL, *dnp; 1534 struct vnode *newvp = NULL; 1535 struct nfsmount *nmp; 1536 struct nfsvattr dnfsva, nfsva; 1537 struct nfsfh *nfhp; 1538 nfsquad_t cverf; 1539 int error = 0, attrflag, dattrflag, fmode = 0; 1540 struct vattr vattr; 1541 1542 /* 1543 * Oops, not for me.. 1544 */ 1545 if (vap->va_type == VSOCK) 1546 return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap)); 1547 1548 if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred))) 1549 return (error); 1550 if (vap->va_vaflags & VA_EXCLUSIVE) 1551 fmode |= O_EXCL; 1552 dnp = VTONFS(dvp); 1553 nmp = VFSTONFS(vnode_mount(dvp)); 1554again: 1555 /* For NFSv4, wait until any remove is done. */ 1556 mtx_lock(&dnp->n_mtx); 1557 while (NFSHASNFSV4(nmp) && (dnp->n_flag & NREMOVEINPROG)) { 1558 dnp->n_flag |= NREMOVEWANT; 1559 (void) msleep((caddr_t)dnp, &dnp->n_mtx, PZERO, "nfscrt", 0); 1560 } 1561 mtx_unlock(&dnp->n_mtx); 1562 1563 cverf = nfs_get_cverf(); 1564 error = nfsrpc_create(dvp, cnp->cn_nameptr, cnp->cn_namelen, 1565 vap, cverf, fmode, cnp->cn_cred, cnp->cn_thread, &dnfsva, &nfsva, 1566 &nfhp, &attrflag, &dattrflag, NULL); 1567 if (!error) { 1568 if (nfhp == NULL) 1569 (void) nfsrpc_lookup(dvp, cnp->cn_nameptr, 1570 cnp->cn_namelen, cnp->cn_cred, cnp->cn_thread, 1571 &dnfsva, &nfsva, &nfhp, &attrflag, &dattrflag, 1572 NULL); 1573 if (nfhp != NULL) 1574 error = nfscl_nget(dvp->v_mount, dvp, nfhp, cnp, 1575 cnp->cn_thread, &np, NULL, LK_EXCLUSIVE); 1576 } 1577 if (dattrflag) 1578 (void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1); 1579 if (!error) { 1580 newvp = NFSTOV(np); 1581 if (attrflag == 0) 1582 error = nfsrpc_getattr(newvp, cnp->cn_cred, 1583 cnp->cn_thread, &nfsva, NULL); 1584 if (error == 0) 1585 error = nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL, 1586 0, 1); 1587 } 1588 if (error) { 1589 if (newvp != NULL) { 1590 vput(newvp); 1591 newvp = NULL; 1592 } 1593 if (NFS_ISV34(dvp) && (fmode & O_EXCL) && 1594 error == NFSERR_NOTSUPP) { 1595 fmode &= ~O_EXCL; 1596 goto again; 1597 } 1598 } else if (NFS_ISV34(dvp) && (fmode & O_EXCL)) { 1599 if (nfscl_checksattr(vap, &nfsva)) { 1600 error = nfsrpc_setattr(newvp, vap, NULL, cnp->cn_cred, 1601 cnp->cn_thread, &nfsva, &attrflag, NULL); 1602 if (error && (vap->va_uid != (uid_t)VNOVAL || 1603 vap->va_gid != (gid_t)VNOVAL)) { 1604 /* try again without setting uid/gid */ 1605 vap->va_uid = (uid_t)VNOVAL; 1606 vap->va_gid = (uid_t)VNOVAL; 1607 error = nfsrpc_setattr(newvp, vap, NULL, 1608 cnp->cn_cred, cnp->cn_thread, &nfsva, 1609 &attrflag, NULL); 1610 } 1611 if (attrflag) 1612 (void) nfscl_loadattrcache(&newvp, &nfsva, NULL, 1613 NULL, 0, 1); 1614 if (error != 0) 1615 vput(newvp); 1616 } 1617 } 1618 if (!error) { 1619 if ((cnp->cn_flags & MAKEENTRY) && attrflag) 1620 cache_enter_time(dvp, newvp, cnp, &nfsva.na_ctime, 1621 NULL); 1622 *ap->a_vpp = newvp; 1623 } else if (NFS_ISV4(dvp)) { 1624 error = nfscl_maperr(cnp->cn_thread, error, vap->va_uid, 1625 vap->va_gid); 1626 } 1627 mtx_lock(&dnp->n_mtx); 1628 dnp->n_flag |= NMODIFIED; 1629 if (!dattrflag) { 1630 dnp->n_attrstamp = 0; 1631 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp); 1632 } 1633 mtx_unlock(&dnp->n_mtx); 1634 return (error); 1635} 1636 1637/* 1638 * nfs file remove call 1639 * To try and make nfs semantics closer to ufs semantics, a file that has 1640 * other processes using the vnode is renamed instead of removed and then 1641 * removed later on the last close. 1642 * - If v_usecount > 1 1643 * If a rename is not already in the works 1644 * call nfs_sillyrename() to set it up 1645 * else 1646 * do the remove rpc 1647 */ 1648static int 1649nfs_remove(struct vop_remove_args *ap) 1650{ 1651 struct vnode *vp = ap->a_vp; 1652 struct vnode *dvp = ap->a_dvp; 1653 struct componentname *cnp = ap->a_cnp; 1654 struct nfsnode *np = VTONFS(vp); 1655 int error = 0; 1656 struct vattr vattr; 1657 1658 KASSERT((cnp->cn_flags & HASBUF) != 0, ("nfs_remove: no name")); 1659 KASSERT(vrefcnt(vp) > 0, ("nfs_remove: bad v_usecount")); 1660 if (vp->v_type == VDIR) 1661 error = EPERM; 1662 else if (vrefcnt(vp) == 1 || (np->n_sillyrename && 1663 VOP_GETATTR(vp, &vattr, cnp->cn_cred) == 0 && 1664 vattr.va_nlink > 1)) { 1665 /* 1666 * Purge the name cache so that the chance of a lookup for 1667 * the name succeeding while the remove is in progress is 1668 * minimized. Without node locking it can still happen, such 1669 * that an I/O op returns ESTALE, but since you get this if 1670 * another host removes the file.. 1671 */ 1672 cache_purge(vp); 1673 /* 1674 * throw away biocache buffers, mainly to avoid 1675 * unnecessary delayed writes later. 1676 */ 1677 error = ncl_vinvalbuf(vp, 0, cnp->cn_thread, 1); 1678 /* Do the rpc */ 1679 if (error != EINTR && error != EIO) 1680 error = nfs_removerpc(dvp, vp, cnp->cn_nameptr, 1681 cnp->cn_namelen, cnp->cn_cred, cnp->cn_thread); 1682 /* 1683 * Kludge City: If the first reply to the remove rpc is lost.. 1684 * the reply to the retransmitted request will be ENOENT 1685 * since the file was in fact removed 1686 * Therefore, we cheat and return success. 1687 */ 1688 if (error == ENOENT) 1689 error = 0; 1690 } else if (!np->n_sillyrename) 1691 error = nfs_sillyrename(dvp, vp, cnp); 1692 mtx_lock(&np->n_mtx); 1693 np->n_attrstamp = 0; 1694 mtx_unlock(&np->n_mtx); 1695 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); 1696 return (error); 1697} 1698 1699/* 1700 * nfs file remove rpc called from nfs_inactive 1701 */ 1702int 1703ncl_removeit(struct sillyrename *sp, struct vnode *vp) 1704{ 1705 /* 1706 * Make sure that the directory vnode is still valid. 1707 * XXX we should lock sp->s_dvp here. 1708 */ 1709 if (sp->s_dvp->v_type == VBAD) 1710 return (0); 1711 return (nfs_removerpc(sp->s_dvp, vp, sp->s_name, sp->s_namlen, 1712 sp->s_cred, NULL)); 1713} 1714 1715/* 1716 * Nfs remove rpc, called from nfs_remove() and ncl_removeit(). 1717 */ 1718static int 1719nfs_removerpc(struct vnode *dvp, struct vnode *vp, char *name, 1720 int namelen, struct ucred *cred, struct thread *td) 1721{ 1722 struct nfsvattr dnfsva; 1723 struct nfsnode *dnp = VTONFS(dvp); 1724 int error = 0, dattrflag; 1725 1726 mtx_lock(&dnp->n_mtx); 1727 dnp->n_flag |= NREMOVEINPROG; 1728 mtx_unlock(&dnp->n_mtx); 1729 error = nfsrpc_remove(dvp, name, namelen, vp, cred, td, &dnfsva, 1730 &dattrflag, NULL); 1731 mtx_lock(&dnp->n_mtx); 1732 if ((dnp->n_flag & NREMOVEWANT)) { 1733 dnp->n_flag &= ~(NREMOVEWANT | NREMOVEINPROG); 1734 mtx_unlock(&dnp->n_mtx); 1735 wakeup((caddr_t)dnp); 1736 } else { 1737 dnp->n_flag &= ~NREMOVEINPROG; 1738 mtx_unlock(&dnp->n_mtx); 1739 } 1740 if (dattrflag) 1741 (void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1); 1742 mtx_lock(&dnp->n_mtx); 1743 dnp->n_flag |= NMODIFIED; 1744 if (!dattrflag) { 1745 dnp->n_attrstamp = 0; 1746 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp); 1747 } 1748 mtx_unlock(&dnp->n_mtx); 1749 if (error && NFS_ISV4(dvp)) 1750 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0); 1751 return (error); 1752} 1753 1754/* 1755 * nfs file rename call 1756 */ 1757static int 1758nfs_rename(struct vop_rename_args *ap) 1759{ 1760 struct vnode *fvp = ap->a_fvp; 1761 struct vnode *tvp = ap->a_tvp; 1762 struct vnode *fdvp = ap->a_fdvp; 1763 struct vnode *tdvp = ap->a_tdvp; 1764 struct componentname *tcnp = ap->a_tcnp; 1765 struct componentname *fcnp = ap->a_fcnp; 1766 struct nfsnode *fnp = VTONFS(ap->a_fvp); 1767 struct nfsnode *tdnp = VTONFS(ap->a_tdvp); 1768 struct nfsv4node *newv4 = NULL; 1769 int error; 1770 1771 KASSERT((tcnp->cn_flags & HASBUF) != 0 && 1772 (fcnp->cn_flags & HASBUF) != 0, ("nfs_rename: no name")); 1773 /* Check for cross-device rename */ 1774 if ((fvp->v_mount != tdvp->v_mount) || 1775 (tvp && (fvp->v_mount != tvp->v_mount))) { 1776 error = EXDEV; 1777 goto out; 1778 } 1779 1780 if (fvp == tvp) { 1781 printf("nfs_rename: fvp == tvp (can't happen)\n"); 1782 error = 0; 1783 goto out; 1784 } 1785 if ((error = NFSVOPLOCK(fvp, LK_EXCLUSIVE)) != 0) 1786 goto out; 1787 1788 /* 1789 * We have to flush B_DELWRI data prior to renaming 1790 * the file. If we don't, the delayed-write buffers 1791 * can be flushed out later after the file has gone stale 1792 * under NFSV3. NFSV2 does not have this problem because 1793 * ( as far as I can tell ) it flushes dirty buffers more 1794 * often. 1795 * 1796 * Skip the rename operation if the fsync fails, this can happen 1797 * due to the server's volume being full, when we pushed out data 1798 * that was written back to our cache earlier. Not checking for 1799 * this condition can result in potential (silent) data loss. 1800 */ 1801 error = VOP_FSYNC(fvp, MNT_WAIT, fcnp->cn_thread); 1802 NFSVOPUNLOCK(fvp, 0); 1803 if (!error && tvp) 1804 error = VOP_FSYNC(tvp, MNT_WAIT, tcnp->cn_thread); 1805 if (error) 1806 goto out; 1807 1808 /* 1809 * If the tvp exists and is in use, sillyrename it before doing the 1810 * rename of the new file over it. 1811 * XXX Can't sillyrename a directory. 1812 */ 1813 if (tvp && vrefcnt(tvp) > 1 && !VTONFS(tvp)->n_sillyrename && 1814 tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) { 1815 vput(tvp); 1816 tvp = NULL; 1817 } 1818 1819 error = nfs_renamerpc(fdvp, fvp, fcnp->cn_nameptr, fcnp->cn_namelen, 1820 tdvp, tvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred, 1821 tcnp->cn_thread); 1822 1823 if (error == 0 && NFS_ISV4(tdvp)) { 1824 /* 1825 * For NFSv4, check to see if it is the same name and 1826 * replace the name, if it is different. 1827 */ 1828 MALLOC(newv4, struct nfsv4node *, 1829 sizeof (struct nfsv4node) + 1830 tdnp->n_fhp->nfh_len + tcnp->cn_namelen - 1, 1831 M_NFSV4NODE, M_WAITOK); 1832 mtx_lock(&tdnp->n_mtx); 1833 mtx_lock(&fnp->n_mtx); 1834 if (fnp->n_v4 != NULL && fvp->v_type == VREG && 1835 (fnp->n_v4->n4_namelen != tcnp->cn_namelen || 1836 NFSBCMP(tcnp->cn_nameptr, NFS4NODENAME(fnp->n_v4), 1837 tcnp->cn_namelen) || 1838 tdnp->n_fhp->nfh_len != fnp->n_v4->n4_fhlen || 1839 NFSBCMP(tdnp->n_fhp->nfh_fh, fnp->n_v4->n4_data, 1840 tdnp->n_fhp->nfh_len))) { 1841#ifdef notdef 1842{ char nnn[100]; int nnnl; 1843nnnl = (tcnp->cn_namelen < 100) ? tcnp->cn_namelen : 99; 1844bcopy(tcnp->cn_nameptr, nnn, nnnl); 1845nnn[nnnl] = '\0'; 1846printf("ren replace=%s\n",nnn); 1847} 1848#endif 1849 FREE((caddr_t)fnp->n_v4, M_NFSV4NODE); 1850 fnp->n_v4 = newv4; 1851 newv4 = NULL; 1852 fnp->n_v4->n4_fhlen = tdnp->n_fhp->nfh_len; 1853 fnp->n_v4->n4_namelen = tcnp->cn_namelen; 1854 NFSBCOPY(tdnp->n_fhp->nfh_fh, fnp->n_v4->n4_data, 1855 tdnp->n_fhp->nfh_len); 1856 NFSBCOPY(tcnp->cn_nameptr, 1857 NFS4NODENAME(fnp->n_v4), tcnp->cn_namelen); 1858 } 1859 mtx_unlock(&tdnp->n_mtx); 1860 mtx_unlock(&fnp->n_mtx); 1861 if (newv4 != NULL) 1862 FREE((caddr_t)newv4, M_NFSV4NODE); 1863 } 1864 1865 if (fvp->v_type == VDIR) { 1866 if (tvp != NULL && tvp->v_type == VDIR) 1867 cache_purge(tdvp); 1868 cache_purge(fdvp); 1869 } 1870 1871out: 1872 if (tdvp == tvp) 1873 vrele(tdvp); 1874 else 1875 vput(tdvp); 1876 if (tvp) 1877 vput(tvp); 1878 vrele(fdvp); 1879 vrele(fvp); 1880 /* 1881 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. 1882 */ 1883 if (error == ENOENT) 1884 error = 0; 1885 return (error); 1886} 1887 1888/* 1889 * nfs file rename rpc called from nfs_remove() above 1890 */ 1891static int 1892nfs_renameit(struct vnode *sdvp, struct vnode *svp, struct componentname *scnp, 1893 struct sillyrename *sp) 1894{ 1895 1896 return (nfs_renamerpc(sdvp, svp, scnp->cn_nameptr, scnp->cn_namelen, 1897 sdvp, NULL, sp->s_name, sp->s_namlen, scnp->cn_cred, 1898 scnp->cn_thread)); 1899} 1900 1901/* 1902 * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit(). 1903 */ 1904static int 1905nfs_renamerpc(struct vnode *fdvp, struct vnode *fvp, char *fnameptr, 1906 int fnamelen, struct vnode *tdvp, struct vnode *tvp, char *tnameptr, 1907 int tnamelen, struct ucred *cred, struct thread *td) 1908{ 1909 struct nfsvattr fnfsva, tnfsva; 1910 struct nfsnode *fdnp = VTONFS(fdvp); 1911 struct nfsnode *tdnp = VTONFS(tdvp); 1912 int error = 0, fattrflag, tattrflag; 1913 1914 error = nfsrpc_rename(fdvp, fvp, fnameptr, fnamelen, tdvp, tvp, 1915 tnameptr, tnamelen, cred, td, &fnfsva, &tnfsva, &fattrflag, 1916 &tattrflag, NULL, NULL); 1917 mtx_lock(&fdnp->n_mtx); 1918 fdnp->n_flag |= NMODIFIED; 1919 if (fattrflag != 0) { 1920 mtx_unlock(&fdnp->n_mtx); 1921 (void) nfscl_loadattrcache(&fdvp, &fnfsva, NULL, NULL, 0, 1); 1922 } else { 1923 fdnp->n_attrstamp = 0; 1924 mtx_unlock(&fdnp->n_mtx); 1925 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(fdvp); 1926 } 1927 mtx_lock(&tdnp->n_mtx); 1928 tdnp->n_flag |= NMODIFIED; 1929 if (tattrflag != 0) { 1930 mtx_unlock(&tdnp->n_mtx); 1931 (void) nfscl_loadattrcache(&tdvp, &tnfsva, NULL, NULL, 0, 1); 1932 } else { 1933 tdnp->n_attrstamp = 0; 1934 mtx_unlock(&tdnp->n_mtx); 1935 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(tdvp); 1936 } 1937 if (error && NFS_ISV4(fdvp)) 1938 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0); 1939 return (error); 1940} 1941 1942/* 1943 * nfs hard link create call 1944 */ 1945static int 1946nfs_link(struct vop_link_args *ap) 1947{ 1948 struct vnode *vp = ap->a_vp; 1949 struct vnode *tdvp = ap->a_tdvp; 1950 struct componentname *cnp = ap->a_cnp; 1951 struct nfsnode *np, *tdnp; 1952 struct nfsvattr nfsva, dnfsva; 1953 int error = 0, attrflag, dattrflag; 1954 1955 /* 1956 * Push all writes to the server, so that the attribute cache 1957 * doesn't get "out of sync" with the server. 1958 * XXX There should be a better way! 1959 */ 1960 VOP_FSYNC(vp, MNT_WAIT, cnp->cn_thread); 1961 1962 error = nfsrpc_link(tdvp, vp, cnp->cn_nameptr, cnp->cn_namelen, 1963 cnp->cn_cred, cnp->cn_thread, &dnfsva, &nfsva, &attrflag, 1964 &dattrflag, NULL); 1965 tdnp = VTONFS(tdvp); 1966 mtx_lock(&tdnp->n_mtx); 1967 tdnp->n_flag |= NMODIFIED; 1968 if (dattrflag != 0) { 1969 mtx_unlock(&tdnp->n_mtx); 1970 (void) nfscl_loadattrcache(&tdvp, &dnfsva, NULL, NULL, 0, 1); 1971 } else { 1972 tdnp->n_attrstamp = 0; 1973 mtx_unlock(&tdnp->n_mtx); 1974 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(tdvp); 1975 } 1976 if (attrflag) 1977 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1); 1978 else { 1979 np = VTONFS(vp); 1980 mtx_lock(&np->n_mtx); 1981 np->n_attrstamp = 0; 1982 mtx_unlock(&np->n_mtx); 1983 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); 1984 } 1985 /* 1986 * If negative lookup caching is enabled, I might as well 1987 * add an entry for this node. Not necessary for correctness, 1988 * but if negative caching is enabled, then the system 1989 * must care about lookup caching hit rate, so... 1990 */ 1991 if (VFSTONFS(vp->v_mount)->nm_negnametimeo != 0 && 1992 (cnp->cn_flags & MAKEENTRY) && attrflag != 0 && error == 0) { 1993 cache_enter_time(tdvp, vp, cnp, &nfsva.na_ctime, NULL); 1994 } 1995 if (error && NFS_ISV4(vp)) 1996 error = nfscl_maperr(cnp->cn_thread, error, (uid_t)0, 1997 (gid_t)0); 1998 return (error); 1999} 2000 2001/* 2002 * nfs symbolic link create call 2003 */ 2004static int 2005nfs_symlink(struct vop_symlink_args *ap) 2006{ 2007 struct vnode *dvp = ap->a_dvp; 2008 struct vattr *vap = ap->a_vap; 2009 struct componentname *cnp = ap->a_cnp; 2010 struct nfsvattr nfsva, dnfsva; 2011 struct nfsfh *nfhp; 2012 struct nfsnode *np = NULL, *dnp; 2013 struct vnode *newvp = NULL; 2014 int error = 0, attrflag, dattrflag, ret; 2015 2016 vap->va_type = VLNK; 2017 error = nfsrpc_symlink(dvp, cnp->cn_nameptr, cnp->cn_namelen, 2018 ap->a_target, vap, cnp->cn_cred, cnp->cn_thread, &dnfsva, 2019 &nfsva, &nfhp, &attrflag, &dattrflag, NULL); 2020 if (nfhp) { 2021 ret = nfscl_nget(dvp->v_mount, dvp, nfhp, cnp, cnp->cn_thread, 2022 &np, NULL, LK_EXCLUSIVE); 2023 if (!ret) 2024 newvp = NFSTOV(np); 2025 else if (!error) 2026 error = ret; 2027 } 2028 if (newvp != NULL) { 2029 if (attrflag) 2030 (void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL, 2031 0, 1); 2032 } else if (!error) { 2033 /* 2034 * If we do not have an error and we could not extract the 2035 * newvp from the response due to the request being NFSv2, we 2036 * have to do a lookup in order to obtain a newvp to return. 2037 */ 2038 error = nfs_lookitup(dvp, cnp->cn_nameptr, cnp->cn_namelen, 2039 cnp->cn_cred, cnp->cn_thread, &np); 2040 if (!error) 2041 newvp = NFSTOV(np); 2042 } 2043 if (error) { 2044 if (newvp) 2045 vput(newvp); 2046 if (NFS_ISV4(dvp)) 2047 error = nfscl_maperr(cnp->cn_thread, error, 2048 vap->va_uid, vap->va_gid); 2049 } else { 2050 *ap->a_vpp = newvp; 2051 } 2052 2053 dnp = VTONFS(dvp); 2054 mtx_lock(&dnp->n_mtx); 2055 dnp->n_flag |= NMODIFIED; 2056 if (dattrflag != 0) { 2057 mtx_unlock(&dnp->n_mtx); 2058 (void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1); 2059 } else { 2060 dnp->n_attrstamp = 0; 2061 mtx_unlock(&dnp->n_mtx); 2062 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp); 2063 } 2064 /* 2065 * If negative lookup caching is enabled, I might as well 2066 * add an entry for this node. Not necessary for correctness, 2067 * but if negative caching is enabled, then the system 2068 * must care about lookup caching hit rate, so... 2069 */ 2070 if (VFSTONFS(dvp->v_mount)->nm_negnametimeo != 0 && 2071 (cnp->cn_flags & MAKEENTRY) && attrflag != 0 && error == 0) { 2072 cache_enter_time(dvp, newvp, cnp, &nfsva.na_ctime, NULL); 2073 } 2074 return (error); 2075} 2076 2077/* 2078 * nfs make dir call 2079 */ 2080static int 2081nfs_mkdir(struct vop_mkdir_args *ap) 2082{ 2083 struct vnode *dvp = ap->a_dvp; 2084 struct vattr *vap = ap->a_vap; 2085 struct componentname *cnp = ap->a_cnp; 2086 struct nfsnode *np = NULL, *dnp; 2087 struct vnode *newvp = NULL; 2088 struct vattr vattr; 2089 struct nfsfh *nfhp; 2090 struct nfsvattr nfsva, dnfsva; 2091 int error = 0, attrflag, dattrflag, ret; 2092 2093 if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred)) != 0) 2094 return (error); 2095 vap->va_type = VDIR; 2096 error = nfsrpc_mkdir(dvp, cnp->cn_nameptr, cnp->cn_namelen, 2097 vap, cnp->cn_cred, cnp->cn_thread, &dnfsva, &nfsva, &nfhp, 2098 &attrflag, &dattrflag, NULL); 2099 dnp = VTONFS(dvp); 2100 mtx_lock(&dnp->n_mtx); 2101 dnp->n_flag |= NMODIFIED; 2102 if (dattrflag != 0) { 2103 mtx_unlock(&dnp->n_mtx); 2104 (void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1); 2105 } else { 2106 dnp->n_attrstamp = 0; 2107 mtx_unlock(&dnp->n_mtx); 2108 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp); 2109 } 2110 if (nfhp) { 2111 ret = nfscl_nget(dvp->v_mount, dvp, nfhp, cnp, cnp->cn_thread, 2112 &np, NULL, LK_EXCLUSIVE); 2113 if (!ret) { 2114 newvp = NFSTOV(np); 2115 if (attrflag) 2116 (void) nfscl_loadattrcache(&newvp, &nfsva, NULL, 2117 NULL, 0, 1); 2118 } else if (!error) 2119 error = ret; 2120 } 2121 if (!error && newvp == NULL) { 2122 error = nfs_lookitup(dvp, cnp->cn_nameptr, cnp->cn_namelen, 2123 cnp->cn_cred, cnp->cn_thread, &np); 2124 if (!error) { 2125 newvp = NFSTOV(np); 2126 if (newvp->v_type != VDIR) 2127 error = EEXIST; 2128 } 2129 } 2130 if (error) { 2131 if (newvp) 2132 vput(newvp); 2133 if (NFS_ISV4(dvp)) 2134 error = nfscl_maperr(cnp->cn_thread, error, 2135 vap->va_uid, vap->va_gid); 2136 } else { 2137 /* 2138 * If negative lookup caching is enabled, I might as well 2139 * add an entry for this node. Not necessary for correctness, 2140 * but if negative caching is enabled, then the system 2141 * must care about lookup caching hit rate, so... 2142 */ 2143 if (VFSTONFS(dvp->v_mount)->nm_negnametimeo != 0 && 2144 (cnp->cn_flags & MAKEENTRY) && 2145 attrflag != 0 && dattrflag != 0) 2146 cache_enter_time(dvp, newvp, cnp, &nfsva.na_ctime, 2147 &dnfsva.na_ctime); 2148 *ap->a_vpp = newvp; 2149 } 2150 return (error); 2151} 2152 2153/* 2154 * nfs remove directory call 2155 */ 2156static int 2157nfs_rmdir(struct vop_rmdir_args *ap) 2158{ 2159 struct vnode *vp = ap->a_vp; 2160 struct vnode *dvp = ap->a_dvp; 2161 struct componentname *cnp = ap->a_cnp; 2162 struct nfsnode *dnp; 2163 struct nfsvattr dnfsva; 2164 int error, dattrflag; 2165 2166 if (dvp == vp) 2167 return (EINVAL); 2168 error = nfsrpc_rmdir(dvp, cnp->cn_nameptr, cnp->cn_namelen, 2169 cnp->cn_cred, cnp->cn_thread, &dnfsva, &dattrflag, NULL); 2170 dnp = VTONFS(dvp); 2171 mtx_lock(&dnp->n_mtx); 2172 dnp->n_flag |= NMODIFIED; 2173 if (dattrflag != 0) { 2174 mtx_unlock(&dnp->n_mtx); 2175 (void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1); 2176 } else { 2177 dnp->n_attrstamp = 0; 2178 mtx_unlock(&dnp->n_mtx); 2179 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp); 2180 } 2181 2182 cache_purge(dvp); 2183 cache_purge(vp); 2184 if (error && NFS_ISV4(dvp)) 2185 error = nfscl_maperr(cnp->cn_thread, error, (uid_t)0, 2186 (gid_t)0); 2187 /* 2188 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry. 2189 */ 2190 if (error == ENOENT) 2191 error = 0; 2192 return (error); 2193} 2194 2195/* 2196 * nfs readdir call 2197 */ 2198static int 2199nfs_readdir(struct vop_readdir_args *ap) 2200{ 2201 struct vnode *vp = ap->a_vp; 2202 struct nfsnode *np = VTONFS(vp); 2203 struct uio *uio = ap->a_uio; 2204 ssize_t tresid, left; 2205 int error = 0; 2206 struct vattr vattr; 2207 2208 if (ap->a_eofflag != NULL) 2209 *ap->a_eofflag = 0; 2210 if (vp->v_type != VDIR) 2211 return(EPERM); 2212 2213 /* 2214 * First, check for hit on the EOF offset cache 2215 */ 2216 if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset && 2217 (np->n_flag & NMODIFIED) == 0) { 2218 if (VOP_GETATTR(vp, &vattr, ap->a_cred) == 0) { 2219 mtx_lock(&np->n_mtx); 2220 if ((NFS_ISV4(vp) && np->n_change == vattr.va_filerev) || 2221 !NFS_TIMESPEC_COMPARE(&np->n_mtime, &vattr.va_mtime)) { 2222 mtx_unlock(&np->n_mtx); 2223 NFSINCRGLOBAL(nfsstatsv1.direofcache_hits); 2224 if (ap->a_eofflag != NULL) 2225 *ap->a_eofflag = 1; 2226 return (0); 2227 } else 2228 mtx_unlock(&np->n_mtx); 2229 } 2230 } 2231 2232 /* 2233 * NFS always guarantees that directory entries don't straddle 2234 * DIRBLKSIZ boundaries. As such, we need to limit the size 2235 * to an exact multiple of DIRBLKSIZ, to avoid copying a partial 2236 * directory entry. 2237 */ 2238 left = uio->uio_resid % DIRBLKSIZ; 2239 if (left == uio->uio_resid) 2240 return (EINVAL); 2241 uio->uio_resid -= left; 2242 2243 /* 2244 * Call ncl_bioread() to do the real work. 2245 */ 2246 tresid = uio->uio_resid; 2247 error = ncl_bioread(vp, uio, 0, ap->a_cred); 2248 2249 if (!error && uio->uio_resid == tresid) { 2250 NFSINCRGLOBAL(nfsstatsv1.direofcache_misses); 2251 if (ap->a_eofflag != NULL) 2252 *ap->a_eofflag = 1; 2253 } 2254 2255 /* Add the partial DIRBLKSIZ (left) back in. */ 2256 uio->uio_resid += left; 2257 return (error); 2258} 2259 2260/* 2261 * Readdir rpc call. 2262 * Called from below the buffer cache by ncl_doio(). 2263 */ 2264int 2265ncl_readdirrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred, 2266 struct thread *td) 2267{ 2268 struct nfsvattr nfsva; 2269 nfsuint64 *cookiep, cookie; 2270 struct nfsnode *dnp = VTONFS(vp); 2271 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2272 int error = 0, eof, attrflag; 2273 2274 KASSERT(uiop->uio_iovcnt == 1 && 2275 (uiop->uio_offset & (DIRBLKSIZ - 1)) == 0 && 2276 (uiop->uio_resid & (DIRBLKSIZ - 1)) == 0, 2277 ("nfs readdirrpc bad uio")); 2278 2279 /* 2280 * If there is no cookie, assume directory was stale. 2281 */ 2282 ncl_dircookie_lock(dnp); 2283 cookiep = ncl_getcookie(dnp, uiop->uio_offset, 0); 2284 if (cookiep) { 2285 cookie = *cookiep; 2286 ncl_dircookie_unlock(dnp); 2287 } else { 2288 ncl_dircookie_unlock(dnp); 2289 return (NFSERR_BAD_COOKIE); 2290 } 2291 2292 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) 2293 (void)ncl_fsinfo(nmp, vp, cred, td); 2294 2295 error = nfsrpc_readdir(vp, uiop, &cookie, cred, td, &nfsva, 2296 &attrflag, &eof, NULL); 2297 if (attrflag) 2298 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1); 2299 2300 if (!error) { 2301 /* 2302 * We are now either at the end of the directory or have filled 2303 * the block. 2304 */ 2305 if (eof) 2306 dnp->n_direofoffset = uiop->uio_offset; 2307 else { 2308 if (uiop->uio_resid > 0) 2309 printf("EEK! readdirrpc resid > 0\n"); 2310 ncl_dircookie_lock(dnp); 2311 cookiep = ncl_getcookie(dnp, uiop->uio_offset, 1); 2312 *cookiep = cookie; 2313 ncl_dircookie_unlock(dnp); 2314 } 2315 } else if (NFS_ISV4(vp)) { 2316 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0); 2317 } 2318 return (error); 2319} 2320 2321/* 2322 * NFS V3 readdir plus RPC. Used in place of ncl_readdirrpc(). 2323 */ 2324int 2325ncl_readdirplusrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred, 2326 struct thread *td) 2327{ 2328 struct nfsvattr nfsva; 2329 nfsuint64 *cookiep, cookie; 2330 struct nfsnode *dnp = VTONFS(vp); 2331 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2332 int error = 0, attrflag, eof; 2333 2334 KASSERT(uiop->uio_iovcnt == 1 && 2335 (uiop->uio_offset & (DIRBLKSIZ - 1)) == 0 && 2336 (uiop->uio_resid & (DIRBLKSIZ - 1)) == 0, 2337 ("nfs readdirplusrpc bad uio")); 2338 2339 /* 2340 * If there is no cookie, assume directory was stale. 2341 */ 2342 ncl_dircookie_lock(dnp); 2343 cookiep = ncl_getcookie(dnp, uiop->uio_offset, 0); 2344 if (cookiep) { 2345 cookie = *cookiep; 2346 ncl_dircookie_unlock(dnp); 2347 } else { 2348 ncl_dircookie_unlock(dnp); 2349 return (NFSERR_BAD_COOKIE); 2350 } 2351 2352 if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp)) 2353 (void)ncl_fsinfo(nmp, vp, cred, td); 2354 error = nfsrpc_readdirplus(vp, uiop, &cookie, cred, td, &nfsva, 2355 &attrflag, &eof, NULL); 2356 if (attrflag) 2357 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1); 2358 2359 if (!error) { 2360 /* 2361 * We are now either at end of the directory or have filled the 2362 * the block. 2363 */ 2364 if (eof) 2365 dnp->n_direofoffset = uiop->uio_offset; 2366 else { 2367 if (uiop->uio_resid > 0) 2368 printf("EEK! readdirplusrpc resid > 0\n"); 2369 ncl_dircookie_lock(dnp); 2370 cookiep = ncl_getcookie(dnp, uiop->uio_offset, 1); 2371 *cookiep = cookie; 2372 ncl_dircookie_unlock(dnp); 2373 } 2374 } else if (NFS_ISV4(vp)) { 2375 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0); 2376 } 2377 return (error); 2378} 2379 2380/* 2381 * Silly rename. To make the NFS filesystem that is stateless look a little 2382 * more like the "ufs" a remove of an active vnode is translated to a rename 2383 * to a funny looking filename that is removed by nfs_inactive on the 2384 * nfsnode. There is the potential for another process on a different client 2385 * to create the same funny name between the nfs_lookitup() fails and the 2386 * nfs_rename() completes, but... 2387 */ 2388static int 2389nfs_sillyrename(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 2390{ 2391 struct sillyrename *sp; 2392 struct nfsnode *np; 2393 int error; 2394 short pid; 2395 unsigned int lticks; 2396 2397 cache_purge(dvp); 2398 np = VTONFS(vp); 2399 KASSERT(vp->v_type != VDIR, ("nfs: sillyrename dir")); 2400 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename), 2401 M_NEWNFSREQ, M_WAITOK); 2402 sp->s_cred = crhold(cnp->cn_cred); 2403 sp->s_dvp = dvp; 2404 VREF(dvp); 2405 2406 /* 2407 * Fudge together a funny name. 2408 * Changing the format of the funny name to accomodate more 2409 * sillynames per directory. 2410 * The name is now changed to .nfs.<ticks>.<pid>.4, where ticks is 2411 * CPU ticks since boot. 2412 */ 2413 pid = cnp->cn_thread->td_proc->p_pid; 2414 lticks = (unsigned int)ticks; 2415 for ( ; ; ) { 2416 sp->s_namlen = sprintf(sp->s_name, 2417 ".nfs.%08x.%04x4.4", lticks, 2418 pid); 2419 if (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 2420 cnp->cn_thread, NULL)) 2421 break; 2422 lticks++; 2423 } 2424 error = nfs_renameit(dvp, vp, cnp, sp); 2425 if (error) 2426 goto bad; 2427 error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 2428 cnp->cn_thread, &np); 2429 np->n_sillyrename = sp; 2430 return (0); 2431bad: 2432 vrele(sp->s_dvp); 2433 crfree(sp->s_cred); 2434 free((caddr_t)sp, M_NEWNFSREQ); 2435 return (error); 2436} 2437 2438/* 2439 * Look up a file name and optionally either update the file handle or 2440 * allocate an nfsnode, depending on the value of npp. 2441 * npp == NULL --> just do the lookup 2442 * *npp == NULL --> allocate a new nfsnode and make sure attributes are 2443 * handled too 2444 * *npp != NULL --> update the file handle in the vnode 2445 */ 2446static int 2447nfs_lookitup(struct vnode *dvp, char *name, int len, struct ucred *cred, 2448 struct thread *td, struct nfsnode **npp) 2449{ 2450 struct vnode *newvp = NULL, *vp; 2451 struct nfsnode *np, *dnp = VTONFS(dvp); 2452 struct nfsfh *nfhp, *onfhp; 2453 struct nfsvattr nfsva, dnfsva; 2454 struct componentname cn; 2455 int error = 0, attrflag, dattrflag; 2456 u_int hash; 2457 2458 error = nfsrpc_lookup(dvp, name, len, cred, td, &dnfsva, &nfsva, 2459 &nfhp, &attrflag, &dattrflag, NULL); 2460 if (dattrflag) 2461 (void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1); 2462 if (npp && !error) { 2463 if (*npp != NULL) { 2464 np = *npp; 2465 vp = NFSTOV(np); 2466 /* 2467 * For NFSv4, check to see if it is the same name and 2468 * replace the name, if it is different. 2469 */ 2470 if (np->n_v4 != NULL && nfsva.na_type == VREG && 2471 (np->n_v4->n4_namelen != len || 2472 NFSBCMP(name, NFS4NODENAME(np->n_v4), len) || 2473 dnp->n_fhp->nfh_len != np->n_v4->n4_fhlen || 2474 NFSBCMP(dnp->n_fhp->nfh_fh, np->n_v4->n4_data, 2475 dnp->n_fhp->nfh_len))) { 2476#ifdef notdef 2477{ char nnn[100]; int nnnl; 2478nnnl = (len < 100) ? len : 99; 2479bcopy(name, nnn, nnnl); 2480nnn[nnnl] = '\0'; 2481printf("replace=%s\n",nnn); 2482} 2483#endif 2484 FREE((caddr_t)np->n_v4, M_NFSV4NODE); 2485 MALLOC(np->n_v4, struct nfsv4node *, 2486 sizeof (struct nfsv4node) + 2487 dnp->n_fhp->nfh_len + len - 1, 2488 M_NFSV4NODE, M_WAITOK); 2489 np->n_v4->n4_fhlen = dnp->n_fhp->nfh_len; 2490 np->n_v4->n4_namelen = len; 2491 NFSBCOPY(dnp->n_fhp->nfh_fh, np->n_v4->n4_data, 2492 dnp->n_fhp->nfh_len); 2493 NFSBCOPY(name, NFS4NODENAME(np->n_v4), len); 2494 } 2495 hash = fnv_32_buf(nfhp->nfh_fh, nfhp->nfh_len, 2496 FNV1_32_INIT); 2497 onfhp = np->n_fhp; 2498 /* 2499 * Rehash node for new file handle. 2500 */ 2501 vfs_hash_rehash(vp, hash); 2502 np->n_fhp = nfhp; 2503 if (onfhp != NULL) 2504 FREE((caddr_t)onfhp, M_NFSFH); 2505 newvp = NFSTOV(np); 2506 } else if (NFS_CMPFH(dnp, nfhp->nfh_fh, nfhp->nfh_len)) { 2507 FREE((caddr_t)nfhp, M_NFSFH); 2508 VREF(dvp); 2509 newvp = dvp; 2510 } else { 2511 cn.cn_nameptr = name; 2512 cn.cn_namelen = len; 2513 error = nfscl_nget(dvp->v_mount, dvp, nfhp, &cn, td, 2514 &np, NULL, LK_EXCLUSIVE); 2515 if (error) 2516 return (error); 2517 newvp = NFSTOV(np); 2518 } 2519 if (!attrflag && *npp == NULL) { 2520 if (newvp == dvp) 2521 vrele(newvp); 2522 else 2523 vput(newvp); 2524 return (ENOENT); 2525 } 2526 if (attrflag) 2527 (void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL, 2528 0, 1); 2529 } 2530 if (npp && *npp == NULL) { 2531 if (error) { 2532 if (newvp) { 2533 if (newvp == dvp) 2534 vrele(newvp); 2535 else 2536 vput(newvp); 2537 } 2538 } else 2539 *npp = np; 2540 } 2541 if (error && NFS_ISV4(dvp)) 2542 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0); 2543 return (error); 2544} 2545 2546/* 2547 * Nfs Version 3 and 4 commit rpc 2548 */ 2549int 2550ncl_commit(struct vnode *vp, u_quad_t offset, int cnt, struct ucred *cred, 2551 struct thread *td) 2552{ 2553 struct nfsvattr nfsva; 2554 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2555 int error, attrflag; 2556 2557 mtx_lock(&nmp->nm_mtx); 2558 if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0) { 2559 mtx_unlock(&nmp->nm_mtx); 2560 return (0); 2561 } 2562 mtx_unlock(&nmp->nm_mtx); 2563 error = nfsrpc_commit(vp, offset, cnt, cred, td, &nfsva, 2564 &attrflag, NULL); 2565 if (attrflag != 0) 2566 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 2567 0, 1); 2568 if (error != 0 && NFS_ISV4(vp)) 2569 error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0); 2570 return (error); 2571} 2572 2573/* 2574 * Strategy routine. 2575 * For async requests when nfsiod(s) are running, queue the request by 2576 * calling ncl_asyncio(), otherwise just all ncl_doio() to do the 2577 * request. 2578 */ 2579static int 2580nfs_strategy(struct vop_strategy_args *ap) 2581{ 2582 struct buf *bp = ap->a_bp; 2583 struct ucred *cr; 2584 2585 KASSERT(!(bp->b_flags & B_DONE), 2586 ("nfs_strategy: buffer %p unexpectedly marked B_DONE", bp)); 2587 BUF_ASSERT_HELD(bp); 2588 2589 if (bp->b_iocmd == BIO_READ) 2590 cr = bp->b_rcred; 2591 else 2592 cr = bp->b_wcred; 2593 2594 /* 2595 * If the op is asynchronous and an i/o daemon is waiting 2596 * queue the request, wake it up and wait for completion 2597 * otherwise just do it ourselves. 2598 */ 2599 if ((bp->b_flags & B_ASYNC) == 0 || 2600 ncl_asyncio(VFSTONFS(ap->a_vp->v_mount), bp, NOCRED, curthread)) 2601 (void) ncl_doio(ap->a_vp, bp, cr, curthread, 1); 2602 return (0); 2603} 2604 2605/* 2606 * fsync vnode op. Just call ncl_flush() with commit == 1. 2607 */ 2608/* ARGSUSED */ 2609static int 2610nfs_fsync(struct vop_fsync_args *ap) 2611{ 2612 2613 if (ap->a_vp->v_type != VREG) { 2614 /* 2615 * For NFS, metadata is changed synchronously on the server, 2616 * so there is nothing to flush. Also, ncl_flush() clears 2617 * the NMODIFIED flag and that shouldn't be done here for 2618 * directories. 2619 */ 2620 return (0); 2621 } 2622 return (ncl_flush(ap->a_vp, ap->a_waitfor, NULL, ap->a_td, 1, 0)); 2623} 2624 2625/* 2626 * Flush all the blocks associated with a vnode. 2627 * Walk through the buffer pool and push any dirty pages 2628 * associated with the vnode. 2629 * If the called_from_renewthread argument is TRUE, it has been called 2630 * from the NFSv4 renew thread and, as such, cannot block indefinitely 2631 * waiting for a buffer write to complete. 2632 */ 2633int 2634ncl_flush(struct vnode *vp, int waitfor, struct ucred *cred, struct thread *td, 2635 int commit, int called_from_renewthread) 2636{ 2637 struct nfsnode *np = VTONFS(vp); 2638 struct buf *bp; 2639 int i; 2640 struct buf *nbp; 2641 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2642 int error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos; 2643 int passone = 1, trycnt = 0; 2644 u_quad_t off, endoff, toff; 2645 struct ucred* wcred = NULL; 2646 struct buf **bvec = NULL; 2647 struct bufobj *bo; 2648#ifndef NFS_COMMITBVECSIZ 2649#define NFS_COMMITBVECSIZ 20 2650#endif 2651 struct buf *bvec_on_stack[NFS_COMMITBVECSIZ]; 2652 int bvecsize = 0, bveccount; 2653 2654 if (called_from_renewthread != 0) 2655 slptimeo = hz; 2656 if (nmp->nm_flag & NFSMNT_INT) 2657 slpflag = PCATCH; 2658 if (!commit) 2659 passone = 0; 2660 bo = &vp->v_bufobj; 2661 /* 2662 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the 2663 * server, but has not been committed to stable storage on the server 2664 * yet. On the first pass, the byte range is worked out and the commit 2665 * rpc is done. On the second pass, ncl_writebp() is called to do the 2666 * job. 2667 */ 2668again: 2669 off = (u_quad_t)-1; 2670 endoff = 0; 2671 bvecpos = 0; 2672 if (NFS_ISV34(vp) && commit) { 2673 if (bvec != NULL && bvec != bvec_on_stack) 2674 free(bvec, M_TEMP); 2675 /* 2676 * Count up how many buffers waiting for a commit. 2677 */ 2678 bveccount = 0; 2679 BO_LOCK(bo); 2680 TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) { 2681 if (!BUF_ISLOCKED(bp) && 2682 (bp->b_flags & (B_DELWRI | B_NEEDCOMMIT)) 2683 == (B_DELWRI | B_NEEDCOMMIT)) 2684 bveccount++; 2685 } 2686 /* 2687 * Allocate space to remember the list of bufs to commit. It is 2688 * important to use M_NOWAIT here to avoid a race with nfs_write. 2689 * If we can't get memory (for whatever reason), we will end up 2690 * committing the buffers one-by-one in the loop below. 2691 */ 2692 if (bveccount > NFS_COMMITBVECSIZ) { 2693 /* 2694 * Release the vnode interlock to avoid a lock 2695 * order reversal. 2696 */ 2697 BO_UNLOCK(bo); 2698 bvec = (struct buf **) 2699 malloc(bveccount * sizeof(struct buf *), 2700 M_TEMP, M_NOWAIT); 2701 BO_LOCK(bo); 2702 if (bvec == NULL) { 2703 bvec = bvec_on_stack; 2704 bvecsize = NFS_COMMITBVECSIZ; 2705 } else 2706 bvecsize = bveccount; 2707 } else { 2708 bvec = bvec_on_stack; 2709 bvecsize = NFS_COMMITBVECSIZ; 2710 } 2711 TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) { 2712 if (bvecpos >= bvecsize) 2713 break; 2714 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) { 2715 nbp = TAILQ_NEXT(bp, b_bobufs); 2716 continue; 2717 } 2718 if ((bp->b_flags & (B_DELWRI | B_NEEDCOMMIT)) != 2719 (B_DELWRI | B_NEEDCOMMIT)) { 2720 BUF_UNLOCK(bp); 2721 nbp = TAILQ_NEXT(bp, b_bobufs); 2722 continue; 2723 } 2724 BO_UNLOCK(bo); 2725 bremfree(bp); 2726 /* 2727 * Work out if all buffers are using the same cred 2728 * so we can deal with them all with one commit. 2729 * 2730 * NOTE: we are not clearing B_DONE here, so we have 2731 * to do it later on in this routine if we intend to 2732 * initiate I/O on the bp. 2733 * 2734 * Note: to avoid loopback deadlocks, we do not 2735 * assign b_runningbufspace. 2736 */ 2737 if (wcred == NULL) 2738 wcred = bp->b_wcred; 2739 else if (wcred != bp->b_wcred) 2740 wcred = NOCRED; 2741 vfs_busy_pages(bp, 1); 2742 2743 BO_LOCK(bo); 2744 /* 2745 * bp is protected by being locked, but nbp is not 2746 * and vfs_busy_pages() may sleep. We have to 2747 * recalculate nbp. 2748 */ 2749 nbp = TAILQ_NEXT(bp, b_bobufs); 2750 2751 /* 2752 * A list of these buffers is kept so that the 2753 * second loop knows which buffers have actually 2754 * been committed. This is necessary, since there 2755 * may be a race between the commit rpc and new 2756 * uncommitted writes on the file. 2757 */ 2758 bvec[bvecpos++] = bp; 2759 toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + 2760 bp->b_dirtyoff; 2761 if (toff < off) 2762 off = toff; 2763 toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff); 2764 if (toff > endoff) 2765 endoff = toff; 2766 } 2767 BO_UNLOCK(bo); 2768 } 2769 if (bvecpos > 0) { 2770 /* 2771 * Commit data on the server, as required. 2772 * If all bufs are using the same wcred, then use that with 2773 * one call for all of them, otherwise commit each one 2774 * separately. 2775 */ 2776 if (wcred != NOCRED) 2777 retv = ncl_commit(vp, off, (int)(endoff - off), 2778 wcred, td); 2779 else { 2780 retv = 0; 2781 for (i = 0; i < bvecpos; i++) { 2782 off_t off, size; 2783 bp = bvec[i]; 2784 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + 2785 bp->b_dirtyoff; 2786 size = (u_quad_t)(bp->b_dirtyend 2787 - bp->b_dirtyoff); 2788 retv = ncl_commit(vp, off, (int)size, 2789 bp->b_wcred, td); 2790 if (retv) break; 2791 } 2792 } 2793 2794 if (retv == NFSERR_STALEWRITEVERF) 2795 ncl_clearcommit(vp->v_mount); 2796 2797 /* 2798 * Now, either mark the blocks I/O done or mark the 2799 * blocks dirty, depending on whether the commit 2800 * succeeded. 2801 */ 2802 for (i = 0; i < bvecpos; i++) { 2803 bp = bvec[i]; 2804 bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK); 2805 if (retv) { 2806 /* 2807 * Error, leave B_DELWRI intact 2808 */ 2809 vfs_unbusy_pages(bp); 2810 brelse(bp); 2811 } else { 2812 /* 2813 * Success, remove B_DELWRI ( bundirty() ). 2814 * 2815 * b_dirtyoff/b_dirtyend seem to be NFS 2816 * specific. We should probably move that 2817 * into bundirty(). XXX 2818 */ 2819 bufobj_wref(bo); 2820 bp->b_flags |= B_ASYNC; 2821 bundirty(bp); 2822 bp->b_flags &= ~B_DONE; 2823 bp->b_ioflags &= ~BIO_ERROR; 2824 bp->b_dirtyoff = bp->b_dirtyend = 0; 2825 bufdone(bp); 2826 } 2827 } 2828 } 2829 2830 /* 2831 * Start/do any write(s) that are required. 2832 */ 2833loop: 2834 BO_LOCK(bo); 2835 TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) { 2836 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) { 2837 if (waitfor != MNT_WAIT || passone) 2838 continue; 2839 2840 error = BUF_TIMELOCK(bp, 2841 LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK, 2842 BO_LOCKPTR(bo), "nfsfsync", slpflag, slptimeo); 2843 if (error == 0) { 2844 BUF_UNLOCK(bp); 2845 goto loop; 2846 } 2847 if (error == ENOLCK) { 2848 error = 0; 2849 goto loop; 2850 } 2851 if (called_from_renewthread != 0) { 2852 /* 2853 * Return EIO so the flush will be retried 2854 * later. 2855 */ 2856 error = EIO; 2857 goto done; 2858 } 2859 if (newnfs_sigintr(nmp, td)) { 2860 error = EINTR; 2861 goto done; 2862 } 2863 if (slpflag == PCATCH) { 2864 slpflag = 0; 2865 slptimeo = 2 * hz; 2866 } 2867 goto loop; 2868 } 2869 if ((bp->b_flags & B_DELWRI) == 0) 2870 panic("nfs_fsync: not dirty"); 2871 if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT)) { 2872 BUF_UNLOCK(bp); 2873 continue; 2874 } 2875 BO_UNLOCK(bo); 2876 bremfree(bp); 2877 if (passone || !commit) 2878 bp->b_flags |= B_ASYNC; 2879 else 2880 bp->b_flags |= B_ASYNC; 2881 bwrite(bp); 2882 if (newnfs_sigintr(nmp, td)) { 2883 error = EINTR; 2884 goto done; 2885 } 2886 goto loop; 2887 } 2888 if (passone) { 2889 passone = 0; 2890 BO_UNLOCK(bo); 2891 goto again; 2892 } 2893 if (waitfor == MNT_WAIT) { 2894 while (bo->bo_numoutput) { 2895 error = bufobj_wwait(bo, slpflag, slptimeo); 2896 if (error) { 2897 BO_UNLOCK(bo); 2898 if (called_from_renewthread != 0) { 2899 /* 2900 * Return EIO so that the flush will be 2901 * retried later. 2902 */ 2903 error = EIO; 2904 goto done; 2905 } 2906 error = newnfs_sigintr(nmp, td); 2907 if (error) 2908 goto done; 2909 if (slpflag == PCATCH) { 2910 slpflag = 0; 2911 slptimeo = 2 * hz; 2912 } 2913 BO_LOCK(bo); 2914 } 2915 } 2916 if (bo->bo_dirty.bv_cnt != 0 && commit) { 2917 BO_UNLOCK(bo); 2918 goto loop; 2919 } 2920 /* 2921 * Wait for all the async IO requests to drain 2922 */ 2923 BO_UNLOCK(bo); 2924 mtx_lock(&np->n_mtx); 2925 while (np->n_directio_asyncwr > 0) { 2926 np->n_flag |= NFSYNCWAIT; 2927 error = newnfs_msleep(td, &np->n_directio_asyncwr, 2928 &np->n_mtx, slpflag | (PRIBIO + 1), 2929 "nfsfsync", 0); 2930 if (error) { 2931 if (newnfs_sigintr(nmp, td)) { 2932 mtx_unlock(&np->n_mtx); 2933 error = EINTR; 2934 goto done; 2935 } 2936 } 2937 } 2938 mtx_unlock(&np->n_mtx); 2939 } else 2940 BO_UNLOCK(bo); 2941 if (NFSHASPNFS(nmp)) { 2942 nfscl_layoutcommit(vp, td); 2943 /* 2944 * Invalidate the attribute cache, since writes to a DS 2945 * won't update the size attribute. 2946 */ 2947 mtx_lock(&np->n_mtx); 2948 np->n_attrstamp = 0; 2949 } else 2950 mtx_lock(&np->n_mtx); 2951 if (np->n_flag & NWRITEERR) { 2952 error = np->n_error; 2953 np->n_flag &= ~NWRITEERR; 2954 } 2955 if (commit && bo->bo_dirty.bv_cnt == 0 && 2956 bo->bo_numoutput == 0 && np->n_directio_asyncwr == 0) 2957 np->n_flag &= ~NMODIFIED; 2958 mtx_unlock(&np->n_mtx); 2959done: 2960 if (bvec != NULL && bvec != bvec_on_stack) 2961 free(bvec, M_TEMP); 2962 if (error == 0 && commit != 0 && waitfor == MNT_WAIT && 2963 (bo->bo_dirty.bv_cnt != 0 || bo->bo_numoutput != 0 || 2964 np->n_directio_asyncwr != 0) && trycnt++ < 5) { 2965 /* try, try again... */ 2966 passone = 1; 2967 wcred = NULL; 2968 bvec = NULL; 2969 bvecsize = 0; 2970printf("try%d\n", trycnt); 2971 goto again; 2972 } 2973 return (error); 2974} 2975 2976/* 2977 * NFS advisory byte-level locks. 2978 */ 2979static int 2980nfs_advlock(struct vop_advlock_args *ap) 2981{ 2982 struct vnode *vp = ap->a_vp; 2983 struct ucred *cred; 2984 struct nfsnode *np = VTONFS(ap->a_vp); 2985 struct proc *p = (struct proc *)ap->a_id; 2986 struct thread *td = curthread; /* XXX */ 2987 struct vattr va; 2988 int ret, error = EOPNOTSUPP; 2989 u_quad_t size; 2990 2991 if (NFS_ISV4(vp) && (ap->a_flags & (F_POSIX | F_FLOCK)) != 0) { 2992 if (vp->v_type != VREG) 2993 return (EINVAL); 2994 if ((ap->a_flags & F_POSIX) != 0) 2995 cred = p->p_ucred; 2996 else 2997 cred = td->td_ucred; 2998 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY); 2999 if (vp->v_iflag & VI_DOOMED) { 3000 NFSVOPUNLOCK(vp, 0); 3001 return (EBADF); 3002 } 3003 3004 /* 3005 * If this is unlocking a write locked region, flush and 3006 * commit them before unlocking. This is required by 3007 * RFC3530 Sec. 9.3.2. 3008 */ 3009 if (ap->a_op == F_UNLCK && 3010 nfscl_checkwritelocked(vp, ap->a_fl, cred, td, ap->a_id, 3011 ap->a_flags)) 3012 (void) ncl_flush(vp, MNT_WAIT, cred, td, 1, 0); 3013 3014 /* 3015 * Loop around doing the lock op, while a blocking lock 3016 * must wait for the lock op to succeed. 3017 */ 3018 do { 3019 ret = nfsrpc_advlock(vp, np->n_size, ap->a_op, 3020 ap->a_fl, 0, cred, td, ap->a_id, ap->a_flags); 3021 if (ret == NFSERR_DENIED && (ap->a_flags & F_WAIT) && 3022 ap->a_op == F_SETLK) { 3023 NFSVOPUNLOCK(vp, 0); 3024 error = nfs_catnap(PZERO | PCATCH, ret, 3025 "ncladvl"); 3026 if (error) 3027 return (EINTR); 3028 NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY); 3029 if (vp->v_iflag & VI_DOOMED) { 3030 NFSVOPUNLOCK(vp, 0); 3031 return (EBADF); 3032 } 3033 } 3034 } while (ret == NFSERR_DENIED && (ap->a_flags & F_WAIT) && 3035 ap->a_op == F_SETLK); 3036 if (ret == NFSERR_DENIED) { 3037 NFSVOPUNLOCK(vp, 0); 3038 return (EAGAIN); 3039 } else if (ret == EINVAL || ret == EBADF || ret == EINTR) { 3040 NFSVOPUNLOCK(vp, 0); 3041 return (ret); 3042 } else if (ret != 0) { 3043 NFSVOPUNLOCK(vp, 0); 3044 return (EACCES); 3045 } 3046 3047 /* 3048 * Now, if we just got a lock, invalidate data in the buffer 3049 * cache, as required, so that the coherency conforms with 3050 * RFC3530 Sec. 9.3.2. 3051 */ 3052 if (ap->a_op == F_SETLK) { 3053 if ((np->n_flag & NMODIFIED) == 0) { 3054 np->n_attrstamp = 0; 3055 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); 3056 ret = VOP_GETATTR(vp, &va, cred); 3057 } 3058 if ((np->n_flag & NMODIFIED) || ret || 3059 np->n_change != va.va_filerev) { 3060 (void) ncl_vinvalbuf(vp, V_SAVE, td, 1); 3061 np->n_attrstamp = 0; 3062 KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp); 3063 ret = VOP_GETATTR(vp, &va, cred); 3064 if (!ret) { 3065 np->n_mtime = va.va_mtime; 3066 np->n_change = va.va_filerev; 3067 } 3068 } 3069 /* Mark that a file lock has been acquired. */ 3070 mtx_lock(&np->n_mtx); 3071 np->n_flag |= NHASBEENLOCKED; 3072 mtx_unlock(&np->n_mtx); 3073 } 3074 NFSVOPUNLOCK(vp, 0); 3075 return (0); 3076 } else if (!NFS_ISV4(vp)) { 3077 error = NFSVOPLOCK(vp, LK_SHARED); 3078 if (error) 3079 return (error); 3080 if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NOLOCKD) != 0) { 3081 size = VTONFS(vp)->n_size; 3082 NFSVOPUNLOCK(vp, 0); 3083 error = lf_advlock(ap, &(vp->v_lockf), size); 3084 } else { 3085 if (nfs_advlock_p != NULL) 3086 error = nfs_advlock_p(ap); 3087 else { 3088 NFSVOPUNLOCK(vp, 0); 3089 error = ENOLCK; 3090 } 3091 } 3092 if (error == 0 && ap->a_op == F_SETLK) { 3093 error = NFSVOPLOCK(vp, LK_SHARED); 3094 if (error == 0) { 3095 /* Mark that a file lock has been acquired. */ 3096 mtx_lock(&np->n_mtx); 3097 np->n_flag |= NHASBEENLOCKED; 3098 mtx_unlock(&np->n_mtx); 3099 NFSVOPUNLOCK(vp, 0); 3100 } 3101 } 3102 } 3103 return (error); 3104} 3105 3106/* 3107 * NFS advisory byte-level locks. 3108 */ 3109static int 3110nfs_advlockasync(struct vop_advlockasync_args *ap) 3111{ 3112 struct vnode *vp = ap->a_vp; 3113 u_quad_t size; 3114 int error; 3115 3116 if (NFS_ISV4(vp)) 3117 return (EOPNOTSUPP); 3118 error = NFSVOPLOCK(vp, LK_SHARED); 3119 if (error) 3120 return (error); 3121 if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NOLOCKD) != 0) { 3122 size = VTONFS(vp)->n_size; 3123 NFSVOPUNLOCK(vp, 0); 3124 error = lf_advlockasync(ap, &(vp->v_lockf), size); 3125 } else { 3126 NFSVOPUNLOCK(vp, 0); 3127 error = EOPNOTSUPP; 3128 } 3129 return (error); 3130} 3131 3132/* 3133 * Print out the contents of an nfsnode. 3134 */ 3135static int 3136nfs_print(struct vop_print_args *ap) 3137{ 3138 struct vnode *vp = ap->a_vp; 3139 struct nfsnode *np = VTONFS(vp); 3140 3141 printf("\tfileid %ld fsid 0x%x", np->n_vattr.na_fileid, 3142 np->n_vattr.na_fsid); 3143 if (vp->v_type == VFIFO) 3144 fifo_printinfo(vp); 3145 printf("\n"); 3146 return (0); 3147} 3148 3149/* 3150 * This is the "real" nfs::bwrite(struct buf*). 3151 * We set B_CACHE if this is a VMIO buffer. 3152 */ 3153int 3154ncl_writebp(struct buf *bp, int force __unused, struct thread *td) 3155{ 3156 int s; 3157 int oldflags = bp->b_flags; 3158#if 0 3159 int retv = 1; 3160 off_t off; 3161#endif 3162 3163 BUF_ASSERT_HELD(bp); 3164 3165 if (bp->b_flags & B_INVAL) { 3166 brelse(bp); 3167 return(0); 3168 } 3169 3170 bp->b_flags |= B_CACHE; 3171 3172 /* 3173 * Undirty the bp. We will redirty it later if the I/O fails. 3174 */ 3175 3176 s = splbio(); 3177 bundirty(bp); 3178 bp->b_flags &= ~B_DONE; 3179 bp->b_ioflags &= ~BIO_ERROR; 3180 bp->b_iocmd = BIO_WRITE; 3181 3182 bufobj_wref(bp->b_bufobj); 3183 curthread->td_ru.ru_oublock++; 3184 splx(s); 3185 3186 /* 3187 * Note: to avoid loopback deadlocks, we do not 3188 * assign b_runningbufspace. 3189 */ 3190 vfs_busy_pages(bp, 1); 3191 3192 BUF_KERNPROC(bp); 3193 bp->b_iooffset = dbtob(bp->b_blkno); 3194 bstrategy(bp); 3195 3196 if( (oldflags & B_ASYNC) == 0) { 3197 int rtval = bufwait(bp); 3198 3199 if (oldflags & B_DELWRI) { 3200 s = splbio(); 3201 reassignbuf(bp); 3202 splx(s); 3203 } 3204 brelse(bp); 3205 return (rtval); 3206 } 3207 3208 return (0); 3209} 3210 3211/* 3212 * nfs special file access vnode op. 3213 * Essentially just get vattr and then imitate iaccess() since the device is 3214 * local to the client. 3215 */ 3216static int 3217nfsspec_access(struct vop_access_args *ap) 3218{ 3219 struct vattr *vap; 3220 struct ucred *cred = ap->a_cred; 3221 struct vnode *vp = ap->a_vp; 3222 accmode_t accmode = ap->a_accmode; 3223 struct vattr vattr; 3224 int error; 3225 3226 /* 3227 * Disallow write attempts on filesystems mounted read-only; 3228 * unless the file is a socket, fifo, or a block or character 3229 * device resident on the filesystem. 3230 */ 3231 if ((accmode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { 3232 switch (vp->v_type) { 3233 case VREG: 3234 case VDIR: 3235 case VLNK: 3236 return (EROFS); 3237 default: 3238 break; 3239 } 3240 } 3241 vap = &vattr; 3242 error = VOP_GETATTR(vp, vap, cred); 3243 if (error) 3244 goto out; 3245 error = vaccess(vp->v_type, vap->va_mode, vap->va_uid, vap->va_gid, 3246 accmode, cred, NULL); 3247out: 3248 return error; 3249} 3250 3251/* 3252 * Read wrapper for fifos. 3253 */ 3254static int 3255nfsfifo_read(struct vop_read_args *ap) 3256{ 3257 struct nfsnode *np = VTONFS(ap->a_vp); 3258 int error; 3259 3260 /* 3261 * Set access flag. 3262 */ 3263 mtx_lock(&np->n_mtx); 3264 np->n_flag |= NACC; 3265 vfs_timestamp(&np->n_atim); 3266 mtx_unlock(&np->n_mtx); 3267 error = fifo_specops.vop_read(ap); 3268 return error; 3269} 3270 3271/* 3272 * Write wrapper for fifos. 3273 */ 3274static int 3275nfsfifo_write(struct vop_write_args *ap) 3276{ 3277 struct nfsnode *np = VTONFS(ap->a_vp); 3278 3279 /* 3280 * Set update flag. 3281 */ 3282 mtx_lock(&np->n_mtx); 3283 np->n_flag |= NUPD; 3284 vfs_timestamp(&np->n_mtim); 3285 mtx_unlock(&np->n_mtx); 3286 return(fifo_specops.vop_write(ap)); 3287} 3288 3289/* 3290 * Close wrapper for fifos. 3291 * 3292 * Update the times on the nfsnode then do fifo close. 3293 */ 3294static int 3295nfsfifo_close(struct vop_close_args *ap) 3296{ 3297 struct vnode *vp = ap->a_vp; 3298 struct nfsnode *np = VTONFS(vp); 3299 struct vattr vattr; 3300 struct timespec ts; 3301 3302 mtx_lock(&np->n_mtx); 3303 if (np->n_flag & (NACC | NUPD)) { 3304 vfs_timestamp(&ts); 3305 if (np->n_flag & NACC) 3306 np->n_atim = ts; 3307 if (np->n_flag & NUPD) 3308 np->n_mtim = ts; 3309 np->n_flag |= NCHG; 3310 if (vrefcnt(vp) == 1 && 3311 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3312 VATTR_NULL(&vattr); 3313 if (np->n_flag & NACC) 3314 vattr.va_atime = np->n_atim; 3315 if (np->n_flag & NUPD) 3316 vattr.va_mtime = np->n_mtim; 3317 mtx_unlock(&np->n_mtx); 3318 (void)VOP_SETATTR(vp, &vattr, ap->a_cred); 3319 goto out; 3320 } 3321 } 3322 mtx_unlock(&np->n_mtx); 3323out: 3324 return (fifo_specops.vop_close(ap)); 3325} 3326 3327/* 3328 * Just call ncl_writebp() with the force argument set to 1. 3329 * 3330 * NOTE: B_DONE may or may not be set in a_bp on call. 3331 */ 3332static int 3333nfs_bwrite(struct buf *bp) 3334{ 3335 3336 return (ncl_writebp(bp, 1, curthread)); 3337} 3338 3339struct buf_ops buf_ops_newnfs = { 3340 .bop_name = "buf_ops_nfs", 3341 .bop_write = nfs_bwrite, 3342 .bop_strategy = bufstrategy, 3343 .bop_sync = bufsync, 3344 .bop_bdflush = bufbdflush, 3345}; 3346 3347static int 3348nfs_getacl(struct vop_getacl_args *ap) 3349{ 3350 int error; 3351 3352 if (ap->a_type != ACL_TYPE_NFS4) 3353 return (EOPNOTSUPP); 3354 error = nfsrpc_getacl(ap->a_vp, ap->a_cred, ap->a_td, ap->a_aclp, 3355 NULL); 3356 if (error > NFSERR_STALE) { 3357 (void) nfscl_maperr(ap->a_td, error, (uid_t)0, (gid_t)0); 3358 error = EPERM; 3359 } 3360 return (error); 3361} 3362 3363static int 3364nfs_setacl(struct vop_setacl_args *ap) 3365{ 3366 int error; 3367 3368 if (ap->a_type != ACL_TYPE_NFS4) 3369 return (EOPNOTSUPP); 3370 error = nfsrpc_setacl(ap->a_vp, ap->a_cred, ap->a_td, ap->a_aclp, 3371 NULL); 3372 if (error > NFSERR_STALE) { 3373 (void) nfscl_maperr(ap->a_td, error, (uid_t)0, (gid_t)0); 3374 error = EPERM; 3375 } 3376 return (error); 3377} 3378 3379/* 3380 * Return POSIX pathconf information applicable to nfs filesystems. 3381 */ 3382static int 3383nfs_pathconf(struct vop_pathconf_args *ap) 3384{ 3385 struct nfsv3_pathconf pc; 3386 struct nfsvattr nfsva; 3387 struct vnode *vp = ap->a_vp; 3388 struct thread *td = curthread; 3389 int attrflag, error; 3390 3391 if ((NFS_ISV34(vp) && (ap->a_name == _PC_LINK_MAX || 3392 ap->a_name == _PC_NAME_MAX || ap->a_name == _PC_CHOWN_RESTRICTED || 3393 ap->a_name == _PC_NO_TRUNC)) || 3394 (NFS_ISV4(vp) && ap->a_name == _PC_ACL_NFS4)) { 3395 /* 3396 * Since only the above 4 a_names are returned by the NFSv3 3397 * Pathconf RPC, there is no point in doing it for others. 3398 * For NFSv4, the Pathconf RPC (actually a Getattr Op.) can 3399 * be used for _PC_NFS4_ACL as well. 3400 */ 3401 error = nfsrpc_pathconf(vp, &pc, td->td_ucred, td, &nfsva, 3402 &attrflag, NULL); 3403 if (attrflag != 0) 3404 (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 3405 1); 3406 if (error != 0) 3407 return (error); 3408 } else { 3409 /* 3410 * For NFSv2 (or NFSv3 when not one of the above 4 a_names), 3411 * just fake them. 3412 */ 3413 pc.pc_linkmax = LINK_MAX; 3414 pc.pc_namemax = NFS_MAXNAMLEN; 3415 pc.pc_notrunc = 1; 3416 pc.pc_chownrestricted = 1; 3417 pc.pc_caseinsensitive = 0; 3418 pc.pc_casepreserving = 1; 3419 error = 0; 3420 } 3421 switch (ap->a_name) { 3422 case _PC_LINK_MAX: 3423 *ap->a_retval = pc.pc_linkmax; 3424 break; 3425 case _PC_NAME_MAX: 3426 *ap->a_retval = pc.pc_namemax; 3427 break; 3428 case _PC_PATH_MAX: 3429 *ap->a_retval = PATH_MAX; 3430 break; 3431 case _PC_PIPE_BUF: 3432 *ap->a_retval = PIPE_BUF; 3433 break; 3434 case _PC_CHOWN_RESTRICTED: 3435 *ap->a_retval = pc.pc_chownrestricted; 3436 break; 3437 case _PC_NO_TRUNC: 3438 *ap->a_retval = pc.pc_notrunc; 3439 break; 3440 case _PC_ACL_EXTENDED: 3441 *ap->a_retval = 0; 3442 break; 3443 case _PC_ACL_NFS4: 3444 if (NFS_ISV4(vp) && nfsrv_useacl != 0 && attrflag != 0 && 3445 NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL)) 3446 *ap->a_retval = 1; 3447 else 3448 *ap->a_retval = 0; 3449 break; 3450 case _PC_ACL_PATH_MAX: 3451 if (NFS_ISV4(vp)) 3452 *ap->a_retval = ACL_MAX_ENTRIES; 3453 else 3454 *ap->a_retval = 3; 3455 break; 3456 case _PC_MAC_PRESENT: 3457 *ap->a_retval = 0; 3458 break; 3459 case _PC_ASYNC_IO: 3460 /* _PC_ASYNC_IO should have been handled by upper layers. */ 3461 KASSERT(0, ("_PC_ASYNC_IO should not get here")); 3462 error = EINVAL; 3463 break; 3464 case _PC_PRIO_IO: 3465 *ap->a_retval = 0; 3466 break; 3467 case _PC_SYNC_IO: 3468 *ap->a_retval = 0; 3469 break; 3470 case _PC_ALLOC_SIZE_MIN: 3471 *ap->a_retval = vp->v_mount->mnt_stat.f_bsize; 3472 break; 3473 case _PC_FILESIZEBITS: 3474 if (NFS_ISV34(vp)) 3475 *ap->a_retval = 64; 3476 else 3477 *ap->a_retval = 32; 3478 break; 3479 case _PC_REC_INCR_XFER_SIZE: 3480 *ap->a_retval = vp->v_mount->mnt_stat.f_iosize; 3481 break; 3482 case _PC_REC_MAX_XFER_SIZE: 3483 *ap->a_retval = -1; /* means ``unlimited'' */ 3484 break; 3485 case _PC_REC_MIN_XFER_SIZE: 3486 *ap->a_retval = vp->v_mount->mnt_stat.f_iosize; 3487 break; 3488 case _PC_REC_XFER_ALIGN: 3489 *ap->a_retval = PAGE_SIZE; 3490 break; 3491 case _PC_SYMLINK_MAX: 3492 *ap->a_retval = NFS_MAXPATHLEN; 3493 break; 3494 3495 default: 3496 error = EINVAL; 3497 break; 3498 } 3499 return (error); 3500} 3501 3502