2024-09-08 20:50:14 -07:00
|
|
|
/* $OpenBSD: nfs_subs.c,v 1.151 2024/09/09 03:50:14 jsg Exp $ */
|
1996-07-27 04:09:39 -07:00
|
|
|
/* $NetBSD: nfs_subs.c,v 1.27.4.3 1996/07/08 20:34:24 jtc Exp $ */
|
1995-10-18 01:37:01 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 1989, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
*
|
|
|
|
* This code is derived from software contributed to Berkeley by
|
|
|
|
* Rick Macklem at The University of Guelph.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2003-06-02 16:27:43 -07:00
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
1995-10-18 01:37:01 -07:00
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
1996-03-31 05:15:23 -08:00
|
|
|
* @(#)nfs_subs.c 8.8 (Berkeley) 5/22/95
|
1995-10-18 01:37:01 -07:00
|
|
|
*/
|
|
|
|
|
1996-03-31 05:15:23 -08:00
|
|
|
|
1995-10-18 01:37:01 -07:00
|
|
|
/*
|
2024-04-30 10:04:23 -07:00
|
|
|
* These functions support the nfsm_subs.h inline functions and help fiddle
|
|
|
|
* mbuf chains for the nfs op functions. They do things such as creating the
|
|
|
|
* rpc header and copying data between mbuf chains and uio lists.
|
1995-10-18 01:37:01 -07:00
|
|
|
*/
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/kernel.h>
|
|
|
|
#include <sys/mount.h>
|
|
|
|
#include <sys/vnode.h>
|
|
|
|
#include <sys/namei.h>
|
|
|
|
#include <sys/mbuf.h>
|
|
|
|
#include <sys/socket.h>
|
1997-04-25 02:30:14 -07:00
|
|
|
#include <sys/socketvar.h>
|
1995-10-18 01:37:01 -07:00
|
|
|
#include <sys/stat.h>
|
2004-05-13 21:00:33 -07:00
|
|
|
#include <sys/pool.h>
|
1996-07-23 14:32:31 -07:00
|
|
|
#include <sys/time.h>
|
1996-03-31 05:15:23 -08:00
|
|
|
|
1995-10-18 01:37:01 -07:00
|
|
|
#include <nfs/rpcv2.h>
|
1996-03-31 05:15:23 -08:00
|
|
|
#include <nfs/nfsproto.h>
|
1995-10-18 01:37:01 -07:00
|
|
|
#include <nfs/nfsnode.h>
|
|
|
|
#include <nfs/nfs.h>
|
|
|
|
#include <nfs/xdr_subs.h>
|
|
|
|
#include <nfs/nfsmount.h>
|
1996-02-29 01:24:48 -08:00
|
|
|
#include <nfs/nfs_var.h>
|
2024-04-30 10:04:23 -07:00
|
|
|
#include <nfs/nfsm_subs.h>
|
1995-10-18 01:37:01 -07:00
|
|
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
2008-06-09 15:47:41 -07:00
|
|
|
#include <crypto/idgen.h>
|
1997-04-27 16:55:49 -07:00
|
|
|
|
2002-03-13 17:26:25 -08:00
|
|
|
int nfs_attrtimeo(struct nfsnode *np);
|
2017-02-22 03:42:46 -08:00
|
|
|
u_int32_t nfs_get_xid(void);
|
1996-12-18 10:30:58 -08:00
|
|
|
|
1995-10-18 01:37:01 -07:00
|
|
|
/*
|
|
|
|
* Data items converted to xdr at startup, since they are constant
|
|
|
|
* This is kinda hokey, but may save a little time doing byte swaps
|
|
|
|
*/
|
1995-12-21 06:42:17 -08:00
|
|
|
u_int32_t nfs_xdrneg1;
|
|
|
|
u_int32_t rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr,
|
2008-06-13 10:24:13 -07:00
|
|
|
rpc_mismatch, rpc_auth_unix, rpc_msgaccepted;
|
2001-06-24 20:28:01 -07:00
|
|
|
u_int32_t nfs_prog, nfs_true, nfs_false;
|
1995-10-18 01:37:01 -07:00
|
|
|
|
|
|
|
/* And other global data */
|
2024-04-30 10:05:20 -07:00
|
|
|
const nfstype nfsv2_type[9] =
|
|
|
|
{ NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON, NFCHR, NFNON };
|
|
|
|
const nfstype nfsv3_type[9] =
|
|
|
|
{ NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK, NFFIFO, NFNON };
|
|
|
|
const enum vtype nv2tov_type[8] =
|
|
|
|
{ VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON, VNON };
|
|
|
|
const enum vtype nv3tov_type[8]=
|
|
|
|
{ VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO };
|
1996-03-31 05:15:23 -08:00
|
|
|
int nfs_ticks;
|
2006-10-31 16:12:35 -08:00
|
|
|
struct nfsstats nfsstats;
|
1996-03-31 05:15:23 -08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Mapping of old NFS Version 2 RPC numbers to generic numbers.
|
|
|
|
*/
|
2024-04-30 10:05:20 -07:00
|
|
|
const int nfsv3_procid[NFS_NPROCS] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSPROC_NULL,
|
|
|
|
NFSPROC_GETATTR,
|
|
|
|
NFSPROC_SETATTR,
|
|
|
|
NFSPROC_NOOP,
|
|
|
|
NFSPROC_LOOKUP,
|
|
|
|
NFSPROC_READLINK,
|
|
|
|
NFSPROC_READ,
|
|
|
|
NFSPROC_NOOP,
|
|
|
|
NFSPROC_WRITE,
|
|
|
|
NFSPROC_CREATE,
|
|
|
|
NFSPROC_REMOVE,
|
|
|
|
NFSPROC_RENAME,
|
|
|
|
NFSPROC_LINK,
|
|
|
|
NFSPROC_SYMLINK,
|
|
|
|
NFSPROC_MKDIR,
|
|
|
|
NFSPROC_RMDIR,
|
|
|
|
NFSPROC_READDIR,
|
|
|
|
NFSPROC_FSSTAT,
|
|
|
|
NFSPROC_NOOP,
|
|
|
|
NFSPROC_NOOP,
|
|
|
|
NFSPROC_NOOP,
|
|
|
|
NFSPROC_NOOP,
|
|
|
|
NFSPROC_NOOP
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* and the reverse mapping from generic to Version 2 procedure numbers
|
|
|
|
*/
|
2024-04-30 10:05:20 -07:00
|
|
|
const int nfsv2_procid[NFS_NPROCS] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSV2PROC_NULL,
|
|
|
|
NFSV2PROC_GETATTR,
|
|
|
|
NFSV2PROC_SETATTR,
|
|
|
|
NFSV2PROC_LOOKUP,
|
|
|
|
NFSV2PROC_NOOP,
|
|
|
|
NFSV2PROC_READLINK,
|
|
|
|
NFSV2PROC_READ,
|
|
|
|
NFSV2PROC_WRITE,
|
|
|
|
NFSV2PROC_CREATE,
|
|
|
|
NFSV2PROC_MKDIR,
|
|
|
|
NFSV2PROC_SYMLINK,
|
|
|
|
NFSV2PROC_CREATE,
|
|
|
|
NFSV2PROC_REMOVE,
|
|
|
|
NFSV2PROC_RMDIR,
|
|
|
|
NFSV2PROC_RENAME,
|
|
|
|
NFSV2PROC_LINK,
|
|
|
|
NFSV2PROC_READDIR,
|
|
|
|
NFSV2PROC_NOOP,
|
|
|
|
NFSV2PROC_STATFS,
|
|
|
|
NFSV2PROC_NOOP,
|
|
|
|
NFSV2PROC_NOOP,
|
|
|
|
NFSV2PROC_NOOP,
|
2009-05-30 10:20:29 -07:00
|
|
|
NFSV2PROC_NOOP
|
1996-03-31 05:15:23 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Maps errno values to nfs error numbers.
|
|
|
|
* Use NFSERR_IO as the catch all for ones not specifically defined in
|
|
|
|
* RFC 1094.
|
|
|
|
*/
|
2024-04-30 10:05:20 -07:00
|
|
|
static const u_char nfsrv_v2errmap[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_PERM, NFSERR_NOENT, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
|
|
|
NFSERR_NXIO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
|
|
|
NFSERR_IO, NFSERR_IO, NFSERR_ACCES, NFSERR_IO, NFSERR_IO,
|
|
|
|
NFSERR_IO, NFSERR_EXIST, NFSERR_IO, NFSERR_NODEV, NFSERR_NOTDIR,
|
|
|
|
NFSERR_ISDIR, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
|
|
|
NFSERR_IO, NFSERR_FBIG, NFSERR_NOSPC, NFSERR_IO, NFSERR_ROFS,
|
|
|
|
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
|
|
|
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
|
|
|
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
|
|
|
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
|
|
|
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
|
|
|
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
|
|
|
|
NFSERR_IO, NFSERR_IO, NFSERR_NAMETOL, NFSERR_IO, NFSERR_IO,
|
2007-10-08 10:39:52 -07:00
|
|
|
NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE
|
|
|
|
/* Everything after this maps to NFSERR_IO, so far */
|
1996-03-31 05:15:23 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Maps errno values to nfs error numbers.
|
|
|
|
* Although it is not obvious whether or not NFS clients really care if
|
|
|
|
* a returned error value is in the specified list for the procedure, the
|
|
|
|
* safest thing to do is filter them appropriately. For Version 2, the
|
|
|
|
* X/Open XNFS document is the only specification that defines error values
|
|
|
|
* for each RPC (The RFC simply lists all possible error values for all RPCs),
|
|
|
|
* so I have decided to not do this for Version 2.
|
|
|
|
* The first entry is the default error return and the rest are the valid
|
|
|
|
* errors for that RPC in increasing numeric order.
|
|
|
|
*/
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_null[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
0,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_getattr[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_setattr[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_PERM,
|
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_ACCES,
|
|
|
|
NFSERR_INVAL,
|
|
|
|
NFSERR_NOSPC,
|
|
|
|
NFSERR_ROFS,
|
|
|
|
NFSERR_DQUOT,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_NOT_SYNC,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_lookup[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_NOENT,
|
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_ACCES,
|
|
|
|
NFSERR_NOTDIR,
|
|
|
|
NFSERR_NAMETOL,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_access[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_readlink[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_ACCES,
|
|
|
|
NFSERR_INVAL,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_NOTSUPP,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_read[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_NXIO,
|
|
|
|
NFSERR_ACCES,
|
|
|
|
NFSERR_INVAL,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_write[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_ACCES,
|
|
|
|
NFSERR_INVAL,
|
|
|
|
NFSERR_FBIG,
|
|
|
|
NFSERR_NOSPC,
|
|
|
|
NFSERR_ROFS,
|
|
|
|
NFSERR_DQUOT,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_create[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_ACCES,
|
|
|
|
NFSERR_EXIST,
|
|
|
|
NFSERR_NOTDIR,
|
|
|
|
NFSERR_NOSPC,
|
|
|
|
NFSERR_ROFS,
|
|
|
|
NFSERR_NAMETOL,
|
|
|
|
NFSERR_DQUOT,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_NOTSUPP,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_mkdir[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_ACCES,
|
|
|
|
NFSERR_EXIST,
|
|
|
|
NFSERR_NOTDIR,
|
|
|
|
NFSERR_NOSPC,
|
|
|
|
NFSERR_ROFS,
|
|
|
|
NFSERR_NAMETOL,
|
|
|
|
NFSERR_DQUOT,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_NOTSUPP,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_symlink[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_ACCES,
|
|
|
|
NFSERR_EXIST,
|
|
|
|
NFSERR_NOTDIR,
|
|
|
|
NFSERR_NOSPC,
|
|
|
|
NFSERR_ROFS,
|
|
|
|
NFSERR_NAMETOL,
|
|
|
|
NFSERR_DQUOT,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_NOTSUPP,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_mknod[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_ACCES,
|
|
|
|
NFSERR_EXIST,
|
|
|
|
NFSERR_NOTDIR,
|
|
|
|
NFSERR_NOSPC,
|
|
|
|
NFSERR_ROFS,
|
|
|
|
NFSERR_NAMETOL,
|
|
|
|
NFSERR_DQUOT,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_NOTSUPP,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
NFSERR_BADTYPE,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_remove[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_NOENT,
|
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_ACCES,
|
|
|
|
NFSERR_NOTDIR,
|
|
|
|
NFSERR_ROFS,
|
|
|
|
NFSERR_NAMETOL,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_rmdir[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_NOENT,
|
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_ACCES,
|
|
|
|
NFSERR_EXIST,
|
|
|
|
NFSERR_NOTDIR,
|
|
|
|
NFSERR_INVAL,
|
|
|
|
NFSERR_ROFS,
|
|
|
|
NFSERR_NAMETOL,
|
|
|
|
NFSERR_NOTEMPTY,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_NOTSUPP,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_rename[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_NOENT,
|
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_ACCES,
|
|
|
|
NFSERR_EXIST,
|
|
|
|
NFSERR_XDEV,
|
|
|
|
NFSERR_NOTDIR,
|
|
|
|
NFSERR_ISDIR,
|
|
|
|
NFSERR_INVAL,
|
|
|
|
NFSERR_NOSPC,
|
|
|
|
NFSERR_ROFS,
|
|
|
|
NFSERR_MLINK,
|
|
|
|
NFSERR_NAMETOL,
|
|
|
|
NFSERR_NOTEMPTY,
|
|
|
|
NFSERR_DQUOT,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_NOTSUPP,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_link[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_ACCES,
|
|
|
|
NFSERR_EXIST,
|
|
|
|
NFSERR_XDEV,
|
|
|
|
NFSERR_NOTDIR,
|
|
|
|
NFSERR_INVAL,
|
|
|
|
NFSERR_NOSPC,
|
|
|
|
NFSERR_ROFS,
|
|
|
|
NFSERR_MLINK,
|
|
|
|
NFSERR_NAMETOL,
|
|
|
|
NFSERR_DQUOT,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_NOTSUPP,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_readdir[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_ACCES,
|
|
|
|
NFSERR_NOTDIR,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_BAD_COOKIE,
|
|
|
|
NFSERR_TOOSMALL,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_readdirplus[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_ACCES,
|
|
|
|
NFSERR_NOTDIR,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_BAD_COOKIE,
|
|
|
|
NFSERR_NOTSUPP,
|
|
|
|
NFSERR_TOOSMALL,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_fsstat[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_fsinfo[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_pathconf[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short nfsv3err_commit[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_IO,
|
|
|
|
NFSERR_STALE,
|
|
|
|
NFSERR_BADHANDLE,
|
|
|
|
NFSERR_SERVERFAULT,
|
|
|
|
0,
|
|
|
|
};
|
|
|
|
|
2024-04-30 10:05:20 -07:00
|
|
|
static const short *nfsrv_v3errmap[] = {
|
1996-03-31 05:15:23 -08:00
|
|
|
nfsv3err_null,
|
|
|
|
nfsv3err_getattr,
|
|
|
|
nfsv3err_setattr,
|
|
|
|
nfsv3err_lookup,
|
|
|
|
nfsv3err_access,
|
|
|
|
nfsv3err_readlink,
|
|
|
|
nfsv3err_read,
|
|
|
|
nfsv3err_write,
|
|
|
|
nfsv3err_create,
|
|
|
|
nfsv3err_mkdir,
|
|
|
|
nfsv3err_symlink,
|
|
|
|
nfsv3err_mknod,
|
|
|
|
nfsv3err_remove,
|
|
|
|
nfsv3err_rmdir,
|
|
|
|
nfsv3err_rename,
|
|
|
|
nfsv3err_link,
|
|
|
|
nfsv3err_readdir,
|
|
|
|
nfsv3err_readdirplus,
|
|
|
|
nfsv3err_fsstat,
|
|
|
|
nfsv3err_fsinfo,
|
|
|
|
nfsv3err_pathconf,
|
|
|
|
nfsv3err_commit,
|
|
|
|
};
|
|
|
|
|
2005-04-01 17:00:38 -08:00
|
|
|
struct pool nfsreqpl;
|
|
|
|
|
1995-10-18 01:37:01 -07:00
|
|
|
/*
|
|
|
|
* Create the header for an rpc request packet
|
|
|
|
* The hsiz is the size of the rest of the nfs request header.
|
|
|
|
* (just used to decide if a cluster is a good idea)
|
|
|
|
*/
|
|
|
|
struct mbuf *
|
2009-10-19 15:24:18 -07:00
|
|
|
nfsm_reqhead(int hsiz)
|
1995-10-18 01:37:01 -07:00
|
|
|
{
|
2002-01-16 13:51:16 -08:00
|
|
|
struct mbuf *mb;
|
1995-10-18 01:37:01 -07:00
|
|
|
|
|
|
|
MGET(mb, M_WAIT, MT_DATA);
|
2008-04-19 12:38:00 -07:00
|
|
|
if (hsiz > MLEN)
|
1995-10-18 01:37:01 -07:00
|
|
|
MCLGET(mb, M_WAIT);
|
|
|
|
mb->m_len = 0;
|
|
|
|
|
|
|
|
/* Finally, return values */
|
|
|
|
return (mb);
|
|
|
|
}
|
|
|
|
|
2008-06-09 15:47:41 -07:00
|
|
|
/*
|
2008-06-11 01:11:33 -07:00
|
|
|
* Return an unpredictable XID in XDR form.
|
2008-06-09 15:47:41 -07:00
|
|
|
*/
|
|
|
|
u_int32_t
|
2008-06-09 15:49:15 -07:00
|
|
|
nfs_get_xid(void)
|
2008-06-09 15:47:41 -07:00
|
|
|
{
|
|
|
|
static struct idgen32_ctx nfs_xid_ctx;
|
|
|
|
static int called = 0;
|
|
|
|
|
|
|
|
if (!called) {
|
|
|
|
called = 1;
|
|
|
|
idgen32_init(&nfs_xid_ctx);
|
|
|
|
}
|
2008-06-11 01:11:33 -07:00
|
|
|
return (txdr_unsigned(idgen32(&nfs_xid_ctx)));
|
2008-06-09 15:47:41 -07:00
|
|
|
}
|
|
|
|
|
1995-10-18 01:37:01 -07:00
|
|
|
/*
|
|
|
|
* Build the RPC header and fill in the authorization info.
|
2007-10-13 10:38:43 -07:00
|
|
|
* Right now we are pretty centric around RPCAUTH_UNIX, in the
|
|
|
|
* future, this function will need some love to be able to handle
|
|
|
|
* other authorization methods, such as Kerberos.
|
1995-10-18 01:37:01 -07:00
|
|
|
*/
|
2007-10-13 10:38:43 -07:00
|
|
|
void
|
2009-01-20 10:03:33 -08:00
|
|
|
nfsm_rpchead(struct nfsreq *req, struct ucred *cr, int auth_type)
|
1995-10-18 01:37:01 -07:00
|
|
|
{
|
2008-01-06 09:38:23 -08:00
|
|
|
struct mbuf *mb;
|
2007-10-13 10:38:43 -07:00
|
|
|
u_int32_t *tl;
|
|
|
|
int i, authsiz, auth_len, ngroups;
|
1995-10-18 01:37:01 -07:00
|
|
|
|
2007-10-13 10:38:43 -07:00
|
|
|
KASSERT(auth_type == RPCAUTH_UNIX);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* RPCAUTH_UNIX fits in an hdr mbuf, in the future other
|
2009-01-20 10:03:33 -08:00
|
|
|
* authorization methods need to figure out their own sizes
|
2022-01-10 19:13:58 -08:00
|
|
|
* and allocate and chain mbufs accordingly.
|
2007-10-13 10:38:43 -07:00
|
|
|
*/
|
2009-01-20 10:03:33 -08:00
|
|
|
mb = req->r_mreq;
|
2007-10-13 10:38:43 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We need to start out by finding how big the authorization cred
|
2024-09-04 00:54:51 -07:00
|
|
|
* and verifier are for the auth_type, to be able to correctly
|
2007-10-13 10:38:43 -07:00
|
|
|
* align the mbuf header/chain.
|
|
|
|
*/
|
|
|
|
switch (auth_type) {
|
|
|
|
case RPCAUTH_UNIX:
|
|
|
|
/*
|
|
|
|
* In the RPCAUTH_UNIX case, the size is the static
|
|
|
|
* part as shown in RFC1831 + the number of groups,
|
2024-09-04 00:54:51 -07:00
|
|
|
* RPCAUTH_UNIX has a zero verifier.
|
2007-10-13 10:38:43 -07:00
|
|
|
*/
|
|
|
|
if (cr->cr_ngroups > req->r_nmp->nm_numgrps)
|
|
|
|
ngroups = req->r_nmp->nm_numgrps;
|
|
|
|
else
|
|
|
|
ngroups = cr->cr_ngroups;
|
|
|
|
|
|
|
|
auth_len = (ngroups << 2) + 5 * NFSX_UNSIGNED;
|
|
|
|
authsiz = nfsm_rndup(auth_len);
|
|
|
|
/* The authorization size + the size of the static part */
|
2018-11-30 01:24:57 -08:00
|
|
|
m_align(mb, authsiz + 10 * NFSX_UNSIGNED);
|
2007-10-13 10:38:43 -07:00
|
|
|
break;
|
1995-10-18 01:37:01 -07:00
|
|
|
}
|
2007-10-13 10:38:43 -07:00
|
|
|
|
1995-10-18 01:37:01 -07:00
|
|
|
mb->m_len = 0;
|
|
|
|
|
2007-10-13 10:38:43 -07:00
|
|
|
/* First the RPC header. */
|
2008-06-12 13:24:06 -07:00
|
|
|
tl = nfsm_build(&mb, 6 * NFSX_UNSIGNED);
|
1996-07-23 14:32:31 -07:00
|
|
|
|
1997-04-27 16:55:49 -07:00
|
|
|
/* Get a new (non-zero) xid */
|
2008-06-11 01:11:33 -07:00
|
|
|
*tl++ = req->r_xid = nfs_get_xid();
|
1995-10-18 01:37:01 -07:00
|
|
|
*tl++ = rpc_call;
|
|
|
|
*tl++ = rpc_vers;
|
2007-10-13 10:38:43 -07:00
|
|
|
*tl++ = nfs_prog;
|
|
|
|
if (ISSET(req->r_nmp->nm_flag, NFSMNT_NFSV3)) {
|
2001-06-24 20:28:01 -07:00
|
|
|
*tl++ = txdr_unsigned(NFS_VER3);
|
2007-10-13 10:38:43 -07:00
|
|
|
*tl = txdr_unsigned(req->r_procnum);
|
|
|
|
} else {
|
2001-06-24 20:28:01 -07:00
|
|
|
*tl++ = txdr_unsigned(NFS_VER2);
|
2007-10-13 10:38:43 -07:00
|
|
|
*tl = txdr_unsigned(nfsv2_procid[req->r_procnum]);
|
|
|
|
}
|
1995-10-18 01:37:01 -07:00
|
|
|
|
2007-10-13 10:38:43 -07:00
|
|
|
/* The Authorization cred and its verifier */
|
1995-10-18 01:37:01 -07:00
|
|
|
switch (auth_type) {
|
|
|
|
case RPCAUTH_UNIX:
|
2008-06-12 13:24:06 -07:00
|
|
|
tl = nfsm_build(&mb, auth_len + 4 * NFSX_UNSIGNED);
|
2007-10-13 10:38:43 -07:00
|
|
|
*tl++ = txdr_unsigned(RPCAUTH_UNIX);
|
|
|
|
*tl++ = txdr_unsigned(authsiz);
|
|
|
|
|
|
|
|
/* The authorization cred */
|
|
|
|
*tl++ = 0; /* stamp */
|
1995-10-18 01:37:01 -07:00
|
|
|
*tl++ = 0; /* NULL hostname */
|
|
|
|
*tl++ = txdr_unsigned(cr->cr_uid);
|
|
|
|
*tl++ = txdr_unsigned(cr->cr_gid);
|
2007-10-13 10:38:43 -07:00
|
|
|
*tl++ = txdr_unsigned(ngroups);
|
|
|
|
for (i = 0; i < ngroups; i++)
|
1995-10-18 01:37:01 -07:00
|
|
|
*tl++ = txdr_unsigned(cr->cr_groups[i]);
|
2007-10-13 10:38:43 -07:00
|
|
|
/* The authorization verifier */
|
1996-03-31 05:15:23 -08:00
|
|
|
*tl++ = txdr_unsigned(RPCAUTH_NULL);
|
|
|
|
*tl = 0;
|
2007-10-13 10:38:43 -07:00
|
|
|
break;
|
1996-03-31 05:15:23 -08:00
|
|
|
}
|
2007-10-13 10:38:43 -07:00
|
|
|
|
2009-01-20 10:03:33 -08:00
|
|
|
mb->m_pkthdr.len += authsiz + 10 * NFSX_UNSIGNED;
|
2015-06-16 04:09:39 -07:00
|
|
|
mb->m_pkthdr.ph_ifidx = 0;
|
1995-10-18 01:37:01 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* copies mbuf chain to the uio scatter/gather list
|
|
|
|
*/
|
1996-02-29 01:24:48 -08:00
|
|
|
int
|
2009-10-19 15:24:18 -07:00
|
|
|
nfsm_mbuftouio(struct mbuf **mrep, struct uio *uiop, int siz, caddr_t *dpos)
|
1995-10-18 01:37:01 -07:00
|
|
|
{
|
2002-01-16 13:51:16 -08:00
|
|
|
char *mbufcp, *uiocp;
|
|
|
|
int xfer, left, len;
|
|
|
|
struct mbuf *mp;
|
1995-10-18 01:37:01 -07:00
|
|
|
long uiosiz, rem;
|
|
|
|
int error = 0;
|
|
|
|
|
|
|
|
mp = *mrep;
|
|
|
|
mbufcp = *dpos;
|
|
|
|
len = mtod(mp, caddr_t)+mp->m_len-mbufcp;
|
2008-06-13 17:26:13 -07:00
|
|
|
rem = nfsm_padlen(siz);
|
1995-10-18 01:37:01 -07:00
|
|
|
while (siz > 0) {
|
|
|
|
if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL)
|
|
|
|
return (EFBIG);
|
|
|
|
left = uiop->uio_iov->iov_len;
|
|
|
|
uiocp = uiop->uio_iov->iov_base;
|
|
|
|
if (left > siz)
|
|
|
|
left = siz;
|
|
|
|
uiosiz = left;
|
|
|
|
while (left > 0) {
|
|
|
|
while (len == 0) {
|
|
|
|
mp = mp->m_next;
|
|
|
|
if (mp == NULL)
|
|
|
|
return (EBADRPC);
|
|
|
|
mbufcp = mtod(mp, caddr_t);
|
|
|
|
len = mp->m_len;
|
|
|
|
}
|
|
|
|
xfer = (left > len) ? len : left;
|
|
|
|
if (uiop->uio_segflg == UIO_SYSSPACE)
|
2014-12-18 13:00:12 -08:00
|
|
|
memcpy(uiocp, mbufcp, xfer);
|
1995-10-18 01:37:01 -07:00
|
|
|
else
|
|
|
|
copyout(mbufcp, uiocp, xfer);
|
|
|
|
left -= xfer;
|
|
|
|
len -= xfer;
|
|
|
|
mbufcp += xfer;
|
|
|
|
uiocp += xfer;
|
|
|
|
uiop->uio_offset += xfer;
|
|
|
|
uiop->uio_resid -= xfer;
|
|
|
|
}
|
|
|
|
if (uiop->uio_iov->iov_len <= siz) {
|
|
|
|
uiop->uio_iovcnt--;
|
|
|
|
uiop->uio_iov++;
|
|
|
|
} else {
|
2009-01-13 11:44:20 -08:00
|
|
|
uiop->uio_iov->iov_base =
|
|
|
|
(char *)uiop->uio_iov->iov_base + uiosiz;
|
1995-10-18 01:37:01 -07:00
|
|
|
uiop->uio_iov->iov_len -= uiosiz;
|
|
|
|
}
|
|
|
|
siz -= uiosiz;
|
|
|
|
}
|
|
|
|
*dpos = mbufcp;
|
|
|
|
*mrep = mp;
|
|
|
|
if (rem > 0) {
|
|
|
|
if (len < rem)
|
|
|
|
error = nfs_adv(mrep, dpos, rem, len);
|
|
|
|
else
|
|
|
|
*dpos += rem;
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2008-04-14 06:46:13 -07:00
|
|
|
* Copy a uio scatter/gather list to an mbuf chain.
|
1995-10-18 01:37:01 -07:00
|
|
|
*/
|
2008-04-14 06:46:13 -07:00
|
|
|
void
|
2008-06-12 13:24:06 -07:00
|
|
|
nfsm_uiotombuf(struct mbuf **mp, struct uio *uiop, size_t len)
|
1995-10-18 01:37:01 -07:00
|
|
|
{
|
2008-04-14 06:46:13 -07:00
|
|
|
struct mbuf *mb, *mb2;
|
|
|
|
size_t xfer, pad;
|
|
|
|
|
|
|
|
mb = *mp;
|
|
|
|
|
|
|
|
pad = nfsm_padlen(len);
|
|
|
|
|
|
|
|
/* XXX -- the following should be done by the caller */
|
|
|
|
uiop->uio_resid = len;
|
|
|
|
uiop->uio_rw = UIO_WRITE;
|
|
|
|
|
|
|
|
while (len) {
|
2018-11-09 06:14:31 -08:00
|
|
|
xfer = ulmin(len, m_trailingspace(mb));
|
2016-02-13 07:45:05 -08:00
|
|
|
uiomove(mb_offset(mb), xfer, uiop);
|
2008-04-14 06:46:13 -07:00
|
|
|
mb->m_len += xfer;
|
|
|
|
len -= xfer;
|
|
|
|
if (len > 0) {
|
|
|
|
MGET(mb2, M_WAIT, MT_DATA);
|
2008-04-16 13:02:46 -07:00
|
|
|
if (len > MLEN)
|
2008-04-14 06:46:13 -07:00
|
|
|
MCLGET(mb2, M_WAIT);
|
|
|
|
mb2->m_len = 0;
|
|
|
|
mb->m_next = mb2;
|
|
|
|
mb = mb2;
|
1995-10-18 01:37:01 -07:00
|
|
|
}
|
|
|
|
}
|
2008-04-14 06:46:13 -07:00
|
|
|
|
|
|
|
if (pad > 0) {
|
2018-11-09 06:14:31 -08:00
|
|
|
if (pad > m_trailingspace(mb)) {
|
2008-04-14 06:46:13 -07:00
|
|
|
MGET(mb2, M_WAIT, MT_DATA);
|
|
|
|
mb2->m_len = 0;
|
|
|
|
mb->m_next = mb2;
|
|
|
|
mb = mb2;
|
1995-10-18 01:37:01 -07:00
|
|
|
}
|
2014-11-14 15:01:44 -08:00
|
|
|
memset(mb_offset(mb), 0, pad);
|
2008-04-14 06:46:13 -07:00
|
|
|
mb->m_len += pad;
|
|
|
|
}
|
|
|
|
|
|
|
|
*mp = mb;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy a buffer to an mbuf chain
|
|
|
|
*/
|
|
|
|
void
|
2008-06-12 13:24:06 -07:00
|
|
|
nfsm_buftombuf(struct mbuf **mp, void *buf, size_t len)
|
2008-04-14 06:46:13 -07:00
|
|
|
{
|
|
|
|
struct iovec iov;
|
|
|
|
struct uio io;
|
|
|
|
|
|
|
|
iov.iov_base = buf;
|
|
|
|
iov.iov_len = len;
|
|
|
|
|
|
|
|
io.uio_iov = &iov;
|
|
|
|
io.uio_iovcnt = 1;
|
|
|
|
io.uio_resid = len;
|
|
|
|
io.uio_segflg = UIO_SYSSPACE;
|
|
|
|
io.uio_rw = UIO_WRITE;
|
|
|
|
|
2008-06-12 13:24:06 -07:00
|
|
|
nfsm_uiotombuf(mp, &io, len);
|
2008-04-14 06:46:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy a string to an mbuf chain
|
|
|
|
*/
|
|
|
|
void
|
2008-06-12 13:24:06 -07:00
|
|
|
nfsm_strtombuf(struct mbuf **mp, void *str, size_t len)
|
2008-04-14 06:46:13 -07:00
|
|
|
{
|
|
|
|
struct iovec iov[2];
|
|
|
|
struct uio io;
|
|
|
|
uint32_t strlen;
|
|
|
|
|
|
|
|
strlen = txdr_unsigned(len);
|
|
|
|
|
|
|
|
iov[0].iov_base = &strlen;
|
|
|
|
iov[0].iov_len = sizeof(uint32_t);
|
|
|
|
iov[1].iov_base = str;
|
|
|
|
iov[1].iov_len = len;
|
|
|
|
|
|
|
|
io.uio_iov = iov;
|
|
|
|
io.uio_iovcnt = 2;
|
|
|
|
io.uio_resid = sizeof(uint32_t) + len;
|
|
|
|
io.uio_segflg = UIO_SYSSPACE;
|
|
|
|
io.uio_rw = UIO_WRITE;
|
|
|
|
|
2008-06-12 13:24:06 -07:00
|
|
|
nfsm_uiotombuf(mp, &io, io.uio_resid);
|
1995-10-18 01:37:01 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Help break down an mbuf chain by setting the first siz bytes contiguous
|
|
|
|
* pointed to by returned val.
|
2024-04-30 10:04:23 -07:00
|
|
|
* This is used by nfsm_dissect for tough cases.
|
1995-10-18 01:37:01 -07:00
|
|
|
*/
|
1996-02-29 01:24:48 -08:00
|
|
|
int
|
2009-10-19 15:24:18 -07:00
|
|
|
nfsm_disct(struct mbuf **mdp, caddr_t *dposp, int siz, int left, caddr_t *cp2)
|
1995-10-18 01:37:01 -07:00
|
|
|
{
|
2002-01-16 13:51:16 -08:00
|
|
|
struct mbuf *mp, *mp2;
|
|
|
|
int siz2, xfer;
|
|
|
|
caddr_t p;
|
1995-10-18 01:37:01 -07:00
|
|
|
|
|
|
|
mp = *mdp;
|
|
|
|
while (left == 0) {
|
|
|
|
*mdp = mp = mp->m_next;
|
|
|
|
if (mp == NULL)
|
|
|
|
return (EBADRPC);
|
|
|
|
left = mp->m_len;
|
|
|
|
*dposp = mtod(mp, caddr_t);
|
|
|
|
}
|
|
|
|
if (left >= siz) {
|
|
|
|
*cp2 = *dposp;
|
|
|
|
*dposp += siz;
|
|
|
|
} else if (mp->m_next == NULL) {
|
|
|
|
return (EBADRPC);
|
|
|
|
} else if (siz > MHLEN) {
|
|
|
|
panic("nfs S too big");
|
|
|
|
} else {
|
|
|
|
MGET(mp2, M_WAIT, MT_DATA);
|
|
|
|
mp2->m_next = mp->m_next;
|
|
|
|
mp->m_next = mp2;
|
|
|
|
mp->m_len -= left;
|
|
|
|
mp = mp2;
|
|
|
|
*cp2 = p = mtod(mp, caddr_t);
|
|
|
|
bcopy(*dposp, p, left); /* Copy what was left */
|
2024-04-30 10:04:23 -07:00
|
|
|
siz2 = siz - left;
|
1995-10-18 01:37:01 -07:00
|
|
|
p += left;
|
|
|
|
mp2 = mp->m_next;
|
|
|
|
/* Loop around copying up the siz2 bytes */
|
|
|
|
while (siz2 > 0) {
|
|
|
|
if (mp2 == NULL)
|
|
|
|
return (EBADRPC);
|
|
|
|
xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
|
|
|
|
if (xfer > 0) {
|
|
|
|
bcopy(mtod(mp2, caddr_t), p, xfer);
|
2008-06-14 21:03:40 -07:00
|
|
|
mp2->m_data += xfer;
|
1995-10-18 01:37:01 -07:00
|
|
|
mp2->m_len -= xfer;
|
|
|
|
p += xfer;
|
|
|
|
siz2 -= xfer;
|
|
|
|
}
|
|
|
|
if (siz2 > 0)
|
|
|
|
mp2 = mp2->m_next;
|
|
|
|
}
|
|
|
|
mp->m_len = siz;
|
|
|
|
*mdp = mp2;
|
|
|
|
*dposp = mtod(mp2, caddr_t);
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Advance the position in the mbuf chain.
|
|
|
|
*/
|
1996-02-29 01:24:48 -08:00
|
|
|
int
|
2009-10-19 15:24:18 -07:00
|
|
|
nfs_adv(struct mbuf **mdp, caddr_t *dposp, int offs, int left)
|
1995-10-18 01:37:01 -07:00
|
|
|
{
|
2002-01-16 13:51:16 -08:00
|
|
|
struct mbuf *m;
|
|
|
|
int s;
|
1995-10-18 01:37:01 -07:00
|
|
|
|
|
|
|
m = *mdp;
|
|
|
|
s = left;
|
|
|
|
while (s < offs) {
|
|
|
|
offs -= s;
|
|
|
|
m = m->m_next;
|
|
|
|
if (m == NULL)
|
|
|
|
return (EBADRPC);
|
|
|
|
s = m->m_len;
|
|
|
|
}
|
|
|
|
*mdp = m;
|
|
|
|
*dposp = mtod(m, caddr_t)+offs;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Called once to initialize data structures...
|
|
|
|
*/
|
1996-02-29 01:24:48 -08:00
|
|
|
void
|
2009-10-19 15:24:18 -07:00
|
|
|
nfs_init(void)
|
1995-10-18 01:37:01 -07:00
|
|
|
{
|
|
|
|
rpc_vers = txdr_unsigned(RPC_VER2);
|
|
|
|
rpc_call = txdr_unsigned(RPC_CALL);
|
|
|
|
rpc_reply = txdr_unsigned(RPC_REPLY);
|
|
|
|
rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);
|
|
|
|
rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
|
|
|
|
rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
|
|
|
|
rpc_autherr = txdr_unsigned(RPC_AUTHERR);
|
|
|
|
rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
|
|
|
|
nfs_prog = txdr_unsigned(NFS_PROG);
|
2008-12-23 18:43:52 -08:00
|
|
|
nfs_true = txdr_unsigned(1);
|
|
|
|
nfs_false = txdr_unsigned(0);
|
1995-10-18 01:37:01 -07:00
|
|
|
nfs_xdrneg1 = txdr_unsigned(-1);
|
1996-03-31 05:15:23 -08:00
|
|
|
nfs_ticks = (hz * NFS_TICKINTVL + 500) / 1000;
|
|
|
|
if (nfs_ticks < 1)
|
|
|
|
nfs_ticks = 1;
|
1995-10-18 01:37:01 -07:00
|
|
|
#ifdef NFSSERVER
|
|
|
|
nfsrv_init(0); /* Init server data structures */
|
|
|
|
nfsrv_initcache(); /* Init the server request cache */
|
1996-10-15 04:34:15 -07:00
|
|
|
#endif /* NFSSERVER */
|
1995-10-18 01:37:01 -07:00
|
|
|
|
all pools have their ipl set via pool_setipl, so fold it into pool_init.
the ioff argument to pool_init() is unused and has been for many
years, so this replaces it with an ipl argument. because the ipl
will be set on init we no longer need pool_setipl.
most of these changes have been done with coccinelle using the spatch
below. cocci sucks at formatting code though, so i fixed that by hand.
the manpage and subr_pool.c bits i did myself.
ok tedu@ jmatthew@
@ipl@
expression pp;
expression ipl;
expression s, a, o, f, m, p;
@@
-pool_init(pp, s, a, o, f, m, p);
-pool_setipl(pp, ipl);
+pool_init(pp, s, a, ipl, f, m, p);
2016-09-14 19:00:16 -07:00
|
|
|
pool_init(&nfsreqpl, sizeof(struct nfsreq), 0, IPL_NONE, PR_WAITOK,
|
2014-12-22 17:55:03 -08:00
|
|
|
"nfsreqpl", NULL);
|
1995-10-18 01:37:01 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef NFSCLIENT
|
1997-11-05 21:58:00 -08:00
|
|
|
int
|
2009-08-10 03:59:11 -07:00
|
|
|
nfs_vfs_init(struct vfsconf *vfsp)
|
1996-09-21 04:06:08 -07:00
|
|
|
{
|
2009-08-10 03:59:11 -07:00
|
|
|
extern struct pool nfs_node_pool;
|
|
|
|
|
2009-09-02 11:20:54 -07:00
|
|
|
TAILQ_INIT(&nfs_bufq);
|
2009-08-10 03:59:11 -07:00
|
|
|
|
all pools have their ipl set via pool_setipl, so fold it into pool_init.
the ioff argument to pool_init() is unused and has been for many
years, so this replaces it with an ipl argument. because the ipl
will be set on init we no longer need pool_setipl.
most of these changes have been done with coccinelle using the spatch
below. cocci sucks at formatting code though, so i fixed that by hand.
the manpage and subr_pool.c bits i did myself.
ok tedu@ jmatthew@
@ipl@
expression pp;
expression ipl;
expression s, a, o, f, m, p;
@@
-pool_init(pp, s, a, o, f, m, p);
-pool_setipl(pp, ipl);
+pool_init(pp, s, a, ipl, f, m, p);
2016-09-14 19:00:16 -07:00
|
|
|
pool_init(&nfs_node_pool, sizeof(struct nfsnode), 0, IPL_NONE,
|
|
|
|
PR_WAITOK, "nfsnodepl", NULL);
|
1997-11-05 21:58:00 -08:00
|
|
|
|
|
|
|
return (0);
|
1996-09-21 04:06:08 -07:00
|
|
|
}
|
|
|
|
|
1995-10-18 01:37:01 -07:00
|
|
|
/*
|
|
|
|
* Attribute cache routines.
|
|
|
|
* nfs_loadattrcache() - loads or updates the cache contents from attributes
|
|
|
|
* that are on the mbuf list
|
|
|
|
* nfs_getattrcache() - returns valid attributes if found in cache, returns
|
|
|
|
* error otherwise
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Load the attribute cache (that lives in the nfsnode entry) with
|
|
|
|
* the values on the mbuf list and
|
|
|
|
* Iff vap not NULL
|
|
|
|
* copy the attributes to *vaper
|
|
|
|
*/
|
1996-02-29 01:24:48 -08:00
|
|
|
int
|
2009-10-19 15:24:18 -07:00
|
|
|
nfs_loadattrcache(struct vnode **vpp, struct mbuf **mdp, caddr_t *dposp,
|
|
|
|
struct vattr *vaper)
|
1995-10-18 01:37:01 -07:00
|
|
|
{
|
2002-01-16 13:51:16 -08:00
|
|
|
struct vnode *vp = *vpp;
|
|
|
|
struct vattr *vap;
|
|
|
|
struct nfs_fattr *fp;
|
2020-01-20 15:21:55 -08:00
|
|
|
extern const struct vops nfs_specvops;
|
2002-01-16 13:51:16 -08:00
|
|
|
struct nfsnode *np;
|
2024-04-30 10:04:23 -07:00
|
|
|
int32_t avail;
|
1996-03-31 05:15:23 -08:00
|
|
|
int error = 0;
|
|
|
|
int32_t rdev;
|
1995-10-18 01:37:01 -07:00
|
|
|
struct mbuf *md;
|
|
|
|
enum vtype vtyp;
|
2004-07-13 14:04:28 -07:00
|
|
|
mode_t vmode;
|
1995-10-18 01:37:01 -07:00
|
|
|
struct timespec mtime;
|
|
|
|
struct vnode *nvp;
|
1996-03-31 05:15:23 -08:00
|
|
|
int v3 = NFS_ISV3(vp);
|
2008-06-10 15:59:09 -07:00
|
|
|
uid_t uid;
|
|
|
|
gid_t gid;
|
1995-10-18 01:37:01 -07:00
|
|
|
|
|
|
|
md = *mdp;
|
2024-04-30 10:04:23 -07:00
|
|
|
avail = (mtod(md, caddr_t) + md->m_len) - *dposp;
|
|
|
|
error = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), avail, (caddr_t *)&fp);
|
1996-02-29 01:24:48 -08:00
|
|
|
if (error)
|
1995-10-18 01:37:01 -07:00
|
|
|
return (error);
|
1996-03-31 05:15:23 -08:00
|
|
|
if (v3) {
|
|
|
|
vtyp = nfsv3tov_type(fp->fa_type);
|
2004-07-13 14:04:28 -07:00
|
|
|
vmode = fxdr_unsigned(mode_t, fp->fa_mode);
|
2004-08-02 23:58:40 -07:00
|
|
|
rdev = makedev(fxdr_unsigned(u_int32_t, fp->fa3_rdev.specdata1),
|
|
|
|
fxdr_unsigned(u_int32_t, fp->fa3_rdev.specdata2));
|
1996-03-31 05:15:23 -08:00
|
|
|
fxdr_nfsv3time(&fp->fa3_mtime, &mtime);
|
1995-10-18 01:37:01 -07:00
|
|
|
} else {
|
1996-03-31 05:15:23 -08:00
|
|
|
vtyp = nfsv2tov_type(fp->fa_type);
|
2004-07-13 14:04:28 -07:00
|
|
|
vmode = fxdr_unsigned(mode_t, fp->fa_mode);
|
1996-03-31 05:15:23 -08:00
|
|
|
if (vtyp == VNON || vtyp == VREG)
|
|
|
|
vtyp = IFTOVT(vmode);
|
|
|
|
rdev = fxdr_unsigned(int32_t, fp->fa2_rdev);
|
|
|
|
fxdr_nfsv2time(&fp->fa2_mtime, &mtime);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Really ugly NFSv2 kludge.
|
|
|
|
*/
|
|
|
|
if (vtyp == VCHR && rdev == 0xffffffff)
|
|
|
|
vtyp = VFIFO;
|
1995-10-18 01:37:01 -07:00
|
|
|
}
|
1996-03-31 05:15:23 -08:00
|
|
|
|
1995-10-18 01:37:01 -07:00
|
|
|
/*
|
|
|
|
* If v_type == VNON it is a new node, so fill in the v_type,
|
|
|
|
* n_mtime fields. Check to see if it represents a special
|
|
|
|
* device, and if so, check for a possible alias. Once the
|
|
|
|
* correct vnode has been obtained, fill in the rest of the
|
|
|
|
* information.
|
|
|
|
*/
|
|
|
|
np = VTONFS(vp);
|
1996-01-07 23:36:23 -08:00
|
|
|
if (vp->v_type != vtyp) {
|
2013-11-27 08:02:54 -08:00
|
|
|
cache_purge(vp);
|
1996-03-31 05:15:23 -08:00
|
|
|
vp->v_type = vtyp;
|
1995-10-18 01:37:01 -07:00
|
|
|
if (vp->v_type == VFIFO) {
|
1996-04-21 15:14:33 -07:00
|
|
|
#ifndef FIFO
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
#else
|
2020-01-20 15:21:55 -08:00
|
|
|
extern const struct vops nfs_fifovops;
|
2010-12-21 12:14:43 -08:00
|
|
|
vp->v_op = &nfs_fifovops;
|
1996-04-21 15:14:33 -07:00
|
|
|
#endif /* FIFO */
|
1995-10-18 01:37:01 -07:00
|
|
|
}
|
|
|
|
if (vp->v_type == VCHR || vp->v_type == VBLK) {
|
2010-12-21 12:14:43 -08:00
|
|
|
vp->v_op = &nfs_specvops;
|
1996-02-29 01:24:48 -08:00
|
|
|
nvp = checkalias(vp, (dev_t)rdev, vp->v_mount);
|
|
|
|
if (nvp) {
|
1995-10-18 01:37:01 -07:00
|
|
|
/*
|
|
|
|
* Discard unneeded vnode, but save its nfsnode.
|
1996-03-31 05:15:23 -08:00
|
|
|
* Since the nfsnode does not have a lock, its
|
|
|
|
* vnode lock has to be carried over.
|
1995-10-18 01:37:01 -07:00
|
|
|
*/
|
1997-11-05 21:58:00 -08:00
|
|
|
|
1995-10-18 01:37:01 -07:00
|
|
|
nvp->v_data = vp->v_data;
|
|
|
|
vp->v_data = NULL;
|
2010-12-21 12:14:43 -08:00
|
|
|
vp->v_op = &spec_vops;
|
1995-10-18 01:37:01 -07:00
|
|
|
vrele(vp);
|
|
|
|
vgone(vp);
|
|
|
|
/*
|
|
|
|
* Reinitialize aliased node.
|
|
|
|
*/
|
|
|
|
np->n_vnode = nvp;
|
|
|
|
*vpp = vp = nvp;
|
|
|
|
}
|
|
|
|
}
|
2009-01-24 15:30:42 -08:00
|
|
|
np->n_mtime = mtime;
|
1995-10-18 01:37:01 -07:00
|
|
|
}
|
|
|
|
vap = &np->n_vattr;
|
|
|
|
vap->va_type = vtyp;
|
|
|
|
vap->va_rdev = (dev_t)rdev;
|
|
|
|
vap->va_mtime = mtime;
|
|
|
|
vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
|
2008-06-10 15:59:09 -07:00
|
|
|
|
|
|
|
uid = fxdr_unsigned(uid_t, fp->fa_uid);
|
|
|
|
gid = fxdr_unsigned(gid_t, fp->fa_gid);
|
|
|
|
/* Invalidate access cache if uid, gid or mode changed. */
|
|
|
|
if (np->n_accstamp != -1 &&
|
|
|
|
(gid != vap->va_gid || uid != vap->va_uid ||
|
2008-08-25 02:26:17 -07:00
|
|
|
(vmode & 07777) != vap->va_mode))
|
2008-06-10 15:59:09 -07:00
|
|
|
np->n_accstamp = -1;
|
|
|
|
|
2008-08-25 02:26:17 -07:00
|
|
|
vap->va_mode = (vmode & 07777);
|
|
|
|
|
2007-11-28 11:27:43 -08:00
|
|
|
switch (vtyp) {
|
|
|
|
case VBLK:
|
|
|
|
vap->va_blocksize = BLKDEV_IOSIZE;
|
|
|
|
break;
|
|
|
|
case VCHR:
|
|
|
|
vap->va_blocksize = MAXBSIZE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
vap->va_blocksize = v3 ? vp->v_mount->mnt_stat.f_iosize :
|
|
|
|
fxdr_unsigned(int32_t, fp->fa2_blocksize);
|
|
|
|
break;
|
|
|
|
}
|
2024-04-30 10:04:23 -07:00
|
|
|
vap->va_nlink = fxdr_unsigned(nlink_t, fp->fa_nlink);
|
|
|
|
vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
|
|
|
|
vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
|
1996-03-31 05:15:23 -08:00
|
|
|
if (v3) {
|
1998-08-19 15:26:51 -07:00
|
|
|
vap->va_size = fxdr_hyper(&fp->fa3_size);
|
|
|
|
vap->va_bytes = fxdr_hyper(&fp->fa3_used);
|
Switch time_t, ino_t, clock_t, and struct kevent's ident and data
members to 64bit types. Assign new syscall numbers for (almost
all) the syscalls that involve the affected types, including anything
with time_t, timeval, itimerval, timespec, rusage, dirent, stat,
or kevent arguments. Add a d_off member to struct dirent and replace
getdirentries() with getdents(), thus immensely simplifying and
accelerating telldir/seekdir. Build perl with -DBIG_TIME.
Bump the major on every single base library: the compat bits included
here are only good enough to make the transition; the T32 compat
option will be burned as soon as we've reached the new world are
are happy with the snapshots for all architectures.
DANGER: ABI incompatibility. Updating to this kernel requires extra
work or you won't be able to login: install a snapshot instead.
Much assistance in fixing userland issues from deraadt@ and tedu@
and build assistance from todd@ and otto@
2013-08-12 22:52:02 -07:00
|
|
|
vap->va_fileid = fxdr_hyper(&fp->fa3_fileid);
|
1996-03-31 05:15:23 -08:00
|
|
|
fxdr_nfsv3time(&fp->fa3_atime, &vap->va_atime);
|
|
|
|
fxdr_nfsv3time(&fp->fa3_ctime, &vap->va_ctime);
|
1995-10-18 01:37:01 -07:00
|
|
|
} else {
|
1996-03-31 05:15:23 -08:00
|
|
|
vap->va_size = fxdr_unsigned(u_int32_t, fp->fa2_size);
|
1999-01-16 05:28:25 -08:00
|
|
|
vap->va_bytes =
|
|
|
|
(u_quad_t)fxdr_unsigned(int32_t, fp->fa2_blocks) *
|
|
|
|
NFS_FABLKSIZE;
|
1996-03-31 05:15:23 -08:00
|
|
|
vap->va_fileid = fxdr_unsigned(int32_t, fp->fa2_fileid);
|
|
|
|
fxdr_nfsv2time(&fp->fa2_atime, &vap->va_atime);
|
|
|
|
vap->va_ctime.tv_sec = fxdr_unsigned(u_int32_t,
|
|
|
|
fp->fa2_ctime.nfsv2_sec);
|
|
|
|
vap->va_ctime.tv_nsec = 0;
|
|
|
|
vap->va_gen = fxdr_unsigned(u_int32_t,fp->fa2_ctime.nfsv2_usec);
|
1995-10-18 01:37:01 -07:00
|
|
|
}
|
2024-04-30 10:04:23 -07:00
|
|
|
vap->va_flags = 0;
|
|
|
|
vap->va_filerev = 0;
|
2008-06-10 15:59:09 -07:00
|
|
|
|
1995-10-18 01:37:01 -07:00
|
|
|
if (vap->va_size != np->n_size) {
|
2001-12-19 00:58:05 -08:00
|
|
|
if (vap->va_type == VREG) {
|
|
|
|
if (np->n_flag & NMODIFIED) {
|
|
|
|
if (vap->va_size < np->n_size)
|
|
|
|
vap->va_size = np->n_size;
|
|
|
|
else
|
|
|
|
np->n_size = vap->va_size;
|
|
|
|
} else
|
|
|
|
np->n_size = vap->va_size;
|
|
|
|
uvm_vnp_setsize(vp, np->n_size);
|
|
|
|
} else
|
1995-10-18 01:37:01 -07:00
|
|
|
np->n_size = vap->va_size;
|
|
|
|
}
|
2020-06-24 15:03:40 -07:00
|
|
|
np->n_attrstamp = gettime();
|
1995-10-18 01:37:01 -07:00
|
|
|
if (vaper != NULL) {
|
2014-12-18 12:59:21 -08:00
|
|
|
bcopy(vap, vaper, sizeof(*vap));
|
1995-10-18 01:37:01 -07:00
|
|
|
if (np->n_flag & NCHG) {
|
1996-03-31 05:15:23 -08:00
|
|
|
if (np->n_flag & NACC)
|
|
|
|
vaper->va_atime = np->n_atim;
|
|
|
|
if (np->n_flag & NUPD)
|
|
|
|
vaper->va_mtime = np->n_mtim;
|
1995-10-18 01:37:01 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2007-11-05 13:18:56 -08:00
|
|
|
int
|
2009-10-19 15:24:18 -07:00
|
|
|
nfs_attrtimeo(struct nfsnode *np)
|
1996-12-16 19:46:36 -08:00
|
|
|
{
|
|
|
|
struct vnode *vp = np->n_vnode;
|
|
|
|
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
|
2020-06-24 15:03:40 -07:00
|
|
|
int tenthage = (gettime() - np->n_mtime.tv_sec) / 10;
|
1996-12-16 19:46:36 -08:00
|
|
|
int minto, maxto;
|
|
|
|
|
|
|
|
if (vp->v_type == VDIR) {
|
|
|
|
maxto = nmp->nm_acdirmax;
|
|
|
|
minto = nmp->nm_acdirmin;
|
2024-04-30 10:04:23 -07:00
|
|
|
} else {
|
1996-12-16 19:46:36 -08:00
|
|
|
maxto = nmp->nm_acregmax;
|
|
|
|
minto = nmp->nm_acregmin;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (np->n_flag & NMODIFIED || tenthage < minto)
|
|
|
|
return minto;
|
|
|
|
else if (tenthage < maxto)
|
|
|
|
return tenthage;
|
|
|
|
else
|
|
|
|
return maxto;
|
|
|
|
}
|
|
|
|
|
1995-10-18 01:37:01 -07:00
|
|
|
/*
|
|
|
|
* Check the time stamp
|
|
|
|
* If the cache is valid, copy contents to *vap and return 0
|
|
|
|
* otherwise return an error
|
|
|
|
*/
|
1996-02-29 01:24:48 -08:00
|
|
|
int
|
2009-10-19 15:24:18 -07:00
|
|
|
nfs_getattrcache(struct vnode *vp, struct vattr *vaper)
|
1995-10-18 01:37:01 -07:00
|
|
|
{
|
2002-01-16 13:51:16 -08:00
|
|
|
struct nfsnode *np = VTONFS(vp);
|
|
|
|
struct vattr *vap;
|
1995-10-18 01:37:01 -07:00
|
|
|
|
2005-03-31 13:47:49 -08:00
|
|
|
if (np->n_attrstamp == 0 ||
|
2020-06-24 15:03:40 -07:00
|
|
|
(gettime() - np->n_attrstamp) >= nfs_attrtimeo(np)) {
|
1995-10-18 01:37:01 -07:00
|
|
|
nfsstats.attrcache_misses++;
|
|
|
|
return (ENOENT);
|
|
|
|
}
|
|
|
|
nfsstats.attrcache_hits++;
|
|
|
|
vap = &np->n_vattr;
|
|
|
|
if (vap->va_size != np->n_size) {
|
|
|
|
if (vap->va_type == VREG) {
|
|
|
|
if (np->n_flag & NMODIFIED) {
|
|
|
|
if (vap->va_size < np->n_size)
|
|
|
|
vap->va_size = np->n_size;
|
|
|
|
else
|
|
|
|
np->n_size = vap->va_size;
|
|
|
|
} else
|
|
|
|
np->n_size = vap->va_size;
|
1999-02-25 19:16:25 -08:00
|
|
|
uvm_vnp_setsize(vp, np->n_size);
|
1995-10-18 01:37:01 -07:00
|
|
|
} else
|
|
|
|
np->n_size = vap->va_size;
|
|
|
|
}
|
2014-12-18 12:59:21 -08:00
|
|
|
bcopy(vap, vaper, sizeof(struct vattr));
|
1995-10-18 01:37:01 -07:00
|
|
|
if (np->n_flag & NCHG) {
|
1996-03-31 05:15:23 -08:00
|
|
|
if (np->n_flag & NACC)
|
|
|
|
vaper->va_atime = np->n_atim;
|
|
|
|
if (np->n_flag & NUPD)
|
|
|
|
vaper->va_mtime = np->n_mtim;
|
1995-10-18 01:37:01 -07:00
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
1996-03-31 05:15:23 -08:00
|
|
|
#endif /* NFSCLIENT */
|
1995-10-18 01:37:01 -07:00
|
|
|
|
1996-03-31 05:15:23 -08:00
|
|
|
/*
|
|
|
|
* The write verifier has changed (probably due to a server reboot), so all
|
|
|
|
* B_NEEDCOMMIT blocks will have to be written again. Since they are on the
|
|
|
|
* dirty block list as B_DELWRI, all this takes is clearing the B_NEEDCOMMIT
|
|
|
|
* flag. Once done the new write verifier can be set for the mount point.
|
|
|
|
*/
|
|
|
|
void
|
2009-10-19 15:24:18 -07:00
|
|
|
nfs_clearcommit(struct mount *mp)
|
1996-03-31 05:15:23 -08:00
|
|
|
{
|
2020-01-14 13:38:02 -08:00
|
|
|
struct vnode *vp;
|
|
|
|
struct buf *bp;
|
1996-03-31 05:15:23 -08:00
|
|
|
int s;
|
|
|
|
|
|
|
|
s = splbio();
|
2001-12-19 00:58:05 -08:00
|
|
|
loop:
|
2020-01-14 13:38:02 -08:00
|
|
|
TAILQ_FOREACH(vp, &mp->mnt_vnodelist, v_mntvnodes) {
|
2001-12-19 00:58:05 -08:00
|
|
|
if (vp->v_mount != mp) /* Paranoia */
|
|
|
|
goto loop;
|
2020-01-14 13:38:02 -08:00
|
|
|
LIST_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs) {
|
2001-12-19 00:58:05 -08:00
|
|
|
if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT))
|
2018-07-02 13:56:22 -07:00
|
|
|
== (B_DELWRI | B_NEEDCOMMIT))
|
2001-12-19 00:58:05 -08:00
|
|
|
bp->b_flags &= ~B_NEEDCOMMIT;
|
1996-03-31 05:15:23 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
|
2004-08-03 10:11:48 -07:00
|
|
|
void
|
2009-10-19 15:24:18 -07:00
|
|
|
nfs_merge_commit_ranges(struct vnode *vp)
|
2004-08-03 10:11:48 -07:00
|
|
|
{
|
|
|
|
struct nfsnode *np = VTONFS(vp);
|
|
|
|
|
|
|
|
if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID)) {
|
|
|
|
np->n_pushedlo = np->n_pushlo;
|
|
|
|
np->n_pushedhi = np->n_pushhi;
|
|
|
|
np->n_commitflags |= NFS_COMMIT_PUSHED_VALID;
|
|
|
|
} else {
|
|
|
|
if (np->n_pushlo < np->n_pushedlo)
|
|
|
|
np->n_pushedlo = np->n_pushlo;
|
|
|
|
if (np->n_pushhi > np->n_pushedhi)
|
|
|
|
np->n_pushedhi = np->n_pushhi;
|
|
|
|
}
|
|
|
|
|
|
|
|
np->n_pushlo = np->n_pushhi = 0;
|
|
|
|
np->n_commitflags &= ~NFS_COMMIT_PUSH_VALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2009-10-19 15:24:18 -07:00
|
|
|
nfs_in_committed_range(struct vnode *vp, struct buf *bp)
|
2004-08-03 10:11:48 -07:00
|
|
|
{
|
|
|
|
struct nfsnode *np = VTONFS(vp);
|
|
|
|
off_t lo, hi;
|
|
|
|
|
|
|
|
if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID))
|
|
|
|
return 0;
|
|
|
|
lo = (off_t)bp->b_blkno * DEV_BSIZE;
|
|
|
|
hi = lo + bp->b_dirtyend;
|
|
|
|
|
|
|
|
return (lo >= np->n_pushedlo && hi <= np->n_pushedhi);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2009-10-19 15:24:18 -07:00
|
|
|
nfs_in_tobecommitted_range(struct vnode *vp, struct buf *bp)
|
2004-08-03 10:11:48 -07:00
|
|
|
{
|
|
|
|
struct nfsnode *np = VTONFS(vp);
|
|
|
|
off_t lo, hi;
|
|
|
|
|
|
|
|
if (!(np->n_commitflags & NFS_COMMIT_PUSH_VALID))
|
|
|
|
return 0;
|
|
|
|
lo = (off_t)bp->b_blkno * DEV_BSIZE;
|
|
|
|
hi = lo + bp->b_dirtyend;
|
|
|
|
|
|
|
|
return (lo >= np->n_pushlo && hi <= np->n_pushhi);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-10-19 15:24:18 -07:00
|
|
|
nfs_add_committed_range(struct vnode *vp, struct buf *bp)
|
2004-08-03 10:11:48 -07:00
|
|
|
{
|
|
|
|
struct nfsnode *np = VTONFS(vp);
|
|
|
|
off_t lo, hi;
|
|
|
|
|
|
|
|
lo = (off_t)bp->b_blkno * DEV_BSIZE;
|
|
|
|
hi = lo + bp->b_dirtyend;
|
|
|
|
|
|
|
|
if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID)) {
|
|
|
|
np->n_pushedlo = lo;
|
|
|
|
np->n_pushedhi = hi;
|
|
|
|
np->n_commitflags |= NFS_COMMIT_PUSHED_VALID;
|
|
|
|
} else {
|
|
|
|
if (hi > np->n_pushedhi)
|
|
|
|
np->n_pushedhi = hi;
|
|
|
|
if (lo < np->n_pushedlo)
|
|
|
|
np->n_pushedlo = lo;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-10-19 15:24:18 -07:00
|
|
|
nfs_del_committed_range(struct vnode *vp, struct buf *bp)
|
2004-08-03 10:11:48 -07:00
|
|
|
{
|
|
|
|
struct nfsnode *np = VTONFS(vp);
|
|
|
|
off_t lo, hi;
|
|
|
|
|
|
|
|
if (!(np->n_commitflags & NFS_COMMIT_PUSHED_VALID))
|
|
|
|
return;
|
|
|
|
|
|
|
|
lo = (off_t)bp->b_blkno * DEV_BSIZE;
|
|
|
|
hi = lo + bp->b_dirtyend;
|
|
|
|
|
|
|
|
if (lo > np->n_pushedhi || hi < np->n_pushedlo)
|
|
|
|
return;
|
|
|
|
if (lo <= np->n_pushedlo)
|
|
|
|
np->n_pushedlo = hi;
|
|
|
|
else if (hi >= np->n_pushedhi)
|
|
|
|
np->n_pushedhi = lo;
|
|
|
|
else {
|
|
|
|
/*
|
|
|
|
* XXX There's only one range. If the deleted range
|
|
|
|
* is in the middle, pick the largest of the
|
|
|
|
* contiguous ranges that it leaves.
|
|
|
|
*/
|
|
|
|
if ((np->n_pushedlo - lo) > (hi - np->n_pushedhi))
|
|
|
|
np->n_pushedhi = lo;
|
|
|
|
else
|
|
|
|
np->n_pushedlo = hi;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-10-19 15:24:18 -07:00
|
|
|
nfs_add_tobecommitted_range(struct vnode *vp, struct buf *bp)
|
2004-08-03 10:11:48 -07:00
|
|
|
{
|
|
|
|
struct nfsnode *np = VTONFS(vp);
|
|
|
|
off_t lo, hi;
|
|
|
|
|
|
|
|
lo = (off_t)bp->b_blkno * DEV_BSIZE;
|
|
|
|
hi = lo + bp->b_dirtyend;
|
|
|
|
|
|
|
|
if (!(np->n_commitflags & NFS_COMMIT_PUSH_VALID)) {
|
|
|
|
np->n_pushlo = lo;
|
|
|
|
np->n_pushhi = hi;
|
|
|
|
np->n_commitflags |= NFS_COMMIT_PUSH_VALID;
|
|
|
|
} else {
|
|
|
|
if (lo < np->n_pushlo)
|
|
|
|
np->n_pushlo = lo;
|
|
|
|
if (hi > np->n_pushhi)
|
|
|
|
np->n_pushhi = hi;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-10-19 15:24:18 -07:00
|
|
|
nfs_del_tobecommitted_range(struct vnode *vp, struct buf *bp)
|
2004-08-03 10:11:48 -07:00
|
|
|
{
|
|
|
|
struct nfsnode *np = VTONFS(vp);
|
|
|
|
off_t lo, hi;
|
|
|
|
|
|
|
|
if (!(np->n_commitflags & NFS_COMMIT_PUSH_VALID))
|
|
|
|
return;
|
|
|
|
|
|
|
|
lo = (off_t)bp->b_blkno * DEV_BSIZE;
|
|
|
|
hi = lo + bp->b_dirtyend;
|
|
|
|
|
|
|
|
if (lo > np->n_pushhi || hi < np->n_pushlo)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (lo <= np->n_pushlo)
|
|
|
|
np->n_pushlo = hi;
|
|
|
|
else if (hi >= np->n_pushhi)
|
|
|
|
np->n_pushhi = lo;
|
|
|
|
else {
|
|
|
|
/*
|
|
|
|
* XXX There's only one range. If the deleted range
|
|
|
|
* is in the middle, pick the largest of the
|
|
|
|
* contiguous ranges that it leaves.
|
|
|
|
*/
|
|
|
|
if ((np->n_pushlo - lo) > (hi - np->n_pushhi))
|
|
|
|
np->n_pushhi = lo;
|
|
|
|
else
|
|
|
|
np->n_pushlo = hi;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-03-31 05:15:23 -08:00
|
|
|
/*
|
|
|
|
* Map errnos to NFS error numbers. For Version 3 also filter out error
|
|
|
|
* numbers not specified for the associated procedure.
|
|
|
|
*/
|
|
|
|
int
|
2009-10-19 15:24:18 -07:00
|
|
|
nfsrv_errmap(struct nfsrv_descript *nd, int err)
|
1996-03-31 05:15:23 -08:00
|
|
|
{
|
2024-04-30 10:05:20 -07:00
|
|
|
const short *defaulterrp, *errp;
|
1996-03-31 05:15:23 -08:00
|
|
|
|
|
|
|
if (nd->nd_flag & ND_NFSV3) {
|
|
|
|
if (nd->nd_procnum <= NFSPROC_COMMIT) {
|
|
|
|
errp = defaulterrp = nfsrv_v3errmap[nd->nd_procnum];
|
|
|
|
while (*++errp) {
|
|
|
|
if (*errp == err)
|
|
|
|
return (err);
|
|
|
|
else if (*errp > err)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return ((int)*defaulterrp);
|
|
|
|
} else
|
|
|
|
return (err & 0xffff);
|
|
|
|
}
|
2008-11-24 12:14:52 -08:00
|
|
|
if (err <= nitems(nfsrv_v2errmap))
|
1996-03-31 05:15:23 -08:00
|
|
|
return ((int)nfsrv_v2errmap[err - 1]);
|
|
|
|
return (NFSERR_IO);
|
|
|
|
}
|
|
|
|
|
2007-12-13 10:32:55 -08:00
|
|
|
/*
|
2008-12-23 18:48:36 -08:00
|
|
|
* If full is non zero, set all fields, otherwise just set mode and time fields
|
2007-12-13 10:32:55 -08:00
|
|
|
*/
|
|
|
|
void
|
2008-06-12 13:24:06 -07:00
|
|
|
nfsm_v3attrbuild(struct mbuf **mp, struct vattr *a, int full)
|
2007-12-13 10:32:55 -08:00
|
|
|
{
|
2008-01-06 09:38:23 -08:00
|
|
|
struct mbuf *mb;
|
2007-12-13 10:32:55 -08:00
|
|
|
u_int32_t *tl;
|
|
|
|
|
|
|
|
mb = *mp;
|
|
|
|
|
|
|
|
if (a->va_mode != (mode_t)VNOVAL) {
|
2008-06-12 13:24:06 -07:00
|
|
|
tl = nfsm_build(&mb, 2 * NFSX_UNSIGNED);
|
2007-12-13 10:32:55 -08:00
|
|
|
*tl++ = nfs_true;
|
|
|
|
*tl = txdr_unsigned(a->va_mode);
|
|
|
|
} else {
|
2008-06-12 13:24:06 -07:00
|
|
|
tl = nfsm_build(&mb, NFSX_UNSIGNED);
|
2007-12-13 10:32:55 -08:00
|
|
|
*tl = nfs_false;
|
|
|
|
}
|
|
|
|
if (full && a->va_uid != (uid_t)VNOVAL) {
|
2008-06-12 13:24:06 -07:00
|
|
|
tl = nfsm_build(&mb, 2 * NFSX_UNSIGNED);
|
2007-12-13 10:32:55 -08:00
|
|
|
*tl++ = nfs_true;
|
|
|
|
*tl = txdr_unsigned(a->va_uid);
|
|
|
|
} else {
|
2008-06-12 13:24:06 -07:00
|
|
|
tl = nfsm_build(&mb, NFSX_UNSIGNED);
|
2007-12-13 10:32:55 -08:00
|
|
|
*tl = nfs_false;
|
|
|
|
}
|
|
|
|
if (full && a->va_gid != (gid_t)VNOVAL) {
|
2008-06-12 13:24:06 -07:00
|
|
|
tl = nfsm_build(&mb, 2 * NFSX_UNSIGNED);
|
2007-12-13 10:32:55 -08:00
|
|
|
*tl++ = nfs_true;
|
|
|
|
*tl = txdr_unsigned((a)->va_gid);
|
|
|
|
} else {
|
2008-06-12 13:24:06 -07:00
|
|
|
tl = nfsm_build(&mb, NFSX_UNSIGNED);
|
2007-12-13 10:32:55 -08:00
|
|
|
*tl = nfs_false;
|
|
|
|
}
|
|
|
|
if (full && a->va_size != VNOVAL) {
|
2008-06-12 13:24:06 -07:00
|
|
|
tl = nfsm_build(&mb, 3 * NFSX_UNSIGNED);
|
2007-12-13 10:32:55 -08:00
|
|
|
*tl++ = nfs_true;
|
|
|
|
txdr_hyper(a->va_size, tl);
|
|
|
|
} else {
|
2008-06-12 13:24:06 -07:00
|
|
|
tl = nfsm_build(&mb, NFSX_UNSIGNED);
|
2007-12-13 10:32:55 -08:00
|
|
|
*tl = nfs_false;
|
|
|
|
}
|
2015-04-16 21:43:20 -07:00
|
|
|
if (a->va_atime.tv_nsec != VNOVAL) {
|
2020-06-24 15:03:40 -07:00
|
|
|
if (a->va_atime.tv_sec != gettime()) {
|
2008-06-12 13:24:06 -07:00
|
|
|
tl = nfsm_build(&mb, 3 * NFSX_UNSIGNED);
|
2007-12-13 10:32:55 -08:00
|
|
|
*tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
|
|
|
|
txdr_nfsv3time(&a->va_atime, tl);
|
|
|
|
} else {
|
2008-06-12 13:24:06 -07:00
|
|
|
tl = nfsm_build(&mb, NFSX_UNSIGNED);
|
2007-12-13 10:32:55 -08:00
|
|
|
*tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER);
|
|
|
|
}
|
|
|
|
} else {
|
2008-06-12 13:24:06 -07:00
|
|
|
tl = nfsm_build(&mb, NFSX_UNSIGNED);
|
2007-12-13 10:32:55 -08:00
|
|
|
*tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
|
|
|
|
}
|
2015-04-16 21:43:20 -07:00
|
|
|
if (a->va_mtime.tv_nsec != VNOVAL) {
|
2020-06-24 15:03:40 -07:00
|
|
|
if (a->va_mtime.tv_sec != gettime()) {
|
2008-06-12 13:24:06 -07:00
|
|
|
tl = nfsm_build(&mb, 3 * NFSX_UNSIGNED);
|
2007-12-13 10:32:55 -08:00
|
|
|
*tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT);
|
|
|
|
txdr_nfsv3time(&a->va_mtime, tl);
|
|
|
|
} else {
|
2008-06-12 13:24:06 -07:00
|
|
|
tl = nfsm_build(&mb, NFSX_UNSIGNED);
|
2007-12-13 10:32:55 -08:00
|
|
|
*tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER);
|
|
|
|
}
|
|
|
|
} else {
|
2008-06-12 13:24:06 -07:00
|
|
|
tl = nfsm_build(&mb, NFSX_UNSIGNED);
|
2007-12-13 10:32:55 -08:00
|
|
|
*tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE);
|
|
|
|
}
|
|
|
|
|
|
|
|
*mp = mb;
|
|
|
|
}
|
2008-01-06 09:38:23 -08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Ensure a contiguous buffer len bytes long
|
|
|
|
*/
|
|
|
|
void *
|
2008-06-12 13:24:06 -07:00
|
|
|
nfsm_build(struct mbuf **mp, u_int len)
|
2008-01-06 09:38:23 -08:00
|
|
|
{
|
|
|
|
struct mbuf *mb, *mb2;
|
|
|
|
caddr_t bpos;
|
|
|
|
|
|
|
|
mb = *mp;
|
2008-06-12 13:24:06 -07:00
|
|
|
bpos = mb_offset(mb);
|
2008-01-06 09:38:23 -08:00
|
|
|
|
2018-11-09 06:14:31 -08:00
|
|
|
if (len > m_trailingspace(mb)) {
|
2008-01-06 09:38:23 -08:00
|
|
|
MGET(mb2, M_WAIT, MT_DATA);
|
|
|
|
if (len > MLEN)
|
|
|
|
panic("build > MLEN");
|
|
|
|
mb->m_next = mb2;
|
|
|
|
mb = mb2;
|
|
|
|
mb->m_len = 0;
|
|
|
|
bpos = mtod(mb, caddr_t);
|
|
|
|
}
|
|
|
|
mb->m_len += len;
|
|
|
|
|
|
|
|
*mp = mb;
|
|
|
|
|
|
|
|
return (bpos);
|
|
|
|
}
|
2009-03-30 12:58:50 -07:00
|
|
|
|
2009-04-13 10:51:57 -07:00
|
|
|
void
|
2009-08-13 08:18:16 -07:00
|
|
|
nfsm_fhtom(struct nfsm_info *info, struct vnode *v, int v3)
|
2009-04-13 10:51:57 -07:00
|
|
|
{
|
|
|
|
struct nfsnode *n = VTONFS(v);
|
|
|
|
|
|
|
|
if (v3) {
|
2009-08-13 08:18:16 -07:00
|
|
|
nfsm_strtombuf(&info->nmi_mb, n->n_fhp, n->n_fhsize);
|
2009-04-13 10:51:57 -07:00
|
|
|
} else {
|
2009-08-13 08:18:16 -07:00
|
|
|
nfsm_buftombuf(&info->nmi_mb, n->n_fhp, NFSX_V2FH);
|
2009-04-13 10:51:57 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nfsm_srvfhtom(struct mbuf **mp, fhandle_t *f, int v3)
|
|
|
|
{
|
|
|
|
if (v3) {
|
|
|
|
nfsm_strtombuf(mp, f, NFSX_V3FH);
|
|
|
|
} else {
|
|
|
|
nfsm_buftombuf(mp, f, NFSX_V2FH);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-16 21:43:20 -07:00
|
|
|
void
|
|
|
|
txdr_nfsv2time(const struct timespec *from, struct nfsv2_time *to)
|
|
|
|
{
|
|
|
|
if (from->tv_nsec == VNOVAL) {
|
|
|
|
to->nfsv2_sec = nfs_xdrneg1;
|
|
|
|
to->nfsv2_usec = nfs_xdrneg1;
|
|
|
|
} else if (from->tv_sec == -1) {
|
|
|
|
/*
|
|
|
|
* can't request a time of -1; send
|
|
|
|
* -1.000001 == {-2,999999} instead
|
|
|
|
*/
|
|
|
|
to->nfsv2_sec = htonl(-2);
|
|
|
|
to->nfsv2_usec = htonl(999999);
|
|
|
|
} else {
|
|
|
|
to->nfsv2_sec = htonl(from->tv_sec);
|
|
|
|
to->nfsv2_usec = htonl(from->tv_nsec / 1000);
|
|
|
|
}
|
|
|
|
}
|