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