1 /* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * @(#)nfs_subs.c 8.8 (Berkeley) 5/22/95 33 * $FreeBSD: /repoman/r/ncvs/src/sys/nfsclient/nfs_subs.c,v 1.128 2004/04/14 23:23:55 peadar Exp $ 34 */ 35 36 /* 37 * These functions support the macros and help fiddle mbuf chains for 38 * the nfs op functions. They do things like create the rpc header and 39 * copy data between mbuf chains and uio lists. 40 */ 41 #include <sys/param.h> 42 #include <sys/systm.h> 43 #include <sys/kernel.h> 44 #include <sys/buf.h> 45 #include <sys/proc.h> 46 #include <sys/mount.h> 47 #include <sys/vnode.h> 48 #include <sys/nlookup.h> 49 #include <sys/namei.h> 50 #include <sys/mbuf.h> 51 #include <sys/socket.h> 52 #include <sys/stat.h> 53 #include <sys/malloc.h> 54 #include <sys/sysent.h> 55 #include <sys/syscall.h> 56 #include <sys/sysproto.h> 57 #include <sys/conf.h> 58 #include <sys/objcache.h> 59 #include <sys/jail.h> 60 61 #include <vm/vm.h> 62 #include <vm/vm_object.h> 63 #include <vm/vm_extern.h> 64 65 #include <sys/buf2.h> 66 67 #include "rpcv2.h" 68 #include "nfsproto.h" 69 #include "nfs.h" 70 #include "nfsmount.h" 71 #include "nfsnode.h" 72 #include "xdr_subs.h" 73 #include "nfsm_subs.h" 74 #include "nfsrtt.h" 75 76 #include <netinet/in.h> 77 78 MALLOC_DEFINE(M_NFSMOUNT, "NFS mount", "NFS mount"); 79 80 /* 81 * Data items converted to xdr at startup, since they are constant 82 * This is kinda hokey, but may save a little time doing byte swaps 83 */ 84 u_int32_t nfs_xdrneg1; 85 u_int32_t rpc_reply, rpc_msgdenied, rpc_mismatch, rpc_vers; 86 u_int32_t rpc_auth_unix, rpc_msgaccepted, rpc_call, rpc_autherr; 87 u_int32_t rpc_auth_kerb; 88 u_int32_t nfs_prog, nfs_true, nfs_false; 89 90 /* And other global data */ 91 static enum vtype nv2tov_type[8]= { 92 VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON 93 }; 94 enum vtype nv3tov_type[8]= { 95 VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO 96 }; 97 98 int nfs_ticks; 99 100 /* 101 * Protect master lists only. Primary protection uses the per-mount 102 * and per nfssvc_sock tokens. 103 */ 104 struct lwkt_token nfs_token = LWKT_TOKEN_INITIALIZER(unp_token); 105 106 static long nfs_pbuf_freecnt = -1; /* start out unlimited */ 107 108 struct nfsmount_head nfs_mountq = TAILQ_HEAD_INITIALIZER(nfs_mountq); 109 struct nfssvc_sockhead nfssvc_sockhead; 110 int nfssvc_sockhead_flag; 111 struct nfsd_head nfsd_head; 112 int nfsd_head_flag; 113 struct nfs_bufq nfs_bufq; 114 struct nqfhhashhead *nqfhhashtbl; 115 u_long nqfhhash; 116 117 static int nfs_prev_nfssvc_sy_narg; 118 static sy_call_t *nfs_prev_nfssvc_sy_call; 119 120 #ifndef NFS_NOSERVER 121 122 /* 123 * Mapping of old NFS Version 2 RPC numbers to generic numbers. 124 */ 125 int nfsv3_procid[NFS_NPROCS] = { 126 NFSPROC_NULL, 127 NFSPROC_GETATTR, 128 NFSPROC_SETATTR, 129 NFSPROC_NOOP, 130 NFSPROC_LOOKUP, 131 NFSPROC_READLINK, 132 NFSPROC_READ, 133 NFSPROC_NOOP, 134 NFSPROC_WRITE, 135 NFSPROC_CREATE, 136 NFSPROC_REMOVE, 137 NFSPROC_RENAME, 138 NFSPROC_LINK, 139 NFSPROC_SYMLINK, 140 NFSPROC_MKDIR, 141 NFSPROC_RMDIR, 142 NFSPROC_READDIR, 143 NFSPROC_FSSTAT, 144 NFSPROC_NOOP, 145 NFSPROC_NOOP, 146 NFSPROC_NOOP, 147 NFSPROC_NOOP, 148 NFSPROC_NOOP, 149 NFSPROC_NOOP, 150 NFSPROC_NOOP, 151 NFSPROC_NOOP 152 }; 153 154 #endif /* NFS_NOSERVER */ 155 /* 156 * and the reverse mapping from generic to Version 2 procedure numbers 157 */ 158 int nfsv2_procid[NFS_NPROCS] = { 159 NFSV2PROC_NULL, 160 NFSV2PROC_GETATTR, 161 NFSV2PROC_SETATTR, 162 NFSV2PROC_LOOKUP, 163 NFSV2PROC_NOOP, 164 NFSV2PROC_READLINK, 165 NFSV2PROC_READ, 166 NFSV2PROC_WRITE, 167 NFSV2PROC_CREATE, 168 NFSV2PROC_MKDIR, 169 NFSV2PROC_SYMLINK, 170 NFSV2PROC_CREATE, 171 NFSV2PROC_REMOVE, 172 NFSV2PROC_RMDIR, 173 NFSV2PROC_RENAME, 174 NFSV2PROC_LINK, 175 NFSV2PROC_READDIR, 176 NFSV2PROC_NOOP, 177 NFSV2PROC_STATFS, 178 NFSV2PROC_NOOP, 179 NFSV2PROC_NOOP, 180 NFSV2PROC_NOOP, 181 NFSV2PROC_NOOP, 182 NFSV2PROC_NOOP, 183 NFSV2PROC_NOOP, 184 NFSV2PROC_NOOP, 185 }; 186 187 #ifndef NFS_NOSERVER 188 /* 189 * Maps errno values to nfs error numbers. 190 * Use NFSERR_IO as the catch all for ones not specifically defined in 191 * RFC 1094. 192 */ 193 static u_char nfsrv_v2errmap[ELAST] = { 194 NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO, 195 NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 196 NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO, 197 NFSERR_IO, NFSERR_EXIST, NFSERR_IO, NFSERR_NODEV, NFSERR_NOTDIR, 198 NFSERR_ISDIR, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 199 NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS, 200 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 201 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 202 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 203 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 204 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 205 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 206 NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO, 207 NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE, 208 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 209 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 210 NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 211 NFSERR_IO /* << Last is 86 */ 212 }; 213 214 /* 215 * Maps errno values to nfs error numbers. 216 * Although it is not obvious whether or not NFS clients really care if 217 * a returned error value is in the specified list for the procedure, the 218 * safest thing to do is filter them appropriately. For Version 2, the 219 * X/Open XNFS document is the only specification that defines error values 220 * for each RPC (The RFC simply lists all possible error values for all RPCs), 221 * so I have decided to not do this for Version 2. 222 * The first entry is the default error return and the rest are the valid 223 * errors for that RPC in increasing numeric order. 224 */ 225 static short nfsv3err_null[] = { 226 0, 227 0, 228 }; 229 230 static short nfsv3err_getattr[] = { 231 NFSERR_IO, 232 NFSERR_IO, 233 NFSERR_STALE, 234 NFSERR_BADHANDLE, 235 NFSERR_SERVERFAULT, 236 0, 237 }; 238 239 static short nfsv3err_setattr[] = { 240 NFSERR_IO, 241 NFSERR_PERM, 242 NFSERR_IO, 243 NFSERR_ACCES, 244 NFSERR_INVAL, 245 NFSERR_NOSPC, 246 NFSERR_ROFS, 247 NFSERR_DQUOT, 248 NFSERR_STALE, 249 NFSERR_BADHANDLE, 250 NFSERR_NOT_SYNC, 251 NFSERR_SERVERFAULT, 252 0, 253 }; 254 255 static short nfsv3err_lookup[] = { 256 NFSERR_IO, 257 NFSERR_NOENT, 258 NFSERR_IO, 259 NFSERR_ACCES, 260 NFSERR_NOTDIR, 261 NFSERR_NAMETOL, 262 NFSERR_STALE, 263 NFSERR_BADHANDLE, 264 NFSERR_SERVERFAULT, 265 0, 266 }; 267 268 static short nfsv3err_access[] = { 269 NFSERR_IO, 270 NFSERR_IO, 271 NFSERR_STALE, 272 NFSERR_BADHANDLE, 273 NFSERR_SERVERFAULT, 274 0, 275 }; 276 277 static short nfsv3err_readlink[] = { 278 NFSERR_IO, 279 NFSERR_IO, 280 NFSERR_ACCES, 281 NFSERR_INVAL, 282 NFSERR_STALE, 283 NFSERR_BADHANDLE, 284 NFSERR_NOTSUPP, 285 NFSERR_SERVERFAULT, 286 0, 287 }; 288 289 static short nfsv3err_read[] = { 290 NFSERR_IO, 291 NFSERR_IO, 292 NFSERR_NXIO, 293 NFSERR_ACCES, 294 NFSERR_INVAL, 295 NFSERR_STALE, 296 NFSERR_BADHANDLE, 297 NFSERR_SERVERFAULT, 298 0, 299 }; 300 301 static short nfsv3err_write[] = { 302 NFSERR_IO, 303 NFSERR_IO, 304 NFSERR_ACCES, 305 NFSERR_INVAL, 306 NFSERR_FBIG, 307 NFSERR_NOSPC, 308 NFSERR_ROFS, 309 NFSERR_DQUOT, 310 NFSERR_STALE, 311 NFSERR_BADHANDLE, 312 NFSERR_SERVERFAULT, 313 0, 314 }; 315 316 static short nfsv3err_create[] = { 317 NFSERR_IO, 318 NFSERR_IO, 319 NFSERR_ACCES, 320 NFSERR_EXIST, 321 NFSERR_NOTDIR, 322 NFSERR_NOSPC, 323 NFSERR_ROFS, 324 NFSERR_NAMETOL, 325 NFSERR_DQUOT, 326 NFSERR_STALE, 327 NFSERR_BADHANDLE, 328 NFSERR_NOTSUPP, 329 NFSERR_SERVERFAULT, 330 0, 331 }; 332 333 static short nfsv3err_mkdir[] = { 334 NFSERR_IO, 335 NFSERR_IO, 336 NFSERR_ACCES, 337 NFSERR_EXIST, 338 NFSERR_NOTDIR, 339 NFSERR_NOSPC, 340 NFSERR_ROFS, 341 NFSERR_NAMETOL, 342 NFSERR_DQUOT, 343 NFSERR_STALE, 344 NFSERR_BADHANDLE, 345 NFSERR_NOTSUPP, 346 NFSERR_SERVERFAULT, 347 0, 348 }; 349 350 static short nfsv3err_symlink[] = { 351 NFSERR_IO, 352 NFSERR_IO, 353 NFSERR_ACCES, 354 NFSERR_EXIST, 355 NFSERR_NOTDIR, 356 NFSERR_NOSPC, 357 NFSERR_ROFS, 358 NFSERR_NAMETOL, 359 NFSERR_DQUOT, 360 NFSERR_STALE, 361 NFSERR_BADHANDLE, 362 NFSERR_NOTSUPP, 363 NFSERR_SERVERFAULT, 364 0, 365 }; 366 367 static short nfsv3err_mknod[] = { 368 NFSERR_IO, 369 NFSERR_IO, 370 NFSERR_ACCES, 371 NFSERR_EXIST, 372 NFSERR_NOTDIR, 373 NFSERR_NOSPC, 374 NFSERR_ROFS, 375 NFSERR_NAMETOL, 376 NFSERR_DQUOT, 377 NFSERR_STALE, 378 NFSERR_BADHANDLE, 379 NFSERR_NOTSUPP, 380 NFSERR_SERVERFAULT, 381 NFSERR_BADTYPE, 382 0, 383 }; 384 385 static short nfsv3err_remove[] = { 386 NFSERR_IO, 387 NFSERR_NOENT, 388 NFSERR_IO, 389 NFSERR_ACCES, 390 NFSERR_NOTDIR, 391 NFSERR_ROFS, 392 NFSERR_NAMETOL, 393 NFSERR_STALE, 394 NFSERR_BADHANDLE, 395 NFSERR_SERVERFAULT, 396 0, 397 }; 398 399 static short nfsv3err_rmdir[] = { 400 NFSERR_IO, 401 NFSERR_NOENT, 402 NFSERR_IO, 403 NFSERR_ACCES, 404 NFSERR_EXIST, 405 NFSERR_NOTDIR, 406 NFSERR_INVAL, 407 NFSERR_ROFS, 408 NFSERR_NAMETOL, 409 NFSERR_NOTEMPTY, 410 NFSERR_STALE, 411 NFSERR_BADHANDLE, 412 NFSERR_NOTSUPP, 413 NFSERR_SERVERFAULT, 414 0, 415 }; 416 417 static short nfsv3err_rename[] = { 418 NFSERR_IO, 419 NFSERR_NOENT, 420 NFSERR_IO, 421 NFSERR_ACCES, 422 NFSERR_EXIST, 423 NFSERR_XDEV, 424 NFSERR_NOTDIR, 425 NFSERR_ISDIR, 426 NFSERR_INVAL, 427 NFSERR_NOSPC, 428 NFSERR_ROFS, 429 NFSERR_MLINK, 430 NFSERR_NAMETOL, 431 NFSERR_NOTEMPTY, 432 NFSERR_DQUOT, 433 NFSERR_STALE, 434 NFSERR_BADHANDLE, 435 NFSERR_NOTSUPP, 436 NFSERR_SERVERFAULT, 437 0, 438 }; 439 440 static short nfsv3err_link[] = { 441 NFSERR_IO, 442 NFSERR_IO, 443 NFSERR_ACCES, 444 NFSERR_EXIST, 445 NFSERR_XDEV, 446 NFSERR_NOTDIR, 447 NFSERR_INVAL, 448 NFSERR_NOSPC, 449 NFSERR_ROFS, 450 NFSERR_MLINK, 451 NFSERR_NAMETOL, 452 NFSERR_DQUOT, 453 NFSERR_STALE, 454 NFSERR_BADHANDLE, 455 NFSERR_NOTSUPP, 456 NFSERR_SERVERFAULT, 457 0, 458 }; 459 460 static short nfsv3err_readdir[] = { 461 NFSERR_IO, 462 NFSERR_IO, 463 NFSERR_ACCES, 464 NFSERR_NOTDIR, 465 NFSERR_STALE, 466 NFSERR_BADHANDLE, 467 NFSERR_BAD_COOKIE, 468 NFSERR_TOOSMALL, 469 NFSERR_SERVERFAULT, 470 0, 471 }; 472 473 static short nfsv3err_readdirplus[] = { 474 NFSERR_IO, 475 NFSERR_IO, 476 NFSERR_ACCES, 477 NFSERR_NOTDIR, 478 NFSERR_STALE, 479 NFSERR_BADHANDLE, 480 NFSERR_BAD_COOKIE, 481 NFSERR_NOTSUPP, 482 NFSERR_TOOSMALL, 483 NFSERR_SERVERFAULT, 484 0, 485 }; 486 487 static short nfsv3err_fsstat[] = { 488 NFSERR_IO, 489 NFSERR_IO, 490 NFSERR_STALE, 491 NFSERR_BADHANDLE, 492 NFSERR_SERVERFAULT, 493 0, 494 }; 495 496 static short nfsv3err_fsinfo[] = { 497 NFSERR_STALE, 498 NFSERR_STALE, 499 NFSERR_BADHANDLE, 500 NFSERR_SERVERFAULT, 501 0, 502 }; 503 504 static short nfsv3err_pathconf[] = { 505 NFSERR_STALE, 506 NFSERR_STALE, 507 NFSERR_BADHANDLE, 508 NFSERR_SERVERFAULT, 509 0, 510 }; 511 512 static short nfsv3err_commit[] = { 513 NFSERR_IO, 514 NFSERR_IO, 515 NFSERR_STALE, 516 NFSERR_BADHANDLE, 517 NFSERR_SERVERFAULT, 518 0, 519 }; 520 521 static short *nfsrv_v3errmap[] = { 522 nfsv3err_null, 523 nfsv3err_getattr, 524 nfsv3err_setattr, 525 nfsv3err_lookup, 526 nfsv3err_access, 527 nfsv3err_readlink, 528 nfsv3err_read, 529 nfsv3err_write, 530 nfsv3err_create, 531 nfsv3err_mkdir, 532 nfsv3err_symlink, 533 nfsv3err_mknod, 534 nfsv3err_remove, 535 nfsv3err_rmdir, 536 nfsv3err_rename, 537 nfsv3err_link, 538 nfsv3err_readdir, 539 nfsv3err_readdirplus, 540 nfsv3err_fsstat, 541 nfsv3err_fsinfo, 542 nfsv3err_pathconf, 543 nfsv3err_commit, 544 }; 545 546 #endif /* NFS_NOSERVER */ 547 548 /* 549 * This needs to return a monotonically increasing or close to monotonically 550 * increasing result, otherwise the write gathering queues won't work 551 * properly. 552 */ 553 u_quad_t 554 nfs_curusec(void) 555 { 556 struct timeval tv; 557 558 getmicrouptime(&tv); 559 return ((u_quad_t)tv.tv_sec * 1000000 + (u_quad_t)tv.tv_usec); 560 } 561 562 /* 563 * Called once to initialize data structures... 564 */ 565 int 566 nfs_init(struct vfsconf *vfsp) 567 { 568 callout_init_mp(&nfs_timer_handle); 569 nfsmount_objcache = objcache_create_simple(M_NFSMOUNT, sizeof(struct nfsmount)); 570 571 nfs_mount_type = vfsp->vfc_typenum; 572 nfsrtt.pos = 0; 573 rpc_vers = txdr_unsigned(RPC_VER2); 574 rpc_call = txdr_unsigned(RPC_CALL); 575 rpc_reply = txdr_unsigned(RPC_REPLY); 576 rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED); 577 rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED); 578 rpc_mismatch = txdr_unsigned(RPC_MISMATCH); 579 rpc_autherr = txdr_unsigned(RPC_AUTHERR); 580 rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX); 581 rpc_auth_kerb = txdr_unsigned(RPCAUTH_KERB4); 582 nfs_prog = txdr_unsigned(NFS_PROG); 583 nfs_true = txdr_unsigned(TRUE); 584 nfs_false = txdr_unsigned(FALSE); 585 nfs_xdrneg1 = txdr_unsigned(-1); 586 nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000; 587 if (nfs_ticks < 1) 588 nfs_ticks = 1; 589 nfs_nhinit(); /* Init the nfsnode table */ 590 #ifndef NFS_NOSERVER 591 nfsrv_init(0); /* Init server data structures */ 592 nfsrv_initcache(); /* Init the server request cache */ 593 #endif 594 595 /* 596 * Mainly for vkernel operation. If memory is severely limited 597 */ 598 if (nfs_maxasyncbio > nmbclusters * MCLBYTES / NFS_MAXDATA / 3) 599 nfs_maxasyncbio = nmbclusters * MCLBYTES / NFS_MAXDATA / 3; 600 if (nfs_maxasyncbio < 4) 601 nfs_maxasyncbio = 4; 602 603 /* 604 * Initialize reply list and start timer 605 */ 606 nfs_timer_callout(0); 607 608 #if 1 /* XXX this isn't really needed */ 609 nfs_prev_nfssvc_sy_narg = sysent[SYS_nfssvc].sy_narg; 610 sysent[SYS_nfssvc].sy_narg = 2; 611 #endif 612 nfs_prev_nfssvc_sy_call = sysent[SYS_nfssvc].sy_call; 613 sysent[SYS_nfssvc].sy_call = (sy_call_t *)sys_nfssvc; 614 615 nfs_pbuf_freecnt = nswbuf_kva / 2 + 1; 616 617 return (0); 618 } 619 620 int 621 nfs_uninit(struct vfsconf *vfsp) 622 { 623 callout_stop(&nfs_timer_handle); 624 nfs_mount_type = -1; 625 sysent[SYS_nfssvc].sy_narg = nfs_prev_nfssvc_sy_narg; 626 sysent[SYS_nfssvc].sy_call = nfs_prev_nfssvc_sy_call; 627 nfs_nhdestroy(); /* Destroy the nfsnode table */ 628 #ifndef NFS_NOSERVER 629 nfsrv_destroycache(); /* Destroy the server request cache */ 630 #endif 631 objcache_destroy(nfsmount_objcache); 632 return (0); 633 } 634 635 /* 636 * Attribute cache routines. 637 * nfs_loadattrcache() - loads or updates the cache contents from attributes 638 * that are on the mbuf list 639 * nfs_getattrcache() - returns valid attributes if found in cache, returns 640 * error otherwise 641 */ 642 643 /* 644 * Load the attribute cache (that lives in the nfsnode entry) with 645 * the values on the mbuf list. Load *vaper with the attributes. vaper 646 * may be NULL. 647 * 648 * As a side effect n_mtime, which we use to determine if the file was 649 * modified by some other host, is set to the attribute timestamp and 650 * NRMODIFIED is set if the two values differ. 651 * 652 * WARNING: the mtime loaded into vaper does not necessarily represent 653 * n_mtime or n_attr.mtime due to NACC and NUPD. 654 */ 655 int 656 nfs_loadattrcache(struct vnode *vp, struct mbuf **mdp, caddr_t *dposp, 657 struct vattr *vaper, int lattr_flags) 658 { 659 struct vattr *vap; 660 struct nfs_fattr *fp; 661 struct nfsnode *np; 662 int32_t t1; 663 caddr_t cp2; 664 int error = 0; 665 int rmajor, rminor; 666 dev_t rdev; 667 struct mbuf *md; 668 enum vtype vtyp; 669 u_short vmode; 670 struct timespec mtime; 671 int v3 = NFS_ISV3(vp); 672 673 md = *mdp; 674 t1 = (mtod(md, caddr_t) + md->m_len) - *dposp; 675 if ((error = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, &cp2)) != 0) 676 return (error); 677 fp = (struct nfs_fattr *)cp2; 678 if (v3) { 679 vtyp = nfsv3tov_type(fp->fa_type); 680 vmode = fxdr_unsigned(u_short, fp->fa_mode); 681 rmajor = (int)fxdr_unsigned(int, fp->fa3_rdev.specdata1); 682 rminor = (int)fxdr_unsigned(int, fp->fa3_rdev.specdata2); 683 fxdr_nfsv3time(&fp->fa3_mtime, &mtime); 684 } else { 685 vtyp = nfsv2tov_type(fp->fa_type); 686 vmode = fxdr_unsigned(u_short, fp->fa_mode); 687 /* 688 * XXX 689 * 690 * The duplicate information returned in fa_type and fa_mode 691 * is an ambiguity in the NFS version 2 protocol. 692 * 693 * VREG should be taken literally as a regular file. If a 694 * server intents to return some type information differently 695 * in the upper bits of the mode field (e.g. for sockets, or 696 * FIFOs), NFSv2 mandates fa_type to be VNON. Anyway, we 697 * leave the examination of the mode bits even in the VREG 698 * case to avoid breakage for bogus servers, but we make sure 699 * that there are actually type bits set in the upper part of 700 * fa_mode (and failing that, trust the va_type field). 701 * 702 * NFSv3 cleared the issue, and requires fa_mode to not 703 * contain any type information (while also introduing sockets 704 * and FIFOs for fa_type). 705 */ 706 if (vtyp == VNON || (vtyp == VREG && (vmode & S_IFMT) != 0)) 707 vtyp = IFTOVT(vmode); 708 rdev = fxdr_unsigned(int32_t, fp->fa2_rdev); 709 rmajor = umajor(rdev); 710 rminor = uminor(rdev); 711 fxdr_nfsv2time(&fp->fa2_mtime, &mtime); 712 713 /* 714 * Really ugly NFSv2 kludge. 715 */ 716 if (vtyp == VCHR && rdev == (dev_t)0xffffffff) 717 vtyp = VFIFO; 718 } 719 720 /* 721 * If v_type == VNON it is a new node, so fill in the v_type, 722 * n_mtime fields. Check to see if it represents a special 723 * device, and if so, check for a possible alias. Once the 724 * correct vnode has been obtained, fill in the rest of the 725 * information. 726 */ 727 np = VTONFS(vp); 728 if (vp->v_type != vtyp) { 729 nfs_setvtype(vp, vtyp); 730 if (vp->v_type == VFIFO) { 731 vp->v_ops = &vp->v_mount->mnt_vn_fifo_ops; 732 } else if (vp->v_type == VCHR || vp->v_type == VBLK) { 733 vp->v_ops = &vp->v_mount->mnt_vn_spec_ops; 734 addaliasu(vp, rmajor, rminor); 735 } else { 736 vp->v_ops = &vp->v_mount->mnt_vn_use_ops; 737 } 738 np->n_mtime = mtime.tv_sec; 739 } else if (np->n_mtime != mtime.tv_sec) { 740 /* 741 * If we haven't modified the file locally and the server 742 * timestamp does not match, then the server probably 743 * modified the file. We must flag this condition so 744 * the proper syncnronization can be done. We do not 745 * try to synchronize the state here because that 746 * could lead to an endless recursion. 747 * 748 * XXX loadattrcache can be set during the reply to a write, 749 * before the write timestamp is properly processed. To 750 * avoid unconditionally setting the rmodified bit (which 751 * has the effect of flushing the cache), we only do this 752 * check if the lmodified bit is not set. 753 */ 754 np->n_mtime = mtime.tv_sec; 755 if ((lattr_flags & NFS_LATTR_NOMTIMECHECK) == 0) 756 np->n_flag |= NRMODIFIED; 757 } 758 vap = &np->n_vattr; 759 vap->va_type = vtyp; 760 vap->va_mode = (vmode & 07777); 761 vap->va_rmajor = rmajor; 762 vap->va_rminor = rminor; 763 vap->va_mtime = mtime; 764 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 765 if (v3) { 766 vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink); 767 vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid); 768 vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid); 769 vap->va_size = fxdr_hyper(&fp->fa3_size); 770 vap->va_blocksize = NFS_FABLKSIZE; 771 vap->va_bytes = fxdr_hyper(&fp->fa3_used); 772 vap->va_fileid = fxdr_hyper(&fp->fa3_fileid); 773 fxdr_nfsv3time(&fp->fa3_atime, &vap->va_atime); 774 fxdr_nfsv3time(&fp->fa3_ctime, &vap->va_ctime); 775 vap->va_flags = 0; 776 vap->va_filerev = 0; 777 } else { 778 vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink); 779 vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid); 780 vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid); 781 vap->va_size = fxdr_unsigned(u_int32_t, fp->fa2_size); 782 vap->va_blocksize = fxdr_unsigned(int32_t, fp->fa2_blocksize); 783 vap->va_bytes = (u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks) 784 * NFS_FABLKSIZE; 785 vap->va_fileid = fxdr_unsigned(int32_t, fp->fa2_fileid); 786 fxdr_nfsv2time(&fp->fa2_atime, &vap->va_atime); 787 vap->va_flags = 0; 788 vap->va_ctime.tv_sec = fxdr_unsigned(u_int32_t, 789 fp->fa2_ctime.nfsv2_sec); 790 vap->va_ctime.tv_nsec = 0; 791 vap->va_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec); 792 vap->va_filerev = 0; 793 } 794 np->n_attrstamp = time_uptime; 795 if (vap->va_size != np->n_size) { 796 if (vap->va_type == VREG) { 797 /* 798 * Get rid of all the junk we had before and just 799 * set NRMODIFIED if NLMODIFIED is 0. Depend on 800 * occassionally flushing our dirty buffers to 801 * clear both the NLMODIFIED and NRMODIFIED flags. 802 */ 803 if ((np->n_flag & NLMODIFIED) == 0) 804 np->n_flag |= NRMODIFIED; 805 #if 0 806 if ((lattr_flags & NFS_LATTR_NOSHRINK) && 807 vap->va_size < np->n_size) { 808 /* 809 * We've been told not to shrink the file; 810 * zero np->n_attrstamp to indicate that 811 * the attributes are stale. 812 * 813 * This occurs primarily due to recursive 814 * NFS ops that are executed during periods 815 * where we cannot safely reduce the size of 816 * the file. 817 * 818 * Additionally, write rpcs are broken down 819 * into buffers and np->n_size is 820 * pre-extended. Setting NRMODIFIED here 821 * can result in n_size getting reset to a 822 * lower value, which is NOT what we want. 823 * XXX this needs to be cleaned up a lot 824 * more. 825 */ 826 vap->va_size = np->n_size; 827 np->n_attrstamp = 0; 828 if ((np->n_flag & NLMODIFIED) == 0) 829 np->n_flag |= NRMODIFIED; 830 } else if (np->n_flag & NLMODIFIED) { 831 /* 832 * We've modified the file: Use the larger 833 * of our size, and the server's size. At 834 * this point the cache coherency is all 835 * shot to hell. To try to handle multiple 836 * clients appending to the file at the same 837 * time mark that the server has changed 838 * the file if the server's notion of the 839 * file size is larger then our notion. 840 * 841 * XXX this needs work. 842 */ 843 if (vap->va_size < np->n_size) { 844 vap->va_size = np->n_size; 845 } else { 846 np->n_size = vap->va_size; 847 np->n_flag |= NRMODIFIED; 848 } 849 } else { 850 /* 851 * Someone changed the file's size on the 852 * server and there are no local changes 853 * to get in the way, set the size and mark 854 * it. 855 */ 856 np->n_size = vap->va_size; 857 np->n_flag |= NRMODIFIED; 858 } 859 nvnode_pager_setsize(vp, np->n_size, XXX); 860 #endif 861 } else { 862 np->n_size = vap->va_size; 863 } 864 } 865 if (vaper != NULL) { 866 bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap)); 867 if (np->n_flag & NCHG) { 868 if (np->n_flag & NACC) 869 vaper->va_atime = np->n_atim; 870 if (np->n_flag & NUPD) 871 vaper->va_mtime = np->n_mtim; 872 } 873 } 874 return (0); 875 } 876 877 #ifdef NFS_ACDEBUG 878 #include <sys/sysctl.h> 879 SYSCTL_DECL(_vfs_nfs); 880 static int nfs_acdebug; 881 SYSCTL_INT(_vfs_nfs, OID_AUTO, acdebug, CTLFLAG_RW, &nfs_acdebug, 0, ""); 882 #endif 883 884 /* 885 * Check the time stamp 886 * If the cache is valid, copy contents to *vap and return 0 887 * otherwise return an error 888 */ 889 int 890 nfs_getattrcache(struct vnode *vp, struct vattr *vaper) 891 { 892 struct nfsnode *np; 893 struct vattr *vap; 894 struct nfsmount *nmp; 895 int timeo; 896 897 np = VTONFS(vp); 898 vap = &np->n_vattr; 899 nmp = VFSTONFS(vp->v_mount); 900 901 /* 902 * Dynamic timeout based on how recently the file was modified. 903 * n_mtime is always valid. 904 */ 905 timeo = (get_approximate_time_t() - np->n_mtime) / 60; 906 907 #ifdef NFS_ACDEBUG 908 if (nfs_acdebug>1) 909 kprintf("nfs_getattrcache: initial timeo = %d\n", timeo); 910 #endif 911 912 if (vap->va_type == VDIR) { 913 if ((np->n_flag & NLMODIFIED) || timeo < nmp->nm_acdirmin) 914 timeo = nmp->nm_acdirmin; 915 else if (timeo > nmp->nm_acdirmax) 916 timeo = nmp->nm_acdirmax; 917 } else { 918 if ((np->n_flag & NLMODIFIED) || timeo < nmp->nm_acregmin) 919 timeo = nmp->nm_acregmin; 920 else if (timeo > nmp->nm_acregmax) 921 timeo = nmp->nm_acregmax; 922 } 923 924 #ifdef NFS_ACDEBUG 925 if (nfs_acdebug > 2) 926 kprintf("acregmin %d; acregmax %d; acdirmin %d; acdirmax %d\n", 927 nmp->nm_acregmin, nmp->nm_acregmax, 928 nmp->nm_acdirmin, nmp->nm_acdirmax); 929 930 if (nfs_acdebug) 931 kprintf("nfs_getattrcache: age = %d; final timeo = %d\n", 932 (int)(time_uptime - np->n_attrstamp), timeo); 933 #endif 934 935 if (np->n_attrstamp == 0 || (time_uptime - np->n_attrstamp) >= timeo) { 936 nfsstats.attrcache_misses++; 937 return (ENOENT); 938 } 939 nfsstats.attrcache_hits++; 940 941 /* 942 * Our attribute cache can be stale due to modifications made on 943 * this host. XXX this is a bad hack. We need a more deterministic 944 * means of finding out which np fields are valid verses attr cache 945 * fields. We really should update the vattr info on the fly when 946 * making local changes. 947 */ 948 if (vap->va_size != np->n_size) { 949 if (vap->va_type == VREG) { 950 if (np->n_flag & NLMODIFIED) 951 vap->va_size = np->n_size; 952 nfs_meta_setsize(vp, curthread, vap->va_size, 0); 953 } else { 954 np->n_size = vap->va_size; 955 } 956 } 957 bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(struct vattr)); 958 if (np->n_flag & NCHG) { 959 if (np->n_flag & NACC) 960 vaper->va_atime = np->n_atim; 961 if (np->n_flag & NUPD) 962 vaper->va_mtime = np->n_mtim; 963 } 964 return (0); 965 } 966 967 #ifndef NFS_NOSERVER 968 969 /* 970 * Set up nameidata for a lookup() call and do it. 971 * 972 * If pubflag is set, this call is done for a lookup operation on the 973 * public filehandle. In that case we allow crossing mountpoints and 974 * absolute pathnames. However, the caller is expected to check that 975 * the lookup result is within the public fs, and deny access if 976 * it is not. 977 * 978 * dirp may be set whether an error is returned or not, and must be 979 * released by the caller. 980 * 981 * On return nd->nl_nch usually points to the target ncp, which may represent 982 * a negative hit. 983 * 984 * NOTE: the caller must call nlookup_done(nd) unconditionally on return 985 * to cleanup. 986 */ 987 int 988 nfs_namei(struct nlookupdata *nd, struct ucred *cred, int nflags, 989 struct vnode **dvpp, struct vnode **vpp, 990 fhandle_t *fhp, int len, 991 struct nfssvc_sock *slp, struct sockaddr *nam, struct mbuf **mdp, 992 caddr_t *dposp, struct vnode **dirpp, struct thread *td, 993 int kerbflag, int pubflag) 994 { 995 int i, rem; 996 struct mbuf *md; 997 char *fromcp, *tocp, *cp; 998 char *namebuf; 999 struct nchandle nch; 1000 struct vnode *dp; 1001 struct mount *mp; 1002 int error, rdonly; 1003 1004 namebuf = objcache_get(namei_oc, M_WAITOK); 1005 *dirpp = NULL; 1006 1007 /* 1008 * Copy the name from the mbuf list to namebuf. 1009 */ 1010 fromcp = *dposp; 1011 tocp = namebuf; 1012 md = *mdp; 1013 rem = mtod(md, caddr_t) + md->m_len - fromcp; 1014 for (i = 0; i < len; i++) { 1015 while (rem == 0) { 1016 md = md->m_next; 1017 if (md == NULL) { 1018 error = EBADRPC; 1019 goto out; 1020 } 1021 fromcp = mtod(md, caddr_t); 1022 rem = md->m_len; 1023 } 1024 if (*fromcp == '\0' || (!pubflag && *fromcp == '/')) { 1025 error = EACCES; 1026 goto out; 1027 } 1028 *tocp++ = *fromcp++; 1029 rem--; 1030 } 1031 *tocp = '\0'; 1032 *mdp = md; 1033 *dposp = fromcp; 1034 len = nfsm_rndup(len)-len; 1035 if (len > 0) { 1036 if (rem >= len) 1037 *dposp += len; 1038 else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0) 1039 goto out; 1040 } 1041 1042 /* 1043 * Extract and set starting directory. The returned dp is refd 1044 * but not locked. 1045 */ 1046 error = nfsrv_fhtovp(fhp, FALSE, &mp, &dp, cred, slp, 1047 nam, &rdonly, kerbflag, pubflag); 1048 if (error) 1049 goto out; 1050 if (dp->v_type != VDIR) { 1051 vrele(dp); 1052 error = ENOTDIR; 1053 goto out; 1054 } 1055 1056 /* 1057 * Set return directory. Reference to dp is implicitly transfered 1058 * to the returned pointer. This must be set before we potentially 1059 * goto out below. 1060 */ 1061 *dirpp = dp; 1062 1063 /* 1064 * read-only - NLC_DELETE, NLC_RENAME_DST are disallowed. NLC_CREATE 1065 * is passed through to nlookup() and will be disallowed 1066 * if the file does not already exist. 1067 */ 1068 if (rdonly) { 1069 nflags |= NLC_NFS_RDONLY; 1070 if (nflags & (NLC_DELETE | NLC_RENAME_DST)) { 1071 error = EROFS; 1072 goto out; 1073 } 1074 } 1075 1076 /* 1077 * Oh joy. For WebNFS, handle those pesky '%' escapes, 1078 * and the 'native path' indicator. 1079 */ 1080 if (pubflag) { 1081 cp = objcache_get(namei_oc, M_WAITOK); 1082 fromcp = namebuf; 1083 tocp = cp; 1084 if ((unsigned char)*fromcp >= WEBNFS_SPECCHAR_START) { 1085 switch ((unsigned char)*fromcp) { 1086 case WEBNFS_NATIVE_CHAR: 1087 /* 1088 * 'Native' path for us is the same 1089 * as a path according to the NFS spec, 1090 * just skip the escape char. 1091 */ 1092 fromcp++; 1093 break; 1094 /* 1095 * More may be added in the future, range 0x80-0xff 1096 */ 1097 default: 1098 error = EIO; 1099 objcache_put(namei_oc, cp); 1100 goto out; 1101 } 1102 } 1103 /* 1104 * Translate the '%' escapes, URL-style. 1105 */ 1106 while (*fromcp != '\0') { 1107 if (*fromcp == WEBNFS_ESC_CHAR) { 1108 if (fromcp[1] != '\0' && fromcp[2] != '\0') { 1109 fromcp++; 1110 *tocp++ = HEXSTRTOI(fromcp); 1111 fromcp += 2; 1112 continue; 1113 } else { 1114 error = ENOENT; 1115 objcache_put(namei_oc, cp); 1116 goto out; 1117 } 1118 } else 1119 *tocp++ = *fromcp++; 1120 } 1121 *tocp = '\0'; 1122 objcache_put(namei_oc, namebuf); 1123 namebuf = cp; 1124 } 1125 1126 /* 1127 * Setup for search. We need to get a start directory from dp. Note 1128 * that dp is ref'd, but we no longer 'own' the ref (*dirpp owns it). 1129 */ 1130 if (pubflag == 0) { 1131 nflags |= NLC_NFS_NOSOFTLINKTRAV; 1132 nflags |= NLC_NOCROSSMOUNT; 1133 } 1134 1135 /* 1136 * We need a starting ncp from the directory vnode dp. dp must not 1137 * be locked. The returned ncp will be refd but not locked. 1138 * 1139 * If no suitable ncp is found we instruct cache_fromdvp() to create 1140 * one. If this fails the directory has probably been removed while 1141 * the target was chdir'd into it and any further lookup will fail. 1142 */ 1143 if ((error = cache_fromdvp(dp, cred, 1, &nch)) != 0) 1144 goto out; 1145 nlookup_init_raw(nd, namebuf, UIO_SYSSPACE, nflags, cred, &nch); 1146 cache_drop(&nch); 1147 1148 /* 1149 * Ok, do the lookup. 1150 */ 1151 error = nlookup(nd); 1152 1153 /* 1154 * If no error occured return the requested dvpp and vpp. If 1155 * NLC_CREATE was specified nd->nl_nch may represent a negative 1156 * cache hit in which case we do not attempt to obtain the vp. 1157 */ 1158 if (error == 0) { 1159 if (dvpp) { 1160 if (nd->nl_nch.ncp->nc_parent) { 1161 nch = nd->nl_nch; 1162 nch.ncp = nch.ncp->nc_parent; 1163 cache_hold(&nch); 1164 cache_lock(&nch); 1165 error = cache_vget(&nch, nd->nl_cred, 1166 LK_EXCLUSIVE, dvpp); 1167 cache_put(&nch); 1168 } else { 1169 error = ENXIO; 1170 } 1171 } 1172 if (vpp && nd->nl_nch.ncp->nc_vp) { 1173 error = cache_vget(&nd->nl_nch, nd->nl_cred, LK_EXCLUSIVE, vpp); 1174 } 1175 if (error) { 1176 if (dvpp && *dvpp) { 1177 vput(*dvpp); 1178 *dvpp = NULL; 1179 } 1180 if (vpp && *vpp) { 1181 vput(*vpp); 1182 *vpp = NULL; 1183 } 1184 } 1185 } 1186 1187 /* 1188 * Finish up. 1189 */ 1190 out: 1191 objcache_put(namei_oc, namebuf); 1192 return (error); 1193 } 1194 1195 /* 1196 * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked) 1197 * - look up fsid in mount list (if not found ret error) 1198 * - get vp and export rights by calling VFS_FHTOVP() 1199 * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon 1200 * - if not lockflag unlock it with vn_unlock() 1201 */ 1202 int 1203 nfsrv_fhtovp(fhandle_t *fhp, int lockflag, 1204 struct mount **mpp, struct vnode **vpp, 1205 struct ucred *cred, struct nfssvc_sock *slp, struct sockaddr *nam, 1206 int *rdonlyp, int kerbflag, int pubflag) 1207 { 1208 struct mount *mp; 1209 int i; 1210 struct ucred *credanon; 1211 int error, exflags; 1212 #ifdef MNT_EXNORESPORT /* XXX needs mountd and /etc/exports help yet */ 1213 struct sockaddr_int *saddr; 1214 #endif 1215 1216 *vpp = NULL; 1217 *mpp = NULL; 1218 1219 if (nfs_ispublicfh(fhp)) { 1220 if (!pubflag || !nfs_pub.np_valid) 1221 return (ESTALE); 1222 fhp = &nfs_pub.np_handle; 1223 } 1224 1225 mp = *mpp = vfs_getvfs(&fhp->fh_fsid); 1226 if (mp == NULL) 1227 return (ESTALE); 1228 error = VFS_CHECKEXP(mp, nam, &exflags, &credanon); 1229 if (error) { 1230 mount_drop(mp); 1231 return (error); 1232 } 1233 error = VFS_FHTOVP(mp, NULL, &fhp->fh_fid, vpp); 1234 mount_drop(mp); 1235 if (error) 1236 return (ESTALE); 1237 #ifdef MNT_EXNORESPORT 1238 if (!(exflags & (MNT_EXNORESPORT|MNT_EXPUBLIC))) { 1239 saddr = (struct sockaddr_in *)nam; 1240 if (saddr->sin_family == AF_INET && 1241 ntohs(saddr->sin_port) >= IPPORT_RESERVED) { 1242 vput(*vpp); 1243 *vpp = NULL; 1244 return (NFSERR_AUTHERR | AUTH_TOOWEAK); 1245 } 1246 } 1247 #endif 1248 /* 1249 * Check/setup credentials. 1250 */ 1251 if (exflags & MNT_EXKERB) { 1252 if (!kerbflag) { 1253 vput(*vpp); 1254 *vpp = NULL; 1255 return (NFSERR_AUTHERR | AUTH_TOOWEAK); 1256 } 1257 } else if (kerbflag) { 1258 vput(*vpp); 1259 *vpp = NULL; 1260 return (NFSERR_AUTHERR | AUTH_TOOWEAK); 1261 } else if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) { 1262 cred->cr_uid = credanon->cr_uid; 1263 for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++) 1264 cred->cr_groups[i] = credanon->cr_groups[i]; 1265 cred->cr_ngroups = i; 1266 } 1267 if (exflags & MNT_EXRDONLY) 1268 *rdonlyp = 1; 1269 else 1270 *rdonlyp = 0; 1271 1272 if (!lockflag) 1273 vn_unlock(*vpp); 1274 return (0); 1275 } 1276 1277 /* 1278 * WebNFS: check if a filehandle is a public filehandle. For v3, this 1279 * means a length of 0, for v2 it means all zeroes. nfsm_srvmtofh has 1280 * transformed this to all zeroes in both cases, so check for it. 1281 */ 1282 int 1283 nfs_ispublicfh(fhandle_t *fhp) 1284 { 1285 char *cp = (char *)fhp; 1286 int i; 1287 1288 for (i = 0; i < NFSX_V3FH; i++) 1289 if (*cp++ != 0) 1290 return (FALSE); 1291 return (TRUE); 1292 } 1293 1294 #endif /* NFS_NOSERVER */ 1295 /* 1296 * This function compares two net addresses by family and returns TRUE 1297 * if they are the same host. 1298 * If there is any doubt, return FALSE. 1299 * The AF_INET family is handled as a special case so that address mbufs 1300 * don't need to be saved to store "struct in_addr", which is only 4 bytes. 1301 */ 1302 int 1303 netaddr_match(int family, union nethostaddr *haddr, struct sockaddr *nam) 1304 { 1305 struct sockaddr_in *inetaddr; 1306 1307 switch (family) { 1308 case AF_INET: 1309 inetaddr = (struct sockaddr_in *)nam; 1310 if (inetaddr->sin_family == AF_INET && 1311 inetaddr->sin_addr.s_addr == haddr->had_inetaddr) 1312 return (1); 1313 break; 1314 default: 1315 break; 1316 } 1317 return (0); 1318 } 1319 1320 static nfsuint64 nfs_nullcookie = { { 0, 0 } }; 1321 /* 1322 * This function finds the directory cookie that corresponds to the 1323 * logical byte offset given. 1324 */ 1325 nfsuint64 * 1326 nfs_getcookie(struct nfsnode *np, off_t off, int add) 1327 { 1328 struct nfsdmap *dp, *dp2; 1329 int pos; 1330 1331 pos = (uoff_t)off / NFS_DIRBLKSIZ; 1332 if (pos == 0 || off < 0) { 1333 #ifdef DIAGNOSTIC 1334 if (add) 1335 panic("nfs getcookie add at <= 0"); 1336 #endif 1337 return (&nfs_nullcookie); 1338 } 1339 pos--; 1340 dp = np->n_cookies.lh_first; 1341 if (!dp) { 1342 if (add) { 1343 dp = kmalloc(sizeof(struct nfsdmap), M_NFSDIROFF, 1344 M_WAITOK); 1345 dp->ndm_eocookie = 0; 1346 LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list); 1347 } else 1348 return (NULL); 1349 } 1350 while (pos >= NFSNUMCOOKIES) { 1351 pos -= NFSNUMCOOKIES; 1352 if (dp->ndm_list.le_next) { 1353 if (!add && dp->ndm_eocookie < NFSNUMCOOKIES && 1354 pos >= dp->ndm_eocookie) 1355 return (NULL); 1356 dp = dp->ndm_list.le_next; 1357 } else if (add) { 1358 dp2 = kmalloc(sizeof(struct nfsdmap), M_NFSDIROFF, 1359 M_WAITOK); 1360 dp2->ndm_eocookie = 0; 1361 LIST_INSERT_AFTER(dp, dp2, ndm_list); 1362 dp = dp2; 1363 } else 1364 return (NULL); 1365 } 1366 if (pos >= dp->ndm_eocookie) { 1367 if (add) 1368 dp->ndm_eocookie = pos + 1; 1369 else 1370 return (NULL); 1371 } 1372 return (&dp->ndm_cookies[pos]); 1373 } 1374 1375 /* 1376 * Invalidate cached directory information, except for the actual directory 1377 * blocks (which are invalidated separately). 1378 * Done mainly to avoid the use of stale offset cookies. 1379 */ 1380 void 1381 nfs_invaldir(struct vnode *vp) 1382 { 1383 struct nfsnode *np = VTONFS(vp); 1384 1385 #ifdef DIAGNOSTIC 1386 if (vp->v_type != VDIR) 1387 panic("nfs: invaldir not dir"); 1388 #endif 1389 np->n_direofoffset = 0; 1390 np->n_cookieverf.nfsuquad[0] = 0; 1391 np->n_cookieverf.nfsuquad[1] = 0; 1392 if (np->n_cookies.lh_first) 1393 np->n_cookies.lh_first->ndm_eocookie = 0; 1394 } 1395 1396 /* 1397 * Set the v_type field for an NFS client's vnode and initialize for 1398 * buffer cache operations if necessary. 1399 */ 1400 void 1401 nfs_setvtype(struct vnode *vp, enum vtype vtyp) 1402 { 1403 vp->v_type = vtyp; 1404 1405 switch(vtyp) { 1406 case VREG: 1407 case VDIR: 1408 case VLNK: 1409 /* 1410 * Needs VMIO, size not yet known, and blocksize 1411 * is not really relevant if we are passing a 1412 * filesize of 0. 1413 */ 1414 vinitvmio(vp, 0, PAGE_SIZE, -1); 1415 break; 1416 default: 1417 break; 1418 } 1419 } 1420 1421 /* 1422 * The write verifier has changed (probably due to a server reboot), so all 1423 * B_NEEDCOMMIT blocks will have to be written again. Since they are on the 1424 * dirty block list as B_DELWRI, all this takes is clearing the B_NEEDCOMMIT 1425 * and B_CLUSTEROK flags. Once done the new write verifier can be set for the 1426 * mount point. 1427 * 1428 * B_CLUSTEROK must be cleared along with B_NEEDCOMMIT because stage 1 data 1429 * writes are not clusterable. 1430 */ 1431 1432 static int nfs_clearcommit_bp(struct buf *bp, void *data __unused); 1433 static int nfs_clearcommit_callback(struct mount *mp, struct vnode *vp, 1434 void *data __unused); 1435 1436 void 1437 nfs_clearcommit(struct mount *mp) 1438 { 1439 vsyncscan(mp, VMSC_NOWAIT, nfs_clearcommit_callback, NULL); 1440 } 1441 1442 static int 1443 nfs_clearcommit_callback(struct mount *mp, struct vnode *vp, 1444 void *data __unused) 1445 { 1446 lwkt_gettoken(&vp->v_token); 1447 RB_SCAN(buf_rb_tree, &vp->v_rbdirty_tree, NULL, 1448 nfs_clearcommit_bp, NULL); 1449 lwkt_reltoken(&vp->v_token); 1450 1451 return(0); 1452 } 1453 1454 static int 1455 nfs_clearcommit_bp(struct buf *bp, void *data __unused) 1456 { 1457 if (BUF_LOCKINUSE(bp) == 0 && 1458 (bp->b_flags & (B_DELWRI | B_NEEDCOMMIT)) 1459 == (B_DELWRI | B_NEEDCOMMIT)) { 1460 bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK); 1461 } 1462 return(0); 1463 } 1464 1465 #ifndef NFS_NOSERVER 1466 /* 1467 * Map errnos to NFS error numbers. For Version 3 also filter out error 1468 * numbers not specified for the associated procedure. 1469 */ 1470 int 1471 nfsrv_errmap(struct nfsrv_descript *nd, int err) 1472 { 1473 short *defaulterrp, *errp; 1474 1475 if (nd->nd_flag & ND_NFSV3) { 1476 if (nd->nd_procnum <= NFSPROC_COMMIT) { 1477 errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum]; 1478 while (*++errp) { 1479 if (*errp == err) 1480 return (err); 1481 else if (*errp > err) 1482 break; 1483 } 1484 return ((int)*defaulterrp); 1485 } else 1486 return (err & 0xffff); 1487 } 1488 if (err <= ELAST) 1489 return ((int)nfsrv_v2errmap[err - 1]); 1490 return (NFSERR_IO); 1491 } 1492 1493 /* 1494 * Sort the group list in increasing numerical order. 1495 * (Insertion sort by Chris Torek, who was grossed out by the bubble sort 1496 * that used to be here.) 1497 */ 1498 void 1499 nfsrvw_sort(gid_t *list, int num) 1500 { 1501 int i, j; 1502 gid_t v; 1503 1504 /* Insertion sort. */ 1505 for (i = 1; i < num; i++) { 1506 v = list[i]; 1507 /* find correct slot for value v, moving others up */ 1508 for (j = i; --j >= 0 && v < list[j];) 1509 list[j + 1] = list[j]; 1510 list[j + 1] = v; 1511 } 1512 } 1513 1514 /* 1515 * copy credentials making sure that the result can be compared with bcmp(). 1516 */ 1517 void 1518 nfsrv_setcred(struct ucred *incred, struct ucred *outcred) 1519 { 1520 int i; 1521 1522 bzero((caddr_t)outcred, sizeof (struct ucred)); 1523 outcred->cr_ref = 1; 1524 outcred->cr_uid = incred->cr_uid; 1525 outcred->cr_ngroups = incred->cr_ngroups; 1526 for (i = 0; i < incred->cr_ngroups; i++) 1527 outcred->cr_groups[i] = incred->cr_groups[i]; 1528 nfsrvw_sort(outcred->cr_groups, outcred->cr_ngroups); 1529 } 1530 #endif /* NFS_NOSERVER */ 1531 1532 /* 1533 * Hold a ucred in nfs_node. Discard prison information, otherwise 1534 * prisons might stick around indefinitely due to NFS node caching. 1535 */ 1536 struct ucred * 1537 nfs_crhold(struct ucred *cred) 1538 { 1539 if (cred) { 1540 if (cred->cr_prison) { 1541 cred = crdup(cred); 1542 prison_free(cred->cr_prison); 1543 cred->cr_prison = NULL; 1544 } else { 1545 cred = crhold(cred); 1546 } 1547 } 1548 return cred; 1549 } 1550 1551 /* 1552 * Return whether two ucreds are the same insofar as NFS cares about. 1553 */ 1554 int 1555 nfs_crsame(struct ucred *cr1, struct ucred *cr2) 1556 { 1557 if (cr1 != cr2) { 1558 if (cr1 == NULL || cr2 == NULL) 1559 return (cr1 == cr2); 1560 if (cr1->cr_uid != cr2->cr_uid || 1561 cr1->cr_ruid != cr2->cr_ruid || 1562 cr1->cr_rgid != cr2->cr_rgid || 1563 cr1->cr_ngroups != cr2->cr_ngroups) { 1564 return 0; 1565 } 1566 if (bcmp(cr1->cr_groups, cr2->cr_groups, 1567 cr1->cr_ngroups * sizeof(cr1->cr_groups[0])) != 0) { 1568 return 0; 1569 } 1570 } 1571 return 1; 1572 } 1573