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