Annotation of kernel/bsd/nfs/nfs_subs.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
                     26: /*
                     27:  * Copyright (c) 1989, 1993
                     28:  *     The Regents of the University of California.  All rights reserved.
                     29:  *
                     30:  * This code is derived from software contributed to Berkeley by
                     31:  * Rick Macklem at The University of Guelph.
                     32:  *
                     33:  * Redistribution and use in source and binary forms, with or without
                     34:  * modification, are permitted provided that the following conditions
                     35:  * are met:
                     36:  * 1. Redistributions of source code must retain the above copyright
                     37:  *    notice, this list of conditions and the following disclaimer.
                     38:  * 2. Redistributions in binary form must reproduce the above copyright
                     39:  *    notice, this list of conditions and the following disclaimer in the
                     40:  *    documentation and/or other materials provided with the distribution.
                     41:  * 3. All advertising materials mentioning features or use of this software
                     42:  *    must display the following acknowledgement:
                     43:  *     This product includes software developed by the University of
                     44:  *     California, Berkeley and its contributors.
                     45:  * 4. Neither the name of the University nor the names of its contributors
                     46:  *    may be used to endorse or promote products derived from this software
                     47:  *    without specific prior written permission.
                     48:  *
                     49:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     50:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     51:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     52:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     53:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     54:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     55:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     56:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     57:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     58:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     59:  * SUCH DAMAGE.
                     60:  *
                     61:  *     @(#)nfs_subs.c  8.8 (Berkeley) 5/22/95
                     62:  * FreeBSD-Id: nfs_subs.c,v 1.47 1997/11/07 08:53:24 phk Exp $
                     63:  */
                     64: 
                     65: /*
                     66:  * These functions support the macros and help fiddle mbuf chains for
                     67:  * the nfs op functions. They do things like create the rpc header and
                     68:  * copy data between mbuf chains and uio lists.
                     69:  */
                     70: #include <mach_nbc.h>
                     71: #include <sys/param.h>
                     72: #include <sys/proc.h>
                     73: #include <sys/systm.h>
                     74: #include <sys/kernel.h>
                     75: #include <sys/mount.h>
                     76: #include <sys/vnode.h>
                     77: #include <sys/namei.h>
                     78: #include <sys/mbuf.h>
                     79: #include <sys/socket.h>
                     80: #include <sys/stat.h>
                     81: #include <sys/malloc.h>
                     82: #include <sys/syscall.h>
                     83: 
                     84: #include <sys/vm.h>
                     85: #include <sys/vmparam.h>
                     86: #include <vm/vnode_pager.h>
                     87: #include <machine/spl.h>
                     88: 
                     89: #include <kern/lock.h>
                     90: 
                     91: #include <nfs/rpcv2.h>
                     92: #include <nfs/nfsproto.h>
                     93: #include <nfs/nfs.h>
                     94: #include <nfs/nfsnode.h>
                     95: #include <nfs/xdr_subs.h>
                     96: #include <nfs/nfsm_subs.h>
                     97: #include <nfs/nfsmount.h>
                     98: #include <nfs/nqnfs.h>
                     99: #include <nfs/nfsrtt.h>
                    100: 
                    101: #include <miscfs/specfs/specdev.h>
                    102: 
                    103: #include <netinet/in.h>
                    104: #if ISO
                    105: #include <netiso/iso.h>
                    106: #endif
                    107: 
                    108: #if MACH_NBC
                    109: #include <kern/mapfs.h>
                    110: #endif /* MACH_NBC */
                    111: 
                    112: /*
                    113:  * Data items converted to xdr at startup, since they are constant
                    114:  * This is kinda hokey, but may save a little time doing byte swaps
                    115:  */
                    116: u_long nfs_xdrneg1;
                    117: u_long rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr,
                    118:        rpc_mismatch, rpc_auth_unix, rpc_msgaccepted,
                    119:        rpc_auth_kerb;
                    120: u_long nfs_prog, nqnfs_prog, nfs_true, nfs_false;
                    121: 
                    122: /* And other global data */
                    123: static u_long nfs_xid = 0;
                    124: static enum vtype nv2tov_type[8]= {
                    125:        VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON,  VNON 
                    126: };
                    127: enum vtype nv3tov_type[8]= {
                    128:        VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO
                    129: };
                    130: 
                    131: int nfs_mount_type;
                    132: int nfs_ticks;
                    133: 
                    134: struct nfs_reqq nfs_reqq;
                    135: struct nfssvc_sockhead nfssvc_sockhead;
                    136: int nfssvc_sockhead_flag;
                    137: struct nfsd_head nfsd_head;
                    138: int nfsd_head_flag;
                    139: struct nfs_bufq nfs_bufq;
                    140: struct nqtimerhead nqtimerhead;
                    141: struct nqfhhashhead *nqfhhashtbl;
                    142: u_long nqfhhash;
                    143: 
                    144: #ifndef NFS_NOSERVER
                    145: /*
                    146:  * Mapping of old NFS Version 2 RPC numbers to generic numbers.
                    147:  */
                    148: int nfsv3_procid[NFS_NPROCS] = {
                    149:        NFSPROC_NULL,
                    150:        NFSPROC_GETATTR,
                    151:        NFSPROC_SETATTR,
                    152:        NFSPROC_NOOP,
                    153:        NFSPROC_LOOKUP,
                    154:        NFSPROC_READLINK,
                    155:        NFSPROC_READ,
                    156:        NFSPROC_NOOP,
                    157:        NFSPROC_WRITE,
                    158:        NFSPROC_CREATE,
                    159:        NFSPROC_REMOVE,
                    160:        NFSPROC_RENAME,
                    161:        NFSPROC_LINK,
                    162:        NFSPROC_SYMLINK,
                    163:        NFSPROC_MKDIR,
                    164:        NFSPROC_RMDIR,
                    165:        NFSPROC_READDIR,
                    166:        NFSPROC_FSSTAT,
                    167:        NFSPROC_NOOP,
                    168:        NFSPROC_NOOP,
                    169:        NFSPROC_NOOP,
                    170:        NFSPROC_NOOP,
                    171:        NFSPROC_NOOP,
                    172:        NFSPROC_NOOP,
                    173:        NFSPROC_NOOP,
                    174:        NFSPROC_NOOP
                    175: };
                    176: 
                    177: #endif /* NFS_NOSERVER */
                    178: /*
                    179:  * and the reverse mapping from generic to Version 2 procedure numbers
                    180:  */
                    181: int nfsv2_procid[NFS_NPROCS] = {
                    182:        NFSV2PROC_NULL,
                    183:        NFSV2PROC_GETATTR,
                    184:        NFSV2PROC_SETATTR,
                    185:        NFSV2PROC_LOOKUP,
                    186:        NFSV2PROC_NOOP,
                    187:        NFSV2PROC_READLINK,
                    188:        NFSV2PROC_READ,
                    189:        NFSV2PROC_WRITE,
                    190:        NFSV2PROC_CREATE,
                    191:        NFSV2PROC_MKDIR,
                    192:        NFSV2PROC_SYMLINK,
                    193:        NFSV2PROC_CREATE,
                    194:        NFSV2PROC_REMOVE,
                    195:        NFSV2PROC_RMDIR,
                    196:        NFSV2PROC_RENAME,
                    197:        NFSV2PROC_LINK,
                    198:        NFSV2PROC_READDIR,
                    199:        NFSV2PROC_NOOP,
                    200:        NFSV2PROC_STATFS,
                    201:        NFSV2PROC_NOOP,
                    202:        NFSV2PROC_NOOP,
                    203:        NFSV2PROC_NOOP,
                    204:        NFSV2PROC_NOOP,
                    205:        NFSV2PROC_NOOP,
                    206:        NFSV2PROC_NOOP,
                    207:        NFSV2PROC_NOOP,
                    208: };
                    209: 
                    210: #ifndef NFS_NOSERVER
                    211: /*
                    212:  * Maps errno values to nfs error numbers.
                    213:  * Use NFSERR_IO as the catch all for ones not specifically defined in
                    214:  * RFC 1094.
                    215:  */
                    216: static u_char nfsrv_v2errmap[ELAST] = {
                    217:   NFSERR_PERM, NFSERR_NOENT,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    218:   NFSERR_NXIO, NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    219:   NFSERR_IO,   NFSERR_IO,      NFSERR_ACCES,   NFSERR_IO,      NFSERR_IO,
                    220:   NFSERR_IO,   NFSERR_EXIST,   NFSERR_IO,      NFSERR_NODEV,   NFSERR_NOTDIR,
                    221:   NFSERR_ISDIR,        NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    222:   NFSERR_IO,   NFSERR_FBIG,    NFSERR_NOSPC,   NFSERR_IO,      NFSERR_ROFS,
                    223:   NFSERR_IO,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    224:   NFSERR_IO,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    225:   NFSERR_IO,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    226:   NFSERR_IO,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    227:   NFSERR_IO,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    228:   NFSERR_IO,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    229:   NFSERR_IO,   NFSERR_IO,      NFSERR_NAMETOL, NFSERR_IO,      NFSERR_IO,
                    230:   NFSERR_NOTEMPTY, NFSERR_IO,  NFSERR_IO,      NFSERR_DQUOT,   NFSERR_STALE,
                    231:   NFSERR_IO,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    232:   NFSERR_IO,   NFSERR_IO,      NFSERR_IO,      NFSERR_IO,      NFSERR_IO,
                    233:   NFSERR_IO,
                    234: };
                    235: 
                    236: /*
                    237:  * Maps errno values to nfs error numbers.
                    238:  * Although it is not obvious whether or not NFS clients really care if
                    239:  * a returned error value is in the specified list for the procedure, the
                    240:  * safest thing to do is filter them appropriately. For Version 2, the
                    241:  * X/Open XNFS document is the only specification that defines error values
                    242:  * for each RPC (The RFC simply lists all possible error values for all RPCs),
                    243:  * so I have decided to not do this for Version 2.
                    244:  * The first entry is the default error return and the rest are the valid
                    245:  * errors for that RPC in increasing numeric order.
                    246:  */
                    247: static short nfsv3err_null[] = {
                    248:        0,
                    249:        0,
                    250: };
                    251: 
                    252: static short nfsv3err_getattr[] = {
                    253:        NFSERR_IO,
                    254:        NFSERR_IO,
                    255:        NFSERR_STALE,
                    256:        NFSERR_BADHANDLE,
                    257:        NFSERR_SERVERFAULT,
                    258:        0,
                    259: };
                    260: 
                    261: static short nfsv3err_setattr[] = {
                    262:        NFSERR_IO,
                    263:        NFSERR_PERM,
                    264:        NFSERR_IO,
                    265:        NFSERR_ACCES,
                    266:        NFSERR_INVAL,
                    267:        NFSERR_NOSPC,
                    268:        NFSERR_ROFS,
                    269:        NFSERR_DQUOT,
                    270:        NFSERR_STALE,
                    271:        NFSERR_BADHANDLE,
                    272:        NFSERR_NOT_SYNC,
                    273:        NFSERR_SERVERFAULT,
                    274:        0,
                    275: };
                    276: 
                    277: static short nfsv3err_lookup[] = {
                    278:        NFSERR_IO,
                    279:        NFSERR_NOENT,
                    280:        NFSERR_IO,
                    281:        NFSERR_ACCES,
                    282:        NFSERR_NOTDIR,
                    283:        NFSERR_NAMETOL,
                    284:        NFSERR_STALE,
                    285:        NFSERR_BADHANDLE,
                    286:        NFSERR_SERVERFAULT,
                    287:        0,
                    288: };
                    289: 
                    290: static short nfsv3err_access[] = {
                    291:        NFSERR_IO,
                    292:        NFSERR_IO,
                    293:        NFSERR_STALE,
                    294:        NFSERR_BADHANDLE,
                    295:        NFSERR_SERVERFAULT,
                    296:        0,
                    297: };
                    298: 
                    299: static short nfsv3err_readlink[] = {
                    300:        NFSERR_IO,
                    301:        NFSERR_IO,
                    302:        NFSERR_ACCES,
                    303:        NFSERR_INVAL,
                    304:        NFSERR_STALE,
                    305:        NFSERR_BADHANDLE,
                    306:        NFSERR_NOTSUPP,
                    307:        NFSERR_SERVERFAULT,
                    308:        0,
                    309: };
                    310: 
                    311: static short nfsv3err_read[] = {
                    312:        NFSERR_IO,
                    313:        NFSERR_IO,
                    314:        NFSERR_NXIO,
                    315:        NFSERR_ACCES,
                    316:        NFSERR_INVAL,
                    317:        NFSERR_STALE,
                    318:        NFSERR_BADHANDLE,
                    319:        NFSERR_SERVERFAULT,
                    320:        0,
                    321: };
                    322: 
                    323: static short nfsv3err_write[] = {
                    324:        NFSERR_IO,
                    325:        NFSERR_IO,
                    326:        NFSERR_ACCES,
                    327:        NFSERR_INVAL,
                    328:        NFSERR_FBIG,
                    329:        NFSERR_NOSPC,
                    330:        NFSERR_ROFS,
                    331:        NFSERR_DQUOT,
                    332:        NFSERR_STALE,
                    333:        NFSERR_BADHANDLE,
                    334:        NFSERR_SERVERFAULT,
                    335:        0,
                    336: };
                    337: 
                    338: static short nfsv3err_create[] = {
                    339:        NFSERR_IO,
                    340:        NFSERR_IO,
                    341:        NFSERR_ACCES,
                    342:        NFSERR_EXIST,
                    343:        NFSERR_NOTDIR,
                    344:        NFSERR_NOSPC,
                    345:        NFSERR_ROFS,
                    346:        NFSERR_NAMETOL,
                    347:        NFSERR_DQUOT,
                    348:        NFSERR_STALE,
                    349:        NFSERR_BADHANDLE,
                    350:        NFSERR_NOTSUPP,
                    351:        NFSERR_SERVERFAULT,
                    352:        0,
                    353: };
                    354: 
                    355: static short nfsv3err_mkdir[] = {
                    356:        NFSERR_IO,
                    357:        NFSERR_IO,
                    358:        NFSERR_ACCES,
                    359:        NFSERR_EXIST,
                    360:        NFSERR_NOTDIR,
                    361:        NFSERR_NOSPC,
                    362:        NFSERR_ROFS,
                    363:        NFSERR_NAMETOL,
                    364:        NFSERR_DQUOT,
                    365:        NFSERR_STALE,
                    366:        NFSERR_BADHANDLE,
                    367:        NFSERR_NOTSUPP,
                    368:        NFSERR_SERVERFAULT,
                    369:        0,
                    370: };
                    371: 
                    372: static short nfsv3err_symlink[] = {
                    373:        NFSERR_IO,
                    374:        NFSERR_IO,
                    375:        NFSERR_ACCES,
                    376:        NFSERR_EXIST,
                    377:        NFSERR_NOTDIR,
                    378:        NFSERR_NOSPC,
                    379:        NFSERR_ROFS,
                    380:        NFSERR_NAMETOL,
                    381:        NFSERR_DQUOT,
                    382:        NFSERR_STALE,
                    383:        NFSERR_BADHANDLE,
                    384:        NFSERR_NOTSUPP,
                    385:        NFSERR_SERVERFAULT,
                    386:        0,
                    387: };
                    388: 
                    389: static short nfsv3err_mknod[] = {
                    390:        NFSERR_IO,
                    391:        NFSERR_IO,
                    392:        NFSERR_ACCES,
                    393:        NFSERR_EXIST,
                    394:        NFSERR_NOTDIR,
                    395:        NFSERR_NOSPC,
                    396:        NFSERR_ROFS,
                    397:        NFSERR_NAMETOL,
                    398:        NFSERR_DQUOT,
                    399:        NFSERR_STALE,
                    400:        NFSERR_BADHANDLE,
                    401:        NFSERR_NOTSUPP,
                    402:        NFSERR_SERVERFAULT,
                    403:        NFSERR_BADTYPE,
                    404:        0,
                    405: };
                    406: 
                    407: static short nfsv3err_remove[] = {
                    408:        NFSERR_IO,
                    409:        NFSERR_NOENT,
                    410:        NFSERR_IO,
                    411:        NFSERR_ACCES,
                    412:        NFSERR_NOTDIR,
                    413:        NFSERR_ROFS,
                    414:        NFSERR_NAMETOL,
                    415:        NFSERR_STALE,
                    416:        NFSERR_BADHANDLE,
                    417:        NFSERR_SERVERFAULT,
                    418:        0,
                    419: };
                    420: 
                    421: static short nfsv3err_rmdir[] = {
                    422:        NFSERR_IO,
                    423:        NFSERR_NOENT,
                    424:        NFSERR_IO,
                    425:        NFSERR_ACCES,
                    426:        NFSERR_EXIST,
                    427:        NFSERR_NOTDIR,
                    428:        NFSERR_INVAL,
                    429:        NFSERR_ROFS,
                    430:        NFSERR_NAMETOL,
                    431:        NFSERR_NOTEMPTY,
                    432:        NFSERR_STALE,
                    433:        NFSERR_BADHANDLE,
                    434:        NFSERR_NOTSUPP,
                    435:        NFSERR_SERVERFAULT,
                    436:        0,
                    437: };
                    438: 
                    439: static short nfsv3err_rename[] = {
                    440:        NFSERR_IO,
                    441:        NFSERR_NOENT,
                    442:        NFSERR_IO,
                    443:        NFSERR_ACCES,
                    444:        NFSERR_EXIST,
                    445:        NFSERR_XDEV,
                    446:        NFSERR_NOTDIR,
                    447:        NFSERR_ISDIR,
                    448:        NFSERR_INVAL,
                    449:        NFSERR_NOSPC,
                    450:        NFSERR_ROFS,
                    451:        NFSERR_MLINK,
                    452:        NFSERR_NAMETOL,
                    453:        NFSERR_NOTEMPTY,
                    454:        NFSERR_DQUOT,
                    455:        NFSERR_STALE,
                    456:        NFSERR_BADHANDLE,
                    457:        NFSERR_NOTSUPP,
                    458:        NFSERR_SERVERFAULT,
                    459:        0,
                    460: };
                    461: 
                    462: static short nfsv3err_link[] = {
                    463:        NFSERR_IO,
                    464:        NFSERR_IO,
                    465:        NFSERR_ACCES,
                    466:        NFSERR_EXIST,
                    467:        NFSERR_XDEV,
                    468:        NFSERR_NOTDIR,
                    469:        NFSERR_INVAL,
                    470:        NFSERR_NOSPC,
                    471:        NFSERR_ROFS,
                    472:        NFSERR_MLINK,
                    473:        NFSERR_NAMETOL,
                    474:        NFSERR_DQUOT,
                    475:        NFSERR_STALE,
                    476:        NFSERR_BADHANDLE,
                    477:        NFSERR_NOTSUPP,
                    478:        NFSERR_SERVERFAULT,
                    479:        0,
                    480: };
                    481: 
                    482: static short nfsv3err_readdir[] = {
                    483:        NFSERR_IO,
                    484:        NFSERR_IO,
                    485:        NFSERR_ACCES,
                    486:        NFSERR_NOTDIR,
                    487:        NFSERR_STALE,
                    488:        NFSERR_BADHANDLE,
                    489:        NFSERR_BAD_COOKIE,
                    490:        NFSERR_TOOSMALL,
                    491:        NFSERR_SERVERFAULT,
                    492:        0,
                    493: };
                    494: 
                    495: static short nfsv3err_readdirplus[] = {
                    496:        NFSERR_IO,
                    497:        NFSERR_IO,
                    498:        NFSERR_ACCES,
                    499:        NFSERR_NOTDIR,
                    500:        NFSERR_STALE,
                    501:        NFSERR_BADHANDLE,
                    502:        NFSERR_BAD_COOKIE,
                    503:        NFSERR_NOTSUPP,
                    504:        NFSERR_TOOSMALL,
                    505:        NFSERR_SERVERFAULT,
                    506:        0,
                    507: };
                    508: 
                    509: static short nfsv3err_fsstat[] = {
                    510:        NFSERR_IO,
                    511:        NFSERR_IO,
                    512:        NFSERR_STALE,
                    513:        NFSERR_BADHANDLE,
                    514:        NFSERR_SERVERFAULT,
                    515:        0,
                    516: };
                    517: 
                    518: static short nfsv3err_fsinfo[] = {
                    519:        NFSERR_STALE,
                    520:        NFSERR_STALE,
                    521:        NFSERR_BADHANDLE,
                    522:        NFSERR_SERVERFAULT,
                    523:        0,
                    524: };
                    525: 
                    526: static short nfsv3err_pathconf[] = {
                    527:        NFSERR_STALE,
                    528:        NFSERR_STALE,
                    529:        NFSERR_BADHANDLE,
                    530:        NFSERR_SERVERFAULT,
                    531:        0,
                    532: };
                    533: 
                    534: static short nfsv3err_commit[] = {
                    535:        NFSERR_IO,
                    536:        NFSERR_IO,
                    537:        NFSERR_STALE,
                    538:        NFSERR_BADHANDLE,
                    539:        NFSERR_SERVERFAULT,
                    540:        0,
                    541: };
                    542: 
                    543: static short *nfsrv_v3errmap[] = {
                    544:        nfsv3err_null,
                    545:        nfsv3err_getattr,
                    546:        nfsv3err_setattr,
                    547:        nfsv3err_lookup,
                    548:        nfsv3err_access,
                    549:        nfsv3err_readlink,
                    550:        nfsv3err_read,
                    551:        nfsv3err_write,
                    552:        nfsv3err_create,
                    553:        nfsv3err_mkdir,
                    554:        nfsv3err_symlink,
                    555:        nfsv3err_mknod,
                    556:        nfsv3err_remove,
                    557:        nfsv3err_rmdir,
                    558:        nfsv3err_rename,
                    559:        nfsv3err_link,
                    560:        nfsv3err_readdir,
                    561:        nfsv3err_readdirplus,
                    562:        nfsv3err_fsstat,
                    563:        nfsv3err_fsinfo,
                    564:        nfsv3err_pathconf,
                    565:        nfsv3err_commit,
                    566: };
                    567: 
                    568: #endif /* NFS_NOSERVER */
                    569: 
                    570: extern struct nfsrtt nfsrtt;
                    571: extern time_t nqnfsstarttime;
                    572: extern int nqsrv_clockskew;
                    573: extern int nqsrv_writeslack;
                    574: extern int nqsrv_maxlease;
                    575: extern struct nfsstats nfsstats;
                    576: extern int nqnfs_piggy[NFS_NPROCS];
                    577: extern nfstype nfsv2_type[9];
                    578: extern nfstype nfsv3_type[9];
                    579: extern struct nfsnodehashhead *nfsnodehashtbl;
                    580: extern u_long nfsnodehash;
                    581: 
                    582: struct getfh_args;
                    583: extern int getfh(struct proc *, struct getfh_args *, int *);
                    584: struct nfssvc_args;
                    585: extern int nfssvc(struct proc *, struct nfssvc_args *, int *);
                    586: 
                    587: extern void mapfs_memfree __P((struct vm_info *, boolean_t));
                    588: 
                    589: LIST_HEAD(nfsnodehashhead, nfsnode);
                    590: 
                    591: int nfs_webnamei __P((struct nameidata *, struct vnode *, struct proc *));
                    592: 
1.1.1.2 ! root      593: #if DIAGNOSTIC
        !           594: int nfsattrcheck;
        !           595: #endif
        !           596: 
1.1       root      597: /*
                    598:  * Create the header for an rpc request packet
                    599:  * The hsiz is the size of the rest of the nfs request header.
                    600:  * (just used to decide if a cluster is a good idea)
                    601:  */
                    602: struct mbuf *
                    603: nfsm_reqh(vp, procid, hsiz, bposp)
                    604:        struct vnode *vp;
                    605:        u_long procid;
                    606:        int hsiz;
                    607:        caddr_t *bposp;
                    608: {
                    609:        register struct mbuf *mb;
                    610:        register u_long *tl;
                    611:        register caddr_t bpos;
                    612:        struct mbuf *mb2;
                    613:        struct nfsmount *nmp;
                    614:        int nqflag;
                    615: 
                    616:        MGET(mb, M_WAIT, MT_DATA);
                    617:        if (hsiz >= MINCLSIZE)
                    618:                MCLGET(mb, M_WAIT);
                    619:        mb->m_len = 0;
                    620:        bpos = mtod(mb, caddr_t);
                    621: 
                    622:        /*
                    623:         * For NQNFS, add lease request.
                    624:         */
                    625:        if (vp) {
                    626:                nmp = VFSTONFS(vp->v_mount);
                    627:                if (nmp->nm_flag & NFSMNT_NQNFS) {
                    628:                        nqflag = NQNFS_NEEDLEASE(vp, procid);
                    629:                        if (nqflag) {
                    630:                                nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
                    631:                                *tl++ = txdr_unsigned(nqflag);
                    632:                                *tl = txdr_unsigned(nmp->nm_leaseterm);
                    633:                        } else {
                    634:                                nfsm_build(tl, u_long *, NFSX_UNSIGNED);
                    635:                                *tl = 0;
                    636:                        }
                    637:                }
                    638:        }
                    639:        /* Finally, return values */
                    640:        *bposp = bpos;
                    641:        return (mb);
                    642: }
                    643: 
                    644: /*
                    645:  * Build the RPC header and fill in the authorization info.
                    646:  * The authorization string argument is only used when the credentials
                    647:  * come from outside of the kernel.
                    648:  * Returns the head of the mbuf list.
                    649:  */
                    650: struct mbuf *
                    651: nfsm_rpchead(cr, nmflag, procid, auth_type, auth_len, auth_str, verf_len,
                    652:        verf_str, mrest, mrest_len, mbp, xidp)
                    653:        register struct ucred *cr;
                    654:        int nmflag;
                    655:        int procid;
                    656:        int auth_type;
                    657:        int auth_len;
                    658:        char *auth_str;
                    659:        int verf_len;
                    660:        char *verf_str;
                    661:        struct mbuf *mrest;
                    662:        int mrest_len;
                    663:        struct mbuf **mbp;
                    664:        u_long *xidp;
                    665: {
                    666:        register struct mbuf *mb;
                    667:        register u_long *tl;
                    668:        register caddr_t bpos;
                    669:        register int i;
                    670:        struct mbuf *mreq, *mb2;
                    671:        int siz, grpsiz, authsiz;
                    672:        struct timeval tv;
                    673:        static u_long base;
                    674: 
                    675:        authsiz = nfsm_rndup(auth_len);
                    676:        MGETHDR(mb, M_WAIT, MT_DATA);
                    677:        if ((authsiz + 10 * NFSX_UNSIGNED) >= MINCLSIZE) {
                    678:                MCLGET(mb, M_WAIT);
                    679:        } else if ((authsiz + 10 * NFSX_UNSIGNED) < MHLEN) {
                    680:                MH_ALIGN(mb, authsiz + 10 * NFSX_UNSIGNED);
                    681:        } else {
                    682:                MH_ALIGN(mb, 8 * NFSX_UNSIGNED);
                    683:        }
                    684:        mb->m_len = 0;
                    685:        mreq = mb;
                    686:        bpos = mtod(mb, caddr_t);
                    687: 
                    688:        /*
                    689:         * First the RPC header.
                    690:         */
                    691:        nfsm_build(tl, u_long *, 8 * NFSX_UNSIGNED);
                    692: 
                    693:        /*
                    694:         * derive initial xid from system time
                    695:         * XXX time is invalid if root not yet mounted
                    696:         */
                    697:        if (!base && (rootvp)) {
                    698:                microtime(&tv);
                    699:                base = tv.tv_sec << 12;
                    700:                nfs_xid = base;
                    701:        }
                    702:        /*
                    703:         * Skip zero xid if it should ever happen.
                    704:         */
                    705:        if (++nfs_xid == 0)
                    706:                nfs_xid++;
                    707: 
                    708:        *tl++ = *xidp = txdr_unsigned(nfs_xid);
                    709:        *tl++ = rpc_call;
                    710:        *tl++ = rpc_vers;
                    711:        if (nmflag & NFSMNT_NQNFS) {
                    712:                *tl++ = txdr_unsigned(NQNFS_PROG);
                    713:                *tl++ = txdr_unsigned(NQNFS_VER3);
                    714:        } else {
                    715:                *tl++ = txdr_unsigned(NFS_PROG);
                    716:                if (nmflag & NFSMNT_NFSV3)
                    717:                        *tl++ = txdr_unsigned(NFS_VER3);
                    718:                else
                    719:                        *tl++ = txdr_unsigned(NFS_VER2);
                    720:        }
                    721:        if (nmflag & NFSMNT_NFSV3)
                    722:                *tl++ = txdr_unsigned(procid);
                    723:        else
                    724:                *tl++ = txdr_unsigned(nfsv2_procid[procid]);
                    725: 
                    726:        /*
                    727:         * And then the authorization cred.
                    728:         */
                    729:        *tl++ = txdr_unsigned(auth_type);
                    730:        *tl = txdr_unsigned(authsiz);
                    731:        switch (auth_type) {
                    732:        case RPCAUTH_UNIX:
                    733:                nfsm_build(tl, u_long *, auth_len);
                    734:                *tl++ = 0;              /* stamp ?? */
                    735:                *tl++ = 0;              /* NULL hostname */
                    736:                *tl++ = txdr_unsigned(cr->cr_uid);
                    737:                *tl++ = txdr_unsigned(cr->cr_groups[0]);
                    738:                grpsiz = (auth_len >> 2) - 5;
                    739:                *tl++ = txdr_unsigned(grpsiz);
                    740:                for (i = 1; i <= grpsiz; i++)
                    741:                        *tl++ = txdr_unsigned(cr->cr_groups[i]);
                    742:                break;
                    743:        case RPCAUTH_KERB4:
                    744:                siz = auth_len;
                    745:                while (siz > 0) {
                    746:                        if (M_TRAILINGSPACE(mb) == 0) {
                    747:                                MGET(mb2, M_WAIT, MT_DATA);
                    748:                                if (siz >= MINCLSIZE)
                    749:                                        MCLGET(mb2, M_WAIT);
                    750:                                mb->m_next = mb2;
                    751:                                mb = mb2;
                    752:                                mb->m_len = 0;
                    753:                                bpos = mtod(mb, caddr_t);
                    754:                        }
                    755:                        i = min(siz, M_TRAILINGSPACE(mb));
                    756:                        bcopy(auth_str, bpos, i);
                    757:                        mb->m_len += i;
                    758:                        auth_str += i;
                    759:                        bpos += i;
                    760:                        siz -= i;
                    761:                }
                    762:                if ((siz = (nfsm_rndup(auth_len) - auth_len)) > 0) {
                    763:                        for (i = 0; i < siz; i++)
                    764:                                *bpos++ = '\0';
                    765:                        mb->m_len += siz;
                    766:                }
                    767:                break;
                    768:        };
                    769: 
                    770:        /*
                    771:         * And the verifier...
                    772:         */
                    773:        nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
                    774:        if (verf_str) {
                    775:                *tl++ = txdr_unsigned(RPCAUTH_KERB4);
                    776:                *tl = txdr_unsigned(verf_len);
                    777:                siz = verf_len;
                    778:                while (siz > 0) {
                    779:                        if (M_TRAILINGSPACE(mb) == 0) {
                    780:                                MGET(mb2, M_WAIT, MT_DATA);
                    781:                                if (siz >= MINCLSIZE)
                    782:                                        MCLGET(mb2, M_WAIT);
                    783:                                mb->m_next = mb2;
                    784:                                mb = mb2;
                    785:                                mb->m_len = 0;
                    786:                                bpos = mtod(mb, caddr_t);
                    787:                        }
                    788:                        i = min(siz, M_TRAILINGSPACE(mb));
                    789:                        bcopy(verf_str, bpos, i);
                    790:                        mb->m_len += i;
                    791:                        verf_str += i;
                    792:                        bpos += i;
                    793:                        siz -= i;
                    794:                }
                    795:                if ((siz = (nfsm_rndup(verf_len) - verf_len)) > 0) {
                    796:                        for (i = 0; i < siz; i++)
                    797:                                *bpos++ = '\0';
                    798:                        mb->m_len += siz;
                    799:                }
                    800:        } else {
                    801:                *tl++ = txdr_unsigned(RPCAUTH_NULL);
                    802:                *tl = 0;
                    803:        }
                    804:        mb->m_next = mrest;
                    805:        mreq->m_pkthdr.len = authsiz + 10 * NFSX_UNSIGNED + mrest_len;
                    806:        mreq->m_pkthdr.rcvif = (struct ifnet *)0;
                    807:        *mbp = mb;
                    808:        return (mreq);
                    809: }
                    810: 
                    811: /*
                    812:  * copies mbuf chain to the uio scatter/gather list
                    813:  */
                    814: int
                    815: nfsm_mbuftouio(mrep, uiop, siz, dpos)
                    816:        struct mbuf **mrep;
                    817:        register struct uio *uiop;
                    818:        int siz;
                    819:        caddr_t *dpos;
                    820: {
                    821:        register char *mbufcp, *uiocp;
                    822:        register int xfer, left, len;
                    823:        register struct mbuf *mp;
                    824:        long uiosiz, rem;
                    825:        int error = 0;
                    826: 
                    827:        mp = *mrep;
                    828:        mbufcp = *dpos;
                    829:        len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
                    830:        rem = nfsm_rndup(siz)-siz;
                    831:        while (siz > 0) {
                    832:                if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
                    833:                        return (EFBIG);
                    834:                left = uiop->uio_iov->iov_len;
                    835:                uiocp = uiop->uio_iov->iov_base;
                    836:                if (left > siz)
                    837:                        left = siz;
                    838:                uiosiz = left;
                    839:                while (left > 0) {
                    840:                        while (len == 0) {
                    841:                                mp = mp->m_next;
                    842:                                if (mp == NULL)
                    843:                                        return (EBADRPC);
                    844:                                mbufcp = mtod(mp, caddr_t);
                    845:                                len = mp->m_len;
                    846:                        }
                    847:                        xfer = (left > len) ? len : left;
                    848: #ifdef notdef
                    849:                        /* Not Yet.. */
                    850:                        if (uiop->uio_iov->iov_op != NULL)
                    851:                                (*(uiop->uio_iov->iov_op))
                    852:                                (mbufcp, uiocp, xfer);
                    853:                        else
                    854: #endif
                    855:                        if (uiop->uio_segflg == UIO_SYSSPACE)
                    856:                                bcopy(mbufcp, uiocp, xfer);
                    857:                        else
                    858:                                copyout(mbufcp, uiocp, xfer);
                    859:                        left -= xfer;
                    860:                        len -= xfer;
                    861:                        mbufcp += xfer;
                    862:                        uiocp += xfer;
                    863:                        uiop->uio_offset += xfer;
                    864:                        uiop->uio_resid -= xfer;
                    865:                }
                    866:                if (uiop->uio_iov->iov_len <= siz) {
                    867:                        uiop->uio_iovcnt--;
                    868:                        uiop->uio_iov++;
                    869:                } else {
                    870:                        uiop->uio_iov->iov_base += uiosiz;
                    871:                        uiop->uio_iov->iov_len -= uiosiz;
                    872:                }
                    873:                siz -= uiosiz;
                    874:        }
                    875:        *dpos = mbufcp;
                    876:        *mrep = mp;
                    877:        if (rem > 0) {
                    878:                if (len < rem)
                    879:                        error = nfs_adv(mrep, dpos, rem, len);
                    880:                else
                    881:                        *dpos += rem;
                    882:        }
                    883:        return (error);
                    884: }
                    885: 
                    886: /*
                    887:  * copies a uio scatter/gather list to an mbuf chain.
                    888:  * NOTE: can ony handle iovcnt == 1
                    889:  */
                    890: int
                    891: nfsm_uiotombuf(uiop, mq, siz, bpos)
                    892:        register struct uio *uiop;
                    893:        struct mbuf **mq;
                    894:        int siz;
                    895:        caddr_t *bpos;
                    896: {
                    897:        register char *uiocp;
                    898:        register struct mbuf *mp, *mp2;
                    899:        register int xfer, left, mlen;
                    900:        int uiosiz, clflg, rem;
                    901:        char *cp;
                    902: 
                    903:        if (uiop->uio_iovcnt != 1)
                    904:                panic("nfsm_uiotombuf: iovcnt != 1");
                    905: 
                    906:        if (siz > MLEN)         /* or should it >= MCLBYTES ?? */
                    907:                clflg = 1;
                    908:        else
                    909:                clflg = 0;
                    910:        rem = nfsm_rndup(siz)-siz;
                    911:        mp = mp2 = *mq;
                    912:        while (siz > 0) {
                    913:                left = uiop->uio_iov->iov_len;
                    914:                uiocp = uiop->uio_iov->iov_base;
                    915:                if (left > siz)
                    916:                        left = siz;
                    917:                uiosiz = left;
                    918:                while (left > 0) {
                    919:                        mlen = M_TRAILINGSPACE(mp);
                    920:                        if (mlen == 0) {
                    921:                                MGET(mp, M_WAIT, MT_DATA);
                    922:                                if (clflg)
                    923:                                        MCLGET(mp, M_WAIT);
                    924:                                mp->m_len = 0;
                    925:                                mp2->m_next = mp;
                    926:                                mp2 = mp;
                    927:                                mlen = M_TRAILINGSPACE(mp);
                    928:                        }
                    929:                        xfer = (left > mlen) ? mlen : left;
                    930: #ifdef notdef
                    931:                        /* Not Yet.. */
                    932:                        if (uiop->uio_iov->iov_op != NULL)
                    933:                                (*(uiop->uio_iov->iov_op))
                    934:                                (uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
                    935:                        else
                    936: #endif
                    937:                        if (uiop->uio_segflg == UIO_SYSSPACE)
                    938:                                bcopy(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
                    939:                        else
                    940:                                copyin(uiocp, mtod(mp, caddr_t)+mp->m_len, xfer);
                    941:                        mp->m_len += xfer;
                    942:                        left -= xfer;
                    943:                        uiocp += xfer;
                    944:                        uiop->uio_offset += xfer;
                    945:                        uiop->uio_resid -= xfer;
                    946:                }
                    947:                uiop->uio_iov->iov_base += uiosiz;
                    948:                uiop->uio_iov->iov_len -= uiosiz;
                    949:                siz -= uiosiz;
                    950:        }
                    951:        if (rem > 0) {
                    952:                if (rem > M_TRAILINGSPACE(mp)) {
                    953:                        MGET(mp, M_WAIT, MT_DATA);
                    954:                        mp->m_len = 0;
                    955:                        mp2->m_next = mp;
                    956:                }
                    957:                cp = mtod(mp, caddr_t)+mp->m_len;
                    958:                for (left = 0; left < rem; left++)
                    959:                        *cp++ = '\0';
                    960:                mp->m_len += rem;
                    961:                *bpos = cp;
                    962:        } else
                    963:                *bpos = mtod(mp, caddr_t)+mp->m_len;
                    964:        *mq = mp;
                    965:        return (0);
                    966: }
                    967: 
                    968: /*
                    969:  * Help break down an mbuf chain by setting the first siz bytes contiguous
                    970:  * pointed to by returned val.
                    971:  * This is used by the macros nfsm_dissect and nfsm_dissecton for tough
                    972:  * cases. (The macros use the vars. dpos and dpos2)
                    973:  */
                    974: int
                    975: nfsm_disct(mdp, dposp, siz, left, cp2)
                    976:        struct mbuf **mdp;
                    977:        caddr_t *dposp;
                    978:        int siz;
                    979:        int left;
                    980:        caddr_t *cp2;
                    981: {
                    982:        register struct mbuf *mp, *mp2;
                    983:        register int siz2, xfer;
                    984:        register caddr_t p;
                    985: 
                    986:        mp = *mdp;
                    987:        while (left == 0) {
                    988:                *mdp = mp = mp->m_next;
                    989:                if (mp == NULL)
                    990:                        return (EBADRPC);
                    991:                left = mp->m_len;
                    992:                *dposp = mtod(mp, caddr_t);
                    993:        }
                    994:        if (left >= siz) {
                    995:                *cp2 = *dposp;
                    996:                *dposp += siz;
                    997:        } else if (mp->m_next == NULL) {
                    998:                return (EBADRPC);
                    999:        } else if (siz > MHLEN) {
                   1000:                panic("nfs S too big");
                   1001:        } else {
                   1002:                MGET(mp2, M_WAIT, MT_DATA);
                   1003:                mp2->m_next = mp->m_next;
                   1004:                mp->m_next = mp2;
                   1005:                mp->m_len -= left;
                   1006:                mp = mp2;
                   1007:                *cp2 = p = mtod(mp, caddr_t);
                   1008:                bcopy(*dposp, p, left);         /* Copy what was left */
                   1009:                siz2 = siz-left;
                   1010:                p += left;
                   1011:                mp2 = mp->m_next;
                   1012:                /* Loop around copying up the siz2 bytes */
                   1013:                while (siz2 > 0) {
                   1014:                        if (mp2 == NULL)
                   1015:                                return (EBADRPC);
                   1016:                        xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
                   1017:                        if (xfer > 0) {
                   1018:                                bcopy(mtod(mp2, caddr_t), p, xfer);
                   1019:                                NFSMADV(mp2, xfer);
                   1020:                                mp2->m_len -= xfer;
                   1021:                                p += xfer;
                   1022:                                siz2 -= xfer;
                   1023:                        }
                   1024:                        if (siz2 > 0)
                   1025:                                mp2 = mp2->m_next;
                   1026:                }
                   1027:                mp->m_len = siz;
                   1028:                *mdp = mp2;
                   1029:                *dposp = mtod(mp2, caddr_t);
                   1030:        }
                   1031:        return (0);
                   1032: }
                   1033: 
                   1034: /*
                   1035:  * Advance the position in the mbuf chain.
                   1036:  */
                   1037: int
                   1038: nfs_adv(mdp, dposp, offs, left)
                   1039:        struct mbuf **mdp;
                   1040:        caddr_t *dposp;
                   1041:        int offs;
                   1042:        int left;
                   1043: {
                   1044:        register struct mbuf *m;
                   1045:        register int s;
                   1046: 
                   1047:        m = *mdp;
                   1048:        s = left;
                   1049:        while (s < offs) {
                   1050:                offs -= s;
                   1051:                m = m->m_next;
                   1052:                if (m == NULL)
                   1053:                        return (EBADRPC);
                   1054:                s = m->m_len;
                   1055:        }
                   1056:        *mdp = m;
                   1057:        *dposp = mtod(m, caddr_t)+offs;
                   1058:        return (0);
                   1059: }
                   1060: 
                   1061: /*
                   1062:  * Copy a string into mbufs for the hard cases...
                   1063:  */
                   1064: int
                   1065: nfsm_strtmbuf(mb, bpos, cp, siz)
                   1066:        struct mbuf **mb;
                   1067:        char **bpos;
                   1068:        char *cp;
                   1069:        long siz;
                   1070: {
                   1071:        register struct mbuf *m1 = 0, *m2;
                   1072:        long left, xfer, len, tlen;
                   1073:        u_long *tl;
                   1074:        int putsize;
                   1075: 
                   1076:        putsize = 1;
                   1077:        m2 = *mb;
                   1078:        left = M_TRAILINGSPACE(m2);
                   1079:        if (left > 0) {
                   1080:                tl = ((u_long *)(*bpos));
                   1081:                *tl++ = txdr_unsigned(siz);
                   1082:                putsize = 0;
                   1083:                left -= NFSX_UNSIGNED;
                   1084:                m2->m_len += NFSX_UNSIGNED;
                   1085:                if (left > 0) {
                   1086:                        bcopy(cp, (caddr_t) tl, left);
                   1087:                        siz -= left;
                   1088:                        cp += left;
                   1089:                        m2->m_len += left;
                   1090:                        left = 0;
                   1091:                }
                   1092:        }
                   1093:        /* Loop around adding mbufs */
                   1094:        while (siz > 0) {
                   1095:                MGET(m1, M_WAIT, MT_DATA);
                   1096:                if (siz > MLEN)
                   1097:                        MCLGET(m1, M_WAIT);
                   1098:                m1->m_len = NFSMSIZ(m1);
                   1099:                m2->m_next = m1;
                   1100:                m2 = m1;
                   1101:                tl = mtod(m1, u_long *);
                   1102:                tlen = 0;
                   1103:                if (putsize) {
                   1104:                        *tl++ = txdr_unsigned(siz);
                   1105:                        m1->m_len -= NFSX_UNSIGNED;
                   1106:                        tlen = NFSX_UNSIGNED;
                   1107:                        putsize = 0;
                   1108:                }
                   1109:                if (siz < m1->m_len) {
                   1110:                        len = nfsm_rndup(siz);
                   1111:                        xfer = siz;
                   1112:                        if (xfer < len)
                   1113:                                *(tl+(xfer>>2)) = 0;
                   1114:                } else {
                   1115:                        xfer = len = m1->m_len;
                   1116:                }
                   1117:                bcopy(cp, (caddr_t) tl, xfer);
                   1118:                m1->m_len = len+tlen;
                   1119:                siz -= xfer;
                   1120:                cp += xfer;
                   1121:        }
                   1122:        *mb = m1;
                   1123:        *bpos = mtod(m1, caddr_t)+m1->m_len;
                   1124:        return (0);
                   1125: }
                   1126: 
                   1127: /*
                   1128:  * Called once to initialize data structures...
                   1129:  */
                   1130: int
                   1131: nfs_init(vfsp)
                   1132:        struct vfsconf *vfsp;
                   1133: {
                   1134:        register int i;
                   1135: 
                   1136:        /*
                   1137:         * Check to see if major data structures haven't bloated.
                   1138:         */
                   1139:        if (sizeof (struct nfsnode) > NFS_NODEALLOC) {
                   1140:                printf("struct nfsnode bloated (> %dbytes)\n", NFS_NODEALLOC);
                   1141:                printf("Try reducing NFS_SMALLFH\n");
                   1142:        }
                   1143:        if (sizeof (struct nfsmount) > NFS_MNTALLOC) {
                   1144:                printf("struct nfsmount bloated (> %dbytes)\n", NFS_MNTALLOC);
                   1145:                printf("Try reducing NFS_MUIDHASHSIZ\n");
                   1146:        }
                   1147:        if (sizeof (struct nfssvc_sock) > NFS_SVCALLOC) {
                   1148:                printf("struct nfssvc_sock bloated (> %dbytes)\n",NFS_SVCALLOC);
                   1149:                printf("Try reducing NFS_UIDHASHSIZ\n");
                   1150:        }
                   1151:        if (sizeof (struct nfsuid) > NFS_UIDALLOC) {
                   1152:                printf("struct nfsuid bloated (> %dbytes)\n",NFS_UIDALLOC);
                   1153:                printf("Try unionizing the nu_nickname and nu_flag fields\n");
                   1154:        }
                   1155:        nfs_mount_type = vfsp->vfc_typenum;
                   1156:        nfsrtt.pos = 0;
                   1157:        rpc_vers = txdr_unsigned(RPC_VER2);
                   1158:        rpc_call = txdr_unsigned(RPC_CALL);
                   1159:        rpc_reply = txdr_unsigned(RPC_REPLY);
                   1160:        rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);
                   1161:        rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
                   1162:        rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
                   1163:        rpc_autherr = txdr_unsigned(RPC_AUTHERR);
                   1164:        rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
                   1165:        rpc_auth_kerb = txdr_unsigned(RPCAUTH_KERB4);
                   1166:        nfs_prog = txdr_unsigned(NFS_PROG);
                   1167:        nqnfs_prog = txdr_unsigned(NQNFS_PROG);
                   1168:        nfs_true = txdr_unsigned(TRUE);
                   1169:        nfs_false = txdr_unsigned(FALSE);
                   1170:        nfs_xdrneg1 = txdr_unsigned(-1);
                   1171:        nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
                   1172:        if (nfs_ticks < 1)
                   1173:                nfs_ticks = 1;
                   1174:        /* Ensure async daemons disabled */
                   1175:        for (i = 0; i < NFS_MAXASYNCDAEMON; i++) {
                   1176:                nfs_iodwant[i] = (struct proc *)0;
                   1177:                nfs_iodmount[i] = (struct nfsmount *)0;
                   1178:        }
                   1179:        nfs_nhinit();                   /* Init the nfsnode table */
                   1180: #ifndef NFS_NOSERVER
                   1181:        nfsrv_init(0);                  /* Init server data structures */
                   1182:        nfsrv_initcache();              /* Init the server request cache */
                   1183: #endif
                   1184: 
                   1185:        /*
                   1186:         * Initialize the nqnfs server stuff.
                   1187:         */
                   1188:        if (nqnfsstarttime == 0) {
                   1189:                nqnfsstarttime = boottime.tv_sec + nqsrv_maxlease
                   1190:                        + nqsrv_clockskew + nqsrv_writeslack;
                   1191:                NQLOADNOVRAM(nqnfsstarttime);
                   1192:                CIRCLEQ_INIT(&nqtimerhead);
                   1193:                nqfhhashtbl = hashinit(NQLCHSZ, M_NQLEASE, &nqfhhash);
                   1194:        }
                   1195: 
                   1196:        /*
                   1197:         * Initialize reply list and start timer
                   1198:         */
                   1199:        TAILQ_INIT(&nfs_reqq);
                   1200: 
                   1201:        nfs_timer(0);
                   1202: 
                   1203: 
                   1204: /* XXX CSM 12/4/97 Where are these declared in FreeBSD? */
                   1205: #ifdef notyet
                   1206:        /*
                   1207:         * Set up lease_check and lease_updatetime so that other parts
                   1208:         * of the system can call us, if we are loadable.
                   1209:         */
                   1210: #ifndef NFS_NOSERVER
                   1211:        default_vnodeop_p[VOFFSET(vop_lease)] = (vop_t *)nqnfs_vop_lease_check;
                   1212: #endif
                   1213:        lease_updatetime = nfs_lease_updatetime;
                   1214: #endif
                   1215:        vfsp->vfc_refcount++; /* make us non-unloadable */
                   1216:        sysent[SYS_nfssvc].sy_narg = 2;
                   1217:        sysent[SYS_nfssvc].sy_call = nfssvc;
                   1218: #ifndef NFS_NOSERVER
                   1219:        sysent[SYS_getfh].sy_narg = 2;
                   1220:        sysent[SYS_getfh].sy_call = getfh;
                   1221: #endif
                   1222: 
                   1223:        return (0);
                   1224: }
                   1225: 
                   1226: /*
                   1227:  * Attribute cache routines.
                   1228:  * nfs_loadattrcache() - loads or updates the cache contents from attributes
                   1229:  *     that are on the mbuf list
                   1230:  * nfs_getattrcache() - returns valid attributes if found in cache, returns
                   1231:  *     error otherwise
                   1232:  */
                   1233: 
                   1234: /*
                   1235:  * Load the attribute cache (that lives in the nfsnode entry) with
                   1236:  * the values on the mbuf list and
                   1237:  * Iff vap not NULL
                   1238:  *    copy the attributes to *vaper
                   1239:  */
                   1240: int
                   1241: nfs_loadattrcache(vpp, mdp, dposp, vaper)
                   1242:        struct vnode **vpp;
                   1243:        struct mbuf **mdp;
                   1244:        caddr_t *dposp;
                   1245:        struct vattr *vaper;
                   1246: {
                   1247:        register struct vnode *vp = *vpp;
                   1248:        register struct vattr *vap;
                   1249:        register struct nfs_fattr *fp;
                   1250:        register struct nfsnode *np;
                   1251:        register long t1;
                   1252:        caddr_t cp2;
                   1253:        int error = 0, rdev;
                   1254:        struct mbuf *md;
                   1255:        enum vtype vtyp;
                   1256:        u_short vmode;
                   1257:        struct timespec mtime;
                   1258:        struct vnode *nvp;
                   1259:        int v3 = NFS_ISV3(vp);
                   1260: 
                   1261:        NFSTRACE(NFSTRC_LAC, vp);
                   1262:        md = *mdp;
                   1263:        t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
                   1264:        if ((error = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, &cp2)))
                   1265:                return (error);
                   1266:        fp = (struct nfs_fattr *)cp2;
                   1267:        if (v3) {
                   1268:                vtyp = nfsv3tov_type(fp->fa_type);
                   1269:                vmode = fxdr_unsigned(u_short, fp->fa_mode);
                   1270:                rdev = makedev(fxdr_unsigned(int, fp->fa3_rdev.specdata1),
                   1271:                        fxdr_unsigned(int, fp->fa3_rdev.specdata2));
                   1272:                fxdr_nfsv3time(&fp->fa3_mtime, &mtime);
                   1273:        } else {
                   1274:                vtyp = nfsv2tov_type(fp->fa_type);
                   1275:                vmode = fxdr_unsigned(u_short, fp->fa_mode);
                   1276:                /*
                   1277:                 * XXX
                   1278:                 *
                   1279:                 * The duplicate information returned in fa_type and fa_mode
                   1280:                 * is an ambiguity in the NFS version 2 protocol.
                   1281:                 *
                   1282:                 * VREG should be taken literally as a regular file.  If a
                   1283:                 * server intents to return some type information differently
                   1284:                 * in the upper bits of the mode field (e.g. for sockets, or
                   1285:                 * FIFOs), NFSv2 mandates fa_type to be VNON.  Anyway, we
                   1286:                 * leave the examination of the mode bits even in the VREG
                   1287:                 * case to avoid breakage for bogus servers, but we make sure
                   1288:                 * that there are actually type bits set in the upper part of
                   1289:                 * fa_mode (and failing that, trust the va_type field).
                   1290:                 *
                   1291:                 * NFSv3 cleared the issue, and requires fa_mode to not
                   1292:                 * contain any type information (while also introduing sockets
                   1293:                 * and FIFOs for fa_type).
                   1294:                 */
                   1295:                if (vtyp == VNON || (vtyp == VREG && (vmode & S_IFMT) != 0))
                   1296:                        vtyp = IFTOVT(vmode);
                   1297:                rdev = fxdr_unsigned(long, fp->fa2_rdev);
                   1298:                fxdr_nfsv2time(&fp->fa2_mtime, &mtime);
                   1299: 
                   1300:                /*
                   1301:                 * Really ugly NFSv2 kludge.
                   1302:                 */
                   1303:                if (vtyp == VCHR && rdev == 0xffffffff)
                   1304:                        vtyp = VFIFO;
                   1305:        }
                   1306: 
                   1307:        /*
                   1308:         * If v_type == VNON it is a new node, so fill in the v_type,
                   1309:         * n_mtime fields. Check to see if it represents a special
                   1310:         * device, and if so, check for a possible alias. Once the
                   1311:         * correct vnode has been obtained, fill in the rest of the
                   1312:         * information.
                   1313:         */
                   1314:        np = VTONFS(vp);
                   1315:        if (vp->v_type != vtyp) {
                   1316:                vp->v_type = vtyp;
                   1317: #if MACH_NBC
                   1318:                if ((vp->v_type == VREG)  && !(vp->v_vm_info)){
                   1319:                        vm_info_init(vp);
                   1320:                }
                   1321: #endif /* MACH_NBC */
                   1322:                if (vp->v_type == VFIFO) {
                   1323:                        vp->v_op = fifo_nfsv2nodeop_p;
                   1324:                }
                   1325:                if (vp->v_type == VCHR || vp->v_type == VBLK) {
                   1326:                        vp->v_op = spec_nfsv2nodeop_p;
                   1327:                        nvp = checkalias(vp, (dev_t)rdev, vp->v_mount);
                   1328:                        if (nvp) {
                   1329:                                /*
                   1330:                                 * Discard unneeded vnode, but save its nfsnode.
                   1331:                                 * Since the nfsnode does not have a lock, its
                   1332:                                 * vnode lock has to be carried over.
                   1333:                                 */
                   1334:                                nvp->v_vnlock = vp->v_vnlock;
                   1335:                                vp->v_vnlock = NULL;
                   1336:                                nvp->v_data = vp->v_data;
                   1337:                                vp->v_data = NULL;
                   1338:                                vp->v_op = spec_vnodeop_p;
                   1339:                                vrele(vp);
                   1340:                                vgone(vp);
                   1341:                                /*
                   1342:                                 * Reinitialize aliased node.
                   1343:                                 */
                   1344:                                np->n_vnode = nvp;
                   1345:                                *vpp = vp = nvp;
                   1346:                        }
                   1347:                }
                   1348:                np->n_mtime = mtime.tv_sec;
                   1349:                NFSTRACE(NFSTRC_LAC_INIT, vp);
                   1350:        }
                   1351:        vap = &np->n_vattr;
                   1352:        vap->va_type = vtyp;
                   1353:        vap->va_mode = (vmode & 07777);
                   1354:        vap->va_rdev = (dev_t)rdev;
                   1355:        vap->va_mtime = mtime;
                   1356:        vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
                   1357:        if (v3) {
                   1358:                vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
                   1359:                vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
                   1360:                vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
                   1361:                fxdr_hyper(&fp->fa3_size, &vap->va_size);
                   1362:                vap->va_blocksize = NFS_FABLKSIZE;
                   1363:                fxdr_hyper(&fp->fa3_used, &vap->va_bytes);
                   1364:                vap->va_fileid = fxdr_unsigned(int, fp->fa3_fileid.nfsuquad[1]);
                   1365:                fxdr_nfsv3time(&fp->fa3_atime, &vap->va_atime);
                   1366:                fxdr_nfsv3time(&fp->fa3_ctime, &vap->va_ctime);
                   1367:                vap->va_flags = 0;
                   1368:                vap->va_filerev = 0;
                   1369:        } else {
                   1370:                vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
                   1371:                vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
                   1372:                vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
                   1373:                vap->va_size = fxdr_unsigned(u_long, fp->fa2_size);
                   1374:                vap->va_blocksize = fxdr_unsigned(long, fp->fa2_blocksize);
                   1375:                vap->va_bytes = fxdr_unsigned(long, fp->fa2_blocks) * NFS_FABLKSIZE;
                   1376:                vap->va_fileid = fxdr_unsigned(long, fp->fa2_fileid);
                   1377:                fxdr_nfsv2time(&fp->fa2_atime, &vap->va_atime);
                   1378:                vap->va_flags = 0;
                   1379:                vap->va_ctime.tv_sec = fxdr_unsigned(long, fp->fa2_ctime.nfsv2_sec);
                   1380:                vap->va_ctime.tv_nsec = 0;
                   1381:                vap->va_gen = fxdr_unsigned(u_long, fp->fa2_ctime.nfsv2_usec);
                   1382:                vap->va_filerev = 0;
                   1383:        }
                   1384: 
                   1385:        if (vap->va_size != np->n_size) {
                   1386:                NFSTRACE4(NFSTRC_LAC_NP, vp, vap->va_size, np->n_size,
                   1387:                          (vap->va_type == VREG) |
                   1388:                          (np->n_flag & NMODIFIED ? 2 : 0));
                   1389:                if (vap->va_type == VREG) {
                   1390:                        if (np->n_flag & NMODIFIED) {
                   1391:                                if (vap->va_size < np->n_size)
                   1392:                                        vap->va_size = np->n_size;
                   1393:                                else
                   1394:                                        np->n_size = vap->va_size;
                   1395:                        } else
                   1396:                                np->n_size = vap->va_size;
                   1397: #if    !MACH_NBC
                   1398:                        vnode_pager_setsize(vp, (u_long)np->n_size);
                   1399: #endif /* MACH_NBC */
                   1400:                } else
                   1401:                        np->n_size = vap->va_size;
                   1402:        }
                   1403: 
                   1404: #if    MACH_NBC
                   1405:        if (vap->va_type == VREG && vp->v_vm_info && vp->v_vm_info->mapped &&
                   1406:            vap->va_size != vp->v_vm_info->vnode_size) {
                   1407:                struct vm_info  *vmp = vp->v_vm_info;
                   1408: 
                   1409:                NFSTRACE4(NFSTRC_LAC_MAP, vp, vap->va_size, vmp->vnode_size,
                   1410:                          ((long)(vmp->lock.thread) > 0         ? 0x1000 : 0) |
                   1411:                          (vmp->lock.thread == current_thread() ? 0x2000 : 0) |
                   1412:                          (vmp->lock.want_write                 ? 0x0100 : 0) |
                   1413:                          (vmp->lock.want_upgrade               ? 0x0200 : 0) |
                   1414:                          (vmp->lock.read_count                 ? 0x0400 : 0) |
                   1415:                          (vmp->nfsdirty                        ? 0x0010 : 0) |
                   1416:                          (np->n_flag & NMODIFIED               ? 0x0001 : 0));
                   1417:                if (vmp->nfsdirty || np->n_flag & NMODIFIED) {
                   1418:                        np->n_size = vap->va_size = vmp->vnode_size;
                   1419:                } else if (vmp->lock.want_write || vmp->lock.want_upgrade ||
                   1420:                           vmp->lock.read_count) {
                   1421:                        vmp->invalidate = TRUE; /* vmp_put will do it */
1.1.1.2 ! root     1422:                        NFS_DPF(ATTR, ("nfs_loadattrcache: invalidate vp %x\n",
        !          1423:                                       (unsigned)vp));
1.1       root     1424:                } else { /* clear the way for server's dirt */
                   1425:                        mapfs_memfree(vmp, TRUE);
                   1426:                        vmp->vnode_size = vap->va_size;
1.1.1.2 ! root     1427:                        NFS_DPF(ATTR, ("nfs_loadattrcache: memfree vp %x\n",
        !          1428:                                       (unsigned)vp));
1.1       root     1429:                }
                   1430:        }
                   1431: #endif /* MACH_NBC */
                   1432: 
                   1433:        np->n_attrstamp = time.tv_sec;
                   1434:        if (vaper != NULL) {
                   1435:                bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));
                   1436:                if (np->n_flag & NCHG) {
                   1437:                        if (np->n_flag & NACC)
                   1438:                                vaper->va_atime = np->n_atim;
                   1439:                        if (np->n_flag & NUPD)
                   1440:                                vaper->va_mtime = np->n_mtim;
                   1441:                }
                   1442:        }
                   1443:        return (0);
                   1444: }
                   1445: 
                   1446: /*
                   1447:  * Check the time stamp
                   1448:  * If the cache is valid, copy contents to *vap and return 0
                   1449:  * otherwise return an error
                   1450:  */
                   1451: int
                   1452: nfs_getattrcache(vp, vaper)
                   1453:        register struct vnode *vp;
                   1454:        struct vattr *vaper;
                   1455: {
                   1456:        register struct nfsnode *np = VTONFS(vp);
                   1457:        register struct vattr *vap;
                   1458: 
                   1459:        if ((time.tv_sec - np->n_attrstamp) >= NFS_ATTRTIMEO(np)) {
                   1460:                NFSTRACE(NFSTRC_GAC_MISS, vp);
                   1461:                nfsstats.attrcache_misses++;
                   1462:                return (ENOENT);
                   1463:        }
                   1464:        NFSTRACE(NFSTRC_GAC_HIT, vp);
                   1465:        nfsstats.attrcache_hits++;
                   1466:        vap = &np->n_vattr;
                   1467: 
                   1468:        if (vap->va_size != np->n_size) {
                   1469:                NFSTRACE4(NFSTRC_GAC_NP, vp, vap->va_size, np->n_size,
                   1470:                          (vap->va_type == VREG) |
                   1471:                          (np->n_flag & NMODIFIED ? 2 : 0));
                   1472:                if (vap->va_type == VREG) {
                   1473:                        if (np->n_flag & NMODIFIED) {
                   1474:                                if (vap->va_size < np->n_size)
                   1475:                                        vap->va_size = np->n_size;
                   1476:                                else
                   1477:                                        np->n_size = vap->va_size;
                   1478:                        } else
                   1479:                                np->n_size = vap->va_size;
                   1480: #if !MACH_NBC
                   1481:                        vnode_pager_setsize(vp, (u_long)np->n_size);
                   1482: #endif /* !MACH_NBC */
                   1483:                } else
                   1484:                        np->n_size = vap->va_size;
                   1485:        }
                   1486: 
                   1487: #if MACH_NBC
                   1488:        if (vap->va_type == VREG && vp->v_vm_info && vp->v_vm_info->mapped &&
                   1489:            vap->va_size != vp->v_vm_info->vnode_size) {
                   1490:                struct vm_info  *vmp = vp->v_vm_info;
                   1491: 
                   1492:                NFSTRACE4(NFSTRC_GAC_MAP, vp, vap->va_size, vmp->vnode_size,
                   1493:                          ((long)(vmp->lock.thread) > 0         ? 0x1000 : 0) |
                   1494:                          (vmp->lock.thread == current_thread() ? 0x2000 : 0) |
                   1495:                          (vmp->lock.want_write                 ? 0x0100 : 0) |
                   1496:                          (vmp->lock.want_upgrade               ? 0x0200 : 0) |
                   1497:                          (vmp->lock.read_count                 ? 0x0400 : 0) |
                   1498:                          (vmp->nfsdirty                        ? 0x0010 : 0) |
                   1499:                          (np->n_flag & NMODIFIED               ? 0x0001 : 0));
                   1500:                if (vmp->nfsdirty || np->n_flag & NMODIFIED) {
                   1501:                        /* keep eating our own dirt */
                   1502:                        np->n_size = vap->va_size = vmp->vnode_size;
                   1503:                } else if (vmp->lock.want_write || vmp->lock.want_upgrade ||
                   1504:                           vmp->lock.read_count) {
                   1505:                        vmp->invalidate = TRUE; /* vmp_put will do it */
1.1.1.2 ! root     1506:                        NFS_DPF(ATTR, ("nfs_getattrcache: invalidate vp %x\n",
        !          1507:                                       (unsigned)vp));
1.1       root     1508:                } else { /* clear the way for server's dirt */
                   1509:                        mapfs_memfree(vmp, TRUE);
                   1510:                        vmp->vnode_size = vap->va_size;
1.1.1.2 ! root     1511:                        NFS_DPF(ATTR, ("nfs_getattrcache: memfree vp %x\n",
        !          1512:                                       (unsigned)vp));
1.1       root     1513:                }
                   1514:        }
                   1515: #endif /* MACH_NBC */
                   1516: 
                   1517:        bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(struct vattr));
                   1518:        if (np->n_flag & NCHG) {
                   1519:                if (np->n_flag & NACC)
                   1520:                        vaper->va_atime = np->n_atim;
                   1521:                if (np->n_flag & NUPD)
                   1522:                        vaper->va_mtime = np->n_mtim;
                   1523:        }
                   1524:        return (0);
                   1525: }
                   1526: 
                   1527: #ifndef NFS_NOSERVER
                   1528: /*
                   1529:  * Set up nameidata for a lookup() call and do it.
                   1530:  *
                   1531:  * If pubflag is set, this call is done for a lookup operation on the
                   1532:  * public filehandle. In that case we allow crossing mountpoints and
                   1533:  * absolute pathnames. However, the caller is expected to check that
                   1534:  * the lookup result is within the public fs, and deny access if
                   1535:  * it is not.
                   1536:  */
                   1537: int
                   1538: nfs_namei(ndp, fhp, len, slp, nam, mdp, dposp, retdirp, p, kerbflag, pubflag)
                   1539:        register struct nameidata *ndp;
                   1540:        fhandle_t *fhp;
                   1541:        int len;
                   1542:        struct nfssvc_sock *slp;
                   1543:        struct mbuf *nam;
                   1544:        struct mbuf **mdp;
                   1545:        caddr_t *dposp;
                   1546:        struct vnode **retdirp;
                   1547:        struct proc *p;
                   1548:        int kerbflag, pubflag;
                   1549: {
                   1550:        register int i, rem;
                   1551:        register struct mbuf *md;
                   1552:        register char *fromcp, *tocp, *cp;
                   1553:        struct iovec aiov;
                   1554:        struct uio auio;
                   1555:        struct vnode *dp;
                   1556:        int error, rdonly, linklen;
                   1557:        struct componentname *cnp = &ndp->ni_cnd;
                   1558:        int olen = len;
                   1559: 
                   1560:        *retdirp = (struct vnode *)0;
                   1561:        MALLOC_ZONE(cnp->cn_pnbuf, char *, len + 1, M_NAMEI, M_WAITOK);
                   1562:        cnp->cn_pnlen = len + 1;
                   1563: 
                   1564:        /*
                   1565:         * Copy the name from the mbuf list to ndp->ni_pnbuf
                   1566:         * and set the various ndp fields appropriately.
                   1567:         */
                   1568:        fromcp = *dposp;
                   1569:        tocp = cnp->cn_pnbuf;
                   1570:        md = *mdp;
                   1571:        rem = mtod(md, caddr_t) + md->m_len - fromcp;
                   1572:        cnp->cn_hash = 0;
                   1573:        for (i = 1; i <= len; i++) {
                   1574:                while (rem == 0) {
                   1575:                        md = md->m_next;
                   1576:                        if (md == NULL) {
                   1577:                                error = EBADRPC;
                   1578:                                goto out;
                   1579:                        }
                   1580:                        fromcp = mtod(md, caddr_t);
                   1581:                        rem = md->m_len;
                   1582:                }
                   1583: /* XXX CSM 12/4/97 Revisit when enabling WebNFS */
                   1584: #ifdef notdef
                   1585:                if (*fromcp == '\0' || (!pubflag && *fromcp == '/')) {
                   1586: #else
                   1587:                if (*fromcp == '\0' || *fromcp == '/') {
                   1588: #endif
                   1589:                        error = EACCES;
                   1590:                        goto out;
                   1591:                }
                   1592:                cnp->cn_hash += (unsigned char)*fromcp * i;
                   1593:                *tocp++ = *fromcp++;
                   1594:                rem--;
                   1595:        }
                   1596:        *tocp = '\0';
                   1597:        *mdp = md;
                   1598:        *dposp = fromcp;
                   1599:        len = nfsm_rndup(len)-len;
                   1600:        if (len > 0) {
                   1601:                if (rem >= len)
                   1602:                        *dposp += len;
                   1603:                else if ((error = nfs_adv(mdp, dposp, len, rem)) != 0)
                   1604:                        goto out;
                   1605:        }
                   1606: 
                   1607:        /*
                   1608:         * Extract and set starting directory.
                   1609:         */
                   1610:        error = nfsrv_fhtovp(fhp, FALSE, &dp, ndp->ni_cnd.cn_cred, slp,
                   1611:            nam, &rdonly, kerbflag, pubflag);
                   1612:        if (error)
                   1613:                goto out;
                   1614:        if (dp->v_type != VDIR) {
                   1615:                vrele(dp);
                   1616:                error = ENOTDIR;
                   1617:                goto out;
                   1618:        }
                   1619: 
                   1620:        if (rdonly)
                   1621:                cnp->cn_flags |= RDONLY;
                   1622: 
                   1623:        *retdirp = dp;
                   1624: 
                   1625: /* XXX CSM 12/4/97 Revisit when enabling WebNFS */
                   1626: /* XXX debo 12/15/97 Need to fix M_NAMEI allocations to use zone protocol */
                   1627: #ifdef notyet
                   1628:        if (pubflag) {
                   1629:                /*
                   1630:                 * Oh joy. For WebNFS, handle those pesky '%' escapes,
                   1631:                 * and the 'native path' indicator.
                   1632:                 */
                   1633:                MALLOC(cp, char *, olen + 1, M_NAMEI, M_WAITOK);
                   1634:                fromcp = cnp->cn_pnbuf;
                   1635:                tocp = cp;
                   1636:                if ((unsigned char)*fromcp >= WEBNFS_SPECCHAR_START) {
                   1637:                        switch ((unsigned char)*fromcp) {
                   1638:                        case WEBNFS_NATIVE_CHAR:
                   1639:                                /*
                   1640:                                 * 'Native' path for us is the same
                   1641:                                 * as a path according to the NFS spec,
                   1642:                                 * just skip the escape char.
                   1643:                                 */
                   1644:                                fromcp++;
                   1645:                                break;
                   1646:                        /*
                   1647:                         * More may be added in the future, range 0x80-0xff
                   1648:                         */
                   1649:                        default:
                   1650:                                error = EIO;
                   1651:                                FREE(cp, M_NAMEI);
                   1652:                                goto out;
                   1653:                        }
                   1654:                }
                   1655:                /*
                   1656:                 * Translate the '%' escapes, URL-style.
                   1657:                 */
                   1658:                while (*fromcp != '\0') {
                   1659:                        if (*fromcp == WEBNFS_ESC_CHAR) {
                   1660:                                if (fromcp[1] != '\0' && fromcp[2] != '\0') {
                   1661:                                        fromcp++;
                   1662:                                        *tocp++ = HEXSTRTOI(fromcp);
                   1663:                                        fromcp += 2;
                   1664:                                        continue;
                   1665:                                } else {
                   1666:                                        error = ENOENT;
                   1667:                                        FREE(cp, M_NAMEI);
                   1668:                                        goto out;
                   1669:                                }
                   1670:                        } else
                   1671:                                *tocp++ = *fromcp++;
                   1672:                }
                   1673:                *tocp = '\0';
                   1674:                FREE(cnp->cn_pnbuf, M_NAMEI);
                   1675:                cnp->cn_pnbuf = cp;
                   1676:        }
                   1677: #endif
                   1678: 
                   1679:        ndp->ni_pathlen = (tocp - cnp->cn_pnbuf) + 1;
                   1680:        ndp->ni_segflg = UIO_SYSSPACE;
                   1681: 
                   1682: /* XXX CSM 12/4/97 Revisit when enabling WebNFS */
                   1683: #ifdef notyet
                   1684:        if (pubflag) {
                   1685:                ndp->ni_rootdir = rootvnode;
                   1686:                ndp->ni_loopcnt = 0;
                   1687:                if (cnp->cn_pnbuf[0] == '/')
                   1688:                        dp = rootvnode;
                   1689:        } else {
                   1690:                cnp->cn_flags |= NOCROSSMOUNT;
                   1691:        }
                   1692: #else
                   1693:        cnp->cn_flags |= NOCROSSMOUNT;
                   1694: #endif
                   1695: 
                   1696:        cnp->cn_proc = p;
                   1697:        VREF(dp);
                   1698: 
                   1699:     for (;;) {
                   1700:        cnp->cn_nameptr = cnp->cn_pnbuf;
                   1701:        ndp->ni_startdir = dp;
                   1702:        /*
                   1703:         * And call lookup() to do the real work
                   1704:         */
                   1705:        error = lookup(ndp);
                   1706:        if (error)
                   1707:                break;
                   1708:        /*
                   1709:         * Check for encountering a symbolic link
                   1710:         */
                   1711:        if ((cnp->cn_flags & ISSYMLINK) == 0) {
                   1712:                nfsrv_object_create(ndp->ni_vp);
                   1713:                if (cnp->cn_flags & (SAVENAME | SAVESTART)) {
                   1714:                        cnp->cn_flags |= HASBUF;
                   1715:                        return (0);
                   1716:                }
                   1717:                break;
                   1718:        } else {
                   1719:                if ((cnp->cn_flags & LOCKPARENT) && ndp->ni_pathlen == 1)
                   1720:                        VOP_UNLOCK(ndp->ni_dvp, 0, p);
                   1721: /* XXX CSM 12/4/97 Revisit when enabling WebNFS */
                   1722: #ifdef notyet
                   1723:                if (!pubflag) {
                   1724: #endif
                   1725:                        vrele(ndp->ni_dvp);
                   1726:                        vput(ndp->ni_vp);
                   1727:                        ndp->ni_vp = NULL;
                   1728:                        error = EINVAL;
                   1729:                        break;
                   1730: /* XXX CSM 12/4/97 Revisit when enabling WebNFS */
                   1731: /* XXX debo 12/15/97 Need to fix M_NAMEI allocations to use zone protocol */
                   1732: #ifdef notyet
                   1733:                }
                   1734: 
                   1735:                if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
                   1736:                        error = ELOOP;
                   1737:                        break;
                   1738:                }
                   1739:                if (ndp->ni_pathlen > 1)
                   1740:                        MALLOC(cp, char *, olen + 1, M_NAMEI, M_WAITOK);
                   1741:                else
                   1742:                        cp = cnp->cn_pnbuf;
                   1743:                aiov.iov_base = cp;
                   1744:                aiov.iov_len = MAXPATHLEN;
                   1745:                auio.uio_iov = &aiov;
                   1746:                auio.uio_iovcnt = 1;
                   1747:                auio.uio_offset = 0;
                   1748:                auio.uio_rw = UIO_READ;
                   1749:                auio.uio_segflg = UIO_SYSSPACE;
                   1750:                auio.uio_procp = (struct proc *)0;
                   1751:                auio.uio_resid = MAXPATHLEN;
                   1752:                error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred);
                   1753:                if (error) {
                   1754:                badlink:
                   1755:                        if (ndp->ni_pathlen > 1)
                   1756:                                FREE(cp, M_NAMEI);
                   1757:                        break;
                   1758:                }
                   1759:                linklen = MAXPATHLEN - auio.uio_resid;
                   1760:                if (linklen == 0) {
                   1761:                        error = ENOENT;
                   1762:                        goto badlink;
                   1763:                }
                   1764:                if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
                   1765:                        error = ENAMETOOLONG;
                   1766:                        goto badlink;
                   1767:                }
                   1768:                if (ndp->ni_pathlen > 1) {
                   1769:                        bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen);
                   1770:                        FREE(cnp->cn_pnbuf, M_NAMEI);
                   1771:                        cnp->cn_pnbuf = cp;
                   1772:                } else
                   1773:                        cnp->cn_pnbuf[linklen] = '\0';
                   1774:                ndp->ni_pathlen += linklen;
                   1775:                vput(ndp->ni_vp);
                   1776:                dp = ndp->ni_dvp;
                   1777:                /*
                   1778:                 * Check if root directory should replace current directory.
                   1779:                 */
                   1780:                if (cnp->cn_pnbuf[0] == '/') {
                   1781:                        vrele(dp);
                   1782:                        dp = ndp->ni_rootdir;
                   1783:                        VREF(dp);
                   1784:                }
                   1785: #endif
                   1786:        }
                   1787:    }
                   1788: out:
                   1789:        FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI);
                   1790:        return (error);
                   1791: }
                   1792: 
                   1793: /*
                   1794:  * A fiddled version of m_adj() that ensures null fill to a long
                   1795:  * boundary and only trims off the back end
                   1796:  */
                   1797: void
                   1798: nfsm_adj(mp, len, nul)
                   1799:        struct mbuf *mp;
                   1800:        register int len;
                   1801:        int nul;
                   1802: {
                   1803:        register struct mbuf *m;
                   1804:        register int count, i;
                   1805:        register char *cp;
                   1806: 
                   1807:        /*
                   1808:         * Trim from tail.  Scan the mbuf chain,
                   1809:         * calculating its length and finding the last mbuf.
                   1810:         * If the adjustment only affects this mbuf, then just
                   1811:         * adjust and return.  Otherwise, rescan and truncate
                   1812:         * after the remaining size.
                   1813:         */
                   1814:        count = 0;
                   1815:        m = mp;
                   1816:        for (;;) {
                   1817:                count += m->m_len;
                   1818:                if (m->m_next == (struct mbuf *)0)
                   1819:                        break;
                   1820:                m = m->m_next;
                   1821:        }
                   1822:        if (m->m_len > len) {
                   1823:                m->m_len -= len;
                   1824:                if (nul > 0) {
                   1825:                        cp = mtod(m, caddr_t)+m->m_len-nul;
                   1826:                        for (i = 0; i < nul; i++)
                   1827:                                *cp++ = '\0';
                   1828:                }
                   1829:                return;
                   1830:        }
                   1831:        count -= len;
                   1832:        if (count < 0)
                   1833:                count = 0;
                   1834:        /*
                   1835:         * Correct length for chain is "count".
                   1836:         * Find the mbuf with last data, adjust its length,
                   1837:         * and toss data from remaining mbufs on chain.
                   1838:         */
                   1839:        for (m = mp; m; m = m->m_next) {
                   1840:                if (m->m_len >= count) {
                   1841:                        m->m_len = count;
                   1842:                        if (nul > 0) {
                   1843:                                cp = mtod(m, caddr_t)+m->m_len-nul;
                   1844:                                for (i = 0; i < nul; i++)
                   1845:                                        *cp++ = '\0';
                   1846:                        }
                   1847:                        break;
                   1848:                }
                   1849:                count -= m->m_len;
                   1850:        }
                   1851:        for (m = m->m_next;m;m = m->m_next)
                   1852:                m->m_len = 0;
                   1853: }
                   1854: 
                   1855: /*
                   1856:  * Make these functions instead of macros, so that the kernel text size
                   1857:  * doesn't get too big...
                   1858:  */
                   1859: void
                   1860: nfsm_srvwcc(nfsd, before_ret, before_vap, after_ret, after_vap, mbp, bposp)
                   1861:        struct nfsrv_descript *nfsd;
                   1862:        int before_ret;
                   1863:        register struct vattr *before_vap;
                   1864:        int after_ret;
                   1865:        struct vattr *after_vap;
                   1866:        struct mbuf **mbp;
                   1867:        char **bposp;
                   1868: {
                   1869:        register struct mbuf *mb = *mbp, *mb2;
                   1870:        register char *bpos = *bposp;
                   1871:        register u_long *tl;
                   1872: 
                   1873:        if (before_ret) {
                   1874:                nfsm_build(tl, u_long *, NFSX_UNSIGNED);
                   1875:                *tl = nfs_false;
                   1876:        } else {
                   1877:                nfsm_build(tl, u_long *, 7 * NFSX_UNSIGNED);
                   1878:                *tl++ = nfs_true;
                   1879:                txdr_hyper(&(before_vap->va_size), tl);
                   1880:                tl += 2;
                   1881:                txdr_nfsv3time(&(before_vap->va_mtime), tl);
                   1882:                tl += 2;
                   1883:                txdr_nfsv3time(&(before_vap->va_ctime), tl);
                   1884:        }
                   1885:        *bposp = bpos;
                   1886:        *mbp = mb;
                   1887:        nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp);
                   1888: }
                   1889: 
                   1890: void
                   1891: nfsm_srvpostopattr(nfsd, after_ret, after_vap, mbp, bposp)
                   1892:        struct nfsrv_descript *nfsd;
                   1893:        int after_ret;
                   1894:        struct vattr *after_vap;
                   1895:        struct mbuf **mbp;
                   1896:        char **bposp;
                   1897: {
                   1898:        register struct mbuf *mb = *mbp, *mb2;
                   1899:        register char *bpos = *bposp;
                   1900:        register u_long *tl;
                   1901:        register struct nfs_fattr *fp;
                   1902: 
                   1903:        if (after_ret) {
                   1904:                nfsm_build(tl, u_long *, NFSX_UNSIGNED);
                   1905:                *tl = nfs_false;
                   1906:        } else {
                   1907:                nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3FATTR);
                   1908:                *tl++ = nfs_true;
                   1909:                fp = (struct nfs_fattr *)tl;
                   1910:                nfsm_srvfattr(nfsd, after_vap, fp);
                   1911:        }
                   1912:        *mbp = mb;
                   1913:        *bposp = bpos;
                   1914: }
                   1915: 
                   1916: void
                   1917: nfsm_srvfattr(nfsd, vap, fp)
                   1918:        register struct nfsrv_descript *nfsd;
                   1919:        register struct vattr *vap;
                   1920:        register struct nfs_fattr *fp;
                   1921: {
                   1922: 
                   1923:        fp->fa_nlink = txdr_unsigned(vap->va_nlink);
                   1924:        fp->fa_uid = txdr_unsigned(vap->va_uid);
                   1925:        fp->fa_gid = txdr_unsigned(vap->va_gid);
                   1926:        if (nfsd->nd_flag & ND_NFSV3) {
                   1927:                fp->fa_type = vtonfsv3_type(vap->va_type);
                   1928:                fp->fa_mode = vtonfsv3_mode(vap->va_mode);
                   1929:                txdr_hyper(&vap->va_size, &fp->fa3_size);
                   1930:                txdr_hyper(&vap->va_bytes, &fp->fa3_used);
                   1931:                fp->fa3_rdev.specdata1 = txdr_unsigned(major(vap->va_rdev));
                   1932:                fp->fa3_rdev.specdata2 = txdr_unsigned(minor(vap->va_rdev));
                   1933:                fp->fa3_fsid.nfsuquad[0] = 0;
                   1934:                fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(vap->va_fsid);
                   1935:                fp->fa3_fileid.nfsuquad[0] = 0;
                   1936:                fp->fa3_fileid.nfsuquad[1] = txdr_unsigned(vap->va_fileid);
                   1937:                txdr_nfsv3time(&vap->va_atime, &fp->fa3_atime);
                   1938:                txdr_nfsv3time(&vap->va_mtime, &fp->fa3_mtime);
                   1939:                txdr_nfsv3time(&vap->va_ctime, &fp->fa3_ctime);
                   1940:        } else {
                   1941:                fp->fa_type = vtonfsv2_type(vap->va_type);
                   1942:                fp->fa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
                   1943:                fp->fa2_size = txdr_unsigned(vap->va_size);
                   1944:                fp->fa2_blocksize = txdr_unsigned(vap->va_blocksize);
                   1945:                if (vap->va_type == VFIFO)
                   1946:                        fp->fa2_rdev = 0xffffffff;
                   1947:                else
                   1948:                        fp->fa2_rdev = txdr_unsigned(vap->va_rdev);
                   1949:                fp->fa2_blocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE);
                   1950:                fp->fa2_fsid = txdr_unsigned(vap->va_fsid);
                   1951:                fp->fa2_fileid = txdr_unsigned(vap->va_fileid);
                   1952:                txdr_nfsv2time(&vap->va_atime, &fp->fa2_atime);
                   1953:                txdr_nfsv2time(&vap->va_mtime, &fp->fa2_mtime);
                   1954:                txdr_nfsv2time(&vap->va_ctime, &fp->fa2_ctime);
                   1955:        }
                   1956: }
                   1957: 
                   1958: /*
                   1959:  * nfsrv_fhtovp() - convert a fh to a vnode ptr (optionally locked)
                   1960:  *     - look up fsid in mount list (if not found ret error)
                   1961:  *     - get vp and export rights by calling VFS_FHTOVP()
                   1962:  *     - if cred->cr_uid == 0 or MNT_EXPORTANON set it to credanon
                   1963:  *     - if not lockflag unlock it with VOP_UNLOCK()
                   1964:  */
                   1965: int
                   1966: nfsrv_fhtovp(fhp, lockflag, vpp, cred, slp, nam, rdonlyp, kerbflag, pubflag)
                   1967:        fhandle_t *fhp;
                   1968:        int lockflag;
                   1969:        struct vnode **vpp;
                   1970:        struct ucred *cred;
                   1971:        struct nfssvc_sock *slp;
                   1972:        struct mbuf *nam;
                   1973:        int *rdonlyp;
                   1974:        int kerbflag;
                   1975:        int pubflag;
                   1976: {
                   1977:        struct proc *p = current_proc();        /* XXX */
                   1978:        register struct mount *mp;
                   1979:        register int i;
                   1980:        struct ucred *credanon;
                   1981:        int error, exflags;
                   1982: 
                   1983:        *vpp = (struct vnode *)0;
                   1984: 
                   1985: /* XXX CSM 12/4/97 Revisit when enabling WebNFS */
                   1986: #ifdef notyet
                   1987:        if (nfs_ispublicfh(fhp)) {
                   1988:                if (!pubflag || !nfs_pub.np_valid)
                   1989:                        return (ESTALE);
                   1990:                fhp = &nfs_pub.np_handle;
                   1991:        }
                   1992: #endif
                   1993: 
                   1994:        mp = vfs_getvfs(&fhp->fh_fsid);
                   1995:        if (!mp)
                   1996:                return (ESTALE);
                   1997:        error = VFS_FHTOVP(mp, &fhp->fh_fid, nam, vpp, &exflags, &credanon);
                   1998:        if (error)
                   1999:                return (error);
                   2000:        /*
                   2001:         * Check/setup credentials.
                   2002:         */
                   2003:        if (exflags & MNT_EXKERB) {
                   2004:                if (!kerbflag) {
                   2005:                        vput(*vpp);
                   2006:                        return (NFSERR_AUTHERR | AUTH_TOOWEAK);
                   2007:                }
                   2008:        } else if (kerbflag) {
                   2009:                vput(*vpp);
                   2010:                return (NFSERR_AUTHERR | AUTH_TOOWEAK);
                   2011:        } else if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
                   2012:                cred->cr_uid = credanon->cr_uid;
                   2013:                for (i = 0; i < credanon->cr_ngroups && i < NGROUPS; i++)
                   2014:                        cred->cr_groups[i] = credanon->cr_groups[i];
                   2015:                cred->cr_ngroups = i;
                   2016:        }
                   2017:        if (exflags & MNT_EXRDONLY)
                   2018:                *rdonlyp = 1;
                   2019:        else
                   2020:                *rdonlyp = 0;
                   2021: 
                   2022:        nfsrv_object_create(*vpp);
                   2023: 
                   2024:        if (!lockflag)
                   2025:                VOP_UNLOCK(*vpp, 0, p);
                   2026:        return (0);
                   2027: }
                   2028: 
                   2029: 
                   2030: /*
                   2031:  * WebNFS: check if a filehandle is a public filehandle. For v3, this
                   2032:  * means a length of 0, for v2 it means all zeroes. nfsm_srvmtofh has
                   2033:  * transformed this to all zeroes in both cases, so check for it.
                   2034:  */
                   2035: int
                   2036: nfs_ispublicfh(fhp)
                   2037:        fhandle_t *fhp;
                   2038: {
                   2039:        char *cp = (char *)fhp;
                   2040:        int i;
                   2041: 
                   2042:        for (i = 0; i < NFSX_V3FH; i++)
                   2043:                if (*cp++ != 0)
                   2044:                        return (FALSE);
                   2045:        return (TRUE);
                   2046: }
                   2047:   
                   2048: #endif /* NFS_NOSERVER */
                   2049: /*
                   2050:  * This function compares two net addresses by family and returns TRUE
                   2051:  * if they are the same host.
                   2052:  * If there is any doubt, return FALSE.
                   2053:  * The AF_INET family is handled as a special case so that address mbufs
                   2054:  * don't need to be saved to store "struct in_addr", which is only 4 bytes.
                   2055:  */
                   2056: int
                   2057: netaddr_match(family, haddr, nam)
                   2058:        int family;
                   2059:        union nethostaddr *haddr;
                   2060:        struct mbuf *nam;
                   2061: {
                   2062:        register struct sockaddr_in *inetaddr;
                   2063: 
                   2064:        switch (family) {
                   2065:        case AF_INET:
                   2066:                inetaddr = mtod(nam, struct sockaddr_in *);
                   2067:                if (inetaddr->sin_family == AF_INET &&
                   2068:                    inetaddr->sin_addr.s_addr == haddr->had_inetaddr)
                   2069:                        return (1);
                   2070:                break;
                   2071: #if ISO
                   2072:        case AF_ISO:
                   2073:            {
                   2074:                register struct sockaddr_iso *isoaddr1, *isoaddr2;
                   2075: 
                   2076:                isoaddr1 = mtod(nam, struct sockaddr_iso *);
                   2077:                isoaddr2 = mtod(haddr->had_nam, struct sockaddr_iso *);
                   2078:                if (isoaddr1->siso_family == AF_ISO &&
                   2079:                    isoaddr1->siso_nlen > 0 &&
                   2080:                    isoaddr1->siso_nlen == isoaddr2->siso_nlen &&
                   2081:                    SAME_ISOADDR(isoaddr1, isoaddr2))
                   2082:                        return (1);
                   2083:                break;
                   2084:            }
                   2085: #endif /* ISO */
                   2086:        default:
                   2087:                break;
                   2088:        };
                   2089:        return (0);
                   2090: }
                   2091: 
                   2092: static nfsuint64 nfs_nullcookie = { 0, 0 };
                   2093: /*
                   2094:  * This function finds the directory cookie that corresponds to the
                   2095:  * logical byte offset given.
                   2096:  */
                   2097: nfsuint64 *
                   2098: nfs_getcookie(np, off, add)
                   2099:        register struct nfsnode *np;
                   2100:        off_t off;
                   2101:        int add;
                   2102: {
                   2103:        register struct nfsdmap *dp, *dp2;
                   2104:        register int pos;
                   2105: 
                   2106:        pos = off / NFS_DIRBLKSIZ;
                   2107:        if (pos == 0) {
                   2108: #if DIAGNOSTIC
                   2109:                if (add)
                   2110:                        panic("nfs getcookie add at 0");
                   2111: #endif
                   2112:                return (&nfs_nullcookie);
                   2113:        }
                   2114:        pos--;
                   2115:        dp = np->n_cookies.lh_first;
                   2116:        if (!dp) {
                   2117:                if (add) {
                   2118:                        MALLOC_ZONE(dp, struct nfsdmap *,
                   2119:                                                sizeof (struct nfsdmap),
                   2120:                                                        M_NFSDIROFF, M_WAITOK);
                   2121:                        dp->ndm_eocookie = 0;
                   2122:                        LIST_INSERT_HEAD(&np->n_cookies, dp, ndm_list);
                   2123:                } else
                   2124:                        return ((nfsuint64 *)0);
                   2125:        }
                   2126:        while (pos >= NFSNUMCOOKIES) {
                   2127:                pos -= NFSNUMCOOKIES;
                   2128:                if (dp->ndm_list.le_next) {
                   2129:                        if (!add && dp->ndm_eocookie < NFSNUMCOOKIES &&
                   2130:                                pos >= dp->ndm_eocookie)
                   2131:                                return ((nfsuint64 *)0);
                   2132:                        dp = dp->ndm_list.le_next;
                   2133:                } else if (add) {
                   2134:                        MALLOC_ZONE(dp2, struct nfsdmap *,
                   2135:                                                sizeof (struct nfsdmap),
                   2136:                                                        M_NFSDIROFF, M_WAITOK);
                   2137:                        dp2->ndm_eocookie = 0;
                   2138:                        LIST_INSERT_AFTER(dp, dp2, ndm_list);
                   2139:                        dp = dp2;
                   2140:                } else
                   2141:                        return ((nfsuint64 *)0);
                   2142:        }
                   2143:        if (pos >= dp->ndm_eocookie) {
                   2144:                if (add)
                   2145:                        dp->ndm_eocookie = pos + 1;
                   2146:                else
                   2147:                        return ((nfsuint64 *)0);
                   2148:        }
                   2149:        return (&dp->ndm_cookies[pos]);
                   2150: }
                   2151: 
                   2152: /*
                   2153:  * Invalidate cached directory information, except for the actual directory
                   2154:  * blocks (which are invalidated separately).
                   2155:  * Done mainly to avoid the use of stale offset cookies.
                   2156:  */
                   2157: void
                   2158: nfs_invaldir(vp)
                   2159:        register struct vnode *vp;
                   2160: {
                   2161:        register struct nfsnode *np = VTONFS(vp);
                   2162: 
                   2163: #if DIAGNOSTIC
                   2164:        if (vp->v_type != VDIR)
                   2165:                panic("nfs: invaldir not dir");
                   2166: #endif
                   2167:        np->n_direofoffset = 0;
                   2168:        np->n_cookieverf.nfsuquad[0] = 0;
                   2169:        np->n_cookieverf.nfsuquad[1] = 0;
                   2170:        if (np->n_cookies.lh_first)
                   2171:                np->n_cookies.lh_first->ndm_eocookie = 0;
                   2172: }
                   2173: 
                   2174: /*
                   2175:  * The write verifier has changed (probably due to a server reboot), so all
                   2176:  * B_NEEDCOMMIT blocks will have to be written again. Since they are on the
                   2177:  * dirty block list as B_DELWRI, all this takes is clearing the B_NEEDCOMMIT
                   2178:  * flag. Once done the new write verifier can be set for the mount point.
                   2179:  */
                   2180: void
                   2181: nfs_clearcommit(mp)
                   2182:        struct mount *mp;
                   2183: {
                   2184:        register struct vnode *vp, *nvp;
                   2185:        register struct buf *bp, *nbp;
                   2186:        int s;
                   2187: 
                   2188:        s = splbio();
                   2189: loop:
                   2190:        for (vp = mp->mnt_vnodelist.lh_first; vp; vp = nvp) {
                   2191:                if (vp->v_mount != mp)  /* Paranoia */
                   2192:                        goto loop;
                   2193:                nvp = vp->v_mntvnodes.le_next;
                   2194:                for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
                   2195:                        nbp = bp->b_vnbufs.le_next;
                   2196:                        if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
                   2197:                                == (B_DELWRI | B_NEEDCOMMIT))
                   2198:                                bp->b_flags &= ~B_NEEDCOMMIT;
                   2199:                }
                   2200:        }
                   2201:        splx(s);
                   2202: }
                   2203: 
                   2204: #ifndef NFS_NOSERVER
                   2205: /*
                   2206:  * Map errnos to NFS error numbers. For Version 3 also filter out error
                   2207:  * numbers not specified for the associated procedure.
                   2208:  */
                   2209: int
                   2210: nfsrv_errmap(nd, err)
                   2211:        struct nfsrv_descript *nd;
                   2212:        register int err;
                   2213: {
                   2214:        register short *defaulterrp, *errp;
                   2215: 
                   2216:        if (nd->nd_flag & ND_NFSV3) {
                   2217:            if (nd->nd_procnum <= NFSPROC_COMMIT) {
                   2218:                errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
                   2219:                while (*++errp) {
                   2220:                        if (*errp == err)
                   2221:                                return (err);
                   2222:                        else if (*errp > err)
                   2223:                                break;
                   2224:                }
                   2225:                return ((int)*defaulterrp);
                   2226:            } else
                   2227:                return (err & 0xffff);
                   2228:        }
                   2229:        if (err <= ELAST)
                   2230:                return ((int)nfsrv_v2errmap[err - 1]);
                   2231:        return (NFSERR_IO);
                   2232: }
                   2233: 
                   2234: /* XXX CSM 11/25/97 Revisit when Ramesh merges vm with buffer cache */
                   2235: #define vfs_object_create(v, p, c, l) (0)
                   2236: 
                   2237: int
                   2238: nfsrv_object_create(struct vnode *vp) {
                   2239:        struct proc *curproc = current_proc();
                   2240: 
                   2241:        if ((vp == NULL) || (vp->v_type != VREG))
                   2242:                return 1;
                   2243:        return vfs_object_create(vp, curproc, curproc?curproc->p_ucred:NULL, 1);
                   2244: }
                   2245: #endif /* NFS_NOSERVER */
                   2246: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.