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