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