nfs_srvsubs.c revision 17186
11541Srgrimes/* 21541Srgrimes * Copyright (c) 1989, 1993 31541Srgrimes * The Regents of the University of California. All rights reserved. 41541Srgrimes * 51541Srgrimes * This code is derived from software contributed to Berkeley by 61541Srgrimes * Rick Macklem at The University of Guelph. 71541Srgrimes * 81541Srgrimes * Redistribution and use in source and binary forms, with or without 91541Srgrimes * modification, are permitted provided that the following conditions 101541Srgrimes * are met: 111541Srgrimes * 1. Redistributions of source code must retain the above copyright 121541Srgrimes * notice, this list of conditions and the following disclaimer. 131541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141541Srgrimes * notice, this list of conditions and the following disclaimer in the 151541Srgrimes * documentation and/or other materials provided with the distribution. 161541Srgrimes * 3. All advertising materials mentioning features or use of this software 171541Srgrimes * must display the following acknowledgement: 181541Srgrimes * This product includes software developed by the University of 191541Srgrimes * California, Berkeley and its contributors. 201541Srgrimes * 4. Neither the name of the University nor the names of its contributors 211541Srgrimes * may be used to endorse or promote products derived from this software 221541Srgrimes * without specific prior written permission. 231541Srgrimes * 241541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271541Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341541Srgrimes * SUCH DAMAGE. 351541Srgrimes * 361541Srgrimes * @(#)nfs_subs.c 8.3 (Berkeley) 1/4/94 3717186Sdfr * $Id: nfs_subs.c,v 1.30 1996/06/23 17:19:25 bde Exp $ 381541Srgrimes */ 391541Srgrimes 401541Srgrimes/* 411541Srgrimes * These functions support the macros and help fiddle mbuf chains for 421541Srgrimes * the nfs op functions. They do things like create the rpc header and 431541Srgrimes * copy data between mbuf chains and uio lists. 441541Srgrimes */ 451541Srgrimes#include <sys/param.h> 461541Srgrimes#include <sys/proc.h> 471541Srgrimes#include <sys/systm.h> 481541Srgrimes#include <sys/kernel.h> 491541Srgrimes#include <sys/mount.h> 501541Srgrimes#include <sys/vnode.h> 511541Srgrimes#include <sys/namei.h> 521541Srgrimes#include <sys/mbuf.h> 531541Srgrimes#include <sys/socket.h> 541541Srgrimes#include <sys/stat.h> 559336Sdfr#include <sys/malloc.h> 562997Swollman#ifdef VFS_LKM 572997Swollman#include <sys/sysent.h> 582997Swollman#include <sys/syscall.h> 592997Swollman#endif 601541Srgrimes 613305Sphk#include <vm/vm.h> 6212662Sdg#include <vm/vm_param.h> 6312662Sdg#include <vm/vm_object.h> 6412662Sdg#include <vm/vm_extern.h> 659507Sdg#include <vm/vnode_pager.h> 663305Sphk 671541Srgrimes#include <nfs/rpcv2.h> 689336Sdfr#include <nfs/nfsproto.h> 691541Srgrimes#include <nfs/nfsnode.h> 701541Srgrimes#include <nfs/nfs.h> 711541Srgrimes#include <nfs/xdr_subs.h> 721541Srgrimes#include <nfs/nfsm_subs.h> 731541Srgrimes#include <nfs/nfsmount.h> 741541Srgrimes#include <nfs/nqnfs.h> 751541Srgrimes#include <nfs/nfsrtt.h> 761541Srgrimes 771541Srgrimes#include <miscfs/specfs/specdev.h> 781541Srgrimes 791541Srgrimes#include <netinet/in.h> 801541Srgrimes#ifdef ISO 811541Srgrimes#include <netiso/iso.h> 821541Srgrimes#endif 831541Srgrimes 841541Srgrimes/* 851541Srgrimes * Data items converted to xdr at startup, since they are constant 861541Srgrimes * This is kinda hokey, but may save a little time doing byte swaps 871541Srgrimes */ 881541Srgrimesu_long nfs_xdrneg1; 891541Srgrimesu_long rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr, 909336Sdfr rpc_mismatch, rpc_auth_unix, rpc_msgaccepted, 911541Srgrimes rpc_auth_kerb; 929336Sdfru_long nfs_prog, nqnfs_prog, nfs_true, nfs_false; 931541Srgrimes 941541Srgrimes/* And other global data */ 951541Srgrimesstatic u_long nfs_xid = 0; 9612911Sphkstatic enum vtype nv2tov_type[8]= { 9712911Sphk VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON 9812911Sphk}; 9912911Sphkenum vtype nv3tov_type[8]= { 10012911Sphk VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO 10112911Sphk}; 10212911Sphk 1039336Sdfrint nfs_ticks; 1049336Sdfr 1059759Sbdestruct nfs_reqq nfs_reqq; 1069759Sbdestruct nfssvc_sockhead nfssvc_sockhead; 1079759Sbdeint nfssvc_sockhead_flag; 1089759Sbdestruct nfsd_head nfsd_head; 1099759Sbdeint nfsd_head_flag; 1109759Sbdestruct nfs_bufq nfs_bufq; 1119759Sbdestruct nqtimerhead nqtimerhead; 1129759Sbdestruct nqfhhashhead *nqfhhashtbl; 1139759Sbdeu_long nqfhhash; 1149759Sbde 11513416Sphk#ifndef NFS_NOSERVER 1169336Sdfr/* 1179336Sdfr * Mapping of old NFS Version 2 RPC numbers to generic numbers. 1189336Sdfr */ 1199336Sdfrint nfsv3_procid[NFS_NPROCS] = { 1209336Sdfr NFSPROC_NULL, 1219336Sdfr NFSPROC_GETATTR, 1229336Sdfr NFSPROC_SETATTR, 1239336Sdfr NFSPROC_NOOP, 1249336Sdfr NFSPROC_LOOKUP, 1259336Sdfr NFSPROC_READLINK, 1269336Sdfr NFSPROC_READ, 1279336Sdfr NFSPROC_NOOP, 1289336Sdfr NFSPROC_WRITE, 1299336Sdfr NFSPROC_CREATE, 1309336Sdfr NFSPROC_REMOVE, 1319336Sdfr NFSPROC_RENAME, 1329336Sdfr NFSPROC_LINK, 1339336Sdfr NFSPROC_SYMLINK, 1349336Sdfr NFSPROC_MKDIR, 1359336Sdfr NFSPROC_RMDIR, 1369336Sdfr NFSPROC_READDIR, 1379336Sdfr NFSPROC_FSSTAT, 1389336Sdfr NFSPROC_NOOP, 1399336Sdfr NFSPROC_NOOP, 1409336Sdfr NFSPROC_NOOP, 1419336Sdfr NFSPROC_NOOP, 1429336Sdfr NFSPROC_NOOP, 1439336Sdfr NFSPROC_NOOP, 1449336Sdfr NFSPROC_NOOP, 1459336Sdfr NFSPROC_NOOP 1469336Sdfr}; 1479336Sdfr 14813416Sphk#endif /* NFS_NOSERVER */ 1499336Sdfr/* 1509336Sdfr * and the reverse mapping from generic to Version 2 procedure numbers 1519336Sdfr */ 1529336Sdfrint nfsv2_procid[NFS_NPROCS] = { 1539336Sdfr NFSV2PROC_NULL, 1549336Sdfr NFSV2PROC_GETATTR, 1559336Sdfr NFSV2PROC_SETATTR, 1569336Sdfr NFSV2PROC_LOOKUP, 1579336Sdfr NFSV2PROC_NOOP, 1589336Sdfr NFSV2PROC_READLINK, 1599336Sdfr NFSV2PROC_READ, 1609336Sdfr NFSV2PROC_WRITE, 1619336Sdfr NFSV2PROC_CREATE, 1629336Sdfr NFSV2PROC_MKDIR, 1639336Sdfr NFSV2PROC_SYMLINK, 1649336Sdfr NFSV2PROC_CREATE, 1659336Sdfr NFSV2PROC_REMOVE, 1669336Sdfr NFSV2PROC_RMDIR, 1679336Sdfr NFSV2PROC_RENAME, 1689336Sdfr NFSV2PROC_LINK, 1699336Sdfr NFSV2PROC_READDIR, 1709336Sdfr NFSV2PROC_NOOP, 1719336Sdfr NFSV2PROC_STATFS, 1729336Sdfr NFSV2PROC_NOOP, 1739336Sdfr NFSV2PROC_NOOP, 1749336Sdfr NFSV2PROC_NOOP, 1759336Sdfr NFSV2PROC_NOOP, 1769336Sdfr NFSV2PROC_NOOP, 1779336Sdfr NFSV2PROC_NOOP, 1789336Sdfr NFSV2PROC_NOOP, 1799336Sdfr}; 1809336Sdfr 18113416Sphk#ifndef NFS_NOSERVER 1829336Sdfr/* 1839336Sdfr * Maps errno values to nfs error numbers. 1849336Sdfr * Use NFSERR_IO as the catch all for ones not specifically defined in 1859336Sdfr * RFC 1094. 1869336Sdfr */ 1879336Sdfrstatic u_char nfsrv_v2errmap[ELAST] = { 1889336Sdfr NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO, 1899336Sdfr NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 1909336Sdfr NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO, 1919336Sdfr NFSERR_IO, NFSERR_EXIST, NFSERR_IO, NFSERR_NODEV, NFSERR_NOTDIR, 1929336Sdfr NFSERR_ISDIR, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 1939336Sdfr NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS, 1949336Sdfr NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 1959336Sdfr NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 1969336Sdfr NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 1979336Sdfr NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 1989336Sdfr NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 1999336Sdfr NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 2009336Sdfr NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO, 2019336Sdfr NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE, 2029336Sdfr NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 2039336Sdfr NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, 2049336Sdfr NFSERR_IO, 2059336Sdfr}; 2069336Sdfr 2079336Sdfr/* 2089336Sdfr * Maps errno values to nfs error numbers. 2099336Sdfr * Although it is not obvious whether or not NFS clients really care if 2109336Sdfr * a returned error value is in the specified list for the procedure, the 2119336Sdfr * safest thing to do is filter them appropriately. For Version 2, the 2129336Sdfr * X/Open XNFS document is the only specification that defines error values 2139336Sdfr * for each RPC (The RFC simply lists all possible error values for all RPCs), 2149336Sdfr * so I have decided to not do this for Version 2. 2159336Sdfr * The first entry is the default error return and the rest are the valid 2169336Sdfr * errors for that RPC in increasing numeric order. 2179336Sdfr */ 2189336Sdfrstatic short nfsv3err_null[] = { 2199336Sdfr 0, 2209336Sdfr 0, 2219336Sdfr}; 2229336Sdfr 2239336Sdfrstatic short nfsv3err_getattr[] = { 2249336Sdfr NFSERR_IO, 2259336Sdfr NFSERR_IO, 2269336Sdfr NFSERR_STALE, 2279336Sdfr NFSERR_BADHANDLE, 2289336Sdfr NFSERR_SERVERFAULT, 2299336Sdfr 0, 2309336Sdfr}; 2319336Sdfr 2329336Sdfrstatic short nfsv3err_setattr[] = { 2339336Sdfr NFSERR_IO, 2349336Sdfr NFSERR_PERM, 2359336Sdfr NFSERR_IO, 2369336Sdfr NFSERR_ACCES, 2379336Sdfr NFSERR_INVAL, 2389336Sdfr NFSERR_NOSPC, 2399336Sdfr NFSERR_ROFS, 2409336Sdfr NFSERR_DQUOT, 2419336Sdfr NFSERR_STALE, 2429336Sdfr NFSERR_BADHANDLE, 2439336Sdfr NFSERR_NOT_SYNC, 2449336Sdfr NFSERR_SERVERFAULT, 2459336Sdfr 0, 2469336Sdfr}; 2479336Sdfr 2489336Sdfrstatic short nfsv3err_lookup[] = { 2499336Sdfr NFSERR_IO, 2509336Sdfr NFSERR_NOENT, 2519336Sdfr NFSERR_IO, 2529336Sdfr NFSERR_ACCES, 2539336Sdfr NFSERR_NOTDIR, 2549336Sdfr NFSERR_NAMETOL, 2559336Sdfr NFSERR_STALE, 2569336Sdfr NFSERR_BADHANDLE, 2579336Sdfr NFSERR_SERVERFAULT, 2589336Sdfr 0, 2599336Sdfr}; 2609336Sdfr 2619336Sdfrstatic short nfsv3err_access[] = { 2629336Sdfr NFSERR_IO, 2639336Sdfr NFSERR_IO, 2649336Sdfr NFSERR_STALE, 2659336Sdfr NFSERR_BADHANDLE, 2669336Sdfr NFSERR_SERVERFAULT, 2679336Sdfr 0, 2689336Sdfr}; 2699336Sdfr 2709336Sdfrstatic short nfsv3err_readlink[] = { 2719336Sdfr NFSERR_IO, 2729336Sdfr NFSERR_IO, 2739336Sdfr NFSERR_ACCES, 2749336Sdfr NFSERR_INVAL, 2759336Sdfr NFSERR_STALE, 2769336Sdfr NFSERR_BADHANDLE, 2779336Sdfr NFSERR_NOTSUPP, 2789336Sdfr NFSERR_SERVERFAULT, 2799336Sdfr 0, 2809336Sdfr}; 2819336Sdfr 2829336Sdfrstatic short nfsv3err_read[] = { 2839336Sdfr NFSERR_IO, 2849336Sdfr NFSERR_IO, 2859336Sdfr NFSERR_NXIO, 2869336Sdfr NFSERR_ACCES, 2879336Sdfr NFSERR_INVAL, 2889336Sdfr NFSERR_STALE, 2899336Sdfr NFSERR_BADHANDLE, 2909336Sdfr NFSERR_SERVERFAULT, 2919336Sdfr 0, 2929336Sdfr}; 2939336Sdfr 2949336Sdfrstatic short nfsv3err_write[] = { 2959336Sdfr NFSERR_IO, 2969336Sdfr NFSERR_IO, 2979336Sdfr NFSERR_ACCES, 2989336Sdfr NFSERR_INVAL, 2999336Sdfr NFSERR_FBIG, 3009336Sdfr NFSERR_NOSPC, 3019336Sdfr NFSERR_ROFS, 3029336Sdfr NFSERR_DQUOT, 3039336Sdfr NFSERR_STALE, 3049336Sdfr NFSERR_BADHANDLE, 3059336Sdfr NFSERR_SERVERFAULT, 3069336Sdfr 0, 3079336Sdfr}; 3089336Sdfr 3099336Sdfrstatic short nfsv3err_create[] = { 3109336Sdfr NFSERR_IO, 3119336Sdfr NFSERR_IO, 3129336Sdfr NFSERR_ACCES, 3139336Sdfr NFSERR_EXIST, 3149336Sdfr NFSERR_NOTDIR, 3159336Sdfr NFSERR_NOSPC, 3169336Sdfr NFSERR_ROFS, 3179336Sdfr NFSERR_NAMETOL, 3189336Sdfr NFSERR_DQUOT, 3199336Sdfr NFSERR_STALE, 3209336Sdfr NFSERR_BADHANDLE, 3219336Sdfr NFSERR_NOTSUPP, 3229336Sdfr NFSERR_SERVERFAULT, 3239336Sdfr 0, 3249336Sdfr}; 3259336Sdfr 3269336Sdfrstatic short nfsv3err_mkdir[] = { 3279336Sdfr NFSERR_IO, 3289336Sdfr NFSERR_IO, 3299336Sdfr NFSERR_ACCES, 3309336Sdfr NFSERR_EXIST, 3319336Sdfr NFSERR_NOTDIR, 3329336Sdfr NFSERR_NOSPC, 3339336Sdfr NFSERR_ROFS, 3349336Sdfr NFSERR_NAMETOL, 3359336Sdfr NFSERR_DQUOT, 3369336Sdfr NFSERR_STALE, 3379336Sdfr NFSERR_BADHANDLE, 3389336Sdfr NFSERR_NOTSUPP, 3399336Sdfr NFSERR_SERVERFAULT, 3409336Sdfr 0, 3419336Sdfr}; 3429336Sdfr 3439336Sdfrstatic short nfsv3err_symlink[] = { 3449336Sdfr NFSERR_IO, 3459336Sdfr NFSERR_IO, 3469336Sdfr NFSERR_ACCES, 3479336Sdfr NFSERR_EXIST, 3489336Sdfr NFSERR_NOTDIR, 3499336Sdfr NFSERR_NOSPC, 3509336Sdfr NFSERR_ROFS, 3519336Sdfr NFSERR_NAMETOL, 3529336Sdfr NFSERR_DQUOT, 3539336Sdfr NFSERR_STALE, 3549336Sdfr NFSERR_BADHANDLE, 3559336Sdfr NFSERR_NOTSUPP, 3569336Sdfr NFSERR_SERVERFAULT, 3579336Sdfr 0, 3589336Sdfr}; 3599336Sdfr 3609336Sdfrstatic short nfsv3err_mknod[] = { 3619336Sdfr NFSERR_IO, 3629336Sdfr NFSERR_IO, 3639336Sdfr NFSERR_ACCES, 3649336Sdfr NFSERR_EXIST, 3659336Sdfr NFSERR_NOTDIR, 3669336Sdfr NFSERR_NOSPC, 3679336Sdfr NFSERR_ROFS, 3689336Sdfr NFSERR_NAMETOL, 3699336Sdfr NFSERR_DQUOT, 3709336Sdfr NFSERR_STALE, 3719336Sdfr NFSERR_BADHANDLE, 3729336Sdfr NFSERR_NOTSUPP, 3739336Sdfr NFSERR_SERVERFAULT, 3749336Sdfr NFSERR_BADTYPE, 3759336Sdfr 0, 3769336Sdfr}; 3779336Sdfr 3789336Sdfrstatic short nfsv3err_remove[] = { 3799336Sdfr NFSERR_IO, 3809336Sdfr NFSERR_NOENT, 3819336Sdfr NFSERR_IO, 3829336Sdfr NFSERR_ACCES, 3839336Sdfr NFSERR_NOTDIR, 3849336Sdfr NFSERR_ROFS, 3859336Sdfr NFSERR_NAMETOL, 3869336Sdfr NFSERR_STALE, 3879336Sdfr NFSERR_BADHANDLE, 3889336Sdfr NFSERR_SERVERFAULT, 3899336Sdfr 0, 3909336Sdfr}; 3919336Sdfr 3929336Sdfrstatic short nfsv3err_rmdir[] = { 3939336Sdfr NFSERR_IO, 3949336Sdfr NFSERR_NOENT, 3959336Sdfr NFSERR_IO, 3969336Sdfr NFSERR_ACCES, 3979336Sdfr NFSERR_EXIST, 3989336Sdfr NFSERR_NOTDIR, 3999336Sdfr NFSERR_INVAL, 4009336Sdfr NFSERR_ROFS, 4019336Sdfr NFSERR_NAMETOL, 4029336Sdfr NFSERR_NOTEMPTY, 4039336Sdfr NFSERR_STALE, 4049336Sdfr NFSERR_BADHANDLE, 4059336Sdfr NFSERR_NOTSUPP, 4069336Sdfr NFSERR_SERVERFAULT, 4079336Sdfr 0, 4089336Sdfr}; 4099336Sdfr 4109336Sdfrstatic short nfsv3err_rename[] = { 4119336Sdfr NFSERR_IO, 4129336Sdfr NFSERR_NOENT, 4139336Sdfr NFSERR_IO, 4149336Sdfr NFSERR_ACCES, 4159336Sdfr NFSERR_EXIST, 4169336Sdfr NFSERR_XDEV, 4179336Sdfr NFSERR_NOTDIR, 4189336Sdfr NFSERR_ISDIR, 4199336Sdfr NFSERR_INVAL, 4209336Sdfr NFSERR_NOSPC, 4219336Sdfr NFSERR_ROFS, 4229336Sdfr NFSERR_MLINK, 4239336Sdfr NFSERR_NAMETOL, 4249336Sdfr NFSERR_NOTEMPTY, 4259336Sdfr NFSERR_DQUOT, 4269336Sdfr NFSERR_STALE, 4279336Sdfr NFSERR_BADHANDLE, 4289336Sdfr NFSERR_NOTSUPP, 4299336Sdfr NFSERR_SERVERFAULT, 4309336Sdfr 0, 4319336Sdfr}; 4329336Sdfr 4339336Sdfrstatic short nfsv3err_link[] = { 4349336Sdfr NFSERR_IO, 4359336Sdfr NFSERR_IO, 4369336Sdfr NFSERR_ACCES, 4379336Sdfr NFSERR_EXIST, 4389336Sdfr NFSERR_XDEV, 4399336Sdfr NFSERR_NOTDIR, 4409336Sdfr NFSERR_INVAL, 4419336Sdfr NFSERR_NOSPC, 4429336Sdfr NFSERR_ROFS, 4439336Sdfr NFSERR_MLINK, 4449336Sdfr NFSERR_NAMETOL, 4459336Sdfr NFSERR_DQUOT, 4469336Sdfr NFSERR_STALE, 4479336Sdfr NFSERR_BADHANDLE, 4489336Sdfr NFSERR_NOTSUPP, 4499336Sdfr NFSERR_SERVERFAULT, 4509336Sdfr 0, 4519336Sdfr}; 4529336Sdfr 4539336Sdfrstatic short nfsv3err_readdir[] = { 4549336Sdfr NFSERR_IO, 4559336Sdfr NFSERR_IO, 4569336Sdfr NFSERR_ACCES, 4579336Sdfr NFSERR_NOTDIR, 4589336Sdfr NFSERR_STALE, 4599336Sdfr NFSERR_BADHANDLE, 4609336Sdfr NFSERR_BAD_COOKIE, 4619336Sdfr NFSERR_TOOSMALL, 4629336Sdfr NFSERR_SERVERFAULT, 4639336Sdfr 0, 4649336Sdfr}; 4659336Sdfr 4669336Sdfrstatic short nfsv3err_readdirplus[] = { 4679336Sdfr NFSERR_IO, 4689336Sdfr NFSERR_IO, 4699336Sdfr NFSERR_ACCES, 4709336Sdfr NFSERR_NOTDIR, 4719336Sdfr NFSERR_STALE, 4729336Sdfr NFSERR_BADHANDLE, 4739336Sdfr NFSERR_BAD_COOKIE, 4749336Sdfr NFSERR_NOTSUPP, 4759336Sdfr NFSERR_TOOSMALL, 4769336Sdfr NFSERR_SERVERFAULT, 4779336Sdfr 0, 4789336Sdfr}; 4799336Sdfr 4809336Sdfrstatic short nfsv3err_fsstat[] = { 4819336Sdfr NFSERR_IO, 4829336Sdfr NFSERR_IO, 4839336Sdfr NFSERR_STALE, 4849336Sdfr NFSERR_BADHANDLE, 4859336Sdfr NFSERR_SERVERFAULT, 4869336Sdfr 0, 4879336Sdfr}; 4889336Sdfr 4899336Sdfrstatic short nfsv3err_fsinfo[] = { 4909336Sdfr NFSERR_STALE, 4919336Sdfr NFSERR_STALE, 4929336Sdfr NFSERR_BADHANDLE, 4939336Sdfr NFSERR_SERVERFAULT, 4949336Sdfr 0, 4959336Sdfr}; 4969336Sdfr 4979336Sdfrstatic short nfsv3err_pathconf[] = { 4989336Sdfr NFSERR_STALE, 4999336Sdfr NFSERR_STALE, 5009336Sdfr NFSERR_BADHANDLE, 5019336Sdfr NFSERR_SERVERFAULT, 5029336Sdfr 0, 5039336Sdfr}; 5049336Sdfr 5059336Sdfrstatic short nfsv3err_commit[] = { 5069336Sdfr NFSERR_IO, 5079336Sdfr NFSERR_IO, 5089336Sdfr NFSERR_STALE, 5099336Sdfr NFSERR_BADHANDLE, 5109336Sdfr NFSERR_SERVERFAULT, 5119336Sdfr 0, 5129336Sdfr}; 5139336Sdfr 5149336Sdfrstatic short *nfsrv_v3errmap[] = { 5159336Sdfr nfsv3err_null, 5169336Sdfr nfsv3err_getattr, 5179336Sdfr nfsv3err_setattr, 5189336Sdfr nfsv3err_lookup, 5199336Sdfr nfsv3err_access, 5209336Sdfr nfsv3err_readlink, 5219336Sdfr nfsv3err_read, 5229336Sdfr nfsv3err_write, 5239336Sdfr nfsv3err_create, 5249336Sdfr nfsv3err_mkdir, 5259336Sdfr nfsv3err_symlink, 5269336Sdfr nfsv3err_mknod, 5279336Sdfr nfsv3err_remove, 5289336Sdfr nfsv3err_rmdir, 5299336Sdfr nfsv3err_rename, 5309336Sdfr nfsv3err_link, 5319336Sdfr nfsv3err_readdir, 5329336Sdfr nfsv3err_readdirplus, 5339336Sdfr nfsv3err_fsstat, 5349336Sdfr nfsv3err_fsinfo, 5359336Sdfr nfsv3err_pathconf, 5369336Sdfr nfsv3err_commit, 5379336Sdfr}; 5389336Sdfr 53913416Sphk#endif /* NFS_NOSERVER */ 54013416Sphk 5411541Srgrimesextern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON]; 5421541Srgrimesextern struct nfsrtt nfsrtt; 5431541Srgrimesextern time_t nqnfsstarttime; 5441541Srgrimesextern int nqsrv_clockskew; 5451541Srgrimesextern int nqsrv_writeslack; 5461541Srgrimesextern int nqsrv_maxlease; 5479336Sdfrextern struct nfsstats nfsstats; 5489336Sdfrextern int nqnfs_piggy[NFS_NPROCS]; 5499336Sdfrextern nfstype nfsv2_type[9]; 5509336Sdfrextern nfstype nfsv3_type[9]; 5519336Sdfrextern struct nfsnodehashhead *nfsnodehashtbl; 5529336Sdfrextern u_long nfsnodehash; 5531541Srgrimes 5542997Swollman#ifdef VFS_LKM 5552997Swollmanstruct getfh_args; 5562997Swollmanextern int getfh(struct proc *, struct getfh_args *, int *); 5572997Swollmanstruct nfssvc_args; 5582997Swollmanextern int nfssvc(struct proc *, struct nfssvc_args *, int *); 5592997Swollman#endif 5602997Swollman 5613664SphkLIST_HEAD(nfsnodehashhead, nfsnode); 5623664Sphk 5631541Srgrimes/* 5641541Srgrimes * Create the header for an rpc request packet 5651541Srgrimes * The hsiz is the size of the rest of the nfs request header. 5661541Srgrimes * (just used to decide if a cluster is a good idea) 5671541Srgrimes */ 5681541Srgrimesstruct mbuf * 5691541Srgrimesnfsm_reqh(vp, procid, hsiz, bposp) 5701541Srgrimes struct vnode *vp; 5711541Srgrimes u_long procid; 5721541Srgrimes int hsiz; 5731541Srgrimes caddr_t *bposp; 5741541Srgrimes{ 5751541Srgrimes register struct mbuf *mb; 5761541Srgrimes register u_long *tl; 5771541Srgrimes register caddr_t bpos; 5781541Srgrimes struct mbuf *mb2; 5791541Srgrimes struct nfsmount *nmp; 5801541Srgrimes int nqflag; 5811541Srgrimes 5821541Srgrimes MGET(mb, M_WAIT, MT_DATA); 5831541Srgrimes if (hsiz >= MINCLSIZE) 5841541Srgrimes MCLGET(mb, M_WAIT); 5851541Srgrimes mb->m_len = 0; 5861541Srgrimes bpos = mtod(mb, caddr_t); 5878876Srgrimes 5881541Srgrimes /* 5891541Srgrimes * For NQNFS, add lease request. 5901541Srgrimes */ 5911541Srgrimes if (vp) { 5921541Srgrimes nmp = VFSTONFS(vp->v_mount); 5931541Srgrimes if (nmp->nm_flag & NFSMNT_NQNFS) { 5941541Srgrimes nqflag = NQNFS_NEEDLEASE(vp, procid); 5951541Srgrimes if (nqflag) { 5961541Srgrimes nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED); 5971541Srgrimes *tl++ = txdr_unsigned(nqflag); 5981541Srgrimes *tl = txdr_unsigned(nmp->nm_leaseterm); 5991541Srgrimes } else { 6001541Srgrimes nfsm_build(tl, u_long *, NFSX_UNSIGNED); 6011541Srgrimes *tl = 0; 6021541Srgrimes } 6031541Srgrimes } 6041541Srgrimes } 6051541Srgrimes /* Finally, return values */ 6061541Srgrimes *bposp = bpos; 6071541Srgrimes return (mb); 6081541Srgrimes} 6091541Srgrimes 6101541Srgrimes/* 6111541Srgrimes * Build the RPC header and fill in the authorization info. 6121541Srgrimes * The authorization string argument is only used when the credentials 6131541Srgrimes * come from outside of the kernel. 6141541Srgrimes * Returns the head of the mbuf list. 6151541Srgrimes */ 6161541Srgrimesstruct mbuf * 6179336Sdfrnfsm_rpchead(cr, nmflag, procid, auth_type, auth_len, auth_str, verf_len, 6189336Sdfr verf_str, mrest, mrest_len, mbp, xidp) 6191541Srgrimes register struct ucred *cr; 6209336Sdfr int nmflag; 6211541Srgrimes int procid; 6221541Srgrimes int auth_type; 6231541Srgrimes int auth_len; 6241541Srgrimes char *auth_str; 6259336Sdfr int verf_len; 6269336Sdfr char *verf_str; 6271541Srgrimes struct mbuf *mrest; 6281541Srgrimes int mrest_len; 6291541Srgrimes struct mbuf **mbp; 6301541Srgrimes u_long *xidp; 6311541Srgrimes{ 6321541Srgrimes register struct mbuf *mb; 6331541Srgrimes register u_long *tl; 6341541Srgrimes register caddr_t bpos; 6351541Srgrimes register int i; 6361541Srgrimes struct mbuf *mreq, *mb2; 6371541Srgrimes int siz, grpsiz, authsiz; 63817186Sdfr struct timeval tv; 63917186Sdfr static u_long base; 6401541Srgrimes 6411541Srgrimes authsiz = nfsm_rndup(auth_len); 6421541Srgrimes MGETHDR(mb, M_WAIT, MT_DATA); 6439336Sdfr if ((authsiz + 10 * NFSX_UNSIGNED) >= MINCLSIZE) { 6441541Srgrimes MCLGET(mb, M_WAIT); 6459336Sdfr } else if ((authsiz + 10 * NFSX_UNSIGNED) < MHLEN) { 6469336Sdfr MH_ALIGN(mb, authsiz + 10 * NFSX_UNSIGNED); 6471541Srgrimes } else { 6489336Sdfr MH_ALIGN(mb, 8 * NFSX_UNSIGNED); 6491541Srgrimes } 6501541Srgrimes mb->m_len = 0; 6511541Srgrimes mreq = mb; 6521541Srgrimes bpos = mtod(mb, caddr_t); 6531541Srgrimes 6541541Srgrimes /* 6551541Srgrimes * First the RPC header. 6561541Srgrimes */ 6579336Sdfr nfsm_build(tl, u_long *, 8 * NFSX_UNSIGNED); 65817186Sdfr 65917186Sdfr /* 66017186Sdfr * derive initial xid from system time 66117186Sdfr * XXX time is invalid if root not yet mounted 66217186Sdfr */ 66317186Sdfr if (!base && (rootvp)) { 66417186Sdfr microtime(&tv); 66517186Sdfr base = tv.tv_sec << 12; 66617186Sdfr nfs_xid = base; 66717186Sdfr } 66817186Sdfr /* 66917186Sdfr * Skip zero xid if it should ever happen. 67017186Sdfr */ 6711541Srgrimes if (++nfs_xid == 0) 6721541Srgrimes nfs_xid++; 67317186Sdfr 6741541Srgrimes *tl++ = *xidp = txdr_unsigned(nfs_xid); 6751541Srgrimes *tl++ = rpc_call; 6761541Srgrimes *tl++ = rpc_vers; 6779336Sdfr if (nmflag & NFSMNT_NQNFS) { 6781541Srgrimes *tl++ = txdr_unsigned(NQNFS_PROG); 6799336Sdfr *tl++ = txdr_unsigned(NQNFS_VER3); 6801541Srgrimes } else { 6811541Srgrimes *tl++ = txdr_unsigned(NFS_PROG); 6829336Sdfr if (nmflag & NFSMNT_NFSV3) 6839336Sdfr *tl++ = txdr_unsigned(NFS_VER3); 6849336Sdfr else 6859336Sdfr *tl++ = txdr_unsigned(NFS_VER2); 6861541Srgrimes } 6879336Sdfr if (nmflag & NFSMNT_NFSV3) 6889336Sdfr *tl++ = txdr_unsigned(procid); 6899336Sdfr else 6909336Sdfr *tl++ = txdr_unsigned(nfsv2_procid[procid]); 6911541Srgrimes 6921541Srgrimes /* 6931541Srgrimes * And then the authorization cred. 6941541Srgrimes */ 6951541Srgrimes *tl++ = txdr_unsigned(auth_type); 6961541Srgrimes *tl = txdr_unsigned(authsiz); 6971541Srgrimes switch (auth_type) { 6981541Srgrimes case RPCAUTH_UNIX: 6991541Srgrimes nfsm_build(tl, u_long *, auth_len); 7001541Srgrimes *tl++ = 0; /* stamp ?? */ 7011541Srgrimes *tl++ = 0; /* NULL hostname */ 7021541Srgrimes *tl++ = txdr_unsigned(cr->cr_uid); 7031541Srgrimes *tl++ = txdr_unsigned(cr->cr_groups[0]); 7041541Srgrimes grpsiz = (auth_len >> 2) - 5; 7051541Srgrimes *tl++ = txdr_unsigned(grpsiz); 7061541Srgrimes for (i = 1; i <= grpsiz; i++) 7071541Srgrimes *tl++ = txdr_unsigned(cr->cr_groups[i]); 7081541Srgrimes break; 7099336Sdfr case RPCAUTH_KERB4: 7101541Srgrimes siz = auth_len; 7111541Srgrimes while (siz > 0) { 7121541Srgrimes if (M_TRAILINGSPACE(mb) == 0) { 7131541Srgrimes MGET(mb2, M_WAIT, MT_DATA); 7141541Srgrimes if (siz >= MINCLSIZE) 7151541Srgrimes MCLGET(mb2, M_WAIT); 7161541Srgrimes mb->m_next = mb2; 7171541Srgrimes mb = mb2; 7181541Srgrimes mb->m_len = 0; 7191541Srgrimes bpos = mtod(mb, caddr_t); 7201541Srgrimes } 7211541Srgrimes i = min(siz, M_TRAILINGSPACE(mb)); 7221541Srgrimes bcopy(auth_str, bpos, i); 7231541Srgrimes mb->m_len += i; 7241541Srgrimes auth_str += i; 7251541Srgrimes bpos += i; 7261541Srgrimes siz -= i; 7271541Srgrimes } 7281541Srgrimes if ((siz = (nfsm_rndup(auth_len) - auth_len)) > 0) { 7291541Srgrimes for (i = 0; i < siz; i++) 7301541Srgrimes *bpos++ = '\0'; 7311541Srgrimes mb->m_len += siz; 7321541Srgrimes } 7331541Srgrimes break; 7341541Srgrimes }; 7359336Sdfr 7369336Sdfr /* 7379336Sdfr * And the verifier... 7389336Sdfr */ 7399336Sdfr nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 7409336Sdfr if (verf_str) { 7419336Sdfr *tl++ = txdr_unsigned(RPCAUTH_KERB4); 7429336Sdfr *tl = txdr_unsigned(verf_len); 7439336Sdfr siz = verf_len; 7449336Sdfr while (siz > 0) { 7459336Sdfr if (M_TRAILINGSPACE(mb) == 0) { 7469336Sdfr MGET(mb2, M_WAIT, MT_DATA); 7479336Sdfr if (siz >= MINCLSIZE) 7489336Sdfr MCLGET(mb2, M_WAIT); 7499336Sdfr mb->m_next = mb2; 7509336Sdfr mb = mb2; 7519336Sdfr mb->m_len = 0; 7529336Sdfr bpos = mtod(mb, caddr_t); 7539336Sdfr } 7549336Sdfr i = min(siz, M_TRAILINGSPACE(mb)); 7559336Sdfr bcopy(verf_str, bpos, i); 7569336Sdfr mb->m_len += i; 7579336Sdfr verf_str += i; 7589336Sdfr bpos += i; 7599336Sdfr siz -= i; 7609336Sdfr } 7619336Sdfr if ((siz = (nfsm_rndup(verf_len) - verf_len)) > 0) { 7629336Sdfr for (i = 0; i < siz; i++) 7639336Sdfr *bpos++ = '\0'; 7649336Sdfr mb->m_len += siz; 7659336Sdfr } 7669336Sdfr } else { 7679336Sdfr *tl++ = txdr_unsigned(RPCAUTH_NULL); 7689336Sdfr *tl = 0; 7699336Sdfr } 7701541Srgrimes mb->m_next = mrest; 7719336Sdfr mreq->m_pkthdr.len = authsiz + 10 * NFSX_UNSIGNED + mrest_len; 7721541Srgrimes mreq->m_pkthdr.rcvif = (struct ifnet *)0; 7731541Srgrimes *mbp = mb; 7741541Srgrimes return (mreq); 7751541Srgrimes} 7761541Srgrimes 7771541Srgrimes/* 7781541Srgrimes * copies mbuf chain to the uio scatter/gather list 7791541Srgrimes */ 7801549Srgrimesint 7811541Srgrimesnfsm_mbuftouio(mrep, uiop, siz, dpos) 7821541Srgrimes struct mbuf **mrep; 7831541Srgrimes register struct uio *uiop; 7841541Srgrimes int siz; 7851541Srgrimes caddr_t *dpos; 7861541Srgrimes{ 7871541Srgrimes register char *mbufcp, *uiocp; 7881541Srgrimes register int xfer, left, len; 7891541Srgrimes register struct mbuf *mp; 7901541Srgrimes long uiosiz, rem; 7911541Srgrimes int error = 0; 7921541Srgrimes 7931541Srgrimes mp = *mrep; 7941541Srgrimes mbufcp = *dpos; 7951541Srgrimes len = mtod(mp, caddr_t)+mp->m_len-mbufcp; 7961541Srgrimes rem = nfsm_rndup(siz)-siz; 7971541Srgrimes while (siz > 0) { 7981541Srgrimes if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) 7991541Srgrimes return (EFBIG); 8001541Srgrimes left = uiop->uio_iov->iov_len; 8011541Srgrimes uiocp = uiop->uio_iov->iov_base; 8021541Srgrimes if (left > siz) 8031541Srgrimes left = siz; 8041541Srgrimes uiosiz = left; 8051541Srgrimes while (left > 0) { 8061541Srgrimes while (len == 0) { 8071541Srgrimes mp = mp->m_next; 8081541Srgrimes if (mp == NULL) 8091541Srgrimes return (EBADRPC); 8101541Srgrimes mbufcp = mtod(mp, caddr_t); 8111541Srgrimes len = mp->m_len; 8121541Srgrimes } 8131541Srgrimes xfer = (left > len) ? len : left; 8141541Srgrimes#ifdef notdef 8151541Srgrimes /* Not Yet.. */ 8161541Srgrimes if (uiop->uio_iov->iov_op != NULL) 8171541Srgrimes (*(uiop->uio_iov->iov_op)) 8181541Srgrimes (mbufcp, uiocp, xfer); 8191541Srgrimes else 8201541Srgrimes#endif 8211541Srgrimes if (uiop->uio_segflg == UIO_SYSSPACE) 8221541Srgrimes bcopy(mbufcp, uiocp, xfer); 8231541Srgrimes else 8241541Srgrimes copyout(mbufcp, uiocp, xfer); 8251541Srgrimes left -= xfer; 8261541Srgrimes len -= xfer; 8271541Srgrimes mbufcp += xfer; 8281541Srgrimes uiocp += xfer; 8291541Srgrimes uiop->uio_offset += xfer; 8301541Srgrimes uiop->uio_resid -= xfer; 8311541Srgrimes } 8321541Srgrimes if (uiop->uio_iov->iov_len <= siz) { 8331541Srgrimes uiop->uio_iovcnt--; 8341541Srgrimes uiop->uio_iov++; 8351541Srgrimes } else { 8361541Srgrimes uiop->uio_iov->iov_base += uiosiz; 8371541Srgrimes uiop->uio_iov->iov_len -= uiosiz; 8381541Srgrimes } 8391541Srgrimes siz -= uiosiz; 8401541Srgrimes } 8411541Srgrimes *dpos = mbufcp; 8421541Srgrimes *mrep = mp; 8431541Srgrimes if (rem > 0) { 8441541Srgrimes if (len < rem) 8451541Srgrimes error = nfs_adv(mrep, dpos, rem, len); 8461541Srgrimes else 8471541Srgrimes *dpos += rem; 8481541Srgrimes } 8491541Srgrimes return (error); 8501541Srgrimes} 8511541Srgrimes 8521541Srgrimes/* 85317186Sdfr * copies a uio scatter/gather list to an mbuf chain. 85417186Sdfr * NOTE: can ony handle iovcnt == 1 8551541Srgrimes */ 8561549Srgrimesint 8571541Srgrimesnfsm_uiotombuf(uiop, mq, siz, bpos) 8581541Srgrimes register struct uio *uiop; 8591541Srgrimes struct mbuf **mq; 8601541Srgrimes int siz; 8611541Srgrimes caddr_t *bpos; 8621541Srgrimes{ 8631541Srgrimes register char *uiocp; 8641541Srgrimes register struct mbuf *mp, *mp2; 8651541Srgrimes register int xfer, left, mlen; 8661541Srgrimes int uiosiz, clflg, rem; 8671541Srgrimes char *cp; 8681541Srgrimes 86917186Sdfr if (uiop->uio_iovcnt != 1) 87017186Sdfr panic("nfsm_uiotombuf: iovcnt != 1"); 87117186Sdfr 8721541Srgrimes if (siz > MLEN) /* or should it >= MCLBYTES ?? */ 8731541Srgrimes clflg = 1; 8741541Srgrimes else 8751541Srgrimes clflg = 0; 8761541Srgrimes rem = nfsm_rndup(siz)-siz; 8771541Srgrimes mp = mp2 = *mq; 8781541Srgrimes while (siz > 0) { 8791541Srgrimes left = uiop->uio_iov->iov_len; 8801541Srgrimes uiocp = uiop->uio_iov->iov_base; 8811541Srgrimes if (left > siz) 8821541Srgrimes left = siz; 8831541Srgrimes uiosiz = left; 8841541Srgrimes while (left > 0) { 8851541Srgrimes mlen = M_TRAILINGSPACE(mp); 8861541Srgrimes if (mlen == 0) { 8871541Srgrimes MGET(mp, M_WAIT, MT_DATA); 8881541Srgrimes if (clflg) 8891541Srgrimes MCLGET(mp, M_WAIT); 8901541Srgrimes mp->m_len = 0; 8911541Srgrimes mp2->m_next = mp; 8921541Srgrimes mp2 = mp; 8931541Srgrimes mlen = M_TRAILINGSPACE(mp); 8941541Srgrimes } 8951541Srgrimes xfer = (left > mlen) ? mlen : left; 8961541Srgrimes#ifdef notdef 8971541Srgrimes /* Not Yet.. */ 8981541Srgrimes if (uiop->uio_iov->iov_op != NULL) 8991541Srgrimes (*(uiop->uio_iov->iov_op)) 9001541Srgrimes (uiocp, mtod(mp, caddr_t)+mp->m_len, xfer); 9011541Srgrimes else 9021541Srgrimes#endif 9031541Srgrimes if (uiop->uio_segflg == UIO_SYSSPACE) 9041541Srgrimes bcopy(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer); 9051541Srgrimes else 9061541Srgrimes copyin(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer); 9071541Srgrimes mp->m_len += xfer; 9081541Srgrimes left -= xfer; 9091541Srgrimes uiocp += xfer; 9101541Srgrimes uiop->uio_offset += xfer; 9111541Srgrimes uiop->uio_resid -= xfer; 9121541Srgrimes } 91317186Sdfr uiop->uio_iov->iov_base += uiosiz; 91417186Sdfr uiop->uio_iov->iov_len -= uiosiz; 9151541Srgrimes siz -= uiosiz; 9161541Srgrimes } 9171541Srgrimes if (rem > 0) { 9181541Srgrimes if (rem > M_TRAILINGSPACE(mp)) { 9191541Srgrimes MGET(mp, M_WAIT, MT_DATA); 9201541Srgrimes mp->m_len = 0; 9211541Srgrimes mp2->m_next = mp; 9221541Srgrimes } 9231541Srgrimes cp = mtod(mp, caddr_t)+mp->m_len; 9241541Srgrimes for (left = 0; left < rem; left++) 9251541Srgrimes *cp++ = '\0'; 9261541Srgrimes mp->m_len += rem; 9271541Srgrimes *bpos = cp; 9281541Srgrimes } else 9291541Srgrimes *bpos = mtod(mp, caddr_t)+mp->m_len; 9301541Srgrimes *mq = mp; 9311541Srgrimes return (0); 9321541Srgrimes} 9331541Srgrimes 9341541Srgrimes/* 9351541Srgrimes * Help break down an mbuf chain by setting the first siz bytes contiguous 9361541Srgrimes * pointed to by returned val. 9371541Srgrimes * This is used by the macros nfsm_dissect and nfsm_dissecton for tough 9381541Srgrimes * cases. (The macros use the vars. dpos and dpos2) 9391541Srgrimes */ 9401549Srgrimesint 9411541Srgrimesnfsm_disct(mdp, dposp, siz, left, cp2) 9421541Srgrimes struct mbuf **mdp; 9431541Srgrimes caddr_t *dposp; 9441541Srgrimes int siz; 9451541Srgrimes int left; 9461541Srgrimes caddr_t *cp2; 9471541Srgrimes{ 9481541Srgrimes register struct mbuf *mp, *mp2; 9491541Srgrimes register int siz2, xfer; 9501541Srgrimes register caddr_t p; 9511541Srgrimes 9521541Srgrimes mp = *mdp; 9531541Srgrimes while (left == 0) { 9541541Srgrimes *mdp = mp = mp->m_next; 9551541Srgrimes if (mp == NULL) 9561541Srgrimes return (EBADRPC); 9571541Srgrimes left = mp->m_len; 9581541Srgrimes *dposp = mtod(mp, caddr_t); 9591541Srgrimes } 9601541Srgrimes if (left >= siz) { 9611541Srgrimes *cp2 = *dposp; 9621541Srgrimes *dposp += siz; 9631541Srgrimes } else if (mp->m_next == NULL) { 9641541Srgrimes return (EBADRPC); 9651541Srgrimes } else if (siz > MHLEN) { 9661541Srgrimes panic("nfs S too big"); 9671541Srgrimes } else { 9681541Srgrimes MGET(mp2, M_WAIT, MT_DATA); 9691541Srgrimes mp2->m_next = mp->m_next; 9701541Srgrimes mp->m_next = mp2; 9711541Srgrimes mp->m_len -= left; 9721541Srgrimes mp = mp2; 9731541Srgrimes *cp2 = p = mtod(mp, caddr_t); 9741541Srgrimes bcopy(*dposp, p, left); /* Copy what was left */ 9751541Srgrimes siz2 = siz-left; 9761541Srgrimes p += left; 9771541Srgrimes mp2 = mp->m_next; 9781541Srgrimes /* Loop around copying up the siz2 bytes */ 9791541Srgrimes while (siz2 > 0) { 9801541Srgrimes if (mp2 == NULL) 9811541Srgrimes return (EBADRPC); 9821541Srgrimes xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2; 9831541Srgrimes if (xfer > 0) { 9841541Srgrimes bcopy(mtod(mp2, caddr_t), p, xfer); 9851541Srgrimes NFSMADV(mp2, xfer); 9861541Srgrimes mp2->m_len -= xfer; 9871541Srgrimes p += xfer; 9881541Srgrimes siz2 -= xfer; 9891541Srgrimes } 9901541Srgrimes if (siz2 > 0) 9911541Srgrimes mp2 = mp2->m_next; 9921541Srgrimes } 9931541Srgrimes mp->m_len = siz; 9941541Srgrimes *mdp = mp2; 9951541Srgrimes *dposp = mtod(mp2, caddr_t); 9961541Srgrimes } 9971541Srgrimes return (0); 9981541Srgrimes} 9991541Srgrimes 10001541Srgrimes/* 10011541Srgrimes * Advance the position in the mbuf chain. 10021541Srgrimes */ 10031549Srgrimesint 10041541Srgrimesnfs_adv(mdp, dposp, offs, left) 10051541Srgrimes struct mbuf **mdp; 10061541Srgrimes caddr_t *dposp; 10071541Srgrimes int offs; 10081541Srgrimes int left; 10091541Srgrimes{ 10101541Srgrimes register struct mbuf *m; 10111541Srgrimes register int s; 10121541Srgrimes 10131541Srgrimes m = *mdp; 10141541Srgrimes s = left; 10151541Srgrimes while (s < offs) { 10161541Srgrimes offs -= s; 10171541Srgrimes m = m->m_next; 10181541Srgrimes if (m == NULL) 10191541Srgrimes return (EBADRPC); 10201541Srgrimes s = m->m_len; 10211541Srgrimes } 10221541Srgrimes *mdp = m; 10231541Srgrimes *dposp = mtod(m, caddr_t)+offs; 10241541Srgrimes return (0); 10251541Srgrimes} 10261541Srgrimes 10271541Srgrimes/* 10281541Srgrimes * Copy a string into mbufs for the hard cases... 10291541Srgrimes */ 10301549Srgrimesint 10311541Srgrimesnfsm_strtmbuf(mb, bpos, cp, siz) 10321541Srgrimes struct mbuf **mb; 10331541Srgrimes char **bpos; 10341541Srgrimes char *cp; 10351541Srgrimes long siz; 10361541Srgrimes{ 10371549Srgrimes register struct mbuf *m1 = 0, *m2; 10381541Srgrimes long left, xfer, len, tlen; 10391541Srgrimes u_long *tl; 10401541Srgrimes int putsize; 10411541Srgrimes 10421541Srgrimes putsize = 1; 10431541Srgrimes m2 = *mb; 10441541Srgrimes left = M_TRAILINGSPACE(m2); 10451541Srgrimes if (left > 0) { 10461541Srgrimes tl = ((u_long *)(*bpos)); 10471541Srgrimes *tl++ = txdr_unsigned(siz); 10481541Srgrimes putsize = 0; 10491541Srgrimes left -= NFSX_UNSIGNED; 10501541Srgrimes m2->m_len += NFSX_UNSIGNED; 10511541Srgrimes if (left > 0) { 10521541Srgrimes bcopy(cp, (caddr_t) tl, left); 10531541Srgrimes siz -= left; 10541541Srgrimes cp += left; 10551541Srgrimes m2->m_len += left; 10561541Srgrimes left = 0; 10571541Srgrimes } 10581541Srgrimes } 10591541Srgrimes /* Loop around adding mbufs */ 10601541Srgrimes while (siz > 0) { 10611541Srgrimes MGET(m1, M_WAIT, MT_DATA); 10621541Srgrimes if (siz > MLEN) 10631541Srgrimes MCLGET(m1, M_WAIT); 10641541Srgrimes m1->m_len = NFSMSIZ(m1); 10651541Srgrimes m2->m_next = m1; 10661541Srgrimes m2 = m1; 10671541Srgrimes tl = mtod(m1, u_long *); 10681541Srgrimes tlen = 0; 10691541Srgrimes if (putsize) { 10701541Srgrimes *tl++ = txdr_unsigned(siz); 10711541Srgrimes m1->m_len -= NFSX_UNSIGNED; 10721541Srgrimes tlen = NFSX_UNSIGNED; 10731541Srgrimes putsize = 0; 10741541Srgrimes } 10751541Srgrimes if (siz < m1->m_len) { 10761541Srgrimes len = nfsm_rndup(siz); 10771541Srgrimes xfer = siz; 10781541Srgrimes if (xfer < len) 10791541Srgrimes *(tl+(xfer>>2)) = 0; 10801541Srgrimes } else { 10811541Srgrimes xfer = len = m1->m_len; 10821541Srgrimes } 10831541Srgrimes bcopy(cp, (caddr_t) tl, xfer); 10841541Srgrimes m1->m_len = len+tlen; 10851541Srgrimes siz -= xfer; 10861541Srgrimes cp += xfer; 10871541Srgrimes } 10881541Srgrimes *mb = m1; 10891541Srgrimes *bpos = mtod(m1, caddr_t)+m1->m_len; 10901541Srgrimes return (0); 10911541Srgrimes} 10921541Srgrimes 10931541Srgrimes/* 10941541Srgrimes * Called once to initialize data structures... 10951541Srgrimes */ 10961549Srgrimesint 10971541Srgrimesnfs_init() 10981541Srgrimes{ 10991541Srgrimes register int i; 11001541Srgrimes 11019336Sdfr /* 11029336Sdfr * Check to see if major data structures haven't bloated. 11039336Sdfr */ 11049336Sdfr if (sizeof (struct nfsnode) > NFS_NODEALLOC) { 11059336Sdfr printf("struct nfsnode bloated (> %dbytes)\n", NFS_NODEALLOC); 11069336Sdfr printf("Try reducing NFS_SMALLFH\n"); 11079336Sdfr } 11089336Sdfr if (sizeof (struct nfsmount) > NFS_MNTALLOC) { 11099336Sdfr printf("struct nfsmount bloated (> %dbytes)\n", NFS_MNTALLOC); 11109336Sdfr printf("Try reducing NFS_MUIDHASHSIZ\n"); 11119336Sdfr } 11129336Sdfr if (sizeof (struct nfssvc_sock) > NFS_SVCALLOC) { 11139336Sdfr printf("struct nfssvc_sock bloated (> %dbytes)\n",NFS_SVCALLOC); 11149336Sdfr printf("Try reducing NFS_UIDHASHSIZ\n"); 11159336Sdfr } 11169336Sdfr if (sizeof (struct nfsuid) > NFS_UIDALLOC) { 11179336Sdfr printf("struct nfsuid bloated (> %dbytes)\n",NFS_UIDALLOC); 11189336Sdfr printf("Try unionizing the nu_nickname and nu_flag fields\n"); 11199336Sdfr } 11201541Srgrimes nfsrtt.pos = 0; 11211541Srgrimes rpc_vers = txdr_unsigned(RPC_VER2); 11221541Srgrimes rpc_call = txdr_unsigned(RPC_CALL); 11231541Srgrimes rpc_reply = txdr_unsigned(RPC_REPLY); 11241541Srgrimes rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED); 11251541Srgrimes rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED); 11261541Srgrimes rpc_mismatch = txdr_unsigned(RPC_MISMATCH); 11271541Srgrimes rpc_autherr = txdr_unsigned(RPC_AUTHERR); 11281541Srgrimes rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX); 11299336Sdfr rpc_auth_kerb = txdr_unsigned(RPCAUTH_KERB4); 11301541Srgrimes nfs_prog = txdr_unsigned(NFS_PROG); 11319336Sdfr nqnfs_prog = txdr_unsigned(NQNFS_PROG); 11321541Srgrimes nfs_true = txdr_unsigned(TRUE); 11331541Srgrimes nfs_false = txdr_unsigned(FALSE); 11343664Sphk nfs_xdrneg1 = txdr_unsigned(-1); 11359336Sdfr nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000; 11369336Sdfr if (nfs_ticks < 1) 11379336Sdfr nfs_ticks = 1; 11381541Srgrimes /* Ensure async daemons disabled */ 11391541Srgrimes for (i = 0; i < NFS_MAXASYNCDAEMON; i++) 11401541Srgrimes nfs_iodwant[i] = (struct proc *)0; 11411541Srgrimes TAILQ_INIT(&nfs_bufq); 11421541Srgrimes nfs_nhinit(); /* Init the nfsnode table */ 114313416Sphk#ifndef NFS_NOSERVER 11441541Srgrimes nfsrv_init(0); /* Init server data structures */ 11451541Srgrimes nfsrv_initcache(); /* Init the server request cache */ 114613416Sphk#endif 11471541Srgrimes 11481541Srgrimes /* 11491541Srgrimes * Initialize the nqnfs server stuff. 11501541Srgrimes */ 11511541Srgrimes if (nqnfsstarttime == 0) { 11521541Srgrimes nqnfsstarttime = boottime.tv_sec + nqsrv_maxlease 11531541Srgrimes + nqsrv_clockskew + nqsrv_writeslack; 11541541Srgrimes NQLOADNOVRAM(nqnfsstarttime); 11553664Sphk CIRCLEQ_INIT(&nqtimerhead); 11563664Sphk nqfhhashtbl = hashinit(NQLCHSZ, M_NQLEASE, &nqfhhash); 11571541Srgrimes } 11581541Srgrimes 11591541Srgrimes /* 11601541Srgrimes * Initialize reply list and start timer 11611541Srgrimes */ 11623664Sphk TAILQ_INIT(&nfs_reqq); 116316365Sphk 11643305Sphk nfs_timer(0); 11651549Srgrimes 116616365Sphk 11679336Sdfr#ifdef __FreeBSD__ 11682997Swollman /* 11692997Swollman * Set up lease_check and lease_updatetime so that other parts 11702997Swollman * of the system can call us, if we are loadable. 11712997Swollman */ 117213416Sphk#ifndef NFS_NOSERVER 11732997Swollman lease_check = nfs_lease_check; 117413416Sphk#endif 11752997Swollman lease_updatetime = nfs_lease_updatetime; 11762997Swollman vfsconf[MOUNT_NFS]->vfc_refcount++; /* make us non-unloadable */ 11772997Swollman#ifdef VFS_LKM 11782997Swollman sysent[SYS_nfssvc].sy_narg = 2; 11792997Swollman sysent[SYS_nfssvc].sy_call = nfssvc; 118013416Sphk#ifndef NFS_NOSERVER 11812997Swollman sysent[SYS_getfh].sy_narg = 2; 11822997Swollman sysent[SYS_getfh].sy_call = getfh; 11832997Swollman#endif 11849336Sdfr#endif 118513416Sphk#endif 11862997Swollman 11871549Srgrimes return (0); 11881541Srgrimes} 11891541Srgrimes 11901541Srgrimes/* 11911541Srgrimes * Attribute cache routines. 11921541Srgrimes * nfs_loadattrcache() - loads or updates the cache contents from attributes 11931541Srgrimes * that are on the mbuf list 11941541Srgrimes * nfs_getattrcache() - returns valid attributes if found in cache, returns 11951541Srgrimes * error otherwise 11961541Srgrimes */ 11971541Srgrimes 11981541Srgrimes/* 11991541Srgrimes * Load the attribute cache (that lives in the nfsnode entry) with 12001541Srgrimes * the values on the mbuf list and 12011541Srgrimes * Iff vap not NULL 12021541Srgrimes * copy the attributes to *vaper 12031541Srgrimes */ 12041549Srgrimesint 12051541Srgrimesnfs_loadattrcache(vpp, mdp, dposp, vaper) 12061541Srgrimes struct vnode **vpp; 12071541Srgrimes struct mbuf **mdp; 12081541Srgrimes caddr_t *dposp; 12091541Srgrimes struct vattr *vaper; 12101541Srgrimes{ 12111541Srgrimes register struct vnode *vp = *vpp; 12121541Srgrimes register struct vattr *vap; 12139336Sdfr register struct nfs_fattr *fp; 12143664Sphk register struct nfsnode *np; 12153664Sphk register struct nfsnodehashhead *nhpp; 12161541Srgrimes register long t1; 12179336Sdfr caddr_t cp2; 12189336Sdfr int error = 0, rdev; 12191541Srgrimes struct mbuf *md; 12201541Srgrimes enum vtype vtyp; 12211541Srgrimes u_short vmode; 12221541Srgrimes struct timespec mtime; 12231541Srgrimes struct vnode *nvp; 12249336Sdfr int v3 = NFS_ISV3(vp); 12251541Srgrimes 12261541Srgrimes md = *mdp; 12279336Sdfr t1 = (mtod(md, caddr_t) + md->m_len) - *dposp; 12289336Sdfr if (error = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, &cp2)) 12291541Srgrimes return (error); 12309336Sdfr fp = (struct nfs_fattr *)cp2; 12319336Sdfr if (v3) { 12329336Sdfr vtyp = nfsv3tov_type(fp->fa_type); 12339336Sdfr vmode = fxdr_unsigned(u_short, fp->fa_mode); 123416634Sbde rdev = makedev(fxdr_unsigned(int, fp->fa3_rdev.specdata1), 123516634Sbde fxdr_unsigned(int, fp->fa3_rdev.specdata2)); 12369336Sdfr fxdr_nfsv3time(&fp->fa3_mtime, &mtime); 12371541Srgrimes } else { 12389336Sdfr vtyp = nfsv2tov_type(fp->fa_type); 12399336Sdfr vmode = fxdr_unsigned(u_short, fp->fa_mode); 12409336Sdfr /* 12419336Sdfr * XXX 12429336Sdfr * 12439336Sdfr * The duplicate information returned in fa_type and fa_mode 12449336Sdfr * is an ambiguity in the NFS version 2 protocol. 12459336Sdfr * 12469336Sdfr * VREG should be taken literally as a regular file. If a 12479336Sdfr * server intents to return some type information differently 12489336Sdfr * in the upper bits of the mode field (e.g. for sockets, or 12499336Sdfr * FIFOs), NFSv2 mandates fa_type to be VNON. Anyway, we 12509336Sdfr * leave the examination of the mode bits even in the VREG 12519336Sdfr * case to avoid breakage for bogus servers, but we make sure 12529336Sdfr * that there are actually type bits set in the upper part of 12539336Sdfr * fa_mode (and failing that, trust the va_type field). 12549336Sdfr * 12559336Sdfr * NFSv3 cleared the issue, and requires fa_mode to not 12569336Sdfr * contain any type information (while also introduing sockets 12579336Sdfr * and FIFOs for fa_type). 12589336Sdfr */ 12599336Sdfr if (vtyp == VNON || (vtyp == VREG && (vmode & S_IFMT) != 0)) 12609336Sdfr vtyp = IFTOVT(vmode); 12619336Sdfr rdev = fxdr_unsigned(long, fp->fa2_rdev); 12629336Sdfr fxdr_nfsv2time(&fp->fa2_mtime, &mtime); 12639336Sdfr 12649336Sdfr /* 12659336Sdfr * Really ugly NFSv2 kludge. 12669336Sdfr */ 12679336Sdfr if (vtyp == VCHR && rdev == 0xffffffff) 12689336Sdfr vtyp = VFIFO; 12691541Srgrimes } 12709336Sdfr 12711541Srgrimes /* 12721541Srgrimes * If v_type == VNON it is a new node, so fill in the v_type, 12738876Srgrimes * n_mtime fields. Check to see if it represents a special 12741541Srgrimes * device, and if so, check for a possible alias. Once the 12751541Srgrimes * correct vnode has been obtained, fill in the rest of the 12761541Srgrimes * information. 12771541Srgrimes */ 12781541Srgrimes np = VTONFS(vp); 127910219Sdfr if (vp->v_type != vtyp) { 12809336Sdfr /* 12819336Sdfr * If we had a lock and it turns out that the vnode 12829336Sdfr * is an object which we don't want to lock (e.g. VDIR) 12839336Sdfr * to avoid nasty hanging problems on a server crash, 12849336Sdfr * then release it here. 12859336Sdfr */ 12869336Sdfr if (vtyp != VREG && VOP_ISLOCKED(vp)) 12879336Sdfr VOP_UNLOCK(vp); 12889336Sdfr vp->v_type = vtyp; 12891541Srgrimes if (vp->v_type == VFIFO) { 12901541Srgrimes vp->v_op = fifo_nfsv2nodeop_p; 12911541Srgrimes } 12921541Srgrimes if (vp->v_type == VCHR || vp->v_type == VBLK) { 12931541Srgrimes vp->v_op = spec_nfsv2nodeop_p; 12943305Sphk nvp = checkalias(vp, (dev_t)rdev, vp->v_mount); 12953305Sphk if (nvp) { 12961541Srgrimes /* 12971541Srgrimes * Discard unneeded vnode, but save its nfsnode. 12981541Srgrimes */ 12993664Sphk LIST_REMOVE(np, n_hash); 13001541Srgrimes nvp->v_data = vp->v_data; 13011541Srgrimes vp->v_data = NULL; 13021541Srgrimes vp->v_op = spec_vnodeop_p; 13031541Srgrimes vrele(vp); 13041541Srgrimes vgone(vp); 13051541Srgrimes /* 13061541Srgrimes * Reinitialize aliased node. 13071541Srgrimes */ 13081541Srgrimes np->n_vnode = nvp; 13099336Sdfr nhpp = NFSNOHASH(nfs_hash(np->n_fhp, np->n_fhsize)); 13103664Sphk LIST_INSERT_HEAD(nhpp, np, n_hash); 13111541Srgrimes *vpp = vp = nvp; 13121541Srgrimes } 13131541Srgrimes } 13141541Srgrimes np->n_mtime = mtime.ts_sec; 13151541Srgrimes } 13161541Srgrimes vap = &np->n_vattr; 13171541Srgrimes vap->va_type = vtyp; 13181541Srgrimes vap->va_mode = (vmode & 07777); 13191541Srgrimes vap->va_rdev = (dev_t)rdev; 13201541Srgrimes vap->va_mtime = mtime; 13211541Srgrimes vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 13229336Sdfr if (v3) { 13239336Sdfr vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink); 13249336Sdfr vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid); 13259336Sdfr vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid); 13269336Sdfr fxdr_hyper(&fp->fa3_size, &vap->va_size); 13279336Sdfr vap->va_blocksize = NFS_FABLKSIZE; 13289336Sdfr fxdr_hyper(&fp->fa3_used, &vap->va_bytes); 13299336Sdfr vap->va_fileid = fxdr_unsigned(int, fp->fa3_fileid.nfsuquad[1]); 13309336Sdfr fxdr_nfsv3time(&fp->fa3_atime, &vap->va_atime); 13319336Sdfr fxdr_nfsv3time(&fp->fa3_ctime, &vap->va_ctime); 13329336Sdfr vap->va_flags = 0; 13339336Sdfr vap->va_filerev = 0; 13341541Srgrimes } else { 13359336Sdfr vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink); 13369336Sdfr vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid); 13379336Sdfr vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid); 13389336Sdfr vap->va_size = fxdr_unsigned(u_long, fp->fa2_size); 13399336Sdfr vap->va_blocksize = fxdr_unsigned(long, fp->fa2_blocksize); 13409336Sdfr vap->va_bytes = fxdr_unsigned(long, fp->fa2_blocks) * NFS_FABLKSIZE; 13419336Sdfr vap->va_fileid = fxdr_unsigned(long, fp->fa2_fileid); 13429336Sdfr fxdr_nfsv2time(&fp->fa2_atime, &vap->va_atime); 13431541Srgrimes vap->va_flags = 0; 13449336Sdfr vap->va_ctime.ts_sec = fxdr_unsigned(long, fp->fa2_ctime.nfsv2_sec); 13459336Sdfr vap->va_ctime.ts_nsec = 0; 13469336Sdfr vap->va_gen = fxdr_unsigned(u_long, fp->fa2_ctime.nfsv2_usec); 13471541Srgrimes vap->va_filerev = 0; 13481541Srgrimes } 13491541Srgrimes if (vap->va_size != np->n_size) { 13501541Srgrimes if (vap->va_type == VREG) { 13511541Srgrimes if (np->n_flag & NMODIFIED) { 13521541Srgrimes if (vap->va_size < np->n_size) 13531541Srgrimes vap->va_size = np->n_size; 13541541Srgrimes else 13551541Srgrimes np->n_size = vap->va_size; 13561541Srgrimes } else 13571541Srgrimes np->n_size = vap->va_size; 13581541Srgrimes vnode_pager_setsize(vp, (u_long)np->n_size); 13591541Srgrimes } else 13601541Srgrimes np->n_size = vap->va_size; 13611541Srgrimes } 13621541Srgrimes np->n_attrstamp = time.tv_sec; 13631541Srgrimes if (vaper != NULL) { 13641541Srgrimes bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap)); 13651541Srgrimes if (np->n_flag & NCHG) { 13669336Sdfr if (np->n_flag & NACC) 13679336Sdfr vaper->va_atime = np->n_atim; 13689336Sdfr if (np->n_flag & NUPD) 13699336Sdfr vaper->va_mtime = np->n_mtim; 13701541Srgrimes } 13711541Srgrimes } 13721541Srgrimes return (0); 13731541Srgrimes} 13741541Srgrimes 13751541Srgrimes/* 13761541Srgrimes * Check the time stamp 13771541Srgrimes * If the cache is valid, copy contents to *vap and return 0 13781541Srgrimes * otherwise return an error 13791541Srgrimes */ 13801549Srgrimesint 13811541Srgrimesnfs_getattrcache(vp, vaper) 13821541Srgrimes register struct vnode *vp; 13831541Srgrimes struct vattr *vaper; 13841541Srgrimes{ 13851541Srgrimes register struct nfsnode *np = VTONFS(vp); 13861541Srgrimes register struct vattr *vap; 13871541Srgrimes 13889336Sdfr if ((time.tv_sec - np->n_attrstamp) >= NFS_ATTRTIMEO(np)) { 13891541Srgrimes nfsstats.attrcache_misses++; 13901541Srgrimes return (ENOENT); 13911541Srgrimes } 13921541Srgrimes nfsstats.attrcache_hits++; 13931541Srgrimes vap = &np->n_vattr; 13941541Srgrimes if (vap->va_size != np->n_size) { 13951541Srgrimes if (vap->va_type == VREG) { 13961541Srgrimes if (np->n_flag & NMODIFIED) { 13971541Srgrimes if (vap->va_size < np->n_size) 13981541Srgrimes vap->va_size = np->n_size; 13991541Srgrimes else 14001541Srgrimes np->n_size = vap->va_size; 14011541Srgrimes } else 14021541Srgrimes np->n_size = vap->va_size; 14031541Srgrimes vnode_pager_setsize(vp, (u_long)np->n_size); 14041541Srgrimes } else 14051541Srgrimes np->n_size = vap->va_size; 14061541Srgrimes } 14071541Srgrimes bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(struct vattr)); 14081541Srgrimes if (np->n_flag & NCHG) { 14099336Sdfr if (np->n_flag & NACC) 14109336Sdfr vaper->va_atime = np->n_atim; 14119336Sdfr if (np->n_flag & NUPD) 14129336Sdfr vaper->va_mtime = np->n_mtim; 14131541Srgrimes } 14141541Srgrimes return (0); 14151541Srgrimes} 14161541Srgrimes 141713416Sphk#ifndef NFS_NOSERVER 14181541Srgrimes/* 14191541Srgrimes * Set up nameidata for a lookup() call and do it 14201541Srgrimes */ 14211549Srgrimesint 14229336Sdfrnfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag) 14231541Srgrimes register struct nameidata *ndp; 14241541Srgrimes fhandle_t *fhp; 14251541Srgrimes int len; 14261541Srgrimes struct nfssvc_sock *slp; 14271541Srgrimes struct mbuf *nam; 14281541Srgrimes struct mbuf **mdp; 14291541Srgrimes caddr_t *dposp; 14309336Sdfr struct vnode **retdirp; 14311541Srgrimes struct proc *p; 14329336Sdfr int kerbflag; 14331541Srgrimes{ 14341541Srgrimes register int i, rem; 14351541Srgrimes register struct mbuf *md; 14361541Srgrimes register char *fromcp, *tocp; 14371541Srgrimes struct vnode *dp; 14381541Srgrimes int error, rdonly; 14391541Srgrimes struct componentname *cnp = &ndp->ni_cnd; 14401541Srgrimes 14419336Sdfr *retdirp = (struct vnode *)0; 14421541Srgrimes MALLOC(cnp->cn_pnbuf, char *, len + 1, M_NAMEI, M_WAITOK); 14431541Srgrimes /* 14441541Srgrimes * Copy the name from the mbuf list to ndp->ni_pnbuf 14451541Srgrimes * and set the various ndp fields appropriately. 14461541Srgrimes */ 14471541Srgrimes fromcp = *dposp; 14481541Srgrimes tocp = cnp->cn_pnbuf; 14491541Srgrimes md = *mdp; 14501541Srgrimes rem = mtod(md, caddr_t) + md->m_len - fromcp; 14511541Srgrimes cnp->cn_hash = 0; 14521541Srgrimes for (i = 0; i < len; i++) { 14531541Srgrimes while (rem == 0) { 14541541Srgrimes md = md->m_next; 14551541Srgrimes if (md == NULL) { 14561541Srgrimes error = EBADRPC; 14571541Srgrimes goto out; 14581541Srgrimes } 14591541Srgrimes fromcp = mtod(md, caddr_t); 14601541Srgrimes rem = md->m_len; 14611541Srgrimes } 14621541Srgrimes if (*fromcp == '\0' || *fromcp == '/') { 14639336Sdfr error = EACCES; 14641541Srgrimes goto out; 14651541Srgrimes } 14661541Srgrimes cnp->cn_hash += (unsigned char)*fromcp; 14671541Srgrimes *tocp++ = *fromcp++; 14681541Srgrimes rem--; 14691541Srgrimes } 14701541Srgrimes *tocp = '\0'; 14711541Srgrimes *mdp = md; 14721541Srgrimes *dposp = fromcp; 14731541Srgrimes len = nfsm_rndup(len)-len; 14741541Srgrimes if (len > 0) { 14751541Srgrimes if (rem >= len) 14761541Srgrimes *dposp += len; 14779336Sdfr else if (error = nfs_adv(mdp, dposp, len, rem)) 14789336Sdfr goto out; 14791541Srgrimes } 14801541Srgrimes ndp->ni_pathlen = tocp - cnp->cn_pnbuf; 14811541Srgrimes cnp->cn_nameptr = cnp->cn_pnbuf; 14821541Srgrimes /* 14831541Srgrimes * Extract and set starting directory. 14841541Srgrimes */ 14859336Sdfr if (error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp, 14869336Sdfr nam, &rdonly, kerbflag)) 14871541Srgrimes goto out; 14881541Srgrimes if (dp->v_type != VDIR) { 14896417Sdg nfsrv_vrele(dp); 14901541Srgrimes error = ENOTDIR; 14911541Srgrimes goto out; 14921541Srgrimes } 14939336Sdfr VREF(dp); 14949336Sdfr *retdirp = dp; 14951541Srgrimes ndp->ni_startdir = dp; 14961541Srgrimes if (rdonly) 14971541Srgrimes cnp->cn_flags |= (NOCROSSMOUNT | RDONLY); 14981541Srgrimes else 14991541Srgrimes cnp->cn_flags |= NOCROSSMOUNT; 15001541Srgrimes /* 15011541Srgrimes * And call lookup() to do the real work 15021541Srgrimes */ 15031541Srgrimes cnp->cn_proc = p; 15049336Sdfr if (error = lookup(ndp)) 15051541Srgrimes goto out; 15061541Srgrimes /* 15071541Srgrimes * Check for encountering a symbolic link 15081541Srgrimes */ 15091541Srgrimes if (cnp->cn_flags & ISSYMLINK) { 15101541Srgrimes if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1) 15111541Srgrimes vput(ndp->ni_dvp); 15121541Srgrimes else 15131541Srgrimes vrele(ndp->ni_dvp); 15141541Srgrimes vput(ndp->ni_vp); 15151541Srgrimes ndp->ni_vp = NULL; 15161541Srgrimes error = EINVAL; 15171541Srgrimes goto out; 15181541Srgrimes } 15198832Sdg 15208832Sdg nfsrv_vmio(ndp->ni_vp); 15218832Sdg 15221541Srgrimes /* 15231541Srgrimes * Check for saved name request 15241541Srgrimes */ 15251541Srgrimes if (cnp->cn_flags & (SAVENAME | SAVESTART)) { 15261541Srgrimes cnp->cn_flags |= HASBUF; 15271541Srgrimes return (0); 15281541Srgrimes } 15291541Srgrimesout: 15301541Srgrimes FREE(cnp->cn_pnbuf, M_NAMEI); 15311541Srgrimes return (error); 15321541Srgrimes} 15331541Srgrimes 15341541Srgrimes/* 15351541Srgrimes * A fiddled version of m_adj() that ensures null fill to a long 15361541Srgrimes * boundary and only trims off the back end 15371541Srgrimes */ 15381541Srgrimesvoid 15391541Srgrimesnfsm_adj(mp, len, nul) 15401541Srgrimes struct mbuf *mp; 15411541Srgrimes register int len; 15421541Srgrimes int nul; 15431541Srgrimes{ 15441541Srgrimes register struct mbuf *m; 15451541Srgrimes register int count, i; 15461541Srgrimes register char *cp; 15471541Srgrimes 15481541Srgrimes /* 15491541Srgrimes * Trim from tail. Scan the mbuf chain, 15501541Srgrimes * calculating its length and finding the last mbuf. 15511541Srgrimes * If the adjustment only affects this mbuf, then just 15521541Srgrimes * adjust and return. Otherwise, rescan and truncate 15531541Srgrimes * after the remaining size. 15541541Srgrimes */ 15551541Srgrimes count = 0; 15561541Srgrimes m = mp; 15571541Srgrimes for (;;) { 15581541Srgrimes count += m->m_len; 15591541Srgrimes if (m->m_next == (struct mbuf *)0) 15601541Srgrimes break; 15611541Srgrimes m = m->m_next; 15621541Srgrimes } 15631541Srgrimes if (m->m_len > len) { 15641541Srgrimes m->m_len -= len; 15651541Srgrimes if (nul > 0) { 15661541Srgrimes cp = mtod(m, caddr_t)+m->m_len-nul; 15671541Srgrimes for (i = 0; i < nul; i++) 15681541Srgrimes *cp++ = '\0'; 15691541Srgrimes } 15701541Srgrimes return; 15711541Srgrimes } 15721541Srgrimes count -= len; 15731541Srgrimes if (count < 0) 15741541Srgrimes count = 0; 15751541Srgrimes /* 15761541Srgrimes * Correct length for chain is "count". 15771541Srgrimes * Find the mbuf with last data, adjust its length, 15781541Srgrimes * and toss data from remaining mbufs on chain. 15791541Srgrimes */ 15801541Srgrimes for (m = mp; m; m = m->m_next) { 15811541Srgrimes if (m->m_len >= count) { 15821541Srgrimes m->m_len = count; 15831541Srgrimes if (nul > 0) { 15841541Srgrimes cp = mtod(m, caddr_t)+m->m_len-nul; 15851541Srgrimes for (i = 0; i < nul; i++) 15861541Srgrimes *cp++ = '\0'; 15871541Srgrimes } 15881541Srgrimes break; 15891541Srgrimes } 15901541Srgrimes count -= m->m_len; 15911541Srgrimes } 15923305Sphk for (m = m->m_next;m;m = m->m_next) 15931541Srgrimes m->m_len = 0; 15941541Srgrimes} 15951541Srgrimes 15961541Srgrimes/* 15979336Sdfr * Make these functions instead of macros, so that the kernel text size 15989336Sdfr * doesn't get too big... 15999336Sdfr */ 16009336Sdfrvoid 16019336Sdfrnfsm_srvwcc(nfsd, before_ret, before_vap, after_ret, after_vap, mbp, bposp) 16029336Sdfr struct nfsrv_descript *nfsd; 16039336Sdfr int before_ret; 16049336Sdfr register struct vattr *before_vap; 16059336Sdfr int after_ret; 16069336Sdfr struct vattr *after_vap; 16079336Sdfr struct mbuf **mbp; 16089336Sdfr char **bposp; 16099336Sdfr{ 16109336Sdfr register struct mbuf *mb = *mbp, *mb2; 16119336Sdfr register char *bpos = *bposp; 16129336Sdfr register u_long *tl; 16139336Sdfr 16149336Sdfr if (before_ret) { 16159336Sdfr nfsm_build(tl, u_long *, NFSX_UNSIGNED); 16169336Sdfr *tl = nfs_false; 16179336Sdfr } else { 16189336Sdfr nfsm_build(tl, u_long *, 7 * NFSX_UNSIGNED); 16199336Sdfr *tl++ = nfs_true; 16209336Sdfr txdr_hyper(&(before_vap->va_size), tl); 16219336Sdfr tl += 2; 16229336Sdfr txdr_nfsv3time(&(before_vap->va_mtime), tl); 16239336Sdfr tl += 2; 16249336Sdfr txdr_nfsv3time(&(before_vap->va_ctime), tl); 16259336Sdfr } 16269336Sdfr *bposp = bpos; 16279336Sdfr *mbp = mb; 16289336Sdfr nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp); 16299336Sdfr} 16309336Sdfr 16319336Sdfrvoid 16329336Sdfrnfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp) 16339336Sdfr struct nfsrv_descript *nfsd; 16349336Sdfr int after_ret; 16359336Sdfr struct vattr *after_vap; 16369336Sdfr struct mbuf **mbp; 16379336Sdfr char **bposp; 16389336Sdfr{ 16399336Sdfr register struct mbuf *mb = *mbp, *mb2; 16409336Sdfr register char *bpos = *bposp; 16419336Sdfr register u_long *tl; 16429336Sdfr register struct nfs_fattr *fp; 16439336Sdfr 16449336Sdfr if (after_ret) { 16459336Sdfr nfsm_build(tl, u_long *, NFSX_UNSIGNED); 16469336Sdfr *tl = nfs_false; 16479336Sdfr } else { 16489336Sdfr nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3FATTR); 16499336Sdfr *tl++ = nfs_true; 16509336Sdfr fp = (struct nfs_fattr *)tl; 16519336Sdfr nfsm_srvfattr(nfsd, after_vap, fp); 16529336Sdfr } 16539336Sdfr *mbp = mb; 16549336Sdfr *bposp = bpos; 16559336Sdfr} 16569336Sdfr 16579336Sdfrvoid 16589336Sdfrnfsm_srvfattr(nfsd, vap, fp) 16599336Sdfr register struct nfsrv_descript *nfsd; 16609336Sdfr register struct vattr *vap; 16619336Sdfr register struct nfs_fattr *fp; 16629336Sdfr{ 16639336Sdfr 16649336Sdfr fp->fa_nlink = txdr_unsigned(vap->va_nlink); 16659336Sdfr fp->fa_uid = txdr_unsigned(vap->va_uid); 16669336Sdfr fp->fa_gid = txdr_unsigned(vap->va_gid); 16679336Sdfr if (nfsd->nd_flag & ND_NFSV3) { 16689336Sdfr fp->fa_type = vtonfsv3_type(vap->va_type); 16699336Sdfr fp->fa_mode = vtonfsv3_mode(vap->va_mode); 16709336Sdfr txdr_hyper(&vap->va_size, &fp->fa3_size); 16719336Sdfr txdr_hyper(&vap->va_bytes, &fp->fa3_used); 16729336Sdfr fp->fa3_rdev.specdata1 = txdr_unsigned(major(vap->va_rdev)); 16739336Sdfr fp->fa3_rdev.specdata2 = txdr_unsigned(minor(vap->va_rdev)); 16749336Sdfr fp->fa3_fsid.nfsuquad[0] = 0; 16759336Sdfr fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid); 16769336Sdfr fp->fa3_fileid.nfsuquad[0] = 0; 16779336Sdfr fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(vap->va_fileid); 16789336Sdfr txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime); 16799336Sdfr txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime); 16809336Sdfr txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime); 16819336Sdfr } else { 16829336Sdfr fp->fa_type = vtonfsv2_type(vap->va_type); 16839336Sdfr fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 16849336Sdfr fp->fa2_size = txdr_unsigned(vap->va_size); 16859336Sdfr fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize); 16869336Sdfr if (vap->va_type == VFIFO) 16879336Sdfr fp->fa2_rdev = 0xffffffff; 16889336Sdfr else 16899336Sdfr fp->fa2_rdev = txdr_unsigned(vap->va_rdev); 16909336Sdfr fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE); 16919336Sdfr fp->fa2_fsid = txdr_unsigned(vap->va_fsid); 16929336Sdfr fp->fa2_fileid = txdr_unsigned(vap->va_fileid); 16939336Sdfr txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime); 16949336Sdfr txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime); 16959336Sdfr txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime); 16969336Sdfr } 16979336Sdfr} 16989336Sdfr 16999336Sdfr/* 17001541Srgrimes * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked) 17011541Srgrimes * - look up fsid in mount list (if not found ret error) 17021541Srgrimes * - get vp and export rights by calling VFS_FHTOVP() 17031541Srgrimes * - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon 17041541Srgrimes * - if not lockflag unlock it with VOP_UNLOCK() 17051541Srgrimes */ 17061549Srgrimesint 17079336Sdfrnfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag) 17081541Srgrimes fhandle_t *fhp; 17091541Srgrimes int lockflag; 17101541Srgrimes struct vnode **vpp; 17111541Srgrimes struct ucred *cred; 17121541Srgrimes struct nfssvc_sock *slp; 17131541Srgrimes struct mbuf *nam; 17141541Srgrimes int *rdonlyp; 17159336Sdfr int kerbflag; 17161541Srgrimes{ 17171541Srgrimes register struct mount *mp; 17181541Srgrimes register int i; 17191541Srgrimes struct ucred *credanon; 17201541Srgrimes int error, exflags; 17211541Srgrimes 17221541Srgrimes *vpp = (struct vnode *)0; 17233305Sphk mp = getvfs(&fhp->fh_fsid); 17243305Sphk if (!mp) 17251541Srgrimes return (ESTALE); 17263305Sphk error = VFS_FHTOVP(mp, &fhp->fh_fid, nam, vpp, &exflags, &credanon); 17273305Sphk if (error) 17281541Srgrimes return (error); 17291541Srgrimes /* 17301541Srgrimes * Check/setup credentials. 17311541Srgrimes */ 17321541Srgrimes if (exflags & MNT_EXKERB) { 17339336Sdfr if (!kerbflag) { 17341541Srgrimes vput(*vpp); 17359336Sdfr return (NFSERR_AUTHERR | AUTH_TOOWEAK); 17361541Srgrimes } 17379336Sdfr } else if (kerbflag) { 17389336Sdfr vput(*vpp); 17399336Sdfr return (NFSERR_AUTHERR | AUTH_TOOWEAK); 17401541Srgrimes } else if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) { 17411541Srgrimes cred->cr_uid = credanon->cr_uid; 17421541Srgrimes for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++) 17431541Srgrimes cred->cr_groups[i] = credanon->cr_groups[i]; 17443664Sphk cred->cr_ngroups = i; 17451541Srgrimes } 17461541Srgrimes if (exflags & MNT_EXRDONLY) 17471541Srgrimes *rdonlyp = 1; 17481541Srgrimes else 17491541Srgrimes *rdonlyp = 0; 17507969Sdyson 17517969Sdyson nfsrv_vmio(*vpp); 17527969Sdyson 17531541Srgrimes if (!lockflag) 17541541Srgrimes VOP_UNLOCK(*vpp); 17551541Srgrimes return (0); 17561541Srgrimes} 17571541Srgrimes 175813416Sphk#endif /* NFS_NOSERVER */ 17591541Srgrimes/* 17601541Srgrimes * This function compares two net addresses by family and returns TRUE 17611541Srgrimes * if they are the same host. 17621541Srgrimes * If there is any doubt, return FALSE. 17631541Srgrimes * The AF_INET family is handled as a special case so that address mbufs 17641541Srgrimes * don't need to be saved to store "struct in_addr", which is only 4 bytes. 17651541Srgrimes */ 17661549Srgrimesint 17671541Srgrimesnetaddr_match(family, haddr, nam) 17681541Srgrimes int family; 17691541Srgrimes union nethostaddr *haddr; 17701541Srgrimes struct mbuf *nam; 17711541Srgrimes{ 17721541Srgrimes register struct sockaddr_in *inetaddr; 17731541Srgrimes 17741541Srgrimes switch (family) { 17751541Srgrimes case AF_INET: 17761541Srgrimes inetaddr = mtod(nam, struct sockaddr_in *); 17771541Srgrimes if (inetaddr->sin_family == AF_INET && 17781541Srgrimes inetaddr->sin_addr.s_addr == haddr->had_inetaddr) 17791541Srgrimes return (1); 17801541Srgrimes break; 17811541Srgrimes#ifdef ISO 17821541Srgrimes case AF_ISO: 17831541Srgrimes { 17841541Srgrimes register struct sockaddr_iso *isoaddr1, *isoaddr2; 17851541Srgrimes 17861541Srgrimes isoaddr1 = mtod(nam, struct sockaddr_iso *); 17871541Srgrimes isoaddr2 = mtod(haddr->had_nam, struct sockaddr_iso *); 17881541Srgrimes if (isoaddr1->siso_family == AF_ISO && 17891541Srgrimes isoaddr1->siso_nlen > 0 && 17901541Srgrimes isoaddr1->siso_nlen == isoaddr2->siso_nlen && 17911541Srgrimes SAME_ISOADDR(isoaddr1, isoaddr2)) 17921541Srgrimes return (1); 17931541Srgrimes break; 17941541Srgrimes } 17951541Srgrimes#endif /* ISO */ 17961541Srgrimes default: 17971541Srgrimes break; 17981541Srgrimes }; 17991541Srgrimes return (0); 18001541Srgrimes} 18015455Sdg 18029336Sdfrstatic nfsuint64 nfs_nullcookie = { 0, 0 }; 18039336Sdfr/* 18049336Sdfr * This function finds the directory cookie that corresponds to the 18059336Sdfr * logical byte offset given. 18069336Sdfr */ 18079336Sdfrnfsuint64 * 18089336Sdfrnfs_getcookie(np, off, add) 18099336Sdfr register struct nfsnode *np; 18109336Sdfr off_t off; 18119336Sdfr int add; 18129336Sdfr{ 18139336Sdfr register struct nfsdmap *dp, *dp2; 18149336Sdfr register int pos; 18159336Sdfr 18169336Sdfr pos = off / NFS_DIRBLKSIZ; 18179336Sdfr if (pos == 0) { 18189336Sdfr#ifdef DIAGNOSTIC 18199336Sdfr if (add) 18209336Sdfr panic("nfs getcookie add at 0"); 18219336Sdfr#endif 18229336Sdfr return (&nfs_nullcookie); 18239336Sdfr } 18249336Sdfr pos--; 18259336Sdfr dp = np->n_cookies.lh_first; 18269336Sdfr if (!dp) { 18279336Sdfr if (add) { 18289336Sdfr MALLOC(dp, struct nfsdmap *, sizeof (struct nfsdmap), 18299336Sdfr M_NFSDIROFF, M_WAITOK); 18309336Sdfr dp->ndm_eocookie = 0; 18319336Sdfr LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list); 18329336Sdfr } else 18339336Sdfr return ((nfsuint64 *)0); 18349336Sdfr } 18359336Sdfr while (pos >= NFSNUMCOOKIES) { 18369336Sdfr pos -= NFSNUMCOOKIES; 18379336Sdfr if (dp->ndm_list.le_next) { 18389336Sdfr if (!add && dp->ndm_eocookie < NFSNUMCOOKIES && 18399336Sdfr pos >= dp->ndm_eocookie) 18409336Sdfr return ((nfsuint64 *)0); 18419336Sdfr dp = dp->ndm_list.le_next; 18429336Sdfr } else if (add) { 18439336Sdfr MALLOC(dp2, struct nfsdmap *, sizeof (struct nfsdmap), 18449336Sdfr M_NFSDIROFF, M_WAITOK); 18459336Sdfr dp2->ndm_eocookie = 0; 18469336Sdfr LIST_INSERT_AFTER(dp, dp2, ndm_list); 18479336Sdfr dp = dp2; 18489336Sdfr } else 18499336Sdfr return ((nfsuint64 *)0); 18509336Sdfr } 18519336Sdfr if (pos >= dp->ndm_eocookie) { 18529336Sdfr if (add) 18539336Sdfr dp->ndm_eocookie = pos + 1; 18549336Sdfr else 18559336Sdfr return ((nfsuint64 *)0); 18569336Sdfr } 18579336Sdfr return (&dp->ndm_cookies[pos]); 18589336Sdfr} 18599336Sdfr 18609336Sdfr/* 18619336Sdfr * Invalidate cached directory information, except for the actual directory 18629336Sdfr * blocks (which are invalidated separately). 18639336Sdfr * Done mainly to avoid the use of stale offset cookies. 18649336Sdfr */ 18659336Sdfrvoid 18669336Sdfrnfs_invaldir(vp) 18679336Sdfr register struct vnode *vp; 18689336Sdfr{ 18699336Sdfr register struct nfsnode *np = VTONFS(vp); 18709336Sdfr 18719336Sdfr#ifdef DIAGNOSTIC 18729336Sdfr if (vp->v_type != VDIR) 18739336Sdfr panic("nfs: invaldir not dir"); 18749336Sdfr#endif 18759336Sdfr np->n_direofoffset = 0; 18769336Sdfr np->n_cookieverf.nfsuquad[0] = 0; 18779336Sdfr np->n_cookieverf.nfsuquad[1] = 0; 18789336Sdfr if (np->n_cookies.lh_first) 18799336Sdfr np->n_cookies.lh_first->ndm_eocookie = 0; 18809336Sdfr} 18819336Sdfr 18829336Sdfr/* 18839336Sdfr * The write verifier has changed (probably due to a server reboot), so all 18849336Sdfr * B_NEEDCOMMIT blocks will have to be written again. Since they are on the 18859336Sdfr * dirty block list as B_DELWRI, all this takes is clearing the B_NEEDCOMMIT 18869336Sdfr * flag. Once done the new write verifier can be set for the mount point. 18879336Sdfr */ 18889336Sdfrvoid 18899336Sdfrnfs_clearcommit(mp) 18909336Sdfr struct mount *mp; 18919336Sdfr{ 18929336Sdfr register struct vnode *vp, *nvp; 18939336Sdfr register struct buf *bp, *nbp; 18949336Sdfr int s; 18959336Sdfr 18969336Sdfr s = splbio(); 18979336Sdfrloop: 18989336Sdfr for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) { 18999336Sdfr if (vp->v_mount != mp) /* Paranoia */ 19009336Sdfr goto loop; 19019336Sdfr nvp = vp->v_mntvnodes.le_next; 19029336Sdfr for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 19039336Sdfr nbp = bp->b_vnbufs.le_next; 19049336Sdfr if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT)) 19059336Sdfr == (B_DELWRI | B_NEEDCOMMIT)) 19069336Sdfr bp->b_flags &= ~B_NEEDCOMMIT; 19079336Sdfr } 19089336Sdfr } 19099336Sdfr splx(s); 19109336Sdfr} 19119336Sdfr 191213416Sphk#ifndef NFS_NOSERVER 19139336Sdfr/* 19149336Sdfr * Map errnos to NFS error numbers. For Version 3 also filter out error 19159336Sdfr * numbers not specified for the associated procedure. 19169336Sdfr */ 19175455Sdgint 19189336Sdfrnfsrv_errmap(nd, err) 19199336Sdfr struct nfsrv_descript *nd; 19209336Sdfr register int err; 19219336Sdfr{ 19229336Sdfr register short *defaulterrp, *errp; 19239336Sdfr 19249336Sdfr if (nd->nd_flag & ND_NFSV3) { 19259336Sdfr if (nd->nd_procnum <= NFSPROC_COMMIT) { 19269336Sdfr errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum]; 19279336Sdfr while (*++errp) { 19289336Sdfr if (*errp == err) 19299336Sdfr return (err); 19309336Sdfr else if (*errp > err) 19319336Sdfr break; 19329336Sdfr } 19339336Sdfr return ((int)*defaulterrp); 19349336Sdfr } else 19359336Sdfr return (err & 0xffff); 19369336Sdfr } 19379336Sdfr if (err <= ELAST) 19389336Sdfr return ((int)nfsrv_v2errmap[err - 1]); 19399336Sdfr return (NFSERR_IO); 19409336Sdfr} 19419336Sdfr 19429336Sdfrint 19439356Sdgnfsrv_vmio(struct vnode *vp) { 19445455Sdg vm_object_t object; 19455455Sdg 19469356Sdg if ((vp == NULL) || (vp->v_type != VREG)) 19475455Sdg return 1; 19485455Sdg 19495455Sdgretry: 19509356Sdg if ((vp->v_flag & VVMIO) == 0) { 19519456Sdg struct vattr vat; 19529456Sdg struct proc *p = curproc; 19539456Sdg 19549456Sdg if (VOP_GETATTR(vp, &vat, p->p_ucred, p) != 0) 19559456Sdg panic("nfsrv_vmio: VOP_GETATTR failed"); 19569456Sdg 195713490Sdyson (void) vnode_pager_alloc(vp, OFF_TO_IDX(round_page(vat.va_size)), 0, 0); 19589456Sdg 19595455Sdg vp->v_flag |= VVMIO; 19605455Sdg } else { 19619356Sdg if ((object = vp->v_object) && 19625455Sdg (object->flags & OBJ_DEAD)) { 19639356Sdg tsleep(object, PVM, "nfdead", 0); 19645455Sdg goto retry; 19655455Sdg } 19669356Sdg if (!object) 19675455Sdg panic("nfsrv_vmio: VMIO object missing"); 19689507Sdg vm_object_reference(object); 19695455Sdg } 19705455Sdg return 0; 19715455Sdg} 19725455Sdgint 19739356Sdgnfsrv_vput(struct vnode *vp) { 19749356Sdg if ((vp->v_flag & VVMIO) && vp->v_object) { 19759356Sdg vput(vp); 19769356Sdg vm_object_deallocate(vp->v_object); 19776210Sdg } else { 19789356Sdg vput(vp); 19795455Sdg } 19805455Sdg return 0; 19815455Sdg} 19825455Sdgint 19839356Sdgnfsrv_vrele(struct vnode *vp) { 19849356Sdg if ((vp->v_flag & VVMIO) && vp->v_object) { 19859356Sdg vrele(vp); 19869356Sdg vm_object_deallocate(vp->v_object); 19876210Sdg } else { 19889356Sdg vrele(vp); 19895455Sdg } 19905455Sdg return 0; 19915455Sdg} 199213416Sphk#endif /* NFS_NOSERVER */ 1993