nfs_vnops.c revision 29293
1244480Sgonzo/* 2244480Sgonzo * Copyright (c) 1989, 1993 3244480Sgonzo * The Regents of the University of California. All rights reserved. 4244480Sgonzo * 5244480Sgonzo * This code is derived from software contributed to Berkeley by 6244480Sgonzo * Rick Macklem at The University of Guelph. 7244480Sgonzo * 8244480Sgonzo * Redistribution and use in source and binary forms, with or without 9244480Sgonzo * modification, are permitted provided that the following conditions 10244480Sgonzo * are met: 11244480Sgonzo * 1. Redistributions of source code must retain the above copyright 12244480Sgonzo * notice, this list of conditions and the following disclaimer. 13244480Sgonzo * 2. Redistributions in binary form must reproduce the above copyright 14244480Sgonzo * notice, this list of conditions and the following disclaimer in the 15244480Sgonzo * documentation and/or other materials provided with the distribution. 16244480Sgonzo * 3. All advertising materials mentioning features or use of this software 17244480Sgonzo * must display the following acknowledgement: 18244480Sgonzo * This product includes software developed by the University of 19244480Sgonzo * California, Berkeley and its contributors. 20244480Sgonzo * 4. Neither the name of the University nor the names of its contributors 21244480Sgonzo * may be used to endorse or promote products derived from this software 22244480Sgonzo * without specific prior written permission. 23244480Sgonzo * 24244480Sgonzo * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25244480Sgonzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26244480Sgonzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27244480Sgonzo * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28244480Sgonzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29244480Sgonzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30244480Sgonzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31244480Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32244480Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33244480Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34244480Sgonzo * SUCH DAMAGE. 35244480Sgonzo * 36244480Sgonzo * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95 37244480Sgonzo * $Id: nfs_vnops.c,v 1.58 1997/09/10 20:22:32 phk Exp $ 38244480Sgonzo */ 39244480Sgonzo 40244480Sgonzo 41244480Sgonzo/* 42244480Sgonzo * vnode op calls for Sun NFS version 2 and 3 43244480Sgonzo */ 44244480Sgonzo 45244480Sgonzo#include <sys/param.h> 46244480Sgonzo#include <sys/kernel.h> 47244480Sgonzo#include <sys/systm.h> 48244480Sgonzo#include <sys/resourcevar.h> 49244480Sgonzo#include <sys/proc.h> 50244480Sgonzo#include <sys/mount.h> 51244480Sgonzo#include <sys/buf.h> 52244480Sgonzo#include <sys/malloc.h> 53244480Sgonzo#include <sys/mbuf.h> 54244480Sgonzo#include <sys/conf.h> 55244480Sgonzo#include <sys/namei.h> 56244480Sgonzo#include <sys/vnode.h> 57244480Sgonzo#include <sys/dirent.h> 58244480Sgonzo#include <sys/fcntl.h> 59244480Sgonzo#include <sys/lockf.h> 60244480Sgonzo 61244480Sgonzo#include <vm/vm.h> 62244480Sgonzo#include <vm/vm_param.h> 63244480Sgonzo#include <vm/vm_extern.h> 64244480Sgonzo#include <vm/vnode_pager.h> 65275767Sandrew 66248028Skientzle#include <miscfs/specfs/specdev.h> 67244480Sgonzo#include <miscfs/fifofs/fifo.h> 68244480Sgonzo 69244480Sgonzo#include <nfs/rpcv2.h> 70244480Sgonzo#include <nfs/nfsproto.h> 71244480Sgonzo#include <nfs/nfs.h> 72244480Sgonzo#include <nfs/nfsnode.h> 73244480Sgonzo#include <nfs/nfsmount.h> 74244480Sgonzo#include <nfs/xdr_subs.h> 75244480Sgonzo#include <nfs/nfsm_subs.h> 76244480Sgonzo#include <nfs/nqnfs.h> 77244480Sgonzo 78244480Sgonzo#include <net/if.h> 79244480Sgonzo#include <netinet/in.h> 80244480Sgonzo#include <netinet/in_var.h> 81244480Sgonzo 82244480Sgonzo/* Defs */ 83244480Sgonzo#define TRUE 1 84244480Sgonzo#define FALSE 0 85244480Sgonzo 86244480Sgonzo/* 87244480Sgonzo * Ifdef for FreeBSD-current merged buffer cache. It is unfortunate that these 88244480Sgonzo * calls are not in getblk() and brelse() so that they would not be necessary 89244480Sgonzo * here. 90244480Sgonzo */ 91244480Sgonzo#ifndef B_VMIO 92244480Sgonzo#define vfs_busy_pages(bp, f) 93244480Sgonzo#endif 94244480Sgonzo 95244480Sgonzostatic int nfsspec_read __P((struct vop_read_args *)); 96244480Sgonzostatic int nfsspec_write __P((struct vop_write_args *)); 97244480Sgonzostatic int nfsfifo_read __P((struct vop_read_args *)); 98244480Sgonzostatic int nfsfifo_write __P((struct vop_write_args *)); 99244480Sgonzostatic int nfsspec_close __P((struct vop_close_args *)); 100244480Sgonzostatic int nfsfifo_close __P((struct vop_close_args *)); 101244480Sgonzostatic int nfs_ioctl __P((struct vop_ioctl_args *)); 102244480Sgonzostatic int nfs_select __P((struct vop_select_args *)); 103244480Sgonzostatic int nfs_flush __P((struct vnode *,struct ucred *,int,struct proc *,int)); 104244480Sgonzostatic int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct proc *)); 105244480Sgonzostatic int nfs_lookup __P((struct vop_cachedlookup_args *)); 106244480Sgonzostatic int nfs_create __P((struct vop_create_args *)); 107244480Sgonzostatic int nfs_mknod __P((struct vop_mknod_args *)); 108244480Sgonzostatic int nfs_open __P((struct vop_open_args *)); 109244480Sgonzostatic int nfs_close __P((struct vop_close_args *)); 110244480Sgonzostatic int nfs_access __P((struct vop_access_args *)); 111244480Sgonzostatic int nfs_getattr __P((struct vop_getattr_args *)); 112244480Sgonzostatic int nfs_setattr __P((struct vop_setattr_args *)); 113244480Sgonzostatic int nfs_read __P((struct vop_read_args *)); 114244480Sgonzostatic int nfs_mmap __P((struct vop_mmap_args *)); 115244480Sgonzostatic int nfs_fsync __P((struct vop_fsync_args *)); 116244480Sgonzostatic int nfs_remove __P((struct vop_remove_args *)); 117244480Sgonzostatic int nfs_link __P((struct vop_link_args *)); 118244480Sgonzostatic int nfs_rename __P((struct vop_rename_args *)); 119244480Sgonzostatic int nfs_mkdir __P((struct vop_mkdir_args *)); 120244480Sgonzostatic int nfs_rmdir __P((struct vop_rmdir_args *)); 121244480Sgonzostatic int nfs_symlink __P((struct vop_symlink_args *)); 122248361Sandrewstatic int nfs_readdir __P((struct vop_readdir_args *)); 123244480Sgonzostatic int nfs_bmap __P((struct vop_bmap_args *)); 124244480Sgonzostatic int nfs_strategy __P((struct vop_strategy_args *)); 125244480Sgonzostatic int nfs_lookitup __P((struct vnode *,char *,int,struct ucred *,struct proc *,struct nfsnode **)); 126244480Sgonzostatic int nfs_sillyrename __P((struct vnode *,struct vnode *,struct componentname *)); 127244480Sgonzostatic int nfsspec_access __P((struct vop_access_args *)); 128248361Sandrewstatic int nfs_readlink __P((struct vop_readlink_args *)); 129244480Sgonzostatic int nfs_print __P((struct vop_print_args *)); 130244480Sgonzostatic int nfs_pathconf __P((struct vop_pathconf_args *)); 131244480Sgonzostatic int nfs_advlock __P((struct vop_advlock_args *)); 132244480Sgonzostatic int nfs_blkatoff __P((struct vop_blkatoff_args *)); 133248361Sandrewstatic int nfs_bwrite __P((struct vop_bwrite_args *)); 134244480Sgonzostatic int nfs_valloc __P((struct vop_valloc_args *)); 135244480Sgonzostatic int nfs_vfree __P((struct vop_vfree_args *)); 136244480Sgonzostatic int nfs_truncate __P((struct vop_truncate_args *)); 137244480Sgonzostatic int nfs_update __P((struct vop_update_args *)); 138244480Sgonzo/* 139248361Sandrew * Global vfs data structures for nfs 140244480Sgonzo */ 141244480Sgonzovop_t **nfsv2_vnodeop_p; 142244480Sgonzostatic struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = { 143244480Sgonzo { &vop_default_desc, (vop_t *)vn_default_error }, 144248361Sandrew { &vop_lookup_desc, (vop_t *)vfs_cache_lookup }, /* lookup */ 145244480Sgonzo { &vop_cachedlookup_desc, (vop_t *)nfs_lookup }, /* lookup */ 146244480Sgonzo { &vop_create_desc, (vop_t *)nfs_create }, /* create */ 147244480Sgonzo { &vop_mknod_desc, (vop_t *)nfs_mknod }, /* mknod */ 148244480Sgonzo { &vop_open_desc, (vop_t *)nfs_open }, /* open */ 149244480Sgonzo { &vop_close_desc, (vop_t *)nfs_close }, /* close */ 150244480Sgonzo { &vop_access_desc, (vop_t *)nfs_access }, /* access */ 151244480Sgonzo { &vop_getattr_desc, (vop_t *)nfs_getattr }, /* getattr */ 152244480Sgonzo { &vop_setattr_desc, (vop_t *)nfs_setattr }, /* setattr */ 153244480Sgonzo { &vop_read_desc, (vop_t *)nfs_read }, /* read */ 154244480Sgonzo { &vop_write_desc, (vop_t *)nfs_write }, /* write */ 155244480Sgonzo { &vop_lease_desc, (vop_t *)nfs_lease_check }, /* lease */ 156244480Sgonzo { &vop_ioctl_desc, (vop_t *)nfs_ioctl }, /* ioctl */ 157244480Sgonzo { &vop_select_desc, (vop_t *)nfs_select }, /* select */ 158244480Sgonzo { &vop_revoke_desc, (vop_t *)nfs_revoke }, /* revoke */ 159244480Sgonzo { &vop_mmap_desc, (vop_t *)nfs_mmap }, /* mmap */ 160244480Sgonzo { &vop_fsync_desc, (vop_t *)nfs_fsync }, /* fsync */ 161244480Sgonzo { &vop_seek_desc, (vop_t *)nfs_seek }, /* seek */ 162244480Sgonzo { &vop_remove_desc, (vop_t *)nfs_remove }, /* remove */ 163244480Sgonzo { &vop_link_desc, (vop_t *)nfs_link }, /* link */ 164244480Sgonzo { &vop_rename_desc, (vop_t *)nfs_rename }, /* rename */ 165244480Sgonzo { &vop_mkdir_desc, (vop_t *)nfs_mkdir }, /* mkdir */ 166244480Sgonzo { &vop_rmdir_desc, (vop_t *)nfs_rmdir }, /* rmdir */ 167244480Sgonzo { &vop_symlink_desc, (vop_t *)nfs_symlink }, /* symlink */ 168244480Sgonzo { &vop_readdir_desc, (vop_t *)nfs_readdir }, /* readdir */ 169244480Sgonzo { &vop_readlink_desc, (vop_t *)nfs_readlink }, /* readlink */ 170244480Sgonzo { &vop_abortop_desc, (vop_t *)nfs_abortop }, /* abortop */ 171248361Sandrew { &vop_inactive_desc, (vop_t *)nfs_inactive }, /* inactive */ 172244480Sgonzo { &vop_reclaim_desc, (vop_t *)nfs_reclaim }, /* reclaim */ 173244480Sgonzo { &vop_lock_desc, (vop_t *)nfs_lock }, /* lock */ 174244480Sgonzo { &vop_unlock_desc, (vop_t *)nfs_unlock }, /* unlock */ 175244480Sgonzo { &vop_bmap_desc, (vop_t *)nfs_bmap }, /* bmap */ 176244480Sgonzo { &vop_strategy_desc, (vop_t *)nfs_strategy }, /* strategy */ 177244480Sgonzo { &vop_print_desc, (vop_t *)nfs_print }, /* print */ 178244480Sgonzo { &vop_islocked_desc, (vop_t *)nfs_islocked }, /* islocked */ 179244480Sgonzo { &vop_pathconf_desc, (vop_t *)nfs_pathconf }, /* pathconf */ 180244480Sgonzo { &vop_advlock_desc, (vop_t *)nfs_advlock }, /* advlock */ 181244480Sgonzo { &vop_blkatoff_desc, (vop_t *)nfs_blkatoff }, /* blkatoff */ 182244480Sgonzo { &vop_valloc_desc, (vop_t *)nfs_valloc }, /* valloc */ 183244480Sgonzo { &vop_reallocblks_desc, (vop_t *)nfs_reallocblks }, /* reallocblks */ 184244480Sgonzo { &vop_vfree_desc, (vop_t *)nfs_vfree }, /* vfree */ 185244480Sgonzo { &vop_truncate_desc, (vop_t *)nfs_truncate }, /* truncate */ 186244480Sgonzo { &vop_update_desc, (vop_t *)nfs_update }, /* update */ 187244480Sgonzo { &vop_bwrite_desc, (vop_t *)nfs_bwrite }, /* bwrite */ 188244480Sgonzo { &vop_getpages_desc, (vop_t *)nfs_getpages }, /* getpages */ 189244480Sgonzo { NULL, NULL } 190244480Sgonzo}; 191244480Sgonzostatic struct vnodeopv_desc nfsv2_vnodeop_opv_desc = 192244480Sgonzo { &nfsv2_vnodeop_p, nfsv2_vnodeop_entries }; 193244480SgonzoVNODEOP_SET(nfsv2_vnodeop_opv_desc); 194244480Sgonzo 195244480Sgonzo/* 196244480Sgonzo * Special device vnode ops 197244480Sgonzo */ 198248361Sandrewvop_t **spec_nfsv2nodeop_p; 199244480Sgonzostatic struct vnodeopv_entry_desc spec_nfsv2nodeop_entries[] = { 200244480Sgonzo { &vop_default_desc, (vop_t *)vn_default_error }, 201244480Sgonzo { &vop_lookup_desc, (vop_t *)spec_lookup }, /* lookup */ 202244480Sgonzo { &vop_create_desc, (vop_t *)spec_create }, /* create */ 203244480Sgonzo { &vop_mknod_desc, (vop_t *)spec_mknod }, /* mknod */ 204244480Sgonzo { &vop_open_desc, (vop_t *)spec_open }, /* open */ 205244480Sgonzo { &vop_close_desc, (vop_t *)nfsspec_close }, /* close */ 206244480Sgonzo { &vop_access_desc, (vop_t *)nfsspec_access }, /* access */ 207244480Sgonzo { &vop_getattr_desc, (vop_t *)nfs_getattr }, /* getattr */ 208244480Sgonzo { &vop_setattr_desc, (vop_t *)nfs_setattr }, /* setattr */ 209244480Sgonzo { &vop_read_desc, (vop_t *)nfsspec_read }, /* read */ 210244480Sgonzo { &vop_write_desc, (vop_t *)nfsspec_write }, /* write */ 211244480Sgonzo { &vop_lease_desc, (vop_t *)spec_lease_check }, /* lease */ 212244480Sgonzo { &vop_ioctl_desc, (vop_t *)spec_ioctl }, /* ioctl */ 213244480Sgonzo { &vop_select_desc, (vop_t *)spec_select }, /* select */ 214244480Sgonzo { &vop_revoke_desc, (vop_t *)spec_revoke }, /* revoke */ 215244480Sgonzo { &vop_mmap_desc, (vop_t *)spec_mmap }, /* mmap */ 216244480Sgonzo { &vop_fsync_desc, (vop_t *)nfs_fsync }, /* fsync */ 217244480Sgonzo { &vop_seek_desc, (vop_t *)spec_seek }, /* seek */ 218244480Sgonzo { &vop_remove_desc, (vop_t *)spec_remove }, /* remove */ 219244480Sgonzo { &vop_link_desc, (vop_t *)spec_link }, /* link */ 220244480Sgonzo { &vop_rename_desc, (vop_t *)spec_rename }, /* rename */ 221248361Sandrew { &vop_mkdir_desc, (vop_t *)spec_mkdir }, /* mkdir */ 222248361Sandrew { &vop_rmdir_desc, (vop_t *)spec_rmdir }, /* rmdir */ 223 { &vop_symlink_desc, (vop_t *)spec_symlink }, /* symlink */ 224 { &vop_readdir_desc, (vop_t *)spec_readdir }, /* readdir */ 225 { &vop_readlink_desc, (vop_t *)spec_readlink }, /* readlink */ 226 { &vop_abortop_desc, (vop_t *)spec_abortop }, /* abortop */ 227 { &vop_inactive_desc, (vop_t *)nfs_inactive }, /* inactive */ 228 { &vop_reclaim_desc, (vop_t *)nfs_reclaim }, /* reclaim */ 229 { &vop_lock_desc, (vop_t *)nfs_lock }, /* lock */ 230 { &vop_unlock_desc, (vop_t *)nfs_unlock }, /* unlock */ 231 { &vop_bmap_desc, (vop_t *)spec_bmap }, /* bmap */ 232 { &vop_strategy_desc, (vop_t *)spec_strategy }, /* strategy */ 233 { &vop_print_desc, (vop_t *)nfs_print }, /* print */ 234 { &vop_islocked_desc, (vop_t *)nfs_islocked }, /* islocked */ 235 { &vop_pathconf_desc, (vop_t *)spec_pathconf }, /* pathconf */ 236 { &vop_advlock_desc, (vop_t *)spec_advlock }, /* advlock */ 237 { &vop_blkatoff_desc, (vop_t *)spec_blkatoff }, /* blkatoff */ 238 { &vop_valloc_desc, (vop_t *)spec_valloc }, /* valloc */ 239 { &vop_reallocblks_desc, (vop_t *)spec_reallocblks }, /* reallocblks */ 240 { &vop_vfree_desc, (vop_t *)spec_vfree }, /* vfree */ 241 { &vop_truncate_desc, (vop_t *)spec_truncate }, /* truncate */ 242 { &vop_update_desc, (vop_t *)nfs_update }, /* update */ 243 { &vop_bwrite_desc, (vop_t *)vn_bwrite }, /* bwrite */ 244 { NULL, NULL } 245}; 246static struct vnodeopv_desc spec_nfsv2nodeop_opv_desc = 247 { &spec_nfsv2nodeop_p, spec_nfsv2nodeop_entries }; 248VNODEOP_SET(spec_nfsv2nodeop_opv_desc); 249 250vop_t **fifo_nfsv2nodeop_p; 251static struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries[] = { 252 { &vop_default_desc, (vop_t *)vn_default_error }, 253 { &vop_lookup_desc, (vop_t *)fifo_lookup }, /* lookup */ 254 { &vop_create_desc, (vop_t *)fifo_create }, /* create */ 255 { &vop_mknod_desc, (vop_t *)fifo_mknod }, /* mknod */ 256 { &vop_open_desc, (vop_t *)fifo_open }, /* open */ 257 { &vop_close_desc, (vop_t *)nfsfifo_close }, /* close */ 258 { &vop_access_desc, (vop_t *)nfsspec_access }, /* access */ 259 { &vop_getattr_desc, (vop_t *)nfs_getattr }, /* getattr */ 260 { &vop_setattr_desc, (vop_t *)nfs_setattr }, /* setattr */ 261 { &vop_read_desc, (vop_t *)nfsfifo_read }, /* read */ 262 { &vop_write_desc, (vop_t *)nfsfifo_write }, /* write */ 263 { &vop_lease_desc, (vop_t *)fifo_lease_check }, /* lease */ 264 { &vop_ioctl_desc, (vop_t *)fifo_ioctl }, /* ioctl */ 265 { &vop_select_desc, (vop_t *)fifo_select }, /* select */ 266 { &vop_revoke_desc, (vop_t *)fifo_revoke }, /* revoke */ 267 { &vop_mmap_desc, (vop_t *)fifo_mmap }, /* mmap */ 268 { &vop_fsync_desc, (vop_t *)nfs_fsync }, /* fsync */ 269 { &vop_seek_desc, (vop_t *)fifo_seek }, /* seek */ 270 { &vop_remove_desc, (vop_t *)fifo_remove }, /* remove */ 271 { &vop_link_desc, (vop_t *)fifo_link }, /* link */ 272 { &vop_rename_desc, (vop_t *)fifo_rename }, /* rename */ 273 { &vop_mkdir_desc, (vop_t *)fifo_mkdir }, /* mkdir */ 274 { &vop_rmdir_desc, (vop_t *)fifo_rmdir }, /* rmdir */ 275 { &vop_symlink_desc, (vop_t *)fifo_symlink }, /* symlink */ 276 { &vop_readdir_desc, (vop_t *)fifo_readdir }, /* readdir */ 277 { &vop_readlink_desc, (vop_t *)fifo_readlink }, /* readlink */ 278 { &vop_abortop_desc, (vop_t *)fifo_abortop }, /* abortop */ 279 { &vop_inactive_desc, (vop_t *)nfs_inactive }, /* inactive */ 280 { &vop_reclaim_desc, (vop_t *)nfs_reclaim }, /* reclaim */ 281 { &vop_lock_desc, (vop_t *)nfs_lock }, /* lock */ 282 { &vop_unlock_desc, (vop_t *)nfs_unlock }, /* unlock */ 283 { &vop_bmap_desc, (vop_t *)fifo_bmap }, /* bmap */ 284 { &vop_strategy_desc, (vop_t *)fifo_badop }, /* strategy */ 285 { &vop_print_desc, (vop_t *)nfs_print }, /* print */ 286 { &vop_islocked_desc, (vop_t *)nfs_islocked }, /* islocked */ 287 { &vop_pathconf_desc, (vop_t *)fifo_pathconf }, /* pathconf */ 288 { &vop_advlock_desc, (vop_t *)fifo_advlock }, /* advlock */ 289 { &vop_blkatoff_desc, (vop_t *)fifo_blkatoff }, /* blkatoff */ 290 { &vop_valloc_desc, (vop_t *)fifo_valloc }, /* valloc */ 291 { &vop_reallocblks_desc, (vop_t *)fifo_reallocblks }, /* reallocblks */ 292 { &vop_vfree_desc, (vop_t *)fifo_vfree }, /* vfree */ 293 { &vop_truncate_desc, (vop_t *)fifo_truncate }, /* truncate */ 294 { &vop_update_desc, (vop_t *)nfs_update }, /* update */ 295 { &vop_bwrite_desc, (vop_t *)vn_bwrite }, /* bwrite */ 296 { NULL, NULL } 297}; 298static struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc = 299 { &fifo_nfsv2nodeop_p, fifo_nfsv2nodeop_entries }; 300VNODEOP_SET(fifo_nfsv2nodeop_opv_desc); 301 302static int nfs_commit __P((struct vnode *vp, u_quad_t offset, int cnt, 303 struct ucred *cred, struct proc *procp)); 304static int nfs_mknodrpc __P((struct vnode *dvp, struct vnode **vpp, 305 struct componentname *cnp, 306 struct vattr *vap)); 307static int nfs_removerpc __P((struct vnode *dvp, char *name, int namelen, 308 struct ucred *cred, struct proc *proc)); 309static int nfs_renamerpc __P((struct vnode *fdvp, char *fnameptr, 310 int fnamelen, struct vnode *tdvp, 311 char *tnameptr, int tnamelen, 312 struct ucred *cred, struct proc *proc)); 313static int nfs_renameit __P((struct vnode *sdvp, 314 struct componentname *scnp, 315 struct sillyrename *sp)); 316 317/* 318 * Global variables 319 */ 320extern u_long nfs_true, nfs_false; 321extern struct nfsstats nfsstats; 322extern nfstype nfsv3_type[9]; 323struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON]; 324struct nfsmount *nfs_iodmount[NFS_MAXASYNCDAEMON]; 325int nfs_numasync = 0; 326#define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1)) 327 328/* 329 * nfs access vnode op. 330 * For nfs version 2, just return ok. File accesses may fail later. 331 * For nfs version 3, use the access rpc to check accessibility. If file modes 332 * are changed on the server, accesses might still fail later. 333 */ 334static int 335nfs_access(ap) 336 struct vop_access_args /* { 337 struct vnode *a_vp; 338 int a_mode; 339 struct ucred *a_cred; 340 struct proc *a_p; 341 } */ *ap; 342{ 343 register struct vnode *vp = ap->a_vp; 344 register u_long *tl; 345 register caddr_t cp; 346 register int t1, t2; 347 caddr_t bpos, dpos, cp2; 348 int error = 0, attrflag; 349 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 350 u_long mode, rmode; 351 int v3 = NFS_ISV3(vp); 352 353 /* 354 * Disallow write attempts on filesystems mounted read-only; 355 * unless the file is a socket, fifo, or a block or character 356 * device resident on the filesystem. 357 */ 358 if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { 359 switch (vp->v_type) { 360 case VREG: case VDIR: case VLNK: 361 return (EROFS); 362 } 363 } 364 /* 365 * For nfs v3, do an access rpc, otherwise you are stuck emulating 366 * ufs_access() locally using the vattr. This may not be correct, 367 * since the server may apply other access criteria such as 368 * client uid-->server uid mapping that we do not know about, but 369 * this is better than just returning anything that is lying about 370 * in the cache. 371 */ 372 if (v3) { 373 nfsstats.rpccnt[NFSPROC_ACCESS]++; 374 nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED); 375 nfsm_fhtom(vp, v3); 376 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 377 if (ap->a_mode & VREAD) 378 mode = NFSV3ACCESS_READ; 379 else 380 mode = 0; 381 if (vp->v_type == VDIR) { 382 if (ap->a_mode & VWRITE) 383 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND | 384 NFSV3ACCESS_DELETE); 385 if (ap->a_mode & VEXEC) 386 mode |= NFSV3ACCESS_LOOKUP; 387 } else { 388 if (ap->a_mode & VWRITE) 389 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND); 390 if (ap->a_mode & VEXEC) 391 mode |= NFSV3ACCESS_EXECUTE; 392 } 393 *tl = txdr_unsigned(mode); 394 nfsm_request(vp, NFSPROC_ACCESS, ap->a_p, ap->a_cred); 395 nfsm_postop_attr(vp, attrflag); 396 if (!error) { 397 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 398 rmode = fxdr_unsigned(u_long, *tl); 399 /* 400 * The NFS V3 spec does not clarify whether or not 401 * the returned access bits can be a superset of 402 * the ones requested, so... 403 */ 404 if ((rmode & mode) != mode) 405 error = EACCES; 406 } 407 nfsm_reqdone; 408 return (error); 409 } else { 410 if (error = nfsspec_access(ap)) 411 return (error); 412 413 /* 414 * Attempt to prevent a mapped root from accessing a file 415 * which it shouldn't. We try to read a byte from the file 416 * if the user is root and the file is not zero length. 417 * After calling nfsspec_access, we should have the correct 418 * file size cached. 419 */ 420 if (ap->a_cred->cr_uid == 0 && (ap->a_mode & VREAD) 421 && VTONFS(vp)->n_size > 0) { 422 struct iovec aiov; 423 struct uio auio; 424 char buf[1]; 425 426 aiov.iov_base = buf; 427 aiov.iov_len = 1; 428 auio.uio_iov = &aiov; 429 auio.uio_iovcnt = 1; 430 auio.uio_offset = 0; 431 auio.uio_resid = 1; 432 auio.uio_segflg = UIO_SYSSPACE; 433 auio.uio_rw = UIO_READ; 434 auio.uio_procp = ap->a_p; 435 436 if (vp->v_type == VREG) 437 error = nfs_readrpc(vp, &auio, ap->a_cred); 438 else if (vp->v_type == VDIR) { 439 char* buf; 440 buf = malloc(NFS_DIRBLKSIZ, M_TEMP, M_WAITOK); 441 aiov.iov_base = buf; 442 aiov.iov_len = auio.uio_resid = NFS_DIRBLKSIZ; 443 error = nfs_readdirrpc(vp, &auio, ap->a_cred); 444 free(buf, M_TEMP); 445 } else if (vp->v_type = VLNK) 446 error = nfs_readlinkrpc(vp, &auio, ap->a_cred); 447 else 448 error = EACCES; 449 } 450 return (error); 451 } 452} 453 454/* 455 * nfs open vnode op 456 * Check to see if the type is ok 457 * and that deletion is not in progress. 458 * For paged in text files, you will need to flush the page cache 459 * if consistency is lost. 460 */ 461/* ARGSUSED */ 462static int 463nfs_open(ap) 464 struct vop_open_args /* { 465 struct vnode *a_vp; 466 int a_mode; 467 struct ucred *a_cred; 468 struct proc *a_p; 469 } */ *ap; 470{ 471 register struct vnode *vp = ap->a_vp; 472 struct nfsnode *np = VTONFS(vp); 473 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 474 struct vattr vattr; 475 int error; 476 477 if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) 478{ printf("open eacces vtyp=%d\n",vp->v_type); 479 return (EACCES); 480} 481 /* 482 * Get a valid lease. If cached data is stale, flush it. 483 */ 484 if (nmp->nm_flag & NFSMNT_NQNFS) { 485 if (NQNFS_CKINVALID(vp, np, ND_READ)) { 486 do { 487 error = nqnfs_getlease(vp, ND_READ, ap->a_cred, 488 ap->a_p); 489 } while (error == NQNFS_EXPIRED); 490 if (error) 491 return (error); 492 if (np->n_lrev != np->n_brev || 493 (np->n_flag & NQNFSNONCACHE)) { 494 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 495 ap->a_p, 1)) == EINTR) 496 return (error); 497 (void) vnode_pager_uncache(vp, ap->a_p); 498 np->n_brev = np->n_lrev; 499 } 500 } 501 } else { 502 if (np->n_flag & NMODIFIED) { 503 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 504 ap->a_p, 1)) == EINTR) 505 return (error); 506 np->n_attrstamp = 0; 507 if (vp->v_type == VDIR) 508 np->n_direofoffset = 0; 509 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p); 510 if (error) 511 return (error); 512 np->n_mtime = vattr.va_mtime.tv_sec; 513 } else { 514 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p); 515 if (error) 516 return (error); 517 if (np->n_mtime != vattr.va_mtime.tv_sec) { 518 if (vp->v_type == VDIR) 519 np->n_direofoffset = 0; 520 if ((error = nfs_vinvalbuf(vp, V_SAVE, 521 ap->a_cred, ap->a_p, 1)) == EINTR) 522 return (error); 523 np->n_mtime = vattr.va_mtime.tv_sec; 524 } 525 } 526 } 527 if ((nmp->nm_flag & NFSMNT_NQNFS) == 0) 528 np->n_attrstamp = 0; /* For Open/Close consistency */ 529 return (0); 530} 531 532/* 533 * nfs close vnode op 534 * What an NFS client should do upon close after writing is a debatable issue. 535 * Most NFS clients push delayed writes to the server upon close, basically for 536 * two reasons: 537 * 1 - So that any write errors may be reported back to the client process 538 * doing the close system call. By far the two most likely errors are 539 * NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure. 540 * 2 - To put a worst case upper bound on cache inconsistency between 541 * multiple clients for the file. 542 * There is also a consistency problem for Version 2 of the protocol w.r.t. 543 * not being able to tell if other clients are writing a file concurrently, 544 * since there is no way of knowing if the changed modify time in the reply 545 * is only due to the write for this client. 546 * (NFS Version 3 provides weak cache consistency data in the reply that 547 * should be sufficient to detect and handle this case.) 548 * 549 * The current code does the following: 550 * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers 551 * for NFS Version 3 - flush dirty buffers to the server but don't invalidate 552 * or commit them (this satisfies 1 and 2 except for the 553 * case where the server crashes after this close but 554 * before the commit RPC, which is felt to be "good 555 * enough". Changing the last argument to nfs_flush() to 556 * a 1 would force a commit operation, if it is felt a 557 * commit is necessary now. 558 * for NQNFS - do nothing now, since 2 is dealt with via leases and 559 * 1 should be dealt with via an fsync() system call for 560 * cases where write errors are important. 561 */ 562/* ARGSUSED */ 563static int 564nfs_close(ap) 565 struct vop_close_args /* { 566 struct vnodeop_desc *a_desc; 567 struct vnode *a_vp; 568 int a_fflag; 569 struct ucred *a_cred; 570 struct proc *a_p; 571 } */ *ap; 572{ 573 register struct vnode *vp = ap->a_vp; 574 register struct nfsnode *np = VTONFS(vp); 575 int error = 0; 576 577 if (vp->v_type == VREG) { 578 if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0 && 579 (np->n_flag & NMODIFIED)) { 580 if (NFS_ISV3(vp)) { 581 error = nfs_flush(vp, ap->a_cred, MNT_WAIT, ap->a_p, 0); 582 np->n_flag &= ~NMODIFIED; 583 } else 584 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1); 585 np->n_attrstamp = 0; 586 } 587 if (np->n_flag & NWRITEERR) { 588 np->n_flag &= ~NWRITEERR; 589 error = np->n_error; 590 } 591 } 592 return (error); 593} 594 595/* 596 * nfs getattr call from vfs. 597 */ 598static int 599nfs_getattr(ap) 600 struct vop_getattr_args /* { 601 struct vnode *a_vp; 602 struct vattr *a_vap; 603 struct ucred *a_cred; 604 struct proc *a_p; 605 } */ *ap; 606{ 607 register struct vnode *vp = ap->a_vp; 608 register struct nfsnode *np = VTONFS(vp); 609 register caddr_t cp; 610 register u_long *tl; 611 register int t1, t2; 612 caddr_t bpos, dpos; 613 int error = 0; 614 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 615 int v3 = NFS_ISV3(vp); 616 617 /* 618 * Update local times for special files. 619 */ 620 if (np->n_flag & (NACC | NUPD)) 621 np->n_flag |= NCHG; 622 /* 623 * First look in the cache. 624 */ 625 if (nfs_getattrcache(vp, ap->a_vap) == 0) 626 return (0); 627 nfsstats.rpccnt[NFSPROC_GETATTR]++; 628 nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH(v3)); 629 nfsm_fhtom(vp, v3); 630 nfsm_request(vp, NFSPROC_GETATTR, ap->a_p, ap->a_cred); 631 if (!error) 632 nfsm_loadattr(vp, ap->a_vap); 633 nfsm_reqdone; 634 return (error); 635} 636 637/* 638 * nfs setattr call. 639 */ 640static int 641nfs_setattr(ap) 642 struct vop_setattr_args /* { 643 struct vnodeop_desc *a_desc; 644 struct vnode *a_vp; 645 struct vattr *a_vap; 646 struct ucred *a_cred; 647 struct proc *a_p; 648 } */ *ap; 649{ 650 register struct vnode *vp = ap->a_vp; 651 register struct nfsnode *np = VTONFS(vp); 652 register struct vattr *vap = ap->a_vap; 653 int error = 0; 654 u_quad_t tsize; 655 656#ifndef nolint 657 tsize = (u_quad_t)0; 658#endif 659 /* 660 * Disallow write attempts if the filesystem is mounted read-only. 661 */ 662 if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || 663 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 664 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) && 665 (vp->v_mount->mnt_flag & MNT_RDONLY)) 666 return (EROFS); 667 if (vap->va_size != VNOVAL) { 668 switch (vp->v_type) { 669 case VDIR: 670 return (EISDIR); 671 case VCHR: 672 case VBLK: 673 case VSOCK: 674 case VFIFO: 675 if (vap->va_mtime.tv_sec == VNOVAL && 676 vap->va_atime.tv_sec == VNOVAL && 677 vap->va_mode == (u_short)VNOVAL && 678 vap->va_uid == (uid_t)VNOVAL && 679 vap->va_gid == (gid_t)VNOVAL) 680 return (0); 681 vap->va_size = VNOVAL; 682 break; 683 default: 684 /* 685 * Disallow write attempts if the filesystem is 686 * mounted read-only. 687 */ 688 if (vp->v_mount->mnt_flag & MNT_RDONLY) 689 return (EROFS); 690 if (np->n_flag & NMODIFIED) { 691 if (vap->va_size == 0) 692 error = nfs_vinvalbuf(vp, 0, 693 ap->a_cred, ap->a_p, 1); 694 else 695 error = nfs_vinvalbuf(vp, V_SAVE, 696 ap->a_cred, ap->a_p, 1); 697 if (error) 698 return (error); 699 } 700 tsize = np->n_size; 701 np->n_size = np->n_vattr.va_size = vap->va_size; 702 vnode_pager_setsize(vp, (u_long)np->n_size); 703 }; 704 } else if ((vap->va_mtime.tv_sec != VNOVAL || 705 vap->va_atime.tv_sec != VNOVAL) && (np->n_flag & NMODIFIED) && 706 vp->v_type == VREG && 707 (error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 708 ap->a_p, 1)) == EINTR) 709 return (error); 710 error = nfs_setattrrpc(vp, vap, ap->a_cred, ap->a_p); 711 if (error && vap->va_size != VNOVAL) { 712 np->n_size = np->n_vattr.va_size = tsize; 713 vnode_pager_setsize(vp, (u_long)np->n_size); 714 } 715 return (error); 716} 717 718/* 719 * Do an nfs setattr rpc. 720 */ 721static int 722nfs_setattrrpc(vp, vap, cred, procp) 723 register struct vnode *vp; 724 register struct vattr *vap; 725 struct ucred *cred; 726 struct proc *procp; 727{ 728 register struct nfsv2_sattr *sp; 729 register caddr_t cp; 730 register long t1, t2; 731 caddr_t bpos, dpos, cp2; 732 u_long *tl; 733 int error = 0, wccflag = NFSV3_WCCRATTR; 734 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 735 int v3 = NFS_ISV3(vp); 736 737 nfsstats.rpccnt[NFSPROC_SETATTR]++; 738 nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3)); 739 nfsm_fhtom(vp, v3); 740 if (v3) { 741 if (vap->va_mode != (u_short)VNOVAL) { 742 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 743 *tl++ = nfs_true; 744 *tl = txdr_unsigned(vap->va_mode); 745 } else { 746 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 747 *tl = nfs_false; 748 } 749 if (vap->va_uid != (uid_t)VNOVAL) { 750 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 751 *tl++ = nfs_true; 752 *tl = txdr_unsigned(vap->va_uid); 753 } else { 754 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 755 *tl = nfs_false; 756 } 757 if (vap->va_gid != (gid_t)VNOVAL) { 758 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 759 *tl++ = nfs_true; 760 *tl = txdr_unsigned(vap->va_gid); 761 } else { 762 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 763 *tl = nfs_false; 764 } 765 if (vap->va_size != VNOVAL) { 766 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 767 *tl++ = nfs_true; 768 txdr_hyper(&vap->va_size, tl); 769 } else { 770 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 771 *tl = nfs_false; 772 } 773 if (vap->va_atime.tv_sec != VNOVAL) { 774 if (vap->va_atime.tv_sec != time.tv_sec) { 775 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 776 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); 777 txdr_nfsv3time(&vap->va_atime, tl); 778 } else { 779 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 780 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); 781 } 782 } else { 783 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 784 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); 785 } 786 if (vap->va_mtime.tv_sec != VNOVAL) { 787 if (vap->va_mtime.tv_sec != time.tv_sec) { 788 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 789 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); 790 txdr_nfsv3time(&vap->va_mtime, tl); 791 } else { 792 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 793 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); 794 } 795 } else { 796 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 797 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); 798 } 799 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 800 *tl = nfs_false; 801 } else { 802 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 803 if (vap->va_mode == (u_short)VNOVAL) 804 sp->sa_mode = VNOVAL; 805 else 806 sp->sa_mode = vtonfsv2_mode(vp->v_type, vap->va_mode); 807 if (vap->va_uid == (uid_t)VNOVAL) 808 sp->sa_uid = VNOVAL; 809 else 810 sp->sa_uid = txdr_unsigned(vap->va_uid); 811 if (vap->va_gid == (gid_t)VNOVAL) 812 sp->sa_gid = VNOVAL; 813 else 814 sp->sa_gid = txdr_unsigned(vap->va_gid); 815 sp->sa_size = txdr_unsigned(vap->va_size); 816 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 817 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 818 } 819 nfsm_request(vp, NFSPROC_SETATTR, procp, cred); 820 if (v3) { 821 nfsm_wcc_data(vp, wccflag); 822 } else 823 nfsm_loadattr(vp, (struct vattr *)0); 824 nfsm_reqdone; 825 return (error); 826} 827 828/* 829 * nfs lookup call, one step at a time... 830 * Generic stuff already done by vfs_cache_lookup() 831 * Unlock the directory nfsnode and do the rpc 832 */ 833static int 834nfs_lookup(ap) 835 struct vop_cachedlookup_args /* { 836 struct vnodeop_desc *a_desc; 837 struct vnode *a_dvp; 838 struct vnode **a_vpp; 839 struct componentname *a_cnp; 840 } */ *ap; 841{ 842 register struct componentname *cnp = ap->a_cnp; 843 register struct vnode *dvp = ap->a_dvp; 844 register struct vnode **vpp = ap->a_vpp; 845 register int flags = cnp->cn_flags; 846 register struct vnode *newvp; 847 register u_long *tl; 848 register caddr_t cp; 849 register long t1, t2; 850 struct nfsmount *nmp; 851 caddr_t bpos, dpos, cp2; 852 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 853 long len; 854 nfsfh_t *fhp; 855 struct nfsnode *np; 856 int lockparent, wantparent, error = 0, attrflag, fhsize; 857 int v3 = NFS_ISV3(dvp); 858 struct proc *p = cnp->cn_proc; 859 860 *vpp = NULLVP; 861 lockparent = flags & LOCKPARENT; 862 wantparent = flags & (LOCKPARENT|WANTPARENT); 863 nmp = VFSTONFS(dvp->v_mount); 864 np = VTONFS(dvp); 865 error = 0; 866 newvp = NULLVP; 867 nfsstats.lookupcache_misses++; 868 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 869 len = cnp->cn_namelen; 870 nfsm_reqhead(dvp, NFSPROC_LOOKUP, 871 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len)); 872 nfsm_fhtom(dvp, v3); 873 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 874 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred); 875 if (error) { 876 nfsm_postop_attr(dvp, attrflag); 877 m_freem(mrep); 878 goto nfsmout; 879 } 880 nfsm_getfh(fhp, fhsize, v3); 881 882 /* 883 * Handle RENAME case... 884 */ 885 if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) { 886 if (NFS_CMPFH(np, fhp, fhsize)) { 887 m_freem(mrep); 888 return (EISDIR); 889 } 890 if (error = nfs_nget(dvp->v_mount, fhp, fhsize, &np)) { 891 m_freem(mrep); 892 return (error); 893 } 894 newvp = NFSTOV(np); 895 if (v3) { 896 nfsm_postop_attr(newvp, attrflag); 897 nfsm_postop_attr(dvp, attrflag); 898 } else 899 nfsm_loadattr(newvp, (struct vattr *)0); 900 *vpp = newvp; 901 m_freem(mrep); 902 cnp->cn_flags |= SAVENAME; 903 if (!lockparent) 904 VOP_UNLOCK(dvp, 0, p); 905 return (0); 906 } 907 908 if (flags & ISDOTDOT) { 909 VOP_UNLOCK(dvp, 0, p); 910 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np); 911 if (error) { 912 vn_lock(dvp, LK_EXCLUSIVE + LK_RETRY, p); 913 return (error); 914 } 915 newvp = NFSTOV(np); 916 if (lockparent && (flags & ISLASTCN) && 917 (error = vn_lock(dvp, LK_EXCLUSIVE, p))) { 918 vput(newvp); 919 return (error); 920 } 921 } else if (NFS_CMPFH(np, fhp, fhsize)) { 922 VREF(dvp); 923 newvp = dvp; 924 } else { 925 if (error = nfs_nget(dvp->v_mount, fhp, fhsize, &np)) { 926 m_freem(mrep); 927 return (error); 928 } 929 if (!lockparent || !(flags & ISLASTCN)) 930 VOP_UNLOCK(dvp, 0, p); 931 newvp = NFSTOV(np); 932 } 933 if (v3) { 934 nfsm_postop_attr(newvp, attrflag); 935 nfsm_postop_attr(dvp, attrflag); 936 } else 937 nfsm_loadattr(newvp, (struct vattr *)0); 938 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 939 cnp->cn_flags |= SAVENAME; 940 if ((cnp->cn_flags & MAKEENTRY) && 941 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) { 942 np->n_ctime = np->n_vattr.va_ctime.tv_sec; 943 cache_enter(dvp, newvp, cnp); 944 } 945 *vpp = newvp; 946 nfsm_reqdone; 947 if (error) { 948 if (newvp != NULLVP) { 949 vrele(newvp); 950 *vpp = NULLVP; 951 } 952 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) && 953 (flags & ISLASTCN) && error == ENOENT) { 954 if (!lockparent) 955 VOP_UNLOCK(dvp, 0, p); 956 if (dvp->v_mount->mnt_flag & MNT_RDONLY) 957 error = EROFS; 958 else 959 error = EJUSTRETURN; 960 } 961 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 962 cnp->cn_flags |= SAVENAME; 963 } 964 return (error); 965} 966 967/* 968 * nfs read call. 969 * Just call nfs_bioread() to do the work. 970 */ 971static int 972nfs_read(ap) 973 struct vop_read_args /* { 974 struct vnode *a_vp; 975 struct uio *a_uio; 976 int a_ioflag; 977 struct ucred *a_cred; 978 } */ *ap; 979{ 980 register struct vnode *vp = ap->a_vp; 981 982 if (vp->v_type != VREG) 983 return (EPERM); 984 return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred, 0)); 985} 986 987/* 988 * nfs readlink call 989 */ 990static int 991nfs_readlink(ap) 992 struct vop_readlink_args /* { 993 struct vnode *a_vp; 994 struct uio *a_uio; 995 struct ucred *a_cred; 996 } */ *ap; 997{ 998 register struct vnode *vp = ap->a_vp; 999 1000 if (vp->v_type != VLNK) 1001 return (EPERM); 1002 return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred, 0)); 1003} 1004 1005/* 1006 * Do a readlink rpc. 1007 * Called by nfs_doio() from below the buffer cache. 1008 */ 1009int 1010nfs_readlinkrpc(vp, uiop, cred) 1011 register struct vnode *vp; 1012 struct uio *uiop; 1013 struct ucred *cred; 1014{ 1015 register u_long *tl; 1016 register caddr_t cp; 1017 register long t1, t2; 1018 caddr_t bpos, dpos, cp2; 1019 int error = 0, len, attrflag; 1020 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1021 int v3 = NFS_ISV3(vp); 1022 1023 nfsstats.rpccnt[NFSPROC_READLINK]++; 1024 nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH(v3)); 1025 nfsm_fhtom(vp, v3); 1026 nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred); 1027 if (v3) 1028 nfsm_postop_attr(vp, attrflag); 1029 if (!error) { 1030 nfsm_strsiz(len, NFS_MAXPATHLEN); 1031 nfsm_mtouio(uiop, len); 1032 } 1033 nfsm_reqdone; 1034 return (error); 1035} 1036 1037/* 1038 * nfs read rpc call 1039 * Ditto above 1040 */ 1041int 1042nfs_readrpc(vp, uiop, cred) 1043 register struct vnode *vp; 1044 struct uio *uiop; 1045 struct ucred *cred; 1046{ 1047 register u_long *tl; 1048 register caddr_t cp; 1049 register long t1, t2; 1050 caddr_t bpos, dpos, cp2; 1051 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1052 struct nfsmount *nmp; 1053 int error = 0, len, retlen, tsiz, eof, attrflag; 1054 int v3 = NFS_ISV3(vp); 1055 1056#ifndef nolint 1057 eof = 0; 1058#endif 1059 nmp = VFSTONFS(vp->v_mount); 1060 tsiz = uiop->uio_resid; 1061 if (uiop->uio_offset + tsiz > 0xffffffff && !v3) 1062 return (EFBIG); 1063 while (tsiz > 0) { 1064 nfsstats.rpccnt[NFSPROC_READ]++; 1065 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz; 1066 nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3); 1067 nfsm_fhtom(vp, v3); 1068 nfsm_build(tl, u_long *, NFSX_UNSIGNED * 3); 1069 if (v3) { 1070 txdr_hyper(&uiop->uio_offset, tl); 1071 *(tl + 2) = txdr_unsigned(len); 1072 } else { 1073 *tl++ = txdr_unsigned(uiop->uio_offset); 1074 *tl++ = txdr_unsigned(len); 1075 *tl = 0; 1076 } 1077 nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, cred); 1078 if (v3) { 1079 nfsm_postop_attr(vp, attrflag); 1080 if (error) { 1081 m_freem(mrep); 1082 goto nfsmout; 1083 } 1084 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 1085 eof = fxdr_unsigned(int, *(tl + 1)); 1086 } else 1087 nfsm_loadattr(vp, (struct vattr *)0); 1088 nfsm_strsiz(retlen, nmp->nm_rsize); 1089 nfsm_mtouio(uiop, retlen); 1090 m_freem(mrep); 1091 tsiz -= retlen; 1092 if (v3) { 1093 if (eof || retlen == 0) 1094 tsiz = 0; 1095 } else if (retlen < len) 1096 tsiz = 0; 1097 } 1098nfsmout: 1099 return (error); 1100} 1101 1102/* 1103 * nfs write call 1104 */ 1105int 1106nfs_writerpc(vp, uiop, cred, iomode, must_commit) 1107 register struct vnode *vp; 1108 register struct uio *uiop; 1109 struct ucred *cred; 1110 int *iomode, *must_commit; 1111{ 1112 register u_long *tl; 1113 register caddr_t cp; 1114 register int t1, t2, backup; 1115 caddr_t bpos, dpos, cp2; 1116 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1117 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 1118 int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit; 1119 int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC; 1120 1121#ifndef DIAGNOSTIC 1122 if (uiop->uio_iovcnt != 1) 1123 panic("nfs: writerpc iovcnt > 1"); 1124#endif 1125 *must_commit = 0; 1126 tsiz = uiop->uio_resid; 1127 if (uiop->uio_offset + tsiz > 0xffffffff && !v3) 1128 return (EFBIG); 1129 while (tsiz > 0) { 1130 nfsstats.rpccnt[NFSPROC_WRITE]++; 1131 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz; 1132 nfsm_reqhead(vp, NFSPROC_WRITE, 1133 NFSX_FH(v3) + 5 * NFSX_UNSIGNED + nfsm_rndup(len)); 1134 nfsm_fhtom(vp, v3); 1135 if (v3) { 1136 nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED); 1137 txdr_hyper(&uiop->uio_offset, tl); 1138 tl += 2; 1139 *tl++ = txdr_unsigned(len); 1140 *tl++ = txdr_unsigned(*iomode); 1141 } else { 1142 nfsm_build(tl, u_long *, 4 * NFSX_UNSIGNED); 1143 *++tl = txdr_unsigned(uiop->uio_offset); 1144 tl += 2; 1145 } 1146 *tl = txdr_unsigned(len); 1147 nfsm_uiotom(uiop, len); 1148 nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, cred); 1149 if (v3) { 1150 wccflag = NFSV3_WCCCHK; 1151 nfsm_wcc_data(vp, wccflag); 1152 if (!error) { 1153 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED + 1154 NFSX_V3WRITEVERF); 1155 rlen = fxdr_unsigned(int, *tl++); 1156 if (rlen == 0) { 1157 error = NFSERR_IO; 1158 break; 1159 } else if (rlen < len) { 1160 backup = len - rlen; 1161 uiop->uio_iov->iov_base -= backup; 1162 uiop->uio_iov->iov_len += backup; 1163 uiop->uio_offset -= backup; 1164 uiop->uio_resid += backup; 1165 len = rlen; 1166 } 1167 commit = fxdr_unsigned(int, *tl++); 1168 1169 /* 1170 * Return the lowest committment level 1171 * obtained by any of the RPCs. 1172 */ 1173 if (committed == NFSV3WRITE_FILESYNC) 1174 committed = commit; 1175 else if (committed == NFSV3WRITE_DATASYNC && 1176 commit == NFSV3WRITE_UNSTABLE) 1177 committed = commit; 1178 if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) { 1179 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 1180 NFSX_V3WRITEVERF); 1181 nmp->nm_flag |= NFSMNT_HASWRITEVERF; 1182 } else if (bcmp((caddr_t)tl, 1183 (caddr_t)nmp->nm_verf, NFSX_V3WRITEVERF)) { 1184 *must_commit = 1; 1185 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 1186 NFSX_V3WRITEVERF); 1187 } 1188 } 1189 } else 1190 nfsm_loadattr(vp, (struct vattr *)0); 1191 if (wccflag) 1192 VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.tv_sec; 1193 m_freem(mrep); 1194 tsiz -= len; 1195 } 1196nfsmout: 1197 if (vp->v_mount->mnt_flag & MNT_ASYNC) 1198 committed = NFSV3WRITE_FILESYNC; 1199 *iomode = committed; 1200 if (error) 1201 uiop->uio_resid = tsiz; 1202 return (error); 1203} 1204 1205/* 1206 * nfs mknod rpc 1207 * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the 1208 * mode set to specify the file type and the size field for rdev. 1209 */ 1210static int 1211nfs_mknodrpc(dvp, vpp, cnp, vap) 1212 register struct vnode *dvp; 1213 register struct vnode **vpp; 1214 register struct componentname *cnp; 1215 register struct vattr *vap; 1216{ 1217 register struct nfsv2_sattr *sp; 1218 register struct nfsv3_sattr *sp3; 1219 register u_long *tl; 1220 register caddr_t cp; 1221 register long t1, t2; 1222 struct vnode *newvp = (struct vnode *)0; 1223 struct nfsnode *np = (struct nfsnode *)0; 1224 struct vattr vattr; 1225 char *cp2; 1226 caddr_t bpos, dpos; 1227 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0; 1228 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1229 u_long rdev; 1230 int v3 = NFS_ISV3(dvp); 1231 1232 if (vap->va_type == VCHR || vap->va_type == VBLK) 1233 rdev = txdr_unsigned(vap->va_rdev); 1234 else if (vap->va_type == VFIFO || vap->va_type == VSOCK) 1235 rdev = 0xffffffff; 1236 else { 1237 VOP_ABORTOP(dvp, cnp); 1238 vput(dvp); 1239 return (EOPNOTSUPP); 1240 } 1241 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1242 VOP_ABORTOP(dvp, cnp); 1243 vput(dvp); 1244 return (error); 1245 } 1246 nfsstats.rpccnt[NFSPROC_MKNOD]++; 1247 nfsm_reqhead(dvp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED + 1248 + nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3)); 1249 nfsm_fhtom(dvp, v3); 1250 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1251 if (v3) { 1252 nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3SRVSATTR); 1253 *tl++ = vtonfsv3_type(vap->va_type); 1254 sp3 = (struct nfsv3_sattr *)tl; 1255 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1256 if (vap->va_type == VCHR || vap->va_type == VBLK) { 1257 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 1258 *tl++ = txdr_unsigned(major(vap->va_rdev)); 1259 *tl = txdr_unsigned(minor(vap->va_rdev)); 1260 } 1261 } else { 1262 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1263 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 1264 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1265 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1266 sp->sa_size = rdev; 1267 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1268 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1269 } 1270 nfsm_request(dvp, NFSPROC_MKNOD, cnp->cn_proc, cnp->cn_cred); 1271 if (!error) { 1272 nfsm_mtofh(dvp, newvp, v3, gotvp); 1273 if (!gotvp) { 1274 if (newvp) { 1275 vput(newvp); 1276 newvp = (struct vnode *)0; 1277 } 1278 error = nfs_lookitup(dvp, cnp->cn_nameptr, 1279 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np); 1280 if (!error) 1281 newvp = NFSTOV(np); 1282 } 1283 } 1284 if (v3) 1285 nfsm_wcc_data(dvp, wccflag); 1286 nfsm_reqdone; 1287 if (error) { 1288 if (newvp) 1289 vput(newvp); 1290 } else { 1291 if (cnp->cn_flags & MAKEENTRY) 1292 cache_enter(dvp, newvp, cnp); 1293 *vpp = newvp; 1294 } 1295 FREE(cnp->cn_pnbuf, M_NAMEI); 1296 VTONFS(dvp)->n_flag |= NMODIFIED; 1297 if (!wccflag) 1298 VTONFS(dvp)->n_attrstamp = 0; 1299 vput(dvp); 1300 return (error); 1301} 1302 1303/* 1304 * nfs mknod vop 1305 * just call nfs_mknodrpc() to do the work. 1306 */ 1307/* ARGSUSED */ 1308static int 1309nfs_mknod(ap) 1310 struct vop_mknod_args /* { 1311 struct vnode *a_dvp; 1312 struct vnode **a_vpp; 1313 struct componentname *a_cnp; 1314 struct vattr *a_vap; 1315 } */ *ap; 1316{ 1317 struct vnode *newvp; 1318 int error; 1319 1320 error = nfs_mknodrpc(ap->a_dvp, &newvp, ap->a_cnp, ap->a_vap); 1321 if (!error) 1322 vput(newvp); 1323 return (error); 1324} 1325 1326static u_long create_verf; 1327/* 1328 * nfs file create call 1329 */ 1330static int 1331nfs_create(ap) 1332 struct vop_create_args /* { 1333 struct vnode *a_dvp; 1334 struct vnode **a_vpp; 1335 struct componentname *a_cnp; 1336 struct vattr *a_vap; 1337 } */ *ap; 1338{ 1339 register struct vnode *dvp = ap->a_dvp; 1340 register struct vattr *vap = ap->a_vap; 1341 register struct componentname *cnp = ap->a_cnp; 1342 register struct nfsv2_sattr *sp; 1343 register struct nfsv3_sattr *sp3; 1344 register u_long *tl; 1345 register caddr_t cp; 1346 register long t1, t2; 1347 struct nfsnode *np = (struct nfsnode *)0; 1348 struct vnode *newvp = (struct vnode *)0; 1349 caddr_t bpos, dpos, cp2; 1350 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0; 1351 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1352 struct vattr vattr; 1353 int v3 = NFS_ISV3(dvp); 1354 1355 /* 1356 * Oops, not for me.. 1357 */ 1358 if (vap->va_type == VSOCK) 1359 return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap)); 1360 1361 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1362 VOP_ABORTOP(dvp, cnp); 1363 vput(dvp); 1364 return (error); 1365 } 1366 if (vap->va_vaflags & VA_EXCLUSIVE) 1367 fmode |= O_EXCL; 1368again: 1369 nfsstats.rpccnt[NFSPROC_CREATE]++; 1370 nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED + 1371 nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3)); 1372 nfsm_fhtom(dvp, v3); 1373 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1374 if (v3) { 1375 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 1376 if (fmode & O_EXCL) { 1377 *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE); 1378 nfsm_build(tl, u_long *, NFSX_V3CREATEVERF); 1379 if (!TAILQ_EMPTY(&in_ifaddrhead)) 1380 *tl++ = IA_SIN(in_ifaddrhead.tqh_first)->sin_addr.s_addr; 1381 else 1382 *tl++ = create_verf; 1383 *tl = ++create_verf; 1384 } else { 1385 *tl = txdr_unsigned(NFSV3CREATE_UNCHECKED); 1386 nfsm_build(tl, u_long *, NFSX_V3SRVSATTR); 1387 sp3 = (struct nfsv3_sattr *)tl; 1388 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1389 } 1390 } else { 1391 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1392 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 1393 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1394 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1395 sp->sa_size = 0; 1396 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1397 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1398 } 1399 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred); 1400 if (!error) { 1401 nfsm_mtofh(dvp, newvp, v3, gotvp); 1402 if (!gotvp) { 1403 if (newvp) { 1404 vput(newvp); 1405 newvp = (struct vnode *)0; 1406 } 1407 error = nfs_lookitup(dvp, cnp->cn_nameptr, 1408 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np); 1409 if (!error) 1410 newvp = NFSTOV(np); 1411 } 1412 } 1413 if (v3) 1414 nfsm_wcc_data(dvp, wccflag); 1415 nfsm_reqdone; 1416 if (error) { 1417 if (v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) { 1418 fmode &= ~O_EXCL; 1419 goto again; 1420 } 1421 if (newvp) 1422 vput(newvp); 1423 } else if (v3 && (fmode & O_EXCL)) 1424 error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_proc); 1425 if (!error) { 1426 if (cnp->cn_flags & MAKEENTRY) 1427 cache_enter(dvp, newvp, cnp); 1428 *ap->a_vpp = newvp; 1429 } 1430 FREE(cnp->cn_pnbuf, M_NAMEI); 1431 VTONFS(dvp)->n_flag |= NMODIFIED; 1432 if (!wccflag) 1433 VTONFS(dvp)->n_attrstamp = 0; 1434 vput(dvp); 1435 return (error); 1436} 1437 1438/* 1439 * nfs file remove call 1440 * To try and make nfs semantics closer to ufs semantics, a file that has 1441 * other processes using the vnode is renamed instead of removed and then 1442 * removed later on the last close. 1443 * - If v_usecount > 1 1444 * If a rename is not already in the works 1445 * call nfs_sillyrename() to set it up 1446 * else 1447 * do the remove rpc 1448 */ 1449static int 1450nfs_remove(ap) 1451 struct vop_remove_args /* { 1452 struct vnodeop_desc *a_desc; 1453 struct vnode * a_dvp; 1454 struct vnode * a_vp; 1455 struct componentname * a_cnp; 1456 } */ *ap; 1457{ 1458 register struct vnode *vp = ap->a_vp; 1459 register struct vnode *dvp = ap->a_dvp; 1460 register struct componentname *cnp = ap->a_cnp; 1461 register struct nfsnode *np = VTONFS(vp); 1462 int error = 0; 1463 struct vattr vattr; 1464 1465#ifndef DIAGNOSTIC 1466 if ((cnp->cn_flags & HASBUF) == 0) 1467 panic("nfs_remove: no name"); 1468 if (vp->v_usecount < 1) 1469 panic("nfs_remove: bad v_usecount"); 1470#endif 1471 if (vp->v_usecount == 1 || (np->n_sillyrename && 1472 VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_proc) == 0 && 1473 vattr.va_nlink > 1)) { 1474 /* 1475 * Purge the name cache so that the chance of a lookup for 1476 * the name succeeding while the remove is in progress is 1477 * minimized. Without node locking it can still happen, such 1478 * that an I/O op returns ESTALE, but since you get this if 1479 * another host removes the file.. 1480 */ 1481 cache_purge(vp); 1482 /* 1483 * throw away biocache buffers, mainly to avoid 1484 * unnecessary delayed writes later. 1485 */ 1486 error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_proc, 1); 1487 /* Do the rpc */ 1488 if (error != EINTR) 1489 error = nfs_removerpc(dvp, cnp->cn_nameptr, 1490 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc); 1491 /* 1492 * Kludge City: If the first reply to the remove rpc is lost.. 1493 * the reply to the retransmitted request will be ENOENT 1494 * since the file was in fact removed 1495 * Therefore, we cheat and return success. 1496 */ 1497 if (error == ENOENT) 1498 error = 0; 1499 } else if (!np->n_sillyrename) 1500 error = nfs_sillyrename(dvp, vp, cnp); 1501 FREE(cnp->cn_pnbuf, M_NAMEI); 1502 np->n_attrstamp = 0; 1503 vput(dvp); 1504 if (vp == dvp) 1505 vrele(vp); 1506 else 1507 vput(vp); 1508 return (error); 1509} 1510 1511/* 1512 * nfs file remove rpc called from nfs_inactive 1513 */ 1514int 1515nfs_removeit(sp) 1516 register struct sillyrename *sp; 1517{ 1518 1519 return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred, 1520 (struct proc *)0)); 1521} 1522 1523/* 1524 * Nfs remove rpc, called from nfs_remove() and nfs_removeit(). 1525 */ 1526static int 1527nfs_removerpc(dvp, name, namelen, cred, proc) 1528 register struct vnode *dvp; 1529 char *name; 1530 int namelen; 1531 struct ucred *cred; 1532 struct proc *proc; 1533{ 1534 register u_long *tl; 1535 register caddr_t cp; 1536 register long t1, t2; 1537 caddr_t bpos, dpos, cp2; 1538 int error = 0, wccflag = NFSV3_WCCRATTR; 1539 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1540 int v3 = NFS_ISV3(dvp); 1541 1542 nfsstats.rpccnt[NFSPROC_REMOVE]++; 1543 nfsm_reqhead(dvp, NFSPROC_REMOVE, 1544 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen)); 1545 nfsm_fhtom(dvp, v3); 1546 nfsm_strtom(name, namelen, NFS_MAXNAMLEN); 1547 nfsm_request(dvp, NFSPROC_REMOVE, proc, cred); 1548 if (v3) 1549 nfsm_wcc_data(dvp, wccflag); 1550 nfsm_reqdone; 1551 VTONFS(dvp)->n_flag |= NMODIFIED; 1552 if (!wccflag) 1553 VTONFS(dvp)->n_attrstamp = 0; 1554 return (error); 1555} 1556 1557/* 1558 * nfs file rename call 1559 */ 1560static int 1561nfs_rename(ap) 1562 struct vop_rename_args /* { 1563 struct vnode *a_fdvp; 1564 struct vnode *a_fvp; 1565 struct componentname *a_fcnp; 1566 struct vnode *a_tdvp; 1567 struct vnode *a_tvp; 1568 struct componentname *a_tcnp; 1569 } */ *ap; 1570{ 1571 register struct vnode *fvp = ap->a_fvp; 1572 register struct vnode *tvp = ap->a_tvp; 1573 register struct vnode *fdvp = ap->a_fdvp; 1574 register struct vnode *tdvp = ap->a_tdvp; 1575 register struct componentname *tcnp = ap->a_tcnp; 1576 register struct componentname *fcnp = ap->a_fcnp; 1577 int error; 1578 1579#ifndef DIAGNOSTIC 1580 if ((tcnp->cn_flags & HASBUF) == 0 || 1581 (fcnp->cn_flags & HASBUF) == 0) 1582 panic("nfs_rename: no name"); 1583#endif 1584 /* Check for cross-device rename */ 1585 if ((fvp->v_mount != tdvp->v_mount) || 1586 (tvp && (fvp->v_mount != tvp->v_mount))) { 1587 error = EXDEV; 1588 goto out; 1589 } 1590 1591 /* 1592 * If the tvp exists and is in use, sillyrename it before doing the 1593 * rename of the new file over it. 1594 * XXX Can't sillyrename a directory. 1595 */ 1596 if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename && 1597 tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) { 1598 vput(tvp); 1599 tvp = NULL; 1600 } 1601 1602 error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen, 1603 tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred, 1604 tcnp->cn_proc); 1605 1606 if (fvp->v_type == VDIR) { 1607 if (tvp != NULL && tvp->v_type == VDIR) 1608 cache_purge(tdvp); 1609 cache_purge(fdvp); 1610 } 1611out: 1612 if (tdvp == tvp) 1613 vrele(tdvp); 1614 else 1615 vput(tdvp); 1616 if (tvp) 1617 vput(tvp); 1618 vrele(fdvp); 1619 vrele(fvp); 1620 /* 1621 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. 1622 */ 1623 if (error == ENOENT) 1624 error = 0; 1625 return (error); 1626} 1627 1628/* 1629 * nfs file rename rpc called from nfs_remove() above 1630 */ 1631static int 1632nfs_renameit(sdvp, scnp, sp) 1633 struct vnode *sdvp; 1634 struct componentname *scnp; 1635 register struct sillyrename *sp; 1636{ 1637 return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen, 1638 sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_proc)); 1639} 1640 1641/* 1642 * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit(). 1643 */ 1644static int 1645nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, proc) 1646 register struct vnode *fdvp; 1647 char *fnameptr; 1648 int fnamelen; 1649 register struct vnode *tdvp; 1650 char *tnameptr; 1651 int tnamelen; 1652 struct ucred *cred; 1653 struct proc *proc; 1654{ 1655 register u_long *tl; 1656 register caddr_t cp; 1657 register long t1, t2; 1658 caddr_t bpos, dpos, cp2; 1659 int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR; 1660 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1661 int v3 = NFS_ISV3(fdvp); 1662 1663 nfsstats.rpccnt[NFSPROC_RENAME]++; 1664 nfsm_reqhead(fdvp, NFSPROC_RENAME, 1665 (NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) + 1666 nfsm_rndup(tnamelen)); 1667 nfsm_fhtom(fdvp, v3); 1668 nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN); 1669 nfsm_fhtom(tdvp, v3); 1670 nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN); 1671 nfsm_request(fdvp, NFSPROC_RENAME, proc, cred); 1672 if (v3) { 1673 nfsm_wcc_data(fdvp, fwccflag); 1674 nfsm_wcc_data(tdvp, twccflag); 1675 } 1676 nfsm_reqdone; 1677 VTONFS(fdvp)->n_flag |= NMODIFIED; 1678 VTONFS(tdvp)->n_flag |= NMODIFIED; 1679 if (!fwccflag) 1680 VTONFS(fdvp)->n_attrstamp = 0; 1681 if (!twccflag) 1682 VTONFS(tdvp)->n_attrstamp = 0; 1683 return (error); 1684} 1685 1686/* 1687 * nfs hard link create call 1688 */ 1689static int 1690nfs_link(ap) 1691 struct vop_link_args /* { 1692 struct vnode *a_tdvp; 1693 struct vnode *a_vp; 1694 struct componentname *a_cnp; 1695 } */ *ap; 1696{ 1697 register struct vnode *vp = ap->a_vp; 1698 register struct vnode *tdvp = ap->a_tdvp; 1699 register struct componentname *cnp = ap->a_cnp; 1700 register u_long *tl; 1701 register caddr_t cp; 1702 register long t1, t2; 1703 caddr_t bpos, dpos, cp2; 1704 int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0; 1705 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1706 int v3 = NFS_ISV3(vp); 1707 1708 if (vp->v_mount != tdvp->v_mount) { 1709 VOP_ABORTOP(vp, cnp); 1710 if (tdvp == vp) 1711 vrele(tdvp); 1712 else 1713 vput(tdvp); 1714 return (EXDEV); 1715 } 1716 1717 /* 1718 * Push all writes to the server, so that the attribute cache 1719 * doesn't get "out of sync" with the server. 1720 * XXX There should be a better way! 1721 */ 1722 VOP_FSYNC(vp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc); 1723 1724 nfsstats.rpccnt[NFSPROC_LINK]++; 1725 nfsm_reqhead(vp, NFSPROC_LINK, 1726 NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen)); 1727 nfsm_fhtom(vp, v3); 1728 nfsm_fhtom(tdvp, v3); 1729 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1730 nfsm_request(vp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred); 1731 if (v3) { 1732 nfsm_postop_attr(vp, attrflag); 1733 nfsm_wcc_data(tdvp, wccflag); 1734 } 1735 nfsm_reqdone; 1736 FREE(cnp->cn_pnbuf, M_NAMEI); 1737 VTONFS(tdvp)->n_flag |= NMODIFIED; 1738 if (!attrflag) 1739 VTONFS(vp)->n_attrstamp = 0; 1740 if (!wccflag) 1741 VTONFS(tdvp)->n_attrstamp = 0; 1742 vput(tdvp); 1743 /* 1744 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1745 */ 1746 if (error == EEXIST) 1747 error = 0; 1748 return (error); 1749} 1750 1751/* 1752 * nfs symbolic link create call 1753 */ 1754static int 1755nfs_symlink(ap) 1756 struct vop_symlink_args /* { 1757 struct vnode *a_dvp; 1758 struct vnode **a_vpp; 1759 struct componentname *a_cnp; 1760 struct vattr *a_vap; 1761 char *a_target; 1762 } */ *ap; 1763{ 1764 register struct vnode *dvp = ap->a_dvp; 1765 register struct vattr *vap = ap->a_vap; 1766 register struct componentname *cnp = ap->a_cnp; 1767 register struct nfsv2_sattr *sp; 1768 register struct nfsv3_sattr *sp3; 1769 register u_long *tl; 1770 register caddr_t cp; 1771 register long t1, t2; 1772 caddr_t bpos, dpos, cp2; 1773 int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp; 1774 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1775 struct vnode *newvp = (struct vnode *)0; 1776 int v3 = NFS_ISV3(dvp); 1777 1778 nfsstats.rpccnt[NFSPROC_SYMLINK]++; 1779 slen = strlen(ap->a_target); 1780 nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED + 1781 nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3)); 1782 nfsm_fhtom(dvp, v3); 1783 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1784 if (v3) { 1785 nfsm_build(sp3, struct nfsv3_sattr *, NFSX_V3SRVSATTR); 1786 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, 1787 cnp->cn_cred->cr_gid); 1788 } 1789 nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN); 1790 if (!v3) { 1791 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1792 sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode); 1793 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1794 sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid); 1795 sp->sa_size = -1; 1796 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1797 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1798 } 1799 nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred); 1800 if (v3) { 1801 if (!error) 1802 nfsm_mtofh(dvp, newvp, v3, gotvp); 1803 nfsm_wcc_data(dvp, wccflag); 1804 } 1805 nfsm_reqdone; 1806 if (newvp) 1807 vput(newvp); 1808 FREE(cnp->cn_pnbuf, M_NAMEI); 1809 VTONFS(dvp)->n_flag |= NMODIFIED; 1810 if (!wccflag) 1811 VTONFS(dvp)->n_attrstamp = 0; 1812 vput(dvp); 1813 /* 1814 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1815 */ 1816 if (error == EEXIST) 1817 error = 0; 1818 return (error); 1819} 1820 1821/* 1822 * nfs make dir call 1823 */ 1824static int 1825nfs_mkdir(ap) 1826 struct vop_mkdir_args /* { 1827 struct vnode *a_dvp; 1828 struct vnode **a_vpp; 1829 struct componentname *a_cnp; 1830 struct vattr *a_vap; 1831 } */ *ap; 1832{ 1833 register struct vnode *dvp = ap->a_dvp; 1834 register struct vattr *vap = ap->a_vap; 1835 register struct componentname *cnp = ap->a_cnp; 1836 register struct nfsv2_sattr *sp; 1837 register struct nfsv3_sattr *sp3; 1838 register u_long *tl; 1839 register caddr_t cp; 1840 register long t1, t2; 1841 register int len; 1842 struct nfsnode *np = (struct nfsnode *)0; 1843 struct vnode *newvp = (struct vnode *)0; 1844 caddr_t bpos, dpos, cp2; 1845 int error = 0, wccflag = NFSV3_WCCRATTR; 1846 int gotvp = 0; 1847 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1848 struct vattr vattr; 1849 int v3 = NFS_ISV3(dvp); 1850 1851 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1852 VOP_ABORTOP(dvp, cnp); 1853 vput(dvp); 1854 return (error); 1855 } 1856 len = cnp->cn_namelen; 1857 nfsstats.rpccnt[NFSPROC_MKDIR]++; 1858 nfsm_reqhead(dvp, NFSPROC_MKDIR, 1859 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3)); 1860 nfsm_fhtom(dvp, v3); 1861 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 1862 if (v3) { 1863 nfsm_build(sp3, struct nfsv3_sattr *, NFSX_V3SRVSATTR); 1864 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1865 } else { 1866 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1867 sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode); 1868 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1869 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1870 sp->sa_size = -1; 1871 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1872 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1873 } 1874 nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred); 1875 if (!error) 1876 nfsm_mtofh(dvp, newvp, v3, gotvp); 1877 if (v3) 1878 nfsm_wcc_data(dvp, wccflag); 1879 nfsm_reqdone; 1880 VTONFS(dvp)->n_flag |= NMODIFIED; 1881 if (!wccflag) 1882 VTONFS(dvp)->n_attrstamp = 0; 1883 /* 1884 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry 1885 * if we can succeed in looking up the directory. 1886 */ 1887 if (error == EEXIST || (!error && !gotvp)) { 1888 if (newvp) { 1889 vrele(newvp); 1890 newvp = (struct vnode *)0; 1891 } 1892 error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred, 1893 cnp->cn_proc, &np); 1894 if (!error) { 1895 newvp = NFSTOV(np); 1896 if (newvp->v_type != VDIR) 1897 error = EEXIST; 1898 } 1899 } 1900 if (error) { 1901 if (newvp) 1902 vrele(newvp); 1903 } else 1904 *ap->a_vpp = newvp; 1905 FREE(cnp->cn_pnbuf, M_NAMEI); 1906 vput(dvp); 1907 return (error); 1908} 1909 1910/* 1911 * nfs remove directory call 1912 */ 1913static int 1914nfs_rmdir(ap) 1915 struct vop_rmdir_args /* { 1916 struct vnode *a_dvp; 1917 struct vnode *a_vp; 1918 struct componentname *a_cnp; 1919 } */ *ap; 1920{ 1921 register struct vnode *vp = ap->a_vp; 1922 register struct vnode *dvp = ap->a_dvp; 1923 register struct componentname *cnp = ap->a_cnp; 1924 register u_long *tl; 1925 register caddr_t cp; 1926 register long t1, t2; 1927 caddr_t bpos, dpos, cp2; 1928 int error = 0, wccflag = NFSV3_WCCRATTR; 1929 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1930 int v3 = NFS_ISV3(dvp); 1931 1932 nfsstats.rpccnt[NFSPROC_RMDIR]++; 1933 nfsm_reqhead(dvp, NFSPROC_RMDIR, 1934 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen)); 1935 nfsm_fhtom(dvp, v3); 1936 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1937 nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred); 1938 if (v3) 1939 nfsm_wcc_data(dvp, wccflag); 1940 nfsm_reqdone; 1941 FREE(cnp->cn_pnbuf, M_NAMEI); 1942 VTONFS(dvp)->n_flag |= NMODIFIED; 1943 if (!wccflag) 1944 VTONFS(dvp)->n_attrstamp = 0; 1945 cache_purge(dvp); 1946 cache_purge(vp); 1947 vput(vp); 1948 vput(dvp); 1949 /* 1950 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry. 1951 */ 1952 if (error == ENOENT) 1953 error = 0; 1954 return (error); 1955} 1956 1957/* 1958 * nfs readdir call 1959 */ 1960static int 1961nfs_readdir(ap) 1962 struct vop_readdir_args /* { 1963 struct vnode *a_vp; 1964 struct uio *a_uio; 1965 struct ucred *a_cred; 1966 } */ *ap; 1967{ 1968 register struct vnode *vp = ap->a_vp; 1969 register struct nfsnode *np = VTONFS(vp); 1970 register struct uio *uio = ap->a_uio; 1971 int tresid, error; 1972 struct vattr vattr; 1973 1974 if (vp->v_type != VDIR) 1975 return (EPERM); 1976 /* 1977 * First, check for hit on the EOF offset cache 1978 */ 1979 if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset && 1980 (np->n_flag & NMODIFIED) == 0) { 1981 if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) { 1982 if (NQNFS_CKCACHABLE(vp, ND_READ)) { 1983 nfsstats.direofcache_hits++; 1984 return (0); 1985 } 1986 } else if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_procp) == 0 && 1987 np->n_mtime == vattr.va_mtime.tv_sec) { 1988 nfsstats.direofcache_hits++; 1989 return (0); 1990 } 1991 } 1992 1993 /* 1994 * Call nfs_bioread() to do the real work. 1995 */ 1996 tresid = uio->uio_resid; 1997 error = nfs_bioread(vp, uio, 0, ap->a_cred, 0); 1998 1999 if (!error && uio->uio_resid == tresid) 2000 nfsstats.direofcache_misses++; 2001 return (error); 2002} 2003 2004/* 2005 * Readdir rpc call. 2006 * Called from below the buffer cache by nfs_doio(). 2007 */ 2008int 2009nfs_readdirrpc(vp, uiop, cred) 2010 struct vnode *vp; 2011 register struct uio *uiop; 2012 struct ucred *cred; 2013 2014{ 2015 register int len, left; 2016 register struct dirent *dp; 2017 register u_long *tl; 2018 register caddr_t cp; 2019 register long t1, t2; 2020 register nfsuint64 *cookiep; 2021 caddr_t bpos, dpos, cp2; 2022 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2023 nfsuint64 cookie; 2024 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2025 struct nfsnode *dnp = VTONFS(vp); 2026 u_quad_t fileno; 2027 int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1; 2028 int attrflag; 2029 int v3 = NFS_ISV3(vp); 2030 2031#ifndef nolint 2032 dp = (struct dirent *)0; 2033#endif 2034#ifndef DIAGNOSTIC 2035 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (NFS_DIRBLKSIZ - 1)) || 2036 (uiop->uio_resid & (NFS_DIRBLKSIZ - 1))) 2037 panic("nfs readdirrpc bad uio"); 2038#endif 2039 2040 /* 2041 * If there is no cookie, assume directory was stale. 2042 */ 2043 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0); 2044 if (cookiep) 2045 cookie = *cookiep; 2046 else 2047 return (NFSERR_BAD_COOKIE); 2048 /* 2049 * Loop around doing readdir rpc's of size nm_readdirsize 2050 * truncated to a multiple of DIRBLKSIZ. 2051 * The stopping criteria is EOF or buffer full. 2052 */ 2053 while (more_dirs && bigenough) { 2054 nfsstats.rpccnt[NFSPROC_READDIR]++; 2055 nfsm_reqhead(vp, NFSPROC_READDIR, NFSX_FH(v3) + 2056 NFSX_READDIR(v3)); 2057 nfsm_fhtom(vp, v3); 2058 if (v3) { 2059 nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED); 2060 *tl++ = cookie.nfsuquad[0]; 2061 *tl++ = cookie.nfsuquad[1]; 2062 *tl++ = dnp->n_cookieverf.nfsuquad[0]; 2063 *tl++ = dnp->n_cookieverf.nfsuquad[1]; 2064 } else { 2065 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 2066 *tl++ = cookie.nfsuquad[0]; 2067 } 2068 *tl = txdr_unsigned(nmp->nm_readdirsize); 2069 nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred); 2070 if (v3) { 2071 nfsm_postop_attr(vp, attrflag); 2072 if (!error) { 2073 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 2074 dnp->n_cookieverf.nfsuquad[0] = *tl++; 2075 dnp->n_cookieverf.nfsuquad[1] = *tl; 2076 } else { 2077 m_freem(mrep); 2078 goto nfsmout; 2079 } 2080 } 2081 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2082 more_dirs = fxdr_unsigned(int, *tl); 2083 2084 /* loop thru the dir entries, doctoring them to 4bsd form */ 2085 while (more_dirs && bigenough) { 2086 if (v3) { 2087 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2088 fxdr_hyper(tl, &fileno); 2089 len = fxdr_unsigned(int, *(tl + 2)); 2090 } else { 2091 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 2092 fileno = fxdr_unsigned(u_quad_t, *tl++); 2093 len = fxdr_unsigned(int, *tl); 2094 } 2095 if (len <= 0 || len > NFS_MAXNAMLEN) { 2096 error = EBADRPC; 2097 m_freem(mrep); 2098 goto nfsmout; 2099 } 2100 tlen = nfsm_rndup(len); 2101 if (tlen == len) 2102 tlen += 4; /* To ensure null termination */ 2103 left = DIRBLKSIZ - blksiz; 2104 if ((tlen + DIRHDSIZ) > left) { 2105 dp->d_reclen += left; 2106 uiop->uio_iov->iov_base += left; 2107 uiop->uio_iov->iov_len -= left; 2108 uiop->uio_offset += left; 2109 uiop->uio_resid -= left; 2110 blksiz = 0; 2111 } 2112 if ((tlen + DIRHDSIZ) > uiop->uio_resid) 2113 bigenough = 0; 2114 if (bigenough) { 2115 dp = (struct dirent *)uiop->uio_iov->iov_base; 2116 dp->d_fileno = (int)fileno; 2117 dp->d_namlen = len; 2118 dp->d_reclen = tlen + DIRHDSIZ; 2119 dp->d_type = DT_UNKNOWN; 2120 blksiz += dp->d_reclen; 2121 if (blksiz == DIRBLKSIZ) 2122 blksiz = 0; 2123 uiop->uio_offset += DIRHDSIZ; 2124 uiop->uio_resid -= DIRHDSIZ; 2125 uiop->uio_iov->iov_base += DIRHDSIZ; 2126 uiop->uio_iov->iov_len -= DIRHDSIZ; 2127 nfsm_mtouio(uiop, len); 2128 cp = uiop->uio_iov->iov_base; 2129 tlen -= len; 2130 *cp = '\0'; /* null terminate */ 2131 uiop->uio_iov->iov_base += tlen; 2132 uiop->uio_iov->iov_len -= tlen; 2133 uiop->uio_offset += tlen; 2134 uiop->uio_resid -= tlen; 2135 } else 2136 nfsm_adv(nfsm_rndup(len)); 2137 if (v3) { 2138 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2139 } else { 2140 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 2141 } 2142 if (bigenough) { 2143 cookie.nfsuquad[0] = *tl++; 2144 if (v3) 2145 cookie.nfsuquad[1] = *tl++; 2146 } else if (v3) 2147 tl += 2; 2148 else 2149 tl++; 2150 more_dirs = fxdr_unsigned(int, *tl); 2151 } 2152 /* 2153 * If at end of rpc data, get the eof boolean 2154 */ 2155 if (!more_dirs) { 2156 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2157 more_dirs = (fxdr_unsigned(int, *tl) == 0); 2158 } 2159 m_freem(mrep); 2160 } 2161 /* 2162 * Fill last record, iff any, out to a multiple of DIRBLKSIZ 2163 * by increasing d_reclen for the last record. 2164 */ 2165 if (blksiz > 0) { 2166 left = DIRBLKSIZ - blksiz; 2167 dp->d_reclen += left; 2168 uiop->uio_iov->iov_base += left; 2169 uiop->uio_iov->iov_len -= left; 2170 uiop->uio_offset += left; 2171 uiop->uio_resid -= left; 2172 } 2173 2174 /* 2175 * We are now either at the end of the directory or have filled the 2176 * block. 2177 */ 2178 if (bigenough) 2179 dnp->n_direofoffset = uiop->uio_offset; 2180 else { 2181 if (uiop->uio_resid > 0) 2182 printf("EEK! readdirrpc resid > 0\n"); 2183 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1); 2184 *cookiep = cookie; 2185 } 2186nfsmout: 2187 return (error); 2188} 2189 2190/* 2191 * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc(). 2192 */ 2193int 2194nfs_readdirplusrpc(vp, uiop, cred) 2195 struct vnode *vp; 2196 register struct uio *uiop; 2197 struct ucred *cred; 2198{ 2199 register int len, left; 2200 register struct dirent *dp; 2201 register u_long *tl; 2202 register caddr_t cp; 2203 register long t1, t2; 2204 register struct vnode *newvp; 2205 register nfsuint64 *cookiep; 2206 caddr_t bpos, dpos, cp2, dpossav1, dpossav2; 2207 struct mbuf *mreq, *mrep, *md, *mb, *mb2, *mdsav1, *mdsav2; 2208 struct nameidata nami, *ndp = &nami; 2209 struct componentname *cnp = &ndp->ni_cnd; 2210 nfsuint64 cookie; 2211 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2212 struct nfsnode *dnp = VTONFS(vp), *np; 2213 nfsfh_t *fhp; 2214 u_quad_t fileno; 2215 int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i; 2216 int attrflag, fhsize; 2217 2218#ifndef nolint 2219 dp = (struct dirent *)0; 2220#endif 2221#ifndef DIAGNOSTIC 2222 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (DIRBLKSIZ - 1)) || 2223 (uiop->uio_resid & (DIRBLKSIZ - 1))) 2224 panic("nfs readdirplusrpc bad uio"); 2225#endif 2226 ndp->ni_dvp = vp; 2227 newvp = NULLVP; 2228 2229 /* 2230 * If there is no cookie, assume directory was stale. 2231 */ 2232 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0); 2233 if (cookiep) 2234 cookie = *cookiep; 2235 else 2236 return (NFSERR_BAD_COOKIE); 2237 /* 2238 * Loop around doing readdir rpc's of size nm_readdirsize 2239 * truncated to a multiple of DIRBLKSIZ. 2240 * The stopping criteria is EOF or buffer full. 2241 */ 2242 while (more_dirs && bigenough) { 2243 nfsstats.rpccnt[NFSPROC_READDIRPLUS]++; 2244 nfsm_reqhead(vp, NFSPROC_READDIRPLUS, 2245 NFSX_FH(1) + 6 * NFSX_UNSIGNED); 2246 nfsm_fhtom(vp, 1); 2247 nfsm_build(tl, u_long *, 6 * NFSX_UNSIGNED); 2248 *tl++ = cookie.nfsuquad[0]; 2249 *tl++ = cookie.nfsuquad[1]; 2250 *tl++ = dnp->n_cookieverf.nfsuquad[0]; 2251 *tl++ = dnp->n_cookieverf.nfsuquad[1]; 2252 *tl++ = txdr_unsigned(nmp->nm_readdirsize); 2253 *tl = txdr_unsigned(nmp->nm_rsize); 2254 nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_procp, cred); 2255 nfsm_postop_attr(vp, attrflag); 2256 if (error) { 2257 m_freem(mrep); 2258 goto nfsmout; 2259 } 2260 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2261 dnp->n_cookieverf.nfsuquad[0] = *tl++; 2262 dnp->n_cookieverf.nfsuquad[1] = *tl++; 2263 more_dirs = fxdr_unsigned(int, *tl); 2264 2265 /* loop thru the dir entries, doctoring them to 4bsd form */ 2266 while (more_dirs && bigenough) { 2267 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2268 fxdr_hyper(tl, &fileno); 2269 len = fxdr_unsigned(int, *(tl + 2)); 2270 if (len <= 0 || len > NFS_MAXNAMLEN) { 2271 error = EBADRPC; 2272 m_freem(mrep); 2273 goto nfsmout; 2274 } 2275 tlen = nfsm_rndup(len); 2276 if (tlen == len) 2277 tlen += 4; /* To ensure null termination*/ 2278 left = DIRBLKSIZ - blksiz; 2279 if ((tlen + DIRHDSIZ) > left) { 2280 dp->d_reclen += left; 2281 uiop->uio_iov->iov_base += left; 2282 uiop->uio_iov->iov_len -= left; 2283 uiop->uio_offset += left; 2284 uiop->uio_resid -= left; 2285 blksiz = 0; 2286 } 2287 if ((tlen + DIRHDSIZ) > uiop->uio_resid) 2288 bigenough = 0; 2289 if (bigenough) { 2290 dp = (struct dirent *)uiop->uio_iov->iov_base; 2291 dp->d_fileno = (int)fileno; 2292 dp->d_namlen = len; 2293 dp->d_reclen = tlen + DIRHDSIZ; 2294 dp->d_type = DT_UNKNOWN; 2295 blksiz += dp->d_reclen; 2296 if (blksiz == DIRBLKSIZ) 2297 blksiz = 0; 2298 uiop->uio_offset += DIRHDSIZ; 2299 uiop->uio_resid -= DIRHDSIZ; 2300 uiop->uio_iov->iov_base += DIRHDSIZ; 2301 uiop->uio_iov->iov_len -= DIRHDSIZ; 2302 cnp->cn_nameptr = uiop->uio_iov->iov_base; 2303 cnp->cn_namelen = len; 2304 nfsm_mtouio(uiop, len); 2305 cp = uiop->uio_iov->iov_base; 2306 tlen -= len; 2307 *cp = '\0'; 2308 uiop->uio_iov->iov_base += tlen; 2309 uiop->uio_iov->iov_len -= tlen; 2310 uiop->uio_offset += tlen; 2311 uiop->uio_resid -= tlen; 2312 } else 2313 nfsm_adv(nfsm_rndup(len)); 2314 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2315 if (bigenough) { 2316 cookie.nfsuquad[0] = *tl++; 2317 cookie.nfsuquad[1] = *tl++; 2318 } else 2319 tl += 2; 2320 2321 /* 2322 * Since the attributes are before the file handle 2323 * (sigh), we must skip over the attributes and then 2324 * come back and get them. 2325 */ 2326 attrflag = fxdr_unsigned(int, *tl); 2327 if (attrflag) { 2328 dpossav1 = dpos; 2329 mdsav1 = md; 2330 nfsm_adv(NFSX_V3FATTR); 2331 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2332 doit = fxdr_unsigned(int, *tl); 2333 if (doit) { 2334 nfsm_getfh(fhp, fhsize, 1); 2335 if (NFS_CMPFH(dnp, fhp, fhsize)) { 2336 VREF(vp); 2337 newvp = vp; 2338 np = dnp; 2339 } else { 2340 if (error = nfs_nget(vp->v_mount, fhp, 2341 fhsize, &np)) 2342 doit = 0; 2343 else 2344 newvp = NFSTOV(np); 2345 } 2346 } 2347 if (doit) { 2348 dpossav2 = dpos; 2349 dpos = dpossav1; 2350 mdsav2 = md; 2351 md = mdsav1; 2352 nfsm_loadattr(newvp, (struct vattr *)0); 2353 dpos = dpossav2; 2354 md = mdsav2; 2355 dp->d_type = 2356 IFTODT(VTTOIF(np->n_vattr.va_type)); 2357 ndp->ni_vp = newvp; 2358 cnp->cn_hash = 0; 2359 for (cp = cnp->cn_nameptr, i = 1; i <= len; 2360 i++, cp++) 2361 cnp->cn_hash += (unsigned char)*cp * i; 2362 cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp); 2363 } 2364 } else { 2365 /* Just skip over the file handle */ 2366 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2367 i = fxdr_unsigned(int, *tl); 2368 nfsm_adv(nfsm_rndup(i)); 2369 } 2370 if (newvp != NULLVP) { 2371 vrele(newvp); 2372 newvp = NULLVP; 2373 } 2374 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2375 more_dirs = fxdr_unsigned(int, *tl); 2376 } 2377 /* 2378 * If at end of rpc data, get the eof boolean 2379 */ 2380 if (!more_dirs) { 2381 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2382 more_dirs = (fxdr_unsigned(int, *tl) == 0); 2383 } 2384 m_freem(mrep); 2385 } 2386 /* 2387 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ 2388 * by increasing d_reclen for the last record. 2389 */ 2390 if (blksiz > 0) { 2391 left = DIRBLKSIZ - blksiz; 2392 dp->d_reclen += left; 2393 uiop->uio_iov->iov_base += left; 2394 uiop->uio_iov->iov_len -= left; 2395 uiop->uio_offset += left; 2396 uiop->uio_resid -= left; 2397 } 2398 2399 /* 2400 * We are now either at the end of the directory or have filled the 2401 * block. 2402 */ 2403 if (bigenough) 2404 dnp->n_direofoffset = uiop->uio_offset; 2405 else { 2406 if (uiop->uio_resid > 0) 2407 printf("EEK! readdirplusrpc resid > 0\n"); 2408 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1); 2409 *cookiep = cookie; 2410 } 2411nfsmout: 2412 if (newvp != NULLVP) { 2413 if (newvp == vp) 2414 vrele(newvp); 2415 else 2416 vput(newvp); 2417 newvp = NULLVP; 2418 } 2419 return (error); 2420} 2421 2422/* 2423 * Silly rename. To make the NFS filesystem that is stateless look a little 2424 * more like the "ufs" a remove of an active vnode is translated to a rename 2425 * to a funny looking filename that is removed by nfs_inactive on the 2426 * nfsnode. There is the potential for another process on a different client 2427 * to create the same funny name between the nfs_lookitup() fails and the 2428 * nfs_rename() completes, but... 2429 */ 2430static int 2431nfs_sillyrename(dvp, vp, cnp) 2432 struct vnode *dvp, *vp; 2433 struct componentname *cnp; 2434{ 2435 register struct sillyrename *sp; 2436 struct nfsnode *np; 2437 int error; 2438 short pid; 2439 2440 cache_purge(dvp); 2441 np = VTONFS(vp); 2442#ifndef DIAGNOSTIC 2443 if (vp->v_type == VDIR) 2444 panic("nfs: sillyrename dir"); 2445#endif 2446 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename), 2447 M_NFSREQ, M_WAITOK); 2448 sp->s_cred = crdup(cnp->cn_cred); 2449 sp->s_dvp = dvp; 2450 VREF(dvp); 2451 2452 /* Fudge together a funny name */ 2453 pid = cnp->cn_proc->p_pid; 2454 sp->s_namlen = sprintf(sp->s_name, ".nfsA%04x4.4", pid); 2455 2456 /* Try lookitups until we get one that isn't there */ 2457 while (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 2458 cnp->cn_proc, (struct nfsnode **)0) == 0) { 2459 sp->s_name[4]++; 2460 if (sp->s_name[4] > 'z') { 2461 error = EINVAL; 2462 goto bad; 2463 } 2464 } 2465 if (error = nfs_renameit(dvp, cnp, sp)) 2466 goto bad; 2467 error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 2468 cnp->cn_proc, &np); 2469 np->n_sillyrename = sp; 2470 return (0); 2471bad: 2472 vrele(sp->s_dvp); 2473 crfree(sp->s_cred); 2474 free((caddr_t)sp, M_NFSREQ); 2475 return (error); 2476} 2477 2478/* 2479 * Look up a file name and optionally either update the file handle or 2480 * allocate an nfsnode, depending on the value of npp. 2481 * npp == NULL --> just do the lookup 2482 * *npp == NULL --> allocate a new nfsnode and make sure attributes are 2483 * handled too 2484 * *npp != NULL --> update the file handle in the vnode 2485 */ 2486static int 2487nfs_lookitup(dvp, name, len, cred, procp, npp) 2488 register struct vnode *dvp; 2489 char *name; 2490 int len; 2491 struct ucred *cred; 2492 struct proc *procp; 2493 struct nfsnode **npp; 2494{ 2495 register u_long *tl; 2496 register caddr_t cp; 2497 register long t1, t2; 2498 struct vnode *newvp = (struct vnode *)0; 2499 struct nfsnode *np, *dnp = VTONFS(dvp); 2500 caddr_t bpos, dpos, cp2; 2501 int error = 0, fhlen, attrflag; 2502 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2503 nfsfh_t *nfhp; 2504 int v3 = NFS_ISV3(dvp); 2505 2506 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 2507 nfsm_reqhead(dvp, NFSPROC_LOOKUP, 2508 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len)); 2509 nfsm_fhtom(dvp, v3); 2510 nfsm_strtom(name, len, NFS_MAXNAMLEN); 2511 nfsm_request(dvp, NFSPROC_LOOKUP, procp, cred); 2512 if (npp && !error) { 2513 nfsm_getfh(nfhp, fhlen, v3); 2514 if (*npp) { 2515 np = *npp; 2516 if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) { 2517 free((caddr_t)np->n_fhp, M_NFSBIGFH); 2518 np->n_fhp = &np->n_fh; 2519 } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH) 2520 np->n_fhp =(nfsfh_t *)malloc(fhlen,M_NFSBIGFH,M_WAITOK); 2521 bcopy((caddr_t)nfhp, (caddr_t)np->n_fhp, fhlen); 2522 np->n_fhsize = fhlen; 2523 newvp = NFSTOV(np); 2524 } else if (NFS_CMPFH(dnp, nfhp, fhlen)) { 2525 VREF(dvp); 2526 newvp = dvp; 2527 } else { 2528 error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np); 2529 if (error) { 2530 m_freem(mrep); 2531 return (error); 2532 } 2533 newvp = NFSTOV(np); 2534 } 2535 if (v3) { 2536 nfsm_postop_attr(newvp, attrflag); 2537 if (!attrflag && *npp == NULL) { 2538 m_freem(mrep); 2539 if (newvp == dvp) 2540 vrele(newvp); 2541 else 2542 vput(newvp); 2543 return (ENOENT); 2544 } 2545 } else 2546 nfsm_loadattr(newvp, (struct vattr *)0); 2547 } 2548 nfsm_reqdone; 2549 if (npp && *npp == NULL) { 2550 if (error) { 2551 if (newvp) 2552 if (newvp == dvp) 2553 vrele(newvp); 2554 else 2555 vput(newvp); 2556 } else 2557 *npp = np; 2558 } 2559 return (error); 2560} 2561 2562/* 2563 * Nfs Version 3 commit rpc 2564 */ 2565static int 2566nfs_commit(vp, offset, cnt, cred, procp) 2567 register struct vnode *vp; 2568 u_quad_t offset; 2569 int cnt; 2570 struct ucred *cred; 2571 struct proc *procp; 2572{ 2573 register caddr_t cp; 2574 register u_long *tl; 2575 register int t1, t2; 2576 register struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2577 caddr_t bpos, dpos, cp2; 2578 int error = 0, wccflag = NFSV3_WCCRATTR; 2579 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2580 2581 if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) 2582 return (0); 2583 nfsstats.rpccnt[NFSPROC_COMMIT]++; 2584 nfsm_reqhead(vp, NFSPROC_COMMIT, NFSX_FH(1)); 2585 nfsm_fhtom(vp, 1); 2586 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 2587 txdr_hyper(&offset, tl); 2588 tl += 2; 2589 *tl = txdr_unsigned(cnt); 2590 nfsm_request(vp, NFSPROC_COMMIT, procp, cred); 2591 nfsm_wcc_data(vp, wccflag); 2592 if (!error) { 2593 nfsm_dissect(tl, u_long *, NFSX_V3WRITEVERF); 2594 if (bcmp((caddr_t)nmp->nm_verf, (caddr_t)tl, 2595 NFSX_V3WRITEVERF)) { 2596 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 2597 NFSX_V3WRITEVERF); 2598 error = NFSERR_STALEWRITEVERF; 2599 } 2600 } 2601 nfsm_reqdone; 2602 return (error); 2603} 2604 2605/* 2606 * Kludge City.. 2607 * - make nfs_bmap() essentially a no-op that does no translation 2608 * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc 2609 * (Maybe I could use the process's page mapping, but I was concerned that 2610 * Kernel Write might not be enabled and also figured copyout() would do 2611 * a lot more work than bcopy() and also it currently happens in the 2612 * context of the swapper process (2). 2613 */ 2614static int 2615nfs_bmap(ap) 2616 struct vop_bmap_args /* { 2617 struct vnode *a_vp; 2618 daddr_t a_bn; 2619 struct vnode **a_vpp; 2620 daddr_t *a_bnp; 2621 int *a_runp; 2622 int *a_runb; 2623 } */ *ap; 2624{ 2625 register struct vnode *vp = ap->a_vp; 2626 2627 if (ap->a_vpp != NULL) 2628 *ap->a_vpp = vp; 2629 if (ap->a_bnp != NULL) 2630 *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize); 2631 if (ap->a_runp != NULL) 2632 *ap->a_runp = 0; 2633 if (ap->a_runb != NULL) 2634 *ap->a_runb = 0; 2635 return (0); 2636} 2637 2638/* 2639 * Strategy routine. 2640 * For async requests when nfsiod(s) are running, queue the request by 2641 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the 2642 * request. 2643 */ 2644static int 2645nfs_strategy(ap) 2646 struct vop_strategy_args *ap; 2647{ 2648 register struct buf *bp = ap->a_bp; 2649 struct ucred *cr; 2650 struct proc *p; 2651 int error = 0; 2652 2653 if (bp->b_flags & B_PHYS) 2654 panic("nfs physio"); 2655 if (bp->b_flags & B_ASYNC) 2656 p = (struct proc *)0; 2657 else 2658 p = curproc; /* XXX */ 2659 if (bp->b_flags & B_READ) 2660 cr = bp->b_rcred; 2661 else 2662 cr = bp->b_wcred; 2663 /* 2664 * If the op is asynchronous and an i/o daemon is waiting 2665 * queue the request, wake it up and wait for completion 2666 * otherwise just do it ourselves. 2667 */ 2668 if ((bp->b_flags & B_ASYNC) == 0 || 2669 nfs_asyncio(bp, NOCRED)) 2670 error = nfs_doio(bp, cr, p); 2671 return (error); 2672} 2673 2674/* 2675 * Mmap a file 2676 * 2677 * NB Currently unsupported. 2678 */ 2679/* ARGSUSED */ 2680static int 2681nfs_mmap(ap) 2682 struct vop_mmap_args /* { 2683 struct vnode *a_vp; 2684 int a_fflags; 2685 struct ucred *a_cred; 2686 struct proc *a_p; 2687 } */ *ap; 2688{ 2689 2690 return (EINVAL); 2691} 2692 2693/* 2694 * fsync vnode op. Just call nfs_flush() with commit == 1. 2695 */ 2696/* ARGSUSED */ 2697static int 2698nfs_fsync(ap) 2699 struct vop_fsync_args /* { 2700 struct vnodeop_desc *a_desc; 2701 struct vnode * a_vp; 2702 struct ucred * a_cred; 2703 int a_waitfor; 2704 struct proc * a_p; 2705 } */ *ap; 2706{ 2707 2708 return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_p, 1)); 2709} 2710 2711/* 2712 * Flush all the blocks associated with a vnode. 2713 * Walk through the buffer pool and push any dirty pages 2714 * associated with the vnode. 2715 */ 2716static int 2717nfs_flush(vp, cred, waitfor, p, commit) 2718 register struct vnode *vp; 2719 struct ucred *cred; 2720 int waitfor; 2721 struct proc *p; 2722 int commit; 2723{ 2724 register struct nfsnode *np = VTONFS(vp); 2725 register struct buf *bp; 2726 register int i; 2727 struct buf *nbp; 2728 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2729 int s, error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos; 2730 int passone = 1; 2731 u_quad_t off, endoff, toff; 2732 struct ucred* wcred = NULL; 2733 struct buf **bvec = NULL; 2734#ifndef NFS_COMMITBVECSIZ 2735#define NFS_COMMITBVECSIZ 20 2736#endif 2737 struct buf *bvec_on_stack[NFS_COMMITBVECSIZ]; 2738 int bvecsize = 0, bveccount; 2739 2740 if (nmp->nm_flag & NFSMNT_INT) 2741 slpflag = PCATCH; 2742 if (!commit) 2743 passone = 0; 2744 /* 2745 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the 2746 * server, but nas not been committed to stable storage on the server 2747 * yet. On the first pass, the byte range is worked out and the commit 2748 * rpc is done. On the second pass, nfs_writebp() is called to do the 2749 * job. 2750 */ 2751again: 2752 off = (u_quad_t)-1; 2753 endoff = 0; 2754 bvecpos = 0; 2755 if (NFS_ISV3(vp) && commit) { 2756 s = splbio(); 2757 /* 2758 * Count up how many buffers waiting for a commit. 2759 */ 2760 bveccount = 0; 2761 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2762 nbp = bp->b_vnbufs.le_next; 2763 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT)) 2764 == (B_DELWRI | B_NEEDCOMMIT)) 2765 bveccount++; 2766 } 2767 /* 2768 * Allocate space to remember the list of bufs to commit. It is 2769 * important to use M_NOWAIT here to avoid a race with nfs_write. 2770 * If we can't get memory (for whatever reason), we will end up 2771 * committing the buffers one-by-one in the loop below. 2772 */ 2773 if (bveccount > NFS_COMMITBVECSIZ) { 2774 if (bvec != NULL && bvec != bvec_on_stack) 2775 free(bvec, M_TEMP); 2776 bvec = (struct buf **) 2777 malloc(bveccount * sizeof(struct buf *), 2778 M_TEMP, M_NOWAIT); 2779 if (bvec == NULL) { 2780 bvec = bvec_on_stack; 2781 bvecsize = NFS_COMMITBVECSIZ; 2782 } else 2783 bvecsize = bveccount; 2784 } else { 2785 bvec = bvec_on_stack; 2786 bvecsize = NFS_COMMITBVECSIZ; 2787 } 2788 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2789 nbp = bp->b_vnbufs.le_next; 2790 if (bvecpos >= bvecsize) 2791 break; 2792 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT)) 2793 != (B_DELWRI | B_NEEDCOMMIT)) 2794 continue; 2795 bremfree(bp); 2796 /* 2797 * Work out if all buffers are using the same cred 2798 * so we can deal with them all with one commit. 2799 */ 2800 if (wcred == NULL) 2801 wcred = bp->b_wcred; 2802 else if (wcred != bp->b_wcred) 2803 wcred = NOCRED; 2804 bp->b_flags |= (B_BUSY | B_WRITEINPROG); 2805 vfs_busy_pages(bp, 1); 2806 /* 2807 * A list of these buffers is kept so that the 2808 * second loop knows which buffers have actually 2809 * been committed. This is necessary, since there 2810 * may be a race between the commit rpc and new 2811 * uncommitted writes on the file. 2812 */ 2813 bvec[bvecpos++] = bp; 2814 toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + 2815 bp->b_dirtyoff; 2816 if (toff < off) 2817 off = toff; 2818 toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff); 2819 if (toff > endoff) 2820 endoff = toff; 2821 } 2822 splx(s); 2823 } 2824 if (bvecpos > 0) { 2825 /* 2826 * Commit data on the server, as required. 2827 * If all bufs are using the same wcred, then use that with 2828 * one call for all of them, otherwise commit each one 2829 * separately. 2830 */ 2831 if (wcred != NOCRED) 2832 retv = nfs_commit(vp, off, (int)(endoff - off), 2833 wcred, p); 2834 else { 2835 retv = 0; 2836 for (i = 0; i < bvecpos; i++) { 2837 off_t off, size; 2838 bp = bvec[i]; 2839 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + 2840 bp->b_dirtyoff; 2841 size = (u_quad_t)(bp->b_dirtyend 2842 - bp->b_dirtyoff); 2843 retv = nfs_commit(vp, off, (int)size, 2844 bp->b_wcred, p); 2845 if (retv) break; 2846 } 2847 } 2848 2849 if (retv == NFSERR_STALEWRITEVERF) 2850 nfs_clearcommit(vp->v_mount); 2851 /* 2852 * Now, either mark the blocks I/O done or mark the 2853 * blocks dirty, depending on whether the commit 2854 * succeeded. 2855 */ 2856 for (i = 0; i < bvecpos; i++) { 2857 bp = bvec[i]; 2858 bp->b_flags &= ~(B_NEEDCOMMIT | B_WRITEINPROG); 2859 if (retv) { 2860 vfs_unbusy_pages(bp); 2861 brelse(bp); 2862 } else { 2863 vp->v_numoutput++; 2864 bp->b_flags |= B_ASYNC; 2865 if (bp->b_flags & B_DELWRI) { 2866 --numdirtybuffers; 2867 if (needsbuffer) { 2868 vfs_bio_need_satisfy(); 2869 } 2870 } 2871 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI); 2872 bp->b_dirtyoff = bp->b_dirtyend = 0; 2873 reassignbuf(bp, vp); 2874 biodone(bp); 2875 } 2876 } 2877 } 2878 2879 /* 2880 * Start/do any write(s) that are required. 2881 */ 2882loop: 2883 s = splbio(); 2884 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2885 nbp = bp->b_vnbufs.le_next; 2886 if (bp->b_flags & B_BUSY) { 2887 if (waitfor != MNT_WAIT || passone) 2888 continue; 2889 bp->b_flags |= B_WANTED; 2890 error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1), 2891 "nfsfsync", slptimeo); 2892 splx(s); 2893 if (error) { 2894 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) { 2895 error = EINTR; 2896 goto done; 2897 } 2898 if (slpflag == PCATCH) { 2899 slpflag = 0; 2900 slptimeo = 2 * hz; 2901 } 2902 } 2903 goto loop; 2904 } 2905 if ((bp->b_flags & B_DELWRI) == 0) 2906 panic("nfs_fsync: not dirty"); 2907 if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT)) 2908 continue; 2909 bremfree(bp); 2910 if (passone || !commit) 2911 bp->b_flags |= (B_BUSY|B_ASYNC); 2912 else 2913 bp->b_flags |= (B_BUSY|B_ASYNC|B_WRITEINPROG|B_NEEDCOMMIT); 2914 splx(s); 2915 VOP_BWRITE(bp); 2916 goto loop; 2917 } 2918 splx(s); 2919 if (passone) { 2920 passone = 0; 2921 goto again; 2922 } 2923 if (waitfor == MNT_WAIT) { 2924 while (vp->v_numoutput) { 2925 vp->v_flag |= VBWAIT; 2926 error = tsleep((caddr_t)&vp->v_numoutput, 2927 slpflag | (PRIBIO + 1), "nfsfsync", slptimeo); 2928 if (error) { 2929 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) { 2930 error = EINTR; 2931 goto done; 2932 } 2933 if (slpflag == PCATCH) { 2934 slpflag = 0; 2935 slptimeo = 2 * hz; 2936 } 2937 } 2938 } 2939 if (vp->v_dirtyblkhd.lh_first && commit) { 2940 goto loop; 2941 } 2942 } 2943 if (np->n_flag & NWRITEERR) { 2944 error = np->n_error; 2945 np->n_flag &= ~NWRITEERR; 2946 } 2947done: 2948 if (bvec != NULL && bvec != bvec_on_stack) 2949 free(bvec, M_TEMP); 2950 return (error); 2951} 2952 2953/* 2954 * Return POSIX pathconf information applicable to nfs. 2955 * 2956 * The NFS V2 protocol doesn't support this, so just return EINVAL 2957 * for V2. 2958 */ 2959/* ARGSUSED */ 2960static int 2961nfs_pathconf(ap) 2962 struct vop_pathconf_args /* { 2963 struct vnode *a_vp; 2964 int a_name; 2965 int *a_retval; 2966 } */ *ap; 2967{ 2968 2969 return (EINVAL); 2970} 2971 2972/* 2973 * NFS advisory byte-level locks. 2974 * Currently unsupported. 2975 */ 2976static int 2977nfs_advlock(ap) 2978 struct vop_advlock_args /* { 2979 struct vnode *a_vp; 2980 caddr_t a_id; 2981 int a_op; 2982 struct flock *a_fl; 2983 int a_flags; 2984 } */ *ap; 2985{ 2986 register struct nfsnode *np = VTONFS(ap->a_vp); 2987 2988 /* 2989 * The following kludge is to allow diskless support to work 2990 * until a real NFS lockd is implemented. Basically, just pretend 2991 * that this is a local lock. 2992 */ 2993 return (lf_advlock(ap, &(np->n_lockf), np->n_size)); 2994} 2995 2996/* 2997 * Print out the contents of an nfsnode. 2998 */ 2999static int 3000nfs_print(ap) 3001 struct vop_print_args /* { 3002 struct vnode *a_vp; 3003 } */ *ap; 3004{ 3005 register struct vnode *vp = ap->a_vp; 3006 register struct nfsnode *np = VTONFS(vp); 3007 3008 printf("tag VT_NFS, fileid %ld fsid 0x%lx", 3009 np->n_vattr.va_fileid, np->n_vattr.va_fsid); 3010 if (vp->v_type == VFIFO) 3011 fifo_printinfo(vp); 3012 printf("\n"); 3013 return (0); 3014} 3015 3016/* 3017 * NFS directory offset lookup. 3018 * Currently unsupported. 3019 */ 3020static int 3021nfs_blkatoff(ap) 3022 struct vop_blkatoff_args /* { 3023 struct vnode *a_vp; 3024 off_t a_offset; 3025 char **a_res; 3026 struct buf **a_bpp; 3027 } */ *ap; 3028{ 3029 3030 return (EOPNOTSUPP); 3031} 3032 3033/* 3034 * NFS flat namespace allocation. 3035 * Currently unsupported. 3036 */ 3037static int 3038nfs_valloc(ap) 3039 struct vop_valloc_args /* { 3040 struct vnode *a_pvp; 3041 int a_mode; 3042 struct ucred *a_cred; 3043 struct vnode **a_vpp; 3044 } */ *ap; 3045{ 3046 3047 return (EOPNOTSUPP); 3048} 3049 3050/* 3051 * NFS flat namespace free. 3052 * Currently unsupported. 3053 */ 3054static int 3055nfs_vfree(ap) 3056 struct vop_vfree_args /* { 3057 struct vnode *a_pvp; 3058 ino_t a_ino; 3059 int a_mode; 3060 } */ *ap; 3061{ 3062 3063 return (EOPNOTSUPP); 3064} 3065 3066/* 3067 * NFS file truncation. 3068 */ 3069static int 3070nfs_truncate(ap) 3071 struct vop_truncate_args /* { 3072 struct vnode *a_vp; 3073 off_t a_length; 3074 int a_flags; 3075 struct ucred *a_cred; 3076 struct proc *a_p; 3077 } */ *ap; 3078{ 3079 3080 /* Use nfs_setattr */ 3081 printf("nfs_truncate: need to implement!!"); 3082 return (EOPNOTSUPP); 3083} 3084 3085/* 3086 * NFS update. 3087 */ 3088static int 3089nfs_update(ap) 3090 struct vop_update_args /* { 3091 struct vnode *a_vp; 3092 struct timeval *a_ta; 3093 struct timeval *a_tm; 3094 int a_waitfor; 3095 } */ *ap; 3096{ 3097 3098#if 0 3099 /* Use nfs_setattr */ 3100 printf("nfs_update: need to implement!!"); 3101#endif 3102 return (EOPNOTSUPP); 3103} 3104 3105/* 3106 * Just call nfs_writebp() with the force argument set to 1. 3107 */ 3108static int 3109nfs_bwrite(ap) 3110 struct vop_bwrite_args /* { 3111 struct vnode *a_bp; 3112 } */ *ap; 3113{ 3114 3115 return (nfs_writebp(ap->a_bp, 1)); 3116} 3117 3118/* 3119 * This is a clone of vn_bwrite(), except that B_WRITEINPROG isn't set unless 3120 * the force flag is one and it also handles the B_NEEDCOMMIT flag. 3121 */ 3122int 3123nfs_writebp(bp, force) 3124 register struct buf *bp; 3125 int force; 3126{ 3127 register int oldflags = bp->b_flags, retv = 1; 3128 off_t off; 3129 3130 if(!(bp->b_flags & B_BUSY)) 3131 panic("bwrite: buffer is not busy???"); 3132 3133 if (bp->b_flags & B_DELWRI) { 3134 --numdirtybuffers; 3135 if (needsbuffer) 3136 vfs_bio_need_satisfy(); 3137 } 3138 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI); 3139 3140 if ((oldflags & (B_ASYNC|B_DELWRI)) == (B_ASYNC|B_DELWRI)) { 3141 reassignbuf(bp, bp->b_vp); 3142 } 3143 3144 bp->b_vp->v_numoutput++; 3145 curproc->p_stats->p_ru.ru_oublock++; 3146 3147 /* 3148 * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not 3149 * an actual write will have to be scheduled via. VOP_STRATEGY(). 3150 * If B_WRITEINPROG is already set, then push it with a write anyhow. 3151 */ 3152 vfs_busy_pages(bp, 1); 3153 if ((oldflags & (B_NEEDCOMMIT | B_WRITEINPROG)) == B_NEEDCOMMIT) { 3154 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff; 3155 bp->b_flags |= B_WRITEINPROG; 3156 retv = nfs_commit(bp->b_vp, off, bp->b_dirtyend-bp->b_dirtyoff, 3157 bp->b_wcred, bp->b_proc); 3158 bp->b_flags &= ~B_WRITEINPROG; 3159 if (!retv) { 3160 bp->b_dirtyoff = bp->b_dirtyend = 0; 3161 bp->b_flags &= ~B_NEEDCOMMIT; 3162 biodone(bp); 3163 } else if (retv == NFSERR_STALEWRITEVERF) 3164 nfs_clearcommit(bp->b_vp->v_mount); 3165 } 3166 if (retv) { 3167 if (force) 3168 bp->b_flags |= B_WRITEINPROG; 3169 VOP_STRATEGY(bp); 3170 } 3171 3172 if( (oldflags & B_ASYNC) == 0) { 3173 int rtval = biowait(bp); 3174 3175 if (oldflags & B_DELWRI) { 3176 reassignbuf(bp, bp->b_vp); 3177 } 3178 brelse(bp); 3179 return (rtval); 3180 } 3181 3182 return (0); 3183} 3184 3185/* 3186 * nfs special file access vnode op. 3187 * Essentially just get vattr and then imitate iaccess() since the device is 3188 * local to the client. 3189 */ 3190static int 3191nfsspec_access(ap) 3192 struct vop_access_args /* { 3193 struct vnode *a_vp; 3194 int a_mode; 3195 struct ucred *a_cred; 3196 struct proc *a_p; 3197 } */ *ap; 3198{ 3199 register struct vattr *vap; 3200 register gid_t *gp; 3201 register struct ucred *cred = ap->a_cred; 3202 struct vnode *vp = ap->a_vp; 3203 mode_t mode = ap->a_mode; 3204 struct vattr vattr; 3205 register int i; 3206 int error; 3207 3208 /* 3209 * Disallow write attempts on filesystems mounted read-only; 3210 * unless the file is a socket, fifo, or a block or character 3211 * device resident on the filesystem. 3212 */ 3213 if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { 3214 switch (vp->v_type) { 3215 case VREG: case VDIR: case VLNK: 3216 return (EROFS); 3217 } 3218 } 3219 /* 3220 * If you're the super-user, 3221 * you always get access. 3222 */ 3223 if (cred->cr_uid == 0) 3224 return (0); 3225 vap = &vattr; 3226 error = VOP_GETATTR(vp, vap, cred, ap->a_p); 3227 if (error) 3228 return (error); 3229 /* 3230 * Access check is based on only one of owner, group, public. 3231 * If not owner, then check group. If not a member of the 3232 * group, then check public access. 3233 */ 3234 if (cred->cr_uid != vap->va_uid) { 3235 mode >>= 3; 3236 gp = cred->cr_groups; 3237 for (i = 0; i < cred->cr_ngroups; i++, gp++) 3238 if (vap->va_gid == *gp) 3239 goto found; 3240 mode >>= 3; 3241found: 3242 ; 3243 } 3244 error = (vap->va_mode & mode) == mode ? 0 : EACCES; 3245 return (error); 3246} 3247 3248/* 3249 * Read wrapper for special devices. 3250 */ 3251static int 3252nfsspec_read(ap) 3253 struct vop_read_args /* { 3254 struct vnode *a_vp; 3255 struct uio *a_uio; 3256 int a_ioflag; 3257 struct ucred *a_cred; 3258 } */ *ap; 3259{ 3260 register struct nfsnode *np = VTONFS(ap->a_vp); 3261 struct timeval tv; 3262 3263 /* 3264 * Set access flag. 3265 */ 3266 np->n_flag |= NACC; 3267 gettime(&tv); 3268 np->n_atim.tv_sec = tv.tv_sec; 3269 np->n_atim.tv_nsec = tv.tv_usec * 1000; 3270 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap)); 3271} 3272 3273/* 3274 * Write wrapper for special devices. 3275 */ 3276static int 3277nfsspec_write(ap) 3278 struct vop_write_args /* { 3279 struct vnode *a_vp; 3280 struct uio *a_uio; 3281 int a_ioflag; 3282 struct ucred *a_cred; 3283 } */ *ap; 3284{ 3285 register struct nfsnode *np = VTONFS(ap->a_vp); 3286 struct timeval tv; 3287 3288 /* 3289 * Set update flag. 3290 */ 3291 np->n_flag |= NUPD; 3292 gettime(&tv); 3293 np->n_mtim.tv_sec = tv.tv_sec; 3294 np->n_mtim.tv_nsec = tv.tv_usec * 1000; 3295 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap)); 3296} 3297 3298/* 3299 * Close wrapper for special devices. 3300 * 3301 * Update the times on the nfsnode then do device close. 3302 */ 3303static int 3304nfsspec_close(ap) 3305 struct vop_close_args /* { 3306 struct vnode *a_vp; 3307 int a_fflag; 3308 struct ucred *a_cred; 3309 struct proc *a_p; 3310 } */ *ap; 3311{ 3312 register struct vnode *vp = ap->a_vp; 3313 register struct nfsnode *np = VTONFS(vp); 3314 struct vattr vattr; 3315 3316 if (np->n_flag & (NACC | NUPD)) { 3317 np->n_flag |= NCHG; 3318 if (vp->v_usecount == 1 && 3319 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3320 VATTR_NULL(&vattr); 3321 if (np->n_flag & NACC) 3322 vattr.va_atime = np->n_atim; 3323 if (np->n_flag & NUPD) 3324 vattr.va_mtime = np->n_mtim; 3325 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 3326 } 3327 } 3328 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap)); 3329} 3330 3331/* 3332 * Read wrapper for fifos. 3333 */ 3334static int 3335nfsfifo_read(ap) 3336 struct vop_read_args /* { 3337 struct vnode *a_vp; 3338 struct uio *a_uio; 3339 int a_ioflag; 3340 struct ucred *a_cred; 3341 } */ *ap; 3342{ 3343 register struct nfsnode *np = VTONFS(ap->a_vp); 3344 struct timeval tv; 3345 3346 /* 3347 * Set access flag. 3348 */ 3349 np->n_flag |= NACC; 3350 gettime(&tv); 3351 np->n_atim.tv_sec = tv.tv_sec; 3352 np->n_atim.tv_nsec = tv.tv_usec * 1000; 3353 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap)); 3354} 3355 3356/* 3357 * Write wrapper for fifos. 3358 */ 3359static int 3360nfsfifo_write(ap) 3361 struct vop_write_args /* { 3362 struct vnode *a_vp; 3363 struct uio *a_uio; 3364 int a_ioflag; 3365 struct ucred *a_cred; 3366 } */ *ap; 3367{ 3368 register struct nfsnode *np = VTONFS(ap->a_vp); 3369 struct timeval tv; 3370 3371 /* 3372 * Set update flag. 3373 */ 3374 np->n_flag |= NUPD; 3375 gettime(&tv); 3376 np->n_mtim.tv_sec = tv.tv_sec; 3377 np->n_mtim.tv_nsec = tv.tv_usec * 1000; 3378 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap)); 3379} 3380 3381/* 3382 * Close wrapper for fifos. 3383 * 3384 * Update the times on the nfsnode then do fifo close. 3385 */ 3386static int 3387nfsfifo_close(ap) 3388 struct vop_close_args /* { 3389 struct vnode *a_vp; 3390 int a_fflag; 3391 struct ucred *a_cred; 3392 struct proc *a_p; 3393 } */ *ap; 3394{ 3395 register struct vnode *vp = ap->a_vp; 3396 register struct nfsnode *np = VTONFS(vp); 3397 struct timeval tv; 3398 struct vattr vattr; 3399 3400 if (np->n_flag & (NACC | NUPD)) { 3401 gettime(&tv); 3402 if (np->n_flag & NACC) { 3403 np->n_atim.tv_sec = tv.tv_sec; 3404 np->n_atim.tv_nsec = tv.tv_usec * 1000; 3405 } 3406 if (np->n_flag & NUPD) { 3407 np->n_mtim.tv_sec = tv.tv_sec; 3408 np->n_mtim.tv_nsec = tv.tv_usec * 1000; 3409 } 3410 np->n_flag |= NCHG; 3411 if (vp->v_usecount == 1 && 3412 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3413 VATTR_NULL(&vattr); 3414 if (np->n_flag & NACC) 3415 vattr.va_atime = np->n_atim; 3416 if (np->n_flag & NUPD) 3417 vattr.va_mtime = np->n_mtim; 3418 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 3419 } 3420 } 3421 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap)); 3422} 3423 3424static int 3425nfs_ioctl(ap) 3426 struct vop_ioctl_args *ap; 3427{ 3428 3429 /* 3430 * XXX we were once bogusly enoictl() which returned this (ENOTTY). 3431 * Probably we should return ENODEV. 3432 */ 3433 return (ENOTTY); 3434} 3435 3436static int 3437nfs_select(ap) 3438 struct vop_select_args *ap; 3439{ 3440 3441 /* 3442 * We were once bogusly seltrue() which returns 1. Is this right? 3443 */ 3444 return (1); 3445} 3446