Changes to support version 3 of the NFS protocol.

The version 2 support has been tested (client+server) against FreeBSD-2.0,
IRIX 5.3 and FreeBSD-current (using a loopback mount).  The version 2 support
is stable AFAIK.
The version 3 support has been tested with a loopback mount and minimally
against an IRIX 5.3 server.  It needs more testing and may have problems.
I have patched amd to support the new variable length filehandles although
it will still only use version 2 of the protocol.

Before booting a kernel with these changes, nfs clients will need to at least
build and install /usr/sbin/mount_nfs.  Servers will need to build and
install /usr/sbin/mountd.

NFS diskless support is untested.

Obtained from: Rick Macklem <rick@snowhite.cis.uoguelph.ca>
This commit is contained in:
Doug Rabson 1995-06-27 11:07:30 +00:00
parent 82aaeb09ad
commit a62dc40654
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=9336
71 changed files with 19011 additions and 6756 deletions

View File

@ -44,8 +44,6 @@
%#include <sys/param.h>
%#include <sys/syslimits.h>
%#include <sys/ucred.h>
%#include <nfs/nfsv2.h>
%#include <nfs/nfs.h>
#else
%#ifndef lint
%/*static char sccsid[] = "from: @(#)bootparam_prot.x 1.2 87/06/24 Copyr 1987 Sun Micro";*/

View File

@ -39,8 +39,9 @@
.Nd mount nfs file systems
.Sh SYNOPSIS
.Nm mount_nfs
.Op Fl KMPTbcdiklqs
.Op Fl 3KPTUbcdilqs
.Op Fl D Ar deadthresh
.Op Fl I Ar readdirsize
.Op Fl L Ar leaseterm
.Op Fl R Ar retrycnt
.Op Fl a Ar maxreadahead
@ -63,10 +64,14 @@ on to the file system tree at the point
.Ar node.
This command is normally executed by
.Xr mount 8 .
It implements the mount protocol as described in RFC 1094, Appendix A.
It implements the mount protocol as described in RFC 1094, Appendix A and
.%T "NFS: Network File System Version 3 Protocol Specification" ,
Appendix I.
.Pp
The options are:
.Bl -tag -width indent
.It Fl 3
Use the NFS Version 3 protocol (Version 2 is the default).
.It Fl D
Used with NQNFS to set the
.Dq "dead server threshold"
@ -80,23 +85,27 @@ Values may be set in the range of 1 - 9, with 9 referring to an
(i.e. never assume cached data still valid).
This option is not generally recommended and is really an experimental
feature.
.It Fl I
Set the readdir read size to the specified value. The value should normally
be a multiple of DIRBLKSIZ that is <= the read size for the mount.
.It Fl K
Pass Kerberos authenticators to the server for client-to-server
user-credential mapping.
This may only be used over TCP mounts between 4.4BSD clients and servers.
This requires that the kernel be built with the NFSKERB option.
(Refer to the INTERNET-DRAFT titled
.%T "Authentication Mechanisms for ONC RPC" ,
for more information.)
.It Fl L
Used with NQNFS to set the lease term to the specified number of seconds.
Only use this argument for mounts with a large round trip delay.
Values are normally in the 10-30 second range.
.It Fl M
Assume that other clients are not writing a file concurrently with this client.
This implements a slightly less strict consistency criteria than 4.3BSD-Reno
did, that is more in line with most commercial client implementations.
This is recommended for servers that do not support leasing.
.It Fl P
Use a reserved socket port number.
This is useful for mounting servers that require clients to use a
reserved port number.
reserved port number on the mistaken belief that this makes NFS
more secure. (For the rare case where the client has a trusted root account
but untrusworthy users and the network cables are in secure areas this does
help, but for normal desktop clients this does not apply.)
.It Fl R
Set the retry count for doing the mount to the specified value.
.It Fl T
@ -104,11 +113,15 @@ Use TCP transport instead of UDP.
This is recommended for servers that are not on the same LAN cable as
the client.
(NB: This is NOT supported by most non-BSD servers.)
.It Fl U
Force the mount protocol to use UDP transport, even for TCP NFS mounts.
(Necessary for some old BSD servers.)
.It Fl a
Set the read-ahead count to the specified value.
This may be in the range of 0 - 4, and determines how many blocks
will be read ahead when a large file is being read sequentially.
This is recommended for mounts with a large bandwidth * delay product.
Trying a value greater than 1 for this is suggested for
mounts with a large bandwidth * delay product.
.It Fl b
If an initial attempt to contact the server fails, fork off a child to keep
trying the mount in the background.
@ -119,10 +132,12 @@ where the filesystem mount is not critical to multiuser operation.
For UDP mount points, do not do a
.Xr connect 2 .
This must be used for servers that do not reply to requests from the
standard port number.
standard NFS port number 2049.
.It Fl d
Do not estimate retransmit timeout dynamically.
This may be useful for UDP mounts that exhibit high retry rates.
Turn off the dynamic retransmit timeout estimator.
This may be useful for UDP mounts that exhibit high retry rates,
since it is possible that the dynamically estimated timeout interval is too
short.
.It Fl g
Set the maximum size of the group list for the credentials to the
specified value.
@ -134,20 +149,15 @@ point.
Make the mount interruptible, which implies that file system calls that
are delayed due to an unresponsive server will fail with EINTR when a
termination signal is posted for the process.
.It Fl k
Used with NQNFS to specify
.Dq get a lease
for the file name being looked up.
This is recommended unless the server is complaining about excessive
lease load.
.It Fl l
Used with NQNFS to specify that the \fBReaddir_and_Lookup\fR RPC should
Used with NQNFS and NFSV3 to specify that the \fBReaddirPlus\fR RPC should
be used.
This option reduces RPC traffic for cases such as
.Dq "ls -l" ,
but increases the lease load on the server.
This is recommended unless the server is complaining about excessive
lease load.
but tends to flood the attribute and name caches with prefetched entries.
Try this option and see whether performance improves or degrades. Probably
most useful for client to server network interconnects with a large bandwidth
times delay product.
.It Fl m
Set the Kerberos realm to the string argument.
Used with the
@ -167,12 +177,16 @@ Use specified port number for NFS requests.
The default is to query the portmapper for the NFS port.
.El
.It Fl q
Use the leasing extensions to the protocol to maintain cache consistency.
This protocol, referred to as Not Quite Nfs (NQNFS),
is only supported by 4.4BSD servers.
Use the leasing extensions to the NFS Version 3 protocol to maintain cache consistency.
This protocol Version 2, referred to as Not Quite Nfs (NQNFS),
is only supported by this updated release of NFS code.
(It is not backwards compatible with the release of NQNFS that went out on
4.4BSD-Lite. To interoperate with a 4.4BSD-Lite NFS system you will have to
avoid this option until you have had an oppurtunity to upgrade the NFS code
on all your 4.4BSD-Lite based systems.)
.It Fl r
Set the read data size to the specified value.
It should be a power of 2 greater than or equal to 1024.
It should normally be a power of 2 greater than or equal to 1024.
This should be used for UDP mounts when the
.Dq "fragments dropped due to timeout"
value is getting large while actively using a mount point.
@ -197,6 +211,9 @@ Try increasing the interval if
.Xr nfsstat 1
shows high retransmit rates while the file system is active or reducing the
value if there is a low retransmit rate but long response delay observed.
(Normally, the -d option should be specified when using this option to manually
tune the timeout
interval.)
.It Fl w
Set the write data size to the specified value.
Ditto the comments w.r.t. the

View File

@ -59,16 +59,16 @@ static char sccsid[] = "@(#)mount_nfs.c 8.3 (Berkeley) 3/27/94";
#include <netiso/iso.h>
#endif
#ifdef KERBEROS
#ifdef NFSKERB
#include <kerberosIV/des.h>
#include <kerberosIV/krb.h>
#endif
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#define KERNEL
#include <nfs/nfsproto.h>
#define _KERNEL
#include <nfs/nfs.h>
#undef KERNEL
#undef _KERNEL
#include <nfs/nqnfs.h>
#include <arpa/inet.h>
@ -86,14 +86,15 @@ static char sccsid[] = "@(#)mount_nfs.c 8.3 (Berkeley) 3/27/94";
#include "mntopts.h"
#ifdef __FreeBSD__
#define ALTF_BG 0x1
#define ALTF_NOCONN 0x2
#define ALTF_DUMBTIMR 0x4
#define ALTF_INTR 0x8
#define ALTF_KERB 0x10
#define ALTF_NQLOOKLSE 0x20
#define ALTF_RDIRALOOK 0x40
#define ALTF_MYWRITE 0x80
#define ALTF_NFSV3 0x20
#define ALTF_RDIRPLUS 0x40
#define ALTF_MNTUDP 0x80
#define ALTF_RESVPORT 0x100
#define ALTF_SEQPACKET 0x200
#define ALTF_NQNFS 0x400
@ -109,12 +110,12 @@ struct mntopt mopts[] = {
{ "conn", 1, ALTF_NOCONN, 1 },
{ "dumbtimer", 0, ALTF_DUMBTIMR, 1 },
{ "intr", 0, ALTF_INTR, 1 },
#ifdef KERBEROS
#ifdef NFSKERB
{ "kerb", 0, ALTF_KERB, 1 },
#endif
{ "nqlooklease", 0, ALTF_NQLOOKLSE, 1 },
{ "rdiralook", 0, ALTF_RDIRALOOK, 1 },
{ "mywrite", 0, ALTF_MYWRITE, 1 },
{ "nfsv3", 0, ALTF_NFSV3, 1 },
{ "rdirplus", 0, ALTF_RDIRPLUS, 1 },
{ "mntudp", 0, ALTF_MNTUDP, 1 },
{ "resvport", 0, ALTF_RESVPORT, 1 },
#ifdef ISO
{ "seqpacket", 0, ALTF_SEQPACKET, 1 },
@ -125,17 +126,27 @@ struct mntopt mopts[] = {
{ "port=", 0, ALTF_PORT, 1 },
{ NULL }
};
#else
struct mntopt mopts[] = {
MOPT_STDOPTS,
MOPT_FORCE,
MOPT_UPDATE,
{ NULL }
};
#endif
struct nfs_args nfsdefargs = {
(struct sockaddr *)0,
sizeof (struct sockaddr_in),
SOCK_DGRAM,
0,
(nfsv2fh_t *)0,
(u_char *)0,
0,
0,
NFS_WSIZE,
NFS_RSIZE,
NFS_TIMEO,
NFS_READDIRSIZE,
10,
NFS_RETRANS,
NFS_MAXGRPS,
NFS_DEFRAHEAD,
@ -145,20 +156,34 @@ struct nfs_args nfsdefargs = {
};
struct nfhret {
u_long stat;
nfsv2fh_t nfh;
u_long stat;
long vers;
long auth;
long fhsize;
u_char nfh[NFSX_V3FHMAX];
};
#define DEF_RETRY 10000
#define BGRND 1
#define ISBGRND 2
int retrycnt = DEF_RETRY;
int opflags = 0;
int nfsproto = IPPROTO_UDP;
int mnttcp_ok = 1;
u_short port_no = 0;
#ifdef KERBEROS
#ifdef NFSKERB
char inst[INST_SZ];
char realm[REALM_SZ];
KTEXT_ST kt;
struct {
u_long kind;
KTEXT_ST kt;
} ktick;
struct nfsrpc_nickverf kverf;
struct nfsrpc_fullblock kin, kout;
NFSKERBKEY_T kivec;
CREDENTIALS kcr;
struct timeval ktv;
NFSKERBKEYSCHED_T kerb_keysched;
#endif
int getnfsargs __P((char *, struct nfs_args *));
@ -182,14 +207,17 @@ main(argc, argv)
int mntflags, altflags, i, nfssvc_flag, num;
char *name, *p, *spec;
struct vfsconf *vfc;
#ifdef KERBEROS
#ifdef NFSKERB
uid_t last_ruid;
#endif
#ifdef KERBEROS
last_ruid = -1;
(void)strcpy(realm, KRB_REALM);
#endif
if (sizeof (struct nfsrpc_nickverf) != RPCX_NICKVERF ||
sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK ||
((char *)&ktick.kt) - ((char *)&ktick) != NFSX_UNSIGNED ||
((char *)ktick.kt.dat) - ((char *)&ktick) != 2 * NFSX_UNSIGNED)
fprintf(stderr, "Yikes! NFSKERB structs not packed!!\n");
#endif /* NFSKERB */
retrycnt = DEF_RETRY;
mntflags = 0;
@ -197,8 +225,11 @@ main(argc, argv)
nfsargs = nfsdefargs;
nfsargsp = &nfsargs;
while ((c = getopt(argc, argv,
"a:bcdD:g:iKklL:Mm:o:PpqR:r:sTt:w:x:")) != EOF)
"3a:bcdD:g:I:iKL:lm:o:PpqR:r:sTt:w:x:U")) != EOF)
switch (c) {
case '3':
nfsargsp->flags |= NFSMNT_NFSV3;
break;
case 'a':
num = strtol(optarg, &p, 10);
if (*p || num < 0)
@ -226,21 +257,27 @@ main(argc, argv)
num = strtol(optarg, &p, 10);
if (*p || num <= 0)
errx(1, "illegal -g value -- %s", optarg);
#ifdef __FreeBSD__
set_rpc_maxgrouplist(num);
#endif
nfsargsp->maxgrouplist = num;
nfsargsp->flags |= NFSMNT_MAXGRPS;
break;
case 'I':
num = strtol(optarg, &p, 10);
if (*p || num <= 0)
errx(1, "illegal -I value -- %s", optarg);
nfsargsp->readdirsize = num;
nfsargsp->flags |= NFSMNT_READDIRSIZE;
break;
case 'i':
nfsargsp->flags |= NFSMNT_INT;
break;
#ifdef KERBEROS
#ifdef NFSKERB
case 'K':
nfsargsp->flags |= NFSMNT_KERB;
break;
#endif
case 'k':
nfsargsp->flags |= NFSMNT_NQLOOKLEASE;
break;
case 'L':
num = strtol(optarg, &p, 10);
if (*p || num < 2)
@ -249,18 +286,16 @@ main(argc, argv)
nfsargsp->flags |= NFSMNT_LEASETERM;
break;
case 'l':
nfsargsp->flags |= NFSMNT_RDIRALOOK;
nfsargsp->flags |= NFSMNT_RDIRPLUS;
break;
case 'M':
nfsargsp->flags |= NFSMNT_MYWRITE;
break;
#ifdef KERBEROS
#ifdef NFSKERB
case 'm':
(void)strncpy(realm, optarg, REALM_SZ - 1);
realm[REALM_SZ - 1] = '\0';
break;
#endif
case 'o':
#ifdef __FreeBSD__
getmntopts(optarg, mopts, &mntflags, &altflags);
if(altflags & ALTF_BG)
opflags |= BGRND;
@ -270,16 +305,16 @@ main(argc, argv)
nfsargsp->flags |= NFSMNT_DUMBTIMR;
if(altflags & ALTF_INTR)
nfsargsp->flags |= NFSMNT_INT;
#ifdef KERBEROS
#ifdef NFSKERB
if(altflags & ALTF_KERB)
nfsargsp->flags |= NFSMNT_KERB;
#endif
if(altflags & ALTF_NQLOOKLSE)
nfsargsp->flags |= NFSMNT_NQLOOKLEASE;
if(altflags & ALTF_RDIRALOOK)
nfsargsp->flags |= NFSMNT_RDIRALOOK;
if(altflags & ALTF_MYWRITE)
nfsargsp->flags |= NFSMNT_MYWRITE;
if(altflags & ALTF_NFSV3)
nfsargsp->flags |= NFSMNT_NFSV3;
if(altflags & ALTF_RDIRPLUS)
nfsargsp->flags |= NFSMNT_RDIRPLUS;
if(altflags & ALTF_MNTUDP)
mnttcp_ok = 0;
if(altflags & ALTF_RESVPORT)
nfsargsp->flags |= NFSMNT_RESVPORT;
#ifdef ISO
@ -287,14 +322,19 @@ main(argc, argv)
nfsargsp->sotype = SOCK_SEQPACKET;
#endif
if(altflags & ALTF_NQNFS)
nfsargsp->flags |= NFSMNT_NQNFS;
nfsargsp->flags |= (NFSMNT_NQNFS|NFSMNT_NFSV3);
if(altflags & ALTF_SOFT)
nfsargsp->flags |= NFSMNT_SOFT;
if(altflags & ALTF_TCP)
if(altflags & ALTF_TCP) {
nfsargsp->sotype = SOCK_STREAM;
nfsproto = IPPROTO_TCP;
}
if(altflags & ALTF_PORT)
port_no = atoi(strstr(optarg, "port=") + 5);
altflags = 0;
#else
getmntopts(optarg, mopts, &mntflags);
#endif
break;
case 'P':
nfsargsp->flags |= NFSMNT_RESVPORT;
@ -305,7 +345,7 @@ main(argc, argv)
break;
#endif
case 'q':
nfsargsp->flags |= NFSMNT_NQNFS;
nfsargsp->flags |= (NFSMNT_NQNFS | NFSMNT_NFSV3);
break;
case 'R':
num = strtol(optarg, &p, 10);
@ -325,6 +365,7 @@ main(argc, argv)
break;
case 'T':
nfsargsp->sotype = SOCK_STREAM;
nfsproto = IPPROTO_TCP;
break;
case 't':
num = strtol(optarg, &p, 10);
@ -347,6 +388,9 @@ main(argc, argv)
nfsargsp->retrans = num;
nfsargsp->flags |= NFSMNT_RETRANS;
break;
case 'U':
mnttcp_ok = 0;
break;
default:
usage();
break;
@ -363,6 +407,7 @@ main(argc, argv)
if (!getnfsargs(spec, nfsargsp))
exit(1);
#ifdef __FreeBSD__
vfc = getvfsbyname("nfs");
if(!vfc && vfsisloadable("nfs")) {
if(vfsload("nfs"))
@ -372,6 +417,9 @@ main(argc, argv)
}
if (mount(vfc ? vfc->vfc_index : MOUNT_NFS, name, mntflags, nfsargsp))
#else
if (mount(MOUNT_NFS, name, mntflags, nfsargsp))
#endif
err(1, "%s", name);
if (nfsargsp->flags & (NFSMNT_NQNFS | NFSMNT_KERB)) {
if ((opflags & ISBGRND) == 0) {
@ -396,13 +444,18 @@ main(argc, argv)
}
nfssvc_flag =
NFSSVC_MNTD | NFSSVC_GOTAUTH | NFSSVC_AUTHINFAIL;
#ifdef KERBEROS
#ifdef NFSKERB
/*
* Set up as ncd_authuid for the kerberos call.
* Must set ruid to ncd_authuid and reset the
* ticket name iff ncd_authuid is not the same
* as last time, so that the right ticket file
* is found.
* Get the Kerberos credential structure so that
* we have the seesion key and get a ticket for
* this uid.
* For more info see the IETF Draft "Authentication
* in ONC RPC".
*/
if (ncd.ncd_authuid != last_ruid) {
char buf[512];
@ -411,15 +464,62 @@ main(argc, argv)
krb_set_tkt_string(buf);
last_ruid = ncd.ncd_authuid;
}
if (krb_mk_req(&kt, "rcmd", inst, realm, 0) ==
KSUCCESS &&
kt.length <= (RPCAUTH_MAXSIZ - 2 * NFSX_UNSIGNED)) {
ncd.ncd_authtype = RPCAUTH_NQNFS;
ncd.ncd_authlen = kt.length;
ncd.ncd_authstr = (char *)kt.dat;
nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH;
setreuid(ncd.ncd_authuid, 0);
kret = krb_get_cred(NFS_KERBSRV, inst, realm, &kcr);
if (kret == RET_NOTKT) {
kret = get_ad_tkt(NFS_KERBSRV, inst, realm,
DEFAULT_TKT_LIFE);
if (kret == KSUCCESS)
kret = krb_get_cred(NFS_KERBSRV, inst, realm,
&kcr);
}
#endif /* KERBEROS */
if (kret == KSUCCESS)
kret = krb_mk_req(&ktick.kt, NFS_KERBSRV, inst,
realm, 0);
/*
* Fill in the AKN_FULLNAME authenticator and verfier.
* Along with the Kerberos ticket, we need to build
* the timestamp verifier and encrypt it in CBC mode.
*/
if (kret == KSUCCESS &&
ktick.kt.length <= (RPCAUTH_MAXSIZ-3*NFSX_UNSIGNED)
&& gettimeofday(&ktv, (struct timezone *)0) == 0) {
ncd.ncd_authtype = RPCAUTH_KERB4;
ncd.ncd_authstr = (u_char *)&ktick;
ncd.ncd_authlen = nfsm_rndup(ktick.kt.length) +
3 * NFSX_UNSIGNED;
ncd.ncd_verfstr = (u_char *)&kverf;
ncd.ncd_verflen = sizeof (kverf);
bcopy((caddr_t)kcr.session, (caddr_t)ncd.ncd_key,
sizeof (kcr.session));
kin.t1 = htonl(ktv.tv_sec);
kin.t2 = htonl(ktv.tv_usec);
kin.w1 = htonl(NFS_KERBTTL);
kin.w2 = htonl(NFS_KERBTTL - 1);
bzero((caddr_t)kivec, sizeof (kivec));
/*
* Encrypt kin in CBC mode using the session
* key in kcr.
*/
XXX
/*
* Finally, fill the timestamp verifier into the
* authenticator and verifier.
*/
ktick.kind = htonl(RPCAKN_FULLNAME);
kverf.kind = htonl(RPCAKN_FULLNAME);
NFS_KERBW1(ktick.kt) = kout.w1;
ktick.kt.length = htonl(ktick.kt.length);
kverf.verf.t1 = kout.t1;
kverf.verf.t2 = kout.t2;
kverf.verf.w2 = kout.w2;
nfssvc_flag = NFSSVC_MNTD | NFSSVC_GOTAUTH;
}
setreuid(0, 0);
#endif /* NFSKERB */
}
}
exit(0);
@ -440,9 +540,9 @@ getnfsargs(spec, nfsargsp)
#endif
struct timeval pertry, try;
enum clnt_stat clnt_stat;
int so = RPC_ANYSOCK, i;
int so = RPC_ANYSOCK, i, nfsvers, mntvers;
char *hostp, *delimp;
#ifdef KERBEROS
#ifdef NFSKERB
char *cp;
#endif
u_short tport;
@ -507,7 +607,7 @@ getnfsargs(spec, nfsargsp)
warnx("can't get net id for host");
return (0);
}
#ifdef KERBEROS
#ifdef NFSKERB
if ((nfsargsp->flags & NFSMNT_KERB)) {
if ((hp = gethostbyaddr((char *)&saddr.sin_addr.s_addr,
sizeof (u_long), AF_INET)) == (struct hostent *)0) {
@ -520,33 +620,46 @@ getnfsargs(spec, nfsargsp)
if (cp = strchr(inst, '.'))
*cp = '\0';
}
#endif /* KERBEROS */
#endif /* NFSKERB */
if (nfsargsp->flags & NFSMNT_NFSV3) {
nfsvers = 3;
mntvers = 3;
} else {
nfsvers = 2;
mntvers = 1;
}
nfhret.stat = EACCES; /* Mark not yet successful */
while (retrycnt > 0) {
saddr.sin_family = AF_INET;
saddr.sin_port = htons(PMAPPORT);
if ((tport = port_no ? port_no :
pmap_getport(&saddr, RPCPROG_NFS,
NFS_VER2, nfsargsp->sotype == SOCK_STREAM ? IPPROTO_TCP :
IPPROTO_UDP)) == 0) {
nfsvers, nfsproto)) == 0) {
if ((opflags & ISBGRND) == 0)
clnt_pcreateerror("NFS Portmap");
} else {
saddr.sin_port = 0;
pertry.tv_sec = 10;
pertry.tv_usec = 0;
if ((clp = (nfsargsp->sotype == SOCK_STREAM ?
clnttcp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1,
&so, 0, 0) :
clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1,
pertry, &so))) == NULL) {
if (mnttcp_ok && nfsargsp->sotype == SOCK_STREAM)
clp = clnttcp_create(&saddr, RPCPROG_MNT, mntvers,
&so, 0, 0);
else
clp = clntudp_create(&saddr, RPCPROG_MNT, mntvers,
pertry, &so);
if (clp == NULL) {
if ((opflags & ISBGRND) == 0)
clnt_pcreateerror("Cannot MNT RPC");
} else {
clp->cl_auth = authunix_create_default();
try.tv_sec = 10;
try.tv_usec = 0;
if (nfsargsp->flags & NFSMNT_KERB)
nfhret.auth = RPCAUTH_KERB4;
else
nfhret.auth = RPCAUTH_UNIX;
nfhret.vers = mntvers;
clnt_stat = clnt_call(clp, RPCMNT_MOUNT,
xdr_dir, spec, xdr_fh, &nfhret, try);
if (clnt_stat != RPC_SUCCESS) {
@ -596,7 +709,8 @@ getnfsargs(spec, nfsargsp)
nfsargsp->addr = (struct sockaddr *) &saddr;
nfsargsp->addrlen = sizeof (saddr);
}
nfsargsp->fh = &nfhret.nfh;
nfsargsp->fh = nfhret.nfh;
nfsargsp->fhsize = nfhret.fhsize;
nfsargsp->hostname = nam;
return (1);
}
@ -615,22 +729,53 @@ xdr_dir(xdrsp, dirp)
int
xdr_fh(xdrsp, np)
XDR *xdrsp;
struct nfhret *np;
register struct nfhret *np;
{
if (!xdr_u_long(xdrsp, &(np->stat)))
register int i;
long auth, authcnt, authfnd = 0;
if (!xdr_u_long(xdrsp, &np->stat))
return (0);
if (np->stat)
return (1);
return (xdr_opaque(xdrsp, (caddr_t)&(np->nfh), NFSX_FH));
switch (np->vers) {
case 1:
np->fhsize = NFSX_V2FH;
return (xdr_opaque(xdrsp, (caddr_t)np->nfh, NFSX_V2FH));
case 3:
if (!xdr_long(xdrsp, &np->fhsize))
return (0);
if (np->fhsize <= 0 || np->fhsize > NFSX_V3FHMAX)
return (0);
if (!xdr_opaque(xdrsp, (caddr_t)np->nfh, np->fhsize))
return (0);
if (!xdr_long(xdrsp, &authcnt))
return (0);
for (i = 0; i < authcnt; i++) {
if (!xdr_long(xdrsp, &auth))
return (0);
if (auth == np->auth)
authfnd++;
}
/*
* Some servers, such as DEC's OSF/1 return a nil authenticator
* list to indicate RPCAUTH_UNIX.
*/
if (!authfnd && (authcnt > 0 || np->auth != RPCAUTH_UNIX))
np->stat = EAUTH;
return (1);
};
return (0);
}
__dead void
usage()
{
(void)fprintf(stderr, "usage: mount_nfs %s\n%s\n%s\n%s\n",
"[-bcdiKklMPqsT] [-a maxreadahead] [-D deadthresh]",
"\t[-g maxgroups] [-L leaseterm] [-m realm] [-o options] [-R retrycnt]",
"\t[-r readsize] [-t timeout] [-w writesize] [-x retrans]",
"\trhost:path node");
(void)fprintf(stderr, "\
usage: mount_nfs [-3KPTUbcdilqs] [-D deadthresh] [-I readdirsize]\n\
[-L leaseterm] [-R retrycnt] [-a maxreadahead] [-g maxgroups]\n\
[-m realm] [-o options] [-r readsize] [-t timeout] [-w writesize]\n\
[-x retrans] rhost:path node\n");
exit(1);
}

View File

@ -49,7 +49,9 @@ file specifies remote mount points for the
mount protocol per the
.Tn NFS
server specification; see
.%T "Network File System Protocol Specification \\*(tNRFC\\*(sP 1094, Appendix A" .
.%T "Network File System Protocol Specification \\*(tNRFC\\*(sP 1094, Appendix A"
and
.%T "NFS: Network File System Version 3 Specification, Appendix I" .
.Pp
Each line in the file
(other than comment lines that begin with a #)
@ -71,7 +73,8 @@ The second is to specify the pathname of the root of the filesystem
followed by the
.Fl alldirs
flag;
this form allows the host(s) to mount any directory within the filesystem.
this form allows the host(s) to mount at any point within the filesystem,
including regular files if the ``-r'' option is used on mountd.
The pathnames must not have any symbolic links in them and should not have
any "." or ".." components.
Mount points for a filesystem may appear on multiple lines each with
@ -140,8 +143,7 @@ The
.Fl kerb
option specifies that the Kerberos authentication server should be
used to authenticate and map client credentials.
(Note that this is NOT Sun NFS compatible and
is supported for TCP transport only.)
This requires that the kernel be built with the NFSKERB option.
.Pp
The
.Fl ro

View File

@ -30,7 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" From: @(#)mountd.8 8.1 (Berkeley) 6/9/93
.\" $Id: mountd.8,v 1.2 1994/09/22 22:16:49 wollman Exp $
.\" $Id: mountd.8,v 1.3 1995/02/22 21:42:48 ats Exp $
.\"
.Dd September 22, 1994
.Dt MOUNTD 8
@ -42,7 +42,7 @@
mount requests
.Sh SYNOPSIS
.Nm /sbin/mountd
.Op Fl n
.Op Fl nr
.Op Ar exportsfile
.Sh DESCRIPTION
.Xr Mountd
@ -54,7 +54,9 @@ listens for service requests at the port indicated in the
.Tn NFS
server specification; see
.%T "Network File System Protocol Specification" ,
RFC1094.
RFC1094, Appendix A and
.%T "NFS: Network File System Version 3 Protocol Specification" ,
Appendix I.
.Pp
Options and operands available for
.Nm mountd :
@ -65,6 +67,15 @@ The
option allows non-root mount requests to be served.
This should only be specified if there are clients such as PC's,
that require it.
.It Fl r
The
.Fl r
option allows mount RPCs requests for regular files to be served.
Although this seems to violate the mount protocol specification, some diskless
workstations do mount requests for their swapfiles and expect them to be
regular files. Since a regular file cannot be specified in /etc/exports, the
entire file system that the swapfiles reside in will have to be exported with
the ``-alldirs'' flag.
.It Ar exportsfile
The
.Ar exportsfile

View File

@ -43,7 +43,7 @@ static char copyright[] =
#ifndef lint
/*static char sccsid[] = "From: @(#)mountd.c 8.8 (Berkeley) 2/20/94";*/
static const char rcsid[] =
"$Id: mountd.c,v 1.7.2.1 1995/06/08 04:34:11 davidg Exp $";
"$Id: mountd.c,v 1.8 1995/06/11 19:30:46 rgrimes Exp $";
#endif /*not lint*/
#include <sys/param.h>
@ -62,7 +62,7 @@ static const char rcsid[] =
#include <netiso/iso.h>
#endif
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <nfs/nfsproto.h>
#include <arpa/inet.h>
@ -100,6 +100,8 @@ struct dirlist {
};
/* dp_flag bits */
#define DP_DEFSET 0x1
#define DP_HOSTSET 0x2
#define DP_KERB 0x4
struct exportlist {
struct exportlist *ex_next;
@ -139,22 +141,29 @@ struct grouplist {
#define GT_IGNORE 0x5
struct hostlist {
int ht_flag; /* Uses DP_xx bits */
struct grouplist *ht_grp;
struct hostlist *ht_next;
};
struct fhreturn {
int fhr_flag;
int fhr_vers;
nfsfh_t fhr_fh;
};
/* Global defs */
char *add_expdir __P((struct dirlist **, char *, int));
void add_dlist __P((struct dirlist **, struct dirlist *,
struct grouplist *));
struct grouplist *, int));
void add_mlist __P((char *, char *));
int check_dirpath __P((char *));
int check_options __P((struct dirlist *));
int chk_host __P((struct dirlist *, u_long, int *));
int chk_host __P((struct dirlist *, u_long, int *, int *));
void del_mlist __P((char *, char *));
struct dirlist *dirp_search __P((struct dirlist *, char *));
int do_mount __P((struct exportlist *, struct grouplist *, int,
struct ucred *, char *, int, struct statfs *));
struct ucred *, char *, int, struct statfs *));
int do_opt __P((char **, char **, struct exportlist *, struct grouplist *,
int *, int *, struct ucred *));
struct exportlist *ex_search __P((fsid_t *));
@ -165,6 +174,7 @@ void free_grp __P((struct grouplist *));
void free_host __P((struct hostlist *));
void get_exportlist __P((void));
int get_host __P((char *, struct grouplist *, struct grouplist *));
int get_num __P((char *));
struct hostlist *get_ht __P((void));
int get_line __P((void));
void get_mountlist __P((void));
@ -183,7 +193,7 @@ void send_umntall __P((void));
int umntall_each __P((caddr_t, struct sockaddr_in *));
int xdr_dir __P((XDR *, char *));
int xdr_explist __P((XDR *, caddr_t));
int xdr_fhs __P((XDR *, nfsv2fh_t *));
int xdr_fhs __P((XDR *, caddr_t));
int xdr_mlist __P((XDR *, caddr_t));
/* C library */
@ -205,7 +215,8 @@ struct ucred def_anon = {
1,
{ (gid_t) -2 }
};
int root_only = 1;
int resvport_only = 1;
int dir_only = 1;
int opt_flags;
/* Bits for above */
#define OP_MAPROOT 0x01
@ -238,6 +249,7 @@ main(argc, argv)
{
SVCXPRT *udptransp, *tcptransp;
int c;
#ifdef __FreeBSD__
struct vfsconf *vfc;
vfc = getvfsbyname("nfs");
@ -250,17 +262,21 @@ main(argc, argv)
if(!vfc) {
errx(1, "NFS support is not available in the running kernel");
}
#endif /* __FreeBSD__ */
while ((c = getopt(argc, argv, "dn")) != EOF)
while ((c = getopt(argc, argv, "dnr")) != EOF)
switch (c) {
case 'n':
resvport_only = 0;
break;
case 'r':
dir_only = 0;
break;
case 'd':
debug = debug ? 0 : 1;
break;
case 'n':
root_only = 0;
break;
default:
fprintf(stderr, "Usage: mountd [-n] [export_file]\n");
fprintf(stderr, "Usage: mountd [-r] [-n] [export_file]\n");
exit(1);
};
argc -= optind;
@ -300,11 +316,12 @@ main(argc, argv)
syslog(LOG_ERR, "Can't create socket");
exit(1);
}
pmap_unset(RPCPROG_MNT, RPCMNT_VER1);
if (!svc_register(udptransp, RPCPROG_MNT, RPCMNT_VER1, mntsrv,
IPPROTO_UDP) ||
!svc_register(tcptransp, RPCPROG_MNT, RPCMNT_VER1, mntsrv,
IPPROTO_TCP)) {
pmap_unset(RPCPROG_MNT, 1);
pmap_unset(RPCPROG_MNT, 3);
if (!svc_register(udptransp, RPCPROG_MNT, 1, mntsrv, IPPROTO_UDP) ||
!svc_register(udptransp, RPCPROG_MNT, 3, mntsrv, IPPROTO_UDP) ||
!svc_register(tcptransp, RPCPROG_MNT, 1, mntsrv, IPPROTO_TCP) ||
!svc_register(tcptransp, RPCPROG_MNT, 3, mntsrv, IPPROTO_TCP)) {
syslog(LOG_ERR, "Can't register mount");
exit(1);
}
@ -323,28 +340,21 @@ mntsrv(rqstp, transp)
{
struct exportlist *ep;
struct dirlist *dp;
nfsv2fh_t nfh;
struct fhreturn fhr;
struct authunix_parms *ucr;
struct stat stb;
struct statfs fsb;
struct hostent *hp;
u_long saddr;
u_short sport;
char rpcpath[RPCMNT_PATHLEN+1], dirpath[MAXPATHLEN];
int bad = ENOENT, omask, defset;
uid_t uid = -2;
/* Get authorization */
switch (rqstp->rq_cred.oa_flavor) {
case AUTH_UNIX:
ucr = (struct authunix_parms *)rqstp->rq_clntcred;
uid = ucr->aup_uid;
break;
case AUTH_NULL:
default:
break;
}
int bad = ENOENT, defset, hostset;
sigset_t sighup_mask;
sigemptyset(&sighup_mask);
sigaddset(&sighup_mask, SIGHUP);
saddr = transp->xp_raddr.sin_addr.s_addr;
sport = ntohs(transp->xp_raddr.sin_port);
hp = (struct hostent *)NULL;
switch (rqstp->rq_proc) {
case NULLPROC:
@ -352,7 +362,7 @@ mntsrv(rqstp, transp)
syslog(LOG_ERR, "Can't send reply");
return;
case RPCMNT_MOUNT:
if ((uid != 0 && root_only) || uid == -2) {
if (sport >= IPPORT_RESERVED && resvport_only) {
svcerr_weakauth(transp);
return;
}
@ -363,11 +373,13 @@ mntsrv(rqstp, transp)
/*
* Get the real pathname and make sure it is a directory
* that exists.
* or a regular file if the -r option was specified
* and it exists.
*/
if (realpath(rpcpath, dirpath) == 0 ||
stat(dirpath, &stb) < 0 ||
(stb.st_mode & S_IFMT) != S_IFDIR ||
(!S_ISDIR(stb.st_mode) &&
(dir_only || !S_ISREG(stb.st_mode))) ||
statfs(dirpath, &fsb) < 0) {
chdir("/"); /* Just in case realpath doesn't */
if (debug)
@ -378,26 +390,31 @@ mntsrv(rqstp, transp)
}
/* Check in the exports list */
omask = sigblock(sigmask(SIGHUP));
sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
ep = ex_search(&fsb.f_fsid);
defset = 0;
if (ep && (chk_host(ep->ex_defdir, saddr, &defset) ||
hostset = defset = 0;
if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset) ||
((dp = dirp_search(ep->ex_dirl, dirpath)) &&
chk_host(dp, saddr, &defset)) ||
chk_host(dp, saddr, &defset, &hostset)) ||
(defset && scan_tree(ep->ex_defdir, saddr) == 0 &&
scan_tree(ep->ex_dirl, saddr) == 0))) {
if (hostset & DP_HOSTSET)
fhr.fhr_flag = hostset;
else
fhr.fhr_flag = defset;
fhr.fhr_vers = rqstp->rq_vers;
/* Get the file handle */
bzero((caddr_t)&nfh, sizeof(nfh));
if (getfh(dirpath, (fhandle_t *)&nfh) < 0) {
bzero((caddr_t)&fhr.fhr_fh, sizeof(nfsfh_t));
if (getfh(dirpath, (fhandle_t *)&fhr.fhr_fh) < 0) {
bad = errno;
syslog(LOG_ERR, "Can't get fh for %s", dirpath);
if (!svc_sendreply(transp, xdr_long,
(caddr_t)&bad))
syslog(LOG_ERR, "Can't send reply");
sigsetmask(omask);
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
return;
}
if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&nfh))
if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&fhr))
syslog(LOG_ERR, "Can't send reply");
if (hp == NULL)
hp = gethostbyaddr((caddr_t)&saddr,
@ -414,14 +431,14 @@ mntsrv(rqstp, transp)
if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
syslog(LOG_ERR, "Can't send reply");
}
sigsetmask(omask);
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
return;
case RPCMNT_DUMP:
if (!svc_sendreply(transp, xdr_mlist, (caddr_t)NULL))
syslog(LOG_ERR, "Can't send reply");
return;
case RPCMNT_UMOUNT:
if ((uid != 0 && root_only) || uid == -2) {
if (sport >= IPPORT_RESERVED && resvport_only) {
svcerr_weakauth(transp);
return;
}
@ -437,7 +454,7 @@ mntsrv(rqstp, transp)
del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), dirpath);
return;
case RPCMNT_UMNTALL:
if ((uid != 0 && root_only) || uid == -2) {
if (sport >= IPPORT_RESERVED && resvport_only) {
svcerr_weakauth(transp);
return;
}
@ -470,18 +487,37 @@ xdr_dir(xdrsp, dirp)
}
/*
* Xdr routine to generate fhstatus
* Xdr routine to generate file handle reply
*/
int
xdr_fhs(xdrsp, nfh)
xdr_fhs(xdrsp, cp)
XDR *xdrsp;
nfsv2fh_t *nfh;
caddr_t cp;
{
u_long ok = 0;
register struct fhreturn *fhrp = (struct fhreturn *)cp;
u_long ok = 0, len, auth;
if (!xdr_long(xdrsp, &ok))
return (0);
return (xdr_opaque(xdrsp, (caddr_t)nfh, NFSX_FH));
switch (fhrp->fhr_vers) {
case 1:
return (xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, NFSX_V2FH));
case 3:
len = NFSX_V3FH;
if (!xdr_long(xdrsp, &len))
return (0);
if (!xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, len))
return (0);
if (fhrp->fhr_flag & DP_KERB)
auth = RPCAUTH_KERB4;
else
auth = RPCAUTH_UNIX;
len = 1;
if (!xdr_long(xdrsp, &len))
return (0);
return (xdr_long(xdrsp, &auth));
};
return (0);
}
int
@ -521,9 +557,12 @@ xdr_explist(xdrsp, cp)
{
struct exportlist *ep;
int false = 0;
int omask, putdef;
int putdef;
sigset_t sighup_mask;
omask = sigblock(sigmask(SIGHUP));
sigemptyset(&sighup_mask);
sigaddset(&sighup_mask, SIGHUP);
sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
ep = exphead;
while (ep) {
putdef = 0;
@ -535,12 +574,12 @@ xdr_explist(xdrsp, cp)
goto errout;
ep = ep->ex_next;
}
sigsetmask(omask);
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
if (!xdr_bool(xdrsp, &false))
return (0);
return (1);
errout:
sigsetmask(omask);
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
return (0);
}
@ -660,6 +699,18 @@ get_exportlist()
struct ufs_args ua;
struct iso_args ia;
struct mfs_args ma;
#ifdef __NetBSD__
struct msdosfs_args da;
} targs;
if (!strcmp(fsp->f_fstypename, MOUNT_MFS) ||
!strcmp(fsp->f_fstypename, MOUNT_UFS) ||
!strcmp(fsp->f_fstypename, MOUNT_MSDOS) ||
!strcmp(fsp->f_fstypename, MOUNT_CD9660)) {
targs.ua.fspec = NULL;
targs.ua.export.ex_flags = MNT_DELEXPORT;
if (mount(fsp->f_fstypename, fsp->f_mntonname,
#else
} targs;
switch (fsp->f_type) {
@ -670,6 +721,7 @@ get_exportlist()
targs.ua.fspec = NULL;
targs.ua.export.ex_flags = MNT_DELEXPORT;
if (mount(fsp->f_type, fsp->f_mntonname,
#endif
fsp->f_flags | MNT_UPDATE,
(caddr_t)&targs) < 0)
syslog(LOG_ERR, "Can't delete exports for %s",
@ -805,6 +857,7 @@ get_exportlist()
if (get_host(hst, grp, tgrp)) {
syslog(LOG_ERR, "Bad netgroup %s", cp);
getexp_err(ep, tgrp);
endnetgrent();
goto nextline;
}
} else if (get_host(cp, grp, tgrp)) {
@ -865,12 +918,12 @@ get_exportlist()
* Success. Update the data structures.
*/
if (has_host) {
hang_dirp(dirhead, tgrp, ep, (opt_flags & OP_ALLDIRS));
hang_dirp(dirhead, tgrp, ep, opt_flags);
grp->gr_next = grphead;
grphead = tgrp;
} else {
hang_dirp(dirhead, (struct grouplist *)NULL, ep,
(opt_flags & OP_ALLDIRS));
opt_flags);
free_grp(grp);
}
dirhead = (struct dirlist *)NULL;
@ -994,24 +1047,28 @@ add_expdir(dpp, cp, len)
* and update the entry for host.
*/
void
hang_dirp(dp, grp, ep, alldirs)
hang_dirp(dp, grp, ep, flags)
struct dirlist *dp;
struct grouplist *grp;
struct exportlist *ep;
int alldirs;
int flags;
{
struct hostlist *hp;
struct dirlist *dp2;
if (alldirs) {
if (flags & OP_ALLDIRS) {
if (ep->ex_defdir)
free((caddr_t)dp);
else
ep->ex_defdir = dp;
if (grp == (struct grouplist *)NULL)
if (grp == (struct grouplist *)NULL) {
ep->ex_defdir->dp_flag |= DP_DEFSET;
else while (grp) {
if (flags & OP_KERB)
ep->ex_defdir->dp_flag |= DP_KERB;
} else while (grp) {
hp = get_ht();
if (flags & OP_KERB)
hp->ht_flag |= DP_KERB;
hp->ht_grp = grp;
hp->ht_next = ep->ex_defdir->dp_hosts;
ep->ex_defdir->dp_hosts = hp;
@ -1024,7 +1081,7 @@ hang_dirp(dp, grp, ep, alldirs)
*/
while (dp) {
dp2 = dp->dp_left;
add_dlist(&ep->ex_dirl, dp, grp);
add_dlist(&ep->ex_dirl, dp, grp, flags);
dp = dp2;
}
}
@ -1035,10 +1092,11 @@ hang_dirp(dp, grp, ep, alldirs)
* for the new directory or adding the new node.
*/
void
add_dlist(dpp, newdp, grp)
add_dlist(dpp, newdp, grp, flags)
struct dirlist **dpp;
struct dirlist *newdp;
struct grouplist *grp;
int flags;
{
struct dirlist *dp;
struct hostlist *hp;
@ -1048,10 +1106,10 @@ add_dlist(dpp, newdp, grp)
if (dp) {
cmp = strcmp(dp->dp_dirp, newdp->dp_dirp);
if (cmp > 0) {
add_dlist(&dp->dp_left, newdp, grp);
add_dlist(&dp->dp_left, newdp, grp, flags);
return;
} else if (cmp < 0) {
add_dlist(&dp->dp_right, newdp, grp);
add_dlist(&dp->dp_right, newdp, grp, flags);
return;
} else
free((caddr_t)newdp);
@ -1067,13 +1125,18 @@ add_dlist(dpp, newdp, grp)
*/
do {
hp = get_ht();
if (flags & OP_KERB)
hp->ht_flag |= DP_KERB;
hp->ht_grp = grp;
hp->ht_next = dp->dp_hosts;
dp->dp_hosts = hp;
grp = grp->gr_next;
} while (grp);
} else
} else {
dp->dp_flag |= DP_DEFSET;
if (flags & OP_KERB)
dp->dp_flag |= DP_KERB;
}
}
/*
@ -1102,10 +1165,11 @@ dirp_search(dp, dirpath)
* Scan for a host match in a directory tree.
*/
int
chk_host(dp, saddr, defsetp)
chk_host(dp, saddr, defsetp, hostsetp)
struct dirlist *dp;
u_long saddr;
int *defsetp;
int *hostsetp;
{
struct hostlist *hp;
struct grouplist *grp;
@ -1113,7 +1177,7 @@ chk_host(dp, saddr, defsetp)
if (dp) {
if (dp->dp_flag & DP_DEFSET)
*defsetp = 1;
*defsetp = dp->dp_flag;
hp = dp->dp_hosts;
while (hp) {
grp = hp->ht_grp;
@ -1122,15 +1186,19 @@ chk_host(dp, saddr, defsetp)
addrp = (u_long **)
grp->gr_ptr.gt_hostent->h_addr_list;
while (*addrp) {
if (**addrp == saddr)
if (**addrp == saddr) {
*hostsetp = (hp->ht_flag | DP_HOSTSET);
return (1);
}
addrp++;
}
break;
case GT_NET:
if ((saddr & grp->gr_ptr.gt_net.nt_mask) ==
grp->gr_ptr.gt_net.nt_net)
grp->gr_ptr.gt_net.nt_net) {
*hostsetp = (hp->ht_flag | DP_HOSTSET);
return (1);
}
break;
};
hp = hp->ht_next;
@ -1147,12 +1215,12 @@ scan_tree(dp, saddr)
struct dirlist *dp;
u_long saddr;
{
int defset;
int defset, hostset;
if (dp) {
if (scan_tree(dp->dp_left, saddr))
return (1);
if (chk_host(dp, saddr, &defset))
if (chk_host(dp, saddr, &defset, &hostset))
return (1);
if (scan_tree(dp->dp_right, saddr))
return (1);
@ -1312,7 +1380,7 @@ get_host(cp, grp, tgrp)
if (isdigit(*cp)) {
saddr = inet_addr(cp);
if (saddr == -1) {
syslog(LOG_ERR, "Inet_addr failed");
syslog(LOG_ERR, "Inet_addr failed for %s", cp);
return (1);
}
if ((hp = gethostbyaddr((caddr_t)&saddr, sizeof (saddr),
@ -1326,7 +1394,7 @@ get_host(cp, grp, tgrp)
aptr[1] = (char *)NULL;
}
} else {
syslog(LOG_ERR, "Gethostbyname failed");
syslog(LOG_ERR, "Gethostbyname failed for %s", cp);
return (1);
}
}
@ -1424,6 +1492,7 @@ get_ht()
if (hp == (struct hostlist *)NULL)
out_of_mem();
hp->ht_next = (struct hostlist *)NULL;
hp->ht_flag = 0;
return (hp);
}
@ -1494,6 +1563,9 @@ do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb)
struct ufs_args ua;
struct iso_args ia;
struct mfs_args ma;
#ifdef __NetBSD__
struct msdosfs_args da;
#endif
} args;
u_long net;
@ -1569,7 +1641,11 @@ do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb)
* Also, needs to know how to export all types of local
* exportable file systems and not just MOUNT_UFS.
*/
#ifdef __NetBSD__
while (mount(fsb->f_fstypename, dirp,
#else
while (mount(fsb->f_type, dirp,
#endif
fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) {
if (cp)
*cp-- = savedc;
@ -2033,15 +2109,30 @@ check_dirpath(dirp)
while (*cp && ret) {
if (*cp == '/') {
*cp = '\0';
if (lstat(dirp, &sb) < 0 ||
(sb.st_mode & S_IFMT) != S_IFDIR)
if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode))
ret = 0;
*cp = '/';
}
cp++;
}
if (lstat(dirp, &sb) < 0 ||
(sb.st_mode & S_IFMT) != S_IFDIR)
if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode))
ret = 0;
return (ret);
}
/*
* Just translate an ascii string to an integer.
*/
int
get_num(cp)
register char *cp;
{
register int res = 0;
while (*cp) {
if (*cp < '0' || *cp > '9')
return (-1);
res = res * 10 + (*cp++ - '0');
}
return (res);
}

View File

@ -98,7 +98,8 @@ listens for service requests at the port indicated in the
.Tn NFS
server specification; see
.%T "Network File System Protocol Specification" ,
RFC1094.
RFC1094 and
.%T "NFS: Network File System Version 3 Protocol Specification" .
.Pp
If
.Nm nfsd

View File

@ -63,10 +63,10 @@ static char sccsid[] = "@(#)nfsd.c 8.7 (Berkeley) 2/22/94";
#include <netiso/iso.h>
#endif
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
#ifdef KERBEROS
#ifdef NFSKERB
#include <kerberosIV/des.h>
#include <kerberosIV/krb.h>
#endif
@ -94,16 +94,23 @@ struct nfsd_srvargs nsd;
char **Argv = NULL; /* pointer to argument vector */
char *LastArg = NULL; /* end of argv */
#ifdef KERBEROS
#ifdef NFSKERB
char lnam[ANAME_SZ];
KTEXT_ST kt;
AUTH_DAT auth;
AUTH_DAT kauth;
char inst[INST_SZ];
struct nfsrpc_fullblock kin, kout;
struct nfsrpc_fullverf kverf;
NFSKERBKEY_T kivec;
struct timeval ktv;
NFSKERBKEYSCHED_T kerb_keysched;
#endif
void nonfs __P((int));
void reapchild __P((int));
#ifdef __FreeBSD__
void setproctitle __P((char *));
#endif
void usage __P((void));
/*
@ -139,11 +146,13 @@ main(argc, argv, envp)
#ifdef ISO
struct sockaddr_iso isoaddr, isopeer;
#endif
struct timeval ktv;
fd_set ready, sockbits;
int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock;
int tp4cnt, tp4flag, tp4sock, tpipcnt, tpipflag, tpipsock, udpflag;
char *cp, **cpp;
#ifdef __FreeBSD__
struct vfsconf *vfc;
vfc = getvfsbyname("nfs");
@ -156,6 +165,7 @@ main(argc, argv, envp)
if(!vfc) {
errx(1, "NFS is not available in the running kernel");
}
#endif
/* Save start and extent of argv for setproctitle. */
Argv = argv;
@ -241,10 +251,12 @@ main(argc, argv, envp)
if (reregister) {
if (udpflag &&
!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT))
(!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
!pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)))
err(1, "can't register with portmap for UDP.");
if (tcpflag &&
!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT))
(!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
!pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)))
err(1, "can't register with portmap for TCP.");
exit(0);
}
@ -261,11 +273,17 @@ main(argc, argv, envp)
continue;
}
setproctitle("nfsd-srv");
setproctitle("server");
nfssvc_flag = NFSSVC_NFSD;
nsd.nsd_nfsd = NULL;
#ifdef KERBEROS
nsd.nsd_authstr = (char *)kt.dat;
#ifdef NFSKERB
if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF ||
sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK)
syslog(LOG_ERR, "Yikes NFSKERB structs not packed!");
nsd.nsd_authstr = (u_char *)&kt;
nsd.nsd_authlen = sizeof (kt);
nsd.nsd_verfstr = (u_char *)&kverf;
nsd.nsd_verflen = sizeof (kverf);
#endif
while (nfssvc(nfssvc_flag, &nsd) < 0) {
if (errno != ENEEDAUTH) {
@ -273,14 +291,27 @@ main(argc, argv, envp)
exit(1);
}
nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
#ifdef KERBEROS
kt.length = nsd.nsd_authlen;
kt.mbz = 0;
(void)strcpy(inst, "*");
if (krb_rd_req(&kt, "rcmd",
inst, nsd.nsd_haddr, &auth, "") == RD_AP_OK &&
krb_kntoln(&auth, lnam) == KSUCCESS &&
(pwd = getpwnam(lnam)) != NULL) {
#ifdef NFSKERB
/*
* Get the Kerberos ticket out of the authenticator
* verify it and convert the principal name to a user
* name. The user name is then converted to a set of
* user credentials via the password and group file.
* Finally, decrypt the timestamp and validate it.
* For more info see the IETF Draft "Authentication
* in ONC RPC".
*/
kt.length = ntohl(kt.length);
if (gettimeofday(&ktv, (struct timezone *)0) == 0 &&
kt.length > 0 && kt.length <=
(RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) {
kin.w1 = NFS_KERBW1(kt);
kt.mbz = 0;
(void)strcpy(inst, "*");
if (krb_rd_req(&kt, NFS_KERBSRV,
inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK &&
krb_kntoln(&kauth, lnam) == KSUCCESS &&
(pwd = getpwnam(lnam)) != NULL) {
cr = &nsd.nsd_cr;
cr->cr_uid = pwd->pw_uid;
cr->cr_groups[0] = pwd->pw_gid;
@ -301,9 +332,34 @@ main(argc, argv, envp)
break;
}
endgrent();
nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
/*
* Get the timestamp verifier out of the
* authenticator and verifier strings.
*/
kin.t1 = kverf.t1;
kin.t2 = kverf.t2;
kin.w2 = kverf.w2;
bzero((caddr_t)kivec, sizeof (kivec));
bcopy((caddr_t)kauth.session,
(caddr_t)nsd.nsd_key,sizeof(kauth.session));
/*
* Decrypt the timestamp verifier in CBC mode.
*/
XXX
/*
* Validate the timestamp verifier, to
* check that the session key is ok.
*/
nsd.nsd_timestamp.tv_sec = ntohl(kout.t1);
nsd.nsd_timestamp.tv_usec = ntohl(kout.t2);
nsd.nsd_ttl = ntohl(kout.w1);
if ((nsd.nsd_ttl - 1) == ntohl(kout.w2))
nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
}
#endif /* KERBEROS */
#endif /* NFSKERB */
}
exit(0);
}
@ -323,7 +379,8 @@ main(argc, argv, envp)
syslog(LOG_ERR, "can't bind udp addr");
exit(1);
}
if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
!pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) {
syslog(LOG_ERR, "can't register with udp portmap");
exit(1);
}
@ -403,7 +460,8 @@ main(argc, argv, envp)
syslog(LOG_ERR, "listen failed");
exit(1);
}
if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
!pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) {
syslog(LOG_ERR, "can't register tcp with portmap");
exit(1);
}
@ -492,7 +550,7 @@ main(argc, argv, envp)
if (connect_type_cnt == 0)
exit(0);
setproctitle("nfsd-master");
setproctitle("master");
/*
* Loop forever accepting connections and passing the sockets
@ -566,7 +624,7 @@ main(argc, argv, envp)
void
usage()
{
(void)fprintf(stderr, "nfsd %s\n", USAGE);
(void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
exit(1);
}
@ -582,9 +640,10 @@ reapchild(signo)
int signo;
{
while (wait3(NULL, WNOHANG, NULL));
while (wait3(NULL, WNOHANG, NULL) > 0);
}
#ifdef __FreeBSD__
void
setproctitle(a)
char *a;
@ -593,9 +652,10 @@ setproctitle(a)
char buf[80];
cp = Argv[0];
(void)snprintf(buf, sizeof(buf), "%s", a);
(void)snprintf(buf, sizeof(buf), "nfsd-%s", a);
(void)strncpy(cp, buf, LastArg - cp);
cp += strlen(cp);
while (cp < LastArg)
*cp++ = '\0';
}
#endif /* __FreeBSD__ */

View File

@ -50,8 +50,10 @@ static char sccsid[] = "@(#)nfsiod.c 8.3 (Berkeley) 2/22/94";
#include <sys/ucred.h>
#include <sys/wait.h>
#include <sys/mount.h>
#include <sys/time.h>
#include <nfs/nfsv2.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
#include <err.h>

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs.h 8.1 (Berkeley) 6/10/93
* $Id: nfs.h,v 1.8 1994/11/02 00:11:00 wollman Exp $
* $Id: nfs.h,v 1.9 1995/02/14 06:22:18 phk Exp $
*/
#ifndef _NFS_NFS_H_
@ -45,11 +45,12 @@
*/
#define NFS_MAXIOVEC 34
#define NFS_HZ 25 /* Ticks per second for NFS timeouts */
#define NFS_TIMEO (1*NFS_HZ) /* Default timeout = 1 second */
#define NFS_MINTIMEO (1*NFS_HZ) /* Min timeout to use */
#define NFS_MAXTIMEO (60*NFS_HZ) /* Max timeout to backoff to */
#define NFS_MINIDEMTIMEO (5*NFS_HZ) /* Min timeout for non-idempotent ops*/
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
#define NFS_MINIDEMTIMEO (5 * NFS_HZ) /* Min timeout for non-idempotent ops*/
#define NFS_MAXREXMIT 100 /* Stop counting after this many */
#define NFS_MAXWINDOW 1024 /* Max number of outstanding requests */
#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
@ -62,13 +63,81 @@
#endif
#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
#define NFS_READDIRSIZE 8192 /* Def. readdir size */
#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
#define NFS_MAXREADDIR NFS_MAXDATA /* Max. size of directory read */
#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
#define NFS_DIRBLKSIZ 1024 /* Size of an NFS directory block */
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
#ifndef NFS_GATHERDELAY
#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
#endif
#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
/*
* Oddballs
*/
#define NMOD(a) ((a) % nfs_asyncdaemons)
#define NFS_CMPFH(n, f, s) \
((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s)))
#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3)
#define NFS_SRVMAXDATA(n) \
(((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \
NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA)
/*
* XXX
* sys/buf.h should be editted to change B_APPENDWRITE --> B_NEEDCOMMIT, but
* until then...
* Same goes for sys/malloc.h, which needs M_NFSDIROFF,
* M_NFSRVDESC and M_NFSBIGFH added.
* The VA_EXCLUSIVE flag should be added for va_vaflags and set for an
* exclusive create.
* The B_INVAFTERWRITE flag should be set to whatever is required by the
* buffer cache code to say "Invalidate the block after it is written back".
*/
#ifndef B_NEEDCOMMIT
#define B_NEEDCOMMIT B_APPENDWRITE
#endif
#ifndef M_NFSRVDESC
#define M_NFSRVDESC M_TEMP
#endif
#ifndef M_NFSDIROFF
#define M_NFSDIROFF M_TEMP
#endif
#ifndef M_NFSBIGFH
#define M_NFSBIGFH M_TEMP
#endif
#ifndef VA_EXCLUSIVE
#define VA_EXCLUSIVE 0
#endif
#ifdef __FreeBSD__
#define B_INVAFTERWRITE B_NOCACHE
#else
#define B_INVAFTERWRITE B_INVAL
#endif
/*
* These ifdefs try to handle the differences between the various 4.4BSD-Lite
* based vfs interfaces.
* btw: NetBSD-current does have a VOP_LEASDE(), but I don't know how to
* differentiate between NetBSD-1.0 and NetBSD-current, so..
* I also don't know about BSDi's 2.0 release.
*/
#if !defined(HAS_VOPLEASE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
#define HAS_VOPLEASE 1
#endif
#if !defined(HAS_VOPREVOKE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
#define HAS_VOPREVOKE 1
#endif
/*
* The IO_METASYNC flag should be implemented for local file systems.
* (Until then, it is nothin at all.)
*/
#ifndef IO_METASYNC
#define IO_METASYNC 0
#endif
/*
* Set the attribute timeout based on how recently the file has been modified.
@ -79,6 +148,20 @@
((time.tv_sec - (np)->n_mtime) / 10 > NFS_MAXATTRTIMO ? NFS_MAXATTRTIMO : \
(time.tv_sec - (np)->n_mtime) / 10))
/*
* Expected allocation sizes for major data structures. If the actual size
* of the structure exceeds these sizes, then malloc() will be allocating
* almost twice the memory required. This is used in nfs_init() to warn
* the sysadmin that the size of a structure should be reduced.
* (These sizes are always a power of 2. If the kernel malloc() changes
* to one that does not allocate space in powers of 2 size, then this all
* becomes bunk!)
*/
#define NFS_NODEALLOC 256
#define NFS_MNTALLOC 512
#define NFS_SVCALLOC 256
#define NFS_UIDALLOC 128
/*
* Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
* should ever try and use it.
@ -95,7 +178,12 @@ struct nfsd_srvargs {
u_long nsd_haddr; /* Ip address of client */
struct ucred nsd_cr; /* Cred. uid maps to */
int nsd_authlen; /* Length of auth string (ret) */
char *nsd_authstr; /* Auth string (ret) */
u_char *nsd_authstr; /* Auth string (ret) */
int nsd_verflen; /* and the verfier */
u_char *nsd_verfstr;
struct timeval nsd_timestamp; /* timestamp from verifier */
u_long nsd_ttl; /* credential ttl (sec) */
NFSKERBKEY_T nsd_key; /* Session key */
};
struct nfsd_cargs {
@ -103,7 +191,10 @@ struct nfsd_cargs {
uid_t ncd_authuid; /* Effective uid */
int ncd_authtype; /* Type of authenticator */
int ncd_authlen; /* Length of authenticator string */
char *ncd_authstr; /* Authenticator string */
u_char *ncd_authstr; /* Authenticator string */
int ncd_verflen; /* and the verifier */
u_char *ncd_verfstr;
NFSKERBKEY_T ncd_key; /* Session key */
};
/*
@ -142,6 +233,7 @@ struct nfsstats {
int srvnqnfs_leases;
int srvnqnfs_maxleases;
int srvnqnfs_getleases;
int srvvop_writes;
};
/*
@ -173,7 +265,7 @@ struct nfsstats {
* such as SIGALRM will not expect file I/O system calls to be interrupted
* by them and break.
*/
#ifdef KERNEL
#if defined(KERNEL) || defined(_KERNEL)
struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
@ -224,17 +316,29 @@ TAILQ_HEAD(, nfsreq) nfs_reqq;
#define R_MUSTRESEND 0x40 /* Must resend request */
#define R_GETONEREP 0x80 /* Probe for one reply only */
extern struct nfsstats nfsstats;
/*
* A list of nfssvc_sock structures is maintained with all the sockets
* that require service by the nfsd.
* The nfsuid structs hang off of the nfssvc_sock structs in both lru
* and uid hash lists.
*/
#define NUIDHASHSIZ 32
#ifndef NFS_UIDHASHSIZ
#define NFS_UIDHASHSIZ 29 /* Tune the size of nfssvc_sock with this */
#endif
#define NUIDHASH(sock, uid) \
(&(sock)->ns_uidhashtbl[(uid) & (sock)->ns_uidhash])
(&(sock)->ns_uidhashtbl[(uid) % NFS_UIDHASHSIZ])
#ifndef NFS_WDELAYHASHSIZ
#define NFS_WDELAYHASHSIZ 16 /* and with this */
#endif
#define NWDELAYHASH(sock, f) \
(&(sock)->ns_wdelayhashtbl[(*((u_long *)(f))) % NFS_WDELAYHASHSIZ])
#ifndef NFS_MUIDHASHSIZ
#define NFS_MUIDHASHSIZ 67 /* Tune the size of nfsmount with this */
#endif
#define NMUIDHASH(nmp, uid) \
(&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
#define NFSNOHASH(fhsum) \
(&nfsnodehashtbl[(fhsum) & nfsnodehash])
/*
* Network address hash list element
@ -248,35 +352,41 @@ struct nfsuid {
TAILQ_ENTRY(nfsuid) nu_lru; /* LRU chain */
LIST_ENTRY(nfsuid) nu_hash; /* Hash list */
int nu_flag; /* Flags */
uid_t nu_uid; /* Uid mapped by this entry */
union nethostaddr nu_haddr; /* Host addr. for dgram sockets */
struct ucred nu_cr; /* Cred uid mapped to */
int nu_expire; /* Expiry time (sec) */
struct timeval nu_timestamp; /* Kerb. timestamp */
u_long nu_nickname; /* Nickname on server */
NFSKERBKEY_T nu_key; /* and session key */
};
#define nu_inetaddr nu_haddr.had_inetaddr
#define nu_nam nu_haddr.had_nam
/* Bits for nu_flag */
#define NU_INETADDR 0x1
#define NU_NAM 0x2
#define NU_NETFAM(u) (((u)->nu_flag & NU_INETADDR) ? AF_INET : AF_ISO)
struct nfssvc_sock {
TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
TAILQ_HEAD(, nfsuid) ns_uidlruhead;
LIST_HEAD(, nfsuid) *ns_uidhashtbl;
u_long ns_uidhash;
int ns_flag;
u_long ns_sref;
struct file *ns_fp;
struct socket *ns_so;
int ns_solock;
struct mbuf *ns_nam;
int ns_cc;
struct mbuf *ns_raw;
struct mbuf *ns_rawend;
int ns_reclen;
struct mbuf *ns_rec;
struct mbuf *ns_recend;
struct mbuf *ns_frag;
int ns_flag;
int ns_solock;
int ns_cc;
int ns_reclen;
int ns_numuids;
u_long ns_sref;
LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
LIST_HEAD(, nfsuid) ns_uidhashtbl[NFS_UIDHASHSIZ];
LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
};
/* Bits for "ns_flag" */
@ -285,6 +395,7 @@ struct nfssvc_sock {
#define SLP_NEEDQ 0x04
#define SLP_DISCONN 0x08
#define SLP_GETSTREAM 0x10
#define SLP_LASTFRAG 0x20
#define SLP_ALLFLAGS 0xff
TAILQ_HEAD(, nfssvc_sock) nfssvc_sockhead;
@ -296,73 +407,124 @@ int nfssvc_sockhead_flag;
* One of these structures is allocated for each nfsd.
*/
struct nfsd {
TAILQ_ENTRY(nfsd) nd_chain; /* List of all nfsd's */
int nd_flag; /* NFSD_ flags */
struct nfssvc_sock *nd_slp; /* Current socket */
struct mbuf *nd_nam; /* Client addr for datagram req. */
struct mbuf *nd_mrep; /* Req. mbuf list */
struct mbuf *nd_md;
caddr_t nd_dpos; /* Position in list */
int nd_procnum; /* RPC procedure number */
u_long nd_retxid; /* RPC xid */
int nd_repstat; /* Reply status value */
struct ucred nd_cr; /* Credentials for req. */
int nd_nqlflag; /* Leasing flag */
u_long nd_duration; /* Lease duration */
int nd_authlen; /* Authenticator len */
u_char nd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
struct proc *nd_procp; /* Proc ptr */
TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
int nfsd_flag; /* NFSD_ flags */
struct nfssvc_sock *nfsd_slp; /* Current socket */
int nfsd_authlen; /* Authenticator len */
u_char nfsd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
int nfsd_verflen; /* and the Verifier */
u_char nfsd_verfstr[RPCVERF_MAXSIZ];
struct proc *nfsd_procp; /* Proc ptr */
struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
};
/* Bits for "nd_flag" */
/* Bits for "nfsd_flag" */
#define NFSD_WAITING 0x01
#define NFSD_REQINPROG 0x02
#define NFSD_NEEDAUTH 0x04
#define NFSD_AUTHFAIL 0x08
/*
* This structure is used by the server for describing each request.
* Some fields are used only when write request gathering is performed.
*/
struct nfsrv_descript {
u_quad_t nd_time; /* Write deadline (usec) */
off_t nd_off; /* Start byte offset */
off_t nd_eoff; /* and end byte offset */
LIST_ENTRY(nfsrv_descript) nd_hash; /* Hash list */
LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
LIST_HEAD(,nfsrv_descript) nd_coalesce; /* coalesced writes */
struct mbuf *nd_mrep; /* Request mbuf list */
struct mbuf *nd_md; /* Current dissect mbuf */
struct mbuf *nd_mreq; /* Reply mbuf list */
struct mbuf *nd_nam; /* and socket addr */
struct mbuf *nd_nam2; /* return socket addr */
caddr_t nd_dpos; /* Current dissect pos */
int nd_procnum; /* RPC # */
int nd_stable; /* storage type */
int nd_flag; /* nd_flag */
int nd_len; /* Length of this write */
int nd_repstat; /* Reply status */
u_long nd_retxid; /* Reply xid */
u_long nd_duration; /* Lease duration */
struct timeval nd_starttime; /* Time RPC initiated */
fhandle_t nd_fh; /* File handle */
struct ucred nd_cr; /* Credentials */
};
/* Bits for "nd_flag" */
#define ND_READ LEASE_READ
#define ND_WRITE LEASE_WRITE
#define ND_CHECK 0x04
#define ND_LEASE (ND_READ | ND_WRITE | ND_CHECK)
#define ND_NFSV3 0x08
#define ND_NQNFS 0x10
#define ND_KERBNICK 0x20
#define ND_KERBFULL 0x40
#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
TAILQ_HEAD(, nfsd) nfsd_head;
int nfsd_head_flag;
#define NFSD_CHECKSLP 0x01
/*
* These macros compare nfsrv_descript structures.
*/
#define NFSW_CONTIG(o, n) \
((o)->nd_eoff >= (n)->nd_off && \
!bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH))
#define NFSW_SAMECRED(o, n) \
(((o)->nd_flag & ND_KERBAUTH) == ((n)->nd_flag & ND_KERBAUTH) && \
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
sizeof (struct ucred)))
int nfs_reply __P((struct nfsreq *));
int nfs_getreq __P((struct nfsd *,int));
int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
int nfs_send __P((struct socket *,struct mbuf *,struct mbuf *,struct nfsreq *));
int nfs_rephead __P((int,struct nfsd *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_rephead __P((int,struct nfsrv_descript *,struct nfssvc_sock *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_sndlock __P((int *,struct nfsreq *));
int nfs_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
int nfs_vinvalbuf __P((struct vnode *,int,struct ucred *,struct proc *,int));
int nfs_readrpc __P((struct vnode *,struct uio *,struct ucred *));
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int));
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int *,int *));
int nfs_readdirrpc __P((register struct vnode *,struct uio *,struct ucred *));
int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct proc *));
int nfs_asyncio __P((struct buf *,struct ucred *));
int nfs_doio __P((struct buf *,struct ucred *,struct proc *));
int nfs_readlinkrpc __P((struct vnode *,struct uio *,struct ucred *));
int nfs_sigintr __P((struct nfsmount *,struct nfsreq *r,struct proc *));
int nfs_readdirlookrpc __P((struct vnode *,register struct uio *,struct ucred *));
int nfs_readdirplusrpc __P((struct vnode *,register struct uio *,struct ucred *));
int nfsm_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *));
void nfsm_srvfattr __P((struct nfsrv_descript *,struct vattr *,struct nfs_fattr *));
void nfsm_srvwcc __P((struct nfsrv_descript *,int,struct vattr *,int,struct vattr *,struct mbuf **,char **));
void nfsm_srvpostopattr __P((struct nfsrv_descript *,int,struct vattr *,struct mbuf **,char **));
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *,int));
int nfsrv_access __P((struct vnode *,int,struct ucred *,int,struct proc *));
int netaddr_match __P((int,union nethostaddr *,struct mbuf *));
int nfs_request __P((struct vnode *,struct mbuf *,int,struct proc *,struct ucred *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_loadattrcache __P((struct vnode **,struct mbuf **,caddr_t *,struct vattr *));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct proc *));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int));
void nfsm_adj __P((struct mbuf *,int,int));
int nfsm_mbuftouio __P((struct mbuf **,struct uio *,int,caddr_t *));
void nfsrv_initcache __P((void));
int nfs_rcvlock __P((struct nfsreq *));
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,int *,char **,int *));
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,char **,int *,char *,int *,NFSKERBKEY_T));
int nfs_getnickauth __P((struct nfsmount *,struct ucred *,char **,int *,char *,int));
int nfs_savenickauth __P((struct nfsmount *,struct ucred *,int,NFSKERBKEY_T,struct mbuf **,char **,struct mbuf *));
int nfs_msg __P((struct proc *,char *,char *));
int nfs_adv __P((struct mbuf **,caddr_t *,int,int));
int nfsrv_getstream __P((struct nfssvc_sock *,int));
void nfs_nhinit __P((void));
void nfs_timer __P((void*));
struct nfsnodehashhead * nfs_hash __P((nfsv2fh_t *));
u_long nfs_hash __P((nfsfh_t *,int));
int nfssvc_iod __P((struct proc *));
int nfssvc_nfsd __P((struct nfsd_srvargs *,caddr_t,struct proc *));
int nfssvc_addsock __P((struct file *,struct mbuf *));
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *));
int nfsrv_getcache __P((struct mbuf *,struct nfsd *,struct mbuf **));
void nfsrv_updatecache __P((struct mbuf *,struct nfsd *,int,struct mbuf *));
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *,struct nfsrv_descript **));
int nfsrv_getcache __P((struct nfsrv_descript *,struct nfssvc_sock *,struct mbuf **));
void nfsrv_updatecache __P((struct nfsrv_descript *,int,struct mbuf *));
int mountnfs __P((struct nfs_args *,struct mount *,struct mbuf *,char *,char *,struct vnode **));
int nfs_connect __P((struct nfsmount *,struct nfsreq *));
int nfs_getattrcache __P((struct vnode *,struct vattr *));
@ -370,9 +532,20 @@ int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long));
int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *));
int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *));
void nfsrv_init __P((int));
void nfs_clearcommit __P((struct mount *));
int nfsrv_errmap __P((struct nfsrv_descript *, int));
void nfsrvw_coalesce __P((struct nfsrv_descript *,struct nfsrv_descript *));
void nfsrvw_sort __P((gid_t [],int));
void nfsrv_setcred __P((struct ucred *,struct ucred *));
int nfs_flush __P((struct vnode *,struct ucred *,int,struct proc *,int));
int nfs_writebp __P((struct buf *,int));
int nfsrv_vput __P(( struct vnode * ));
int nfsrv_vrele __P(( struct vnode * ));
int nfsrv_vmio __P(( struct vnode * ));
int nfsrv_writegather __P((struct nfsrv_descript **, struct nfssvc_sock *,
struct proc *, struct mbuf **));
int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
struct proc *p));
#endif /* KERNEL */

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_bio.c 8.5 (Berkeley) 1/4/94
* $Id: nfs_bio.c,v 1.13 1995/05/21 21:39:21 davidg Exp $
* $Id: nfs_bio.c,v 1.14 1995/05/30 08:12:35 rgrimes Exp $
*/
#include <sys/param.h>
@ -49,16 +49,30 @@
#include <vm/vm.h>
#include <nfs/nfsnode.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
#include <nfs/nfsmount.h>
#include <nfs/nqnfs.h>
#include <nfs/nfsnode.h>
struct buf *nfs_getcacheblk();
extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
extern int nfs_numasync;
extern struct nfsstats nfsstats;
/*
* Ifdefs for FreeBSD-current's merged VM/buffer cache. It is unfortunate
* that this isn't done inside getblk() and brelse() so these calls
* wouldn't need to be here.
*/
#ifdef B_VMIO
#define vnode_pager_uncache(vp)
#else
#define vfs_busy_pages(bp, f)
#define vfs_unbusy_pages(bp)
#define vfs_dirty_pages(bp)
#endif
/*
* Vnode op for read using bio
@ -72,29 +86,28 @@ nfs_bioread(vp, uio, ioflag, cred)
struct ucred *cred;
{
register struct nfsnode *np = VTONFS(vp);
register int biosize, diff;
register int biosize, diff, i;
struct buf *bp = 0, *rabp;
struct vattr vattr;
struct proc *p;
struct nfsmount *nmp;
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
daddr_t lbn, rabn;
int bufsize;
int nra, error = 0, n = 0, on = 0, not_readin;
nfsquad_t tquad;
#ifdef lint
ioflag = ioflag;
#endif /* lint */
#ifdef DIAGNOSTIC
if (uio->uio_rw != UIO_READ)
panic("nfs_read mode");
#endif
if (uio->uio_resid == 0)
return (0);
if (uio->uio_offset < 0 && vp->v_type != VDIR)
if (uio->uio_offset < 0)
return (EINVAL);
nmp = VFSTONFS(vp->v_mount);
biosize = NFS_MAXDGRAMDATA;
p = uio->uio_procp;
if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
(void)nfs_fsinfo(nmp, vp, cred, p);
biosize = nmp->nm_rsize;
/*
* For nfs, cache consistency can only be maintained approximately.
* Although RFC1094 does not specify the criteria, the following is
@ -107,8 +120,6 @@ nfs_bioread(vp, uio, ioflag, cred)
* server, so flush all of the file's data out of the cache.
* Then force a getattr rpc to ensure that you have up to date
* attributes.
* The mount flag NFSMNT_MYWRITE says "Assume that my writes are
* the ones changing the modify time.
* NB: This implies that cache data can be read when up to
* NFS_ATTRTIMEO seconds out of date. If you find that you need current
* attributes this could be forced by setting n_attrstamp to 0 before
@ -116,14 +127,15 @@ nfs_bioread(vp, uio, ioflag, cred)
*/
if ((nmp->nm_flag & NFSMNT_NQNFS) == 0 && vp->v_type != VLNK) {
if (np->n_flag & NMODIFIED) {
if ((nmp->nm_flag & NFSMNT_MYWRITE) == 0 ||
vp->v_type != VREG) {
if (vp->v_type != VREG) {
if (vp->v_type != VDIR)
panic("nfs: bioread, not dir");
nfs_invaldir(vp);
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
if (error)
return (error);
}
np->n_attrstamp = 0;
np->n_direofoffset = 0;
error = VOP_GETATTR(vp, &vattr, cred, p);
if (error)
return (error);
@ -133,7 +145,8 @@ nfs_bioread(vp, uio, ioflag, cred)
if (error)
return (error);
if (np->n_mtime != vattr.va_mtime.ts_sec) {
np->n_direofoffset = 0;
if (vp->v_type == VDIR)
nfs_invaldir(vp);
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
if (error)
return (error);
@ -147,27 +160,24 @@ nfs_bioread(vp, uio, ioflag, cred)
* Get a valid lease. If cached data is stale, flush it.
*/
if (nmp->nm_flag & NFSMNT_NQNFS) {
if (NQNFS_CKINVALID(vp, np, NQL_READ)) {
if (NQNFS_CKINVALID(vp, np, ND_READ)) {
do {
error = nqnfs_getlease(vp, NQL_READ, cred, p);
error = nqnfs_getlease(vp, ND_READ, cred, p);
} while (error == NQNFS_EXPIRED);
if (error)
return (error);
if (np->n_lrev != np->n_brev ||
(np->n_flag & NQNFSNONCACHE) ||
((np->n_flag & NMODIFIED) && vp->v_type == VDIR)) {
if (vp->v_type == VDIR) {
np->n_direofoffset = 0;
cache_purge(vp);
}
if (vp->v_type == VDIR)
nfs_invaldir(vp);
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
if (error)
return (error);
np->n_brev = np->n_lrev;
}
} else if (vp->v_type == VDIR && (np->n_flag & NMODIFIED)) {
np->n_direofoffset = 0;
cache_purge(vp);
nfs_invaldir(vp);
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
if (error)
return (error);
@ -176,33 +186,27 @@ nfs_bioread(vp, uio, ioflag, cred)
if (np->n_flag & NQNFSNONCACHE) {
switch (vp->v_type) {
case VREG:
error = nfs_readrpc(vp, uio, cred);
break;
return (nfs_readrpc(vp, uio, cred));
case VLNK:
error = nfs_readlinkrpc(vp, uio, cred);
break;
return (nfs_readlinkrpc(vp, uio, cred));
case VDIR:
error = nfs_readdirrpc(vp, uio, cred);
break;
default:
printf(" NQNFSNONCACHE: type %x unexpected\n",
vp->v_type);
break;
};
return (error);
}
switch (vp->v_type) {
case VREG:
nfsstats.biocache_reads++;
lbn = uio->uio_offset / biosize;
on = uio->uio_offset & (biosize-1);
on = uio->uio_offset & (biosize - 1);
not_readin = 1;
/*
* Start the read ahead(s), as required.
*/
if (nfs_numasync > 0 && nmp->nm_readahead > 0 &&
lbn == vp->v_lastr + 1) {
if (nfs_numasync > 0 && nmp->nm_readahead > 0) {
for (nra = 0; nra < nmp->nm_readahead &&
(lbn + 1 + nra) * biosize < np->n_size; nra++) {
rabn = lbn + 1 + nra;
@ -296,32 +300,55 @@ nfs_bioread(vp, uio, ioflag, cred)
break;
case VDIR:
nfsstats.biocache_readdirs++;
lbn = (daddr_t)uio->uio_offset;
lbn = uio->uio_offset / NFS_DIRBLKSIZ;
on = uio->uio_offset & (NFS_DIRBLKSIZ - 1);
bp = nfs_getcacheblk(vp, lbn, NFS_DIRBLKSIZ, p);
if (!bp)
return (EINTR);
return (EINTR);
if ((bp->b_flags & B_CACHE) == 0) {
bp->b_flags |= B_READ;
vfs_busy_pages(bp, 0);
error = nfs_doio(bp, cred, p);
if (error) {
bp->b_flags |= B_ERROR;
brelse(bp);
return (error);
bp->b_flags |= B_READ;
vfs_busy_pages(bp, 0);
error = nfs_doio(bp, cred, p);
if (error) {
brelse(bp);
while (error == NFSERR_BAD_COOKIE) {
nfs_invaldir(vp);
error = nfs_vinvalbuf(vp, 0, cred, p, 1);
/*
* Yuck! The directory has been modified on the
* server. The only way to get the block is by
* reading from the beginning to get all the
* offset cookies.
*/
for (i = 0; i <= lbn && !error; i++) {
bp = nfs_getcacheblk(vp, i, NFS_DIRBLKSIZ, p);
if (!bp)
return (EINTR);
if ((bp->b_flags & B_DONE) == 0) {
bp->b_flags |= B_READ;
vfs_busy_pages(bp, 0);
error = nfs_doio(bp, cred, p);
if (error)
brelse(bp);
}
}
}
if (error)
return (error);
}
}
/*
* If not eof and read aheads are enabled, start one.
* (You need the current block first, so that you have the
* directory offset cookie of the next block.
* directory offset cookie of the next block.)
*/
rabn = bp->b_blkno;
if (nfs_numasync > 0 && nmp->nm_readahead > 0 &&
rabn != 0 && rabn != np->n_direofoffset &&
!incore(vp, rabn)) {
rabp = nfs_getcacheblk(vp, rabn, NFS_DIRBLKSIZ, p);
(np->n_direofoffset == 0 ||
(lbn + 1) * NFS_DIRBLKSIZ < np->n_direofoffset) &&
!(np->n_flag & NQNFSNONCACHE) &&
!incore(vp, lbn + 1)) {
rabp = nfs_getcacheblk(vp, lbn + 1, NFS_DIRBLKSIZ, p);
if (rabp) {
if ((rabp->b_flags & (B_CACHE|B_DELWRI)) == 0) {
rabp->b_flags |= (B_READ | B_ASYNC);
@ -336,11 +363,10 @@ nfs_bioread(vp, uio, ioflag, cred)
}
}
}
on = 0;
n = min(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid);
n = min(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid - on);
break;
default:
printf(" nfsbioread: type %x unexpected\n",vp->v_type);
printf(" nfs_bioread: type %x unexpected\n",vp->v_type);
break;
};
@ -354,11 +380,11 @@ nfs_bioread(vp, uio, ioflag, cred)
n = 0;
break;
case VDIR:
uio->uio_offset = bp->b_blkno;
if (np->n_flag & NQNFSNONCACHE)
bp->b_flags |= B_INVAL;
break;
default:
printf(" nfsbioread: type %x unexpected\n",vp->v_type);
break;
printf(" nfs_bioread: type %x unexpected\n",vp->v_type);
}
brelse(bp);
} while (error == 0 && uio->uio_resid > 0 && n > 0);
@ -386,10 +412,10 @@ nfs_write(ap)
int ioflag = ap->a_ioflag;
struct buf *bp;
struct vattr vattr;
struct nfsmount *nmp;
daddr_t lbn;
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
daddr_t lbn, bn;
int bufsize;
int n, on, error = 0;
int n, on, error = 0, iomode, must_commit;
#ifdef DIAGNOSTIC
if (uio->uio_rw != UIO_WRITE)
@ -403,6 +429,8 @@ nfs_write(ap)
np->n_flag &= ~NWRITEERR;
return (np->n_error);
}
if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
(void)nfs_fsinfo(nmp, vp, cred, p);
if (ioflag & (IO_APPEND | IO_SYNC)) {
if (np->n_flag & NMODIFIED) {
np->n_attrstamp = 0;
@ -418,7 +446,6 @@ nfs_write(ap)
uio->uio_offset = np->n_size;
}
}
nmp = VFSTONFS(vp->v_mount);
if (uio->uio_offset < 0)
return (EINVAL);
if (uio->uio_resid == 0)
@ -437,7 +464,7 @@ nfs_write(ap)
* will be the same size within a filesystem. nfs_writerpc will
* still use nm_wsize when sizing the rpc's.
*/
biosize = NFS_MAXDGRAMDATA;
biosize = nmp->nm_rsize;
do {
/*
@ -445,12 +472,11 @@ nfs_write(ap)
*/
/*
* Check for a valid write lease.
* If non-cachable, just do the rpc
*/
if ((nmp->nm_flag & NFSMNT_NQNFS) &&
NQNFS_CKINVALID(vp, np, NQL_WRITE)) {
NQNFS_CKINVALID(vp, np, ND_WRITE)) {
do {
error = nqnfs_getlease(vp, NQL_WRITE, cred, p);
error = nqnfs_getlease(vp, ND_WRITE, cred, p);
} while (error == NQNFS_EXPIRED);
if (error)
return (error);
@ -462,8 +488,13 @@ nfs_write(ap)
np->n_brev = np->n_lrev;
}
}
if (np->n_flag & NQNFSNONCACHE)
return (nfs_writerpc(vp, uio, cred, ioflag));
if ((np->n_flag & NQNFSNONCACHE) && uio->uio_iovcnt == 1) {
iomode = NFSV3WRITE_FILESYNC;
error = nfs_writerpc(vp, uio, cred, &iomode, &must_commit);
if (must_commit)
nfs_clearcommit(vp->v_mount);
return (error);
}
nfsstats.biocache_writes++;
lbn = uio->uio_offset / biosize;
on = uio->uio_offset & (biosize-1);
@ -509,9 +540,9 @@ nfs_write(ap)
* In case getblk() and/or bwrite() delayed us.
*/
if ((nmp->nm_flag & NFSMNT_NQNFS) &&
NQNFS_CKINVALID(vp, np, NQL_WRITE)) {
NQNFS_CKINVALID(vp, np, ND_WRITE)) {
do {
error = nqnfs_getlease(vp, NQL_WRITE, cred, p);
error = nqnfs_getlease(vp, ND_WRITE, cred, p);
} while (error == NQNFS_EXPIRED);
if (error) {
brelse(bp);
@ -540,7 +571,6 @@ nfs_write(ap)
bp->b_dirtyoff = on;
bp->b_dirtyend = on + n;
}
#ifndef notdef
if (bp->b_validend == 0 || bp->b_validend < bp->b_dirtyoff ||
bp->b_validoff > bp->b_dirtyend) {
bp->b_validoff = bp->b_dirtyoff;
@ -549,13 +579,6 @@ nfs_write(ap)
bp->b_validoff = min(bp->b_validoff, bp->b_dirtyoff);
bp->b_validend = max(bp->b_validend, bp->b_dirtyend);
}
#else
bp->b_validoff = bp->b_dirtyoff;
bp->b_validend = bp->b_dirtyend;
#endif
if (ioflag & IO_APPEND)
bp->b_flags |= B_APPENDWRITE;
/*
* If the lease is non-cachable or IO_SYNC do bwrite().
*/
@ -564,10 +587,16 @@ nfs_write(ap)
error = VOP_BWRITE(bp);
if (error)
return (error);
if (np->n_flag & NQNFSNONCACHE) {
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
if (error)
return (error);
}
} else if ((n + on) == biosize &&
(nmp->nm_flag & NFSMNT_NQNFS) == 0) {
bp->b_proc = (struct proc *)0;
bawrite(bp);
bp->b_flags |= B_ASYNC;
(void)nfs_writebp(bp, 0);
} else
bdwrite(bp);
} while (uio->uio_resid > 0 && n > 0);
@ -590,6 +619,7 @@ nfs_getcacheblk(vp, bn, size, p)
{
register struct buf *bp;
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
int biosize = nmp->nm_rsize;
if (nmp->nm_flag & NFSMNT_INT) {
bp = getblk(vp, bn, size, PCATCH, 0);
@ -602,7 +632,7 @@ nfs_getcacheblk(vp, bn, size, p)
bp = getblk(vp, bn, size, 0, 0);
if( vp->v_type == VREG)
bp->b_blkno = (bn * NFS_MAXDGRAMDATA) / DEV_BSIZE;
bp->b_blkno = (bn * biosize) / DEV_BSIZE;
return (bp);
}
@ -689,6 +719,7 @@ nfs_asyncio(bp, cred)
bp->b_rcred = cred;
}
} else {
bp->b_flags |= B_WRITEINPROG;
if (bp->b_wcred == NOCRED && cred != NOCRED) {
crhold(cred);
bp->b_wcred = cred;
@ -700,7 +731,25 @@ nfs_asyncio(bp, cred)
wakeup((caddr_t)&nfs_iodwant[i]);
return (0);
}
return (EIO);
/*
* If it is a read or a write already marked B_WRITEINPROG or B_NOCACHE
* return EIO so the process will call nfs_doio() and do it
* synchronously.
*/
if (bp->b_flags & (B_READ | B_WRITEINPROG | B_NOCACHE))
return (EIO);
/*
* Just turn the async write into a delayed write, instead of
* doing in synchronously. Hopefully, at least one of the nfsiods
* is currently doing a write for this file and will pick up the
* delayed writes before going back to sleep.
*/
bp->b_flags |= B_DELWRI;
reassignbuf(bp, bp->b_vp);
biodone(bp);
return (0);
}
/*
@ -717,9 +766,10 @@ nfs_doio(bp, cr, p)
register struct vnode *vp;
struct nfsnode *np;
struct nfsmount *nmp;
int error = 0, diff, len;
int error = 0, diff, len, iomode, must_commit = 0;
struct uio uio;
struct iovec io;
nfsquad_t tquad;
vp = bp->b_vp;
np = VTONFS(vp);
@ -740,15 +790,18 @@ nfs_doio(bp, cr, p)
io.iov_len = uiop->uio_resid = bp->b_bcount;
/* mapping was done by vmapbuf() */
io.iov_base = bp->b_data;
uiop->uio_offset = bp->b_blkno * DEV_BSIZE;
uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE;
if (bp->b_flags & B_READ) {
uiop->uio_rw = UIO_READ;
nfsstats.read_physios++;
error = nfs_readrpc(vp, uiop, cr);
} else {
int com;
iomode = NFSV3WRITE_DATASYNC;
uiop->uio_rw = UIO_WRITE;
nfsstats.write_physios++;
error = nfs_writerpc(vp, uiop, cr,0);
error = nfs_writerpc(vp, uiop, cr, &iomode, &com);
}
if (error) {
bp->b_flags |= B_ERROR;
@ -760,7 +813,7 @@ nfs_doio(bp, cr, p)
uiop->uio_rw = UIO_READ;
switch (vp->v_type) {
case VREG:
uiop->uio_offset = bp->b_blkno * DEV_BSIZE;
uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE;
nfsstats.read_bios++;
error = nfs_readrpc(vp, uiop, cr);
if (!error) {
@ -773,7 +826,7 @@ nfs_doio(bp, cr, p)
* Just zero fill the rest of the valid area.
*/
diff = bp->b_bcount - uiop->uio_resid;
len = np->n_size - (bp->b_blkno * DEV_BSIZE
len = np->n_size - (((u_quad_t)bp->b_blkno) * DEV_BSIZE
+ diff);
if (len > 0) {
len = min(len, uiop->uio_resid);
@ -786,31 +839,34 @@ nfs_doio(bp, cr, p)
}
if (p && (vp->v_flag & VTEXT) &&
(((nmp->nm_flag & NFSMNT_NQNFS) &&
NQNFS_CKINVALID(vp, np, NQL_READ) &&
NQNFS_CKINVALID(vp, np, ND_READ) &&
np->n_lrev != np->n_brev) ||
(!(nmp->nm_flag & NFSMNT_NQNFS) &&
np->n_mtime != np->n_vattr.va_mtime.ts_sec))) {
uprintf("Process killed due to text file modification\n");
psignal(p, SIGKILL);
#ifdef __NetBSD__
p->p_holdcnt++;
#else
p->p_flag |= P_NOSWAP;
#endif
}
break;
case VLNK:
uiop->uio_offset = 0;
uiop->uio_offset = (off_t)0;
nfsstats.readlink_bios++;
error = nfs_readlinkrpc(vp, uiop, cr);
break;
case VDIR:
uiop->uio_offset = bp->b_lblkno;
nfsstats.readdir_bios++;
if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS)
error = nfs_readdirlookrpc(vp, uiop, cr);
else
error = nfs_readdirrpc(vp, uiop, cr);
/*
* Save offset cookie in b_blkno.
*/
bp->b_blkno = uiop->uio_offset;
uiop->uio_offset = ((u_quad_t)bp->b_lblkno) * NFS_DIRBLKSIZ;
if (nmp->nm_flag & NFSMNT_RDIRPLUS) {
error = nfs_readdirplusrpc(vp, uiop, cr);
if (error == NFSERR_NOTSUPP)
nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
}
if ((nmp->nm_flag & NFSMNT_RDIRPLUS) == 0)
error = nfs_readdirrpc(vp, uiop, cr);
break;
default:
printf("nfs_doio: type %x unexpected\n",vp->v_type);
@ -821,32 +877,44 @@ nfs_doio(bp, cr, p)
bp->b_error = error;
}
} else {
if (((bp->b_blkno * DEV_BSIZE) + bp->b_dirtyend) > np->n_size)
bp->b_dirtyend = np->n_size - (bp->b_blkno * DEV_BSIZE);
if (bp->b_dirtyend > bp->b_dirtyoff) {
io.iov_len = uiop->uio_resid = bp->b_dirtyend
- bp->b_dirtyoff;
uiop->uio_offset = (bp->b_blkno * DEV_BSIZE)
+ bp->b_dirtyoff;
- bp->b_dirtyoff;
uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE
+ bp->b_dirtyoff;
io.iov_base = (char *)bp->b_data + bp->b_dirtyoff;
uiop->uio_rw = UIO_WRITE;
nfsstats.write_bios++;
if (bp->b_flags & B_APPENDWRITE)
error = nfs_writerpc(vp, uiop, cr, IO_APPEND);
if ((bp->b_flags & (B_ASYNC | B_NEEDCOMMIT | B_NOCACHE)) == B_ASYNC)
iomode = NFSV3WRITE_UNSTABLE;
else
error = nfs_writerpc(vp, uiop, cr, 0);
bp->b_flags &= ~(B_WRITEINPROG | B_APPENDWRITE);
iomode = NFSV3WRITE_FILESYNC;
bp->b_flags |= B_WRITEINPROG;
error = nfs_writerpc(vp, uiop, cr, &iomode, &must_commit);
if (!error && iomode == NFSV3WRITE_UNSTABLE)
bp->b_flags |= B_NEEDCOMMIT;
else
bp->b_flags &= ~B_NEEDCOMMIT;
bp->b_flags &= ~B_WRITEINPROG;
/*
* For an interrupted write, the buffer is still valid and the
* write hasn't been pushed to the server yet, so we can't set
* B_ERROR and report the interruption by setting B_EINTR. For
* the B_ASYNC case, B_EINTR is not relevant, so the rpc attempt
* is essentially a noop.
*/
if (error == EINTR) {
/*
* For an interrupted write, the buffer is still valid
* and the write hasn't been pushed to the server yet,
* so we can't set B_ERROR and report the interruption
* by setting B_EINTR. For the B_ASYNC case, B_EINTR
* is not relevant, so the rpc attempt is essentially
* a noop. For the case of a V3 write rpc not being
* committed to stable storage, the block is still
* dirty and requires either a commit rpc or another
* write rpc with iomode == NFSV3WRITE_FILESYNC before
* the block is reused. This is indicated by setting
* the B_DELWRI and B_NEEDCOMMIT flags.
*/
if (error == EINTR
|| (!error && (bp->b_flags & B_NEEDCOMMIT))) {
bp->b_flags &= ~(B_INVAL|B_NOCACHE);
bp->b_flags |= B_DELWRI;
@ -874,6 +942,8 @@ nfs_doio(bp, cr, p)
}
}
bp->b_resid = uiop->uio_resid;
if (must_commit)
nfs_clearcommit(vp->v_mount);
biodone(bp);
return (error);
}

File diff suppressed because it is too large Load Diff

View File

@ -34,12 +34,13 @@
* SUCH DAMAGE.
*
* @(#)nfsm_subs.h 8.1 (Berkeley) 6/16/93
* $Id: nfsm_subs.h,v 1.5 1994/10/17 17:47:42 phk Exp $
* $Id: nfsm_subs.h,v 1.6 1995/05/30 08:12:51 rgrimes Exp $
*/
#ifndef _NFS_NFSM_SUBS_H_
#define _NFS_NFSM_SUBS_H_
/*
* These macros do strange and peculiar things to mbuf chains for
* the assistance of the nfs code. To attempt to use them for any
@ -90,49 +91,153 @@ extern struct mbuf *nfsm_reqh();
mb->m_len += (s); \
bpos += (s); }
#define nfsm_dissect(a,c,s) \
#define nfsm_dissect(a, c, s) \
{ t1 = mtod(md, caddr_t)+md->m_len-dpos; \
if (t1 >= (s)) { \
(a) = (c)(dpos); \
dpos += (s); \
} else if (t1 = nfsm_disct(&md, &dpos, (s), t1, &cp2)) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
} else { \
error = nfsm_disct(&md, &dpos, (s), t1, &cp2); \
if (error) { \
m_freem(mrep); \
goto nfsmout; \
} else { \
(a) = (c)cp2; \
} \
(a) = (c)cp2; \
} }
#define nfsm_fhtom(v) \
nfsm_build(cp,caddr_t,NFSX_FH); \
bcopy((caddr_t)&(VTONFS(v)->n_fh), cp, NFSX_FH)
#define nfsm_fhtom(v, v3) \
{ if (v3) { \
t2 = nfsm_rndup(VTONFS(v)->n_fhsize) + NFSX_UNSIGNED; \
if (t2 <= M_TRAILINGSPACE(mb)) { \
nfsm_build(tl, u_long *, t2); \
*tl++ = txdr_unsigned(VTONFS(v)->n_fhsize); \
*(tl + ((t2>>2) - 2)) = 0; \
bcopy((caddr_t)VTONFS(v)->n_fhp,(caddr_t)tl, \
VTONFS(v)->n_fhsize); \
} else if (t2 = nfsm_strtmbuf(&mb, &bpos, \
(caddr_t)VTONFS(v)->n_fhp, VTONFS(v)->n_fhsize)) { \
error = t2; \
m_freem(mreq); \
goto nfsmout; \
} \
} else { \
nfsm_build(cp, caddr_t, NFSX_V2FH); \
bcopy((caddr_t)VTONFS(v)->n_fhp, cp, NFSX_V2FH); \
} }
#define nfsm_srvfhtom(f) \
nfsm_build(cp,caddr_t,NFSX_FH); \
bcopy((caddr_t)(f), cp, NFSX_FH)
#define nfsm_srvfhtom(f, v3) \
{ if (v3) { \
nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3FH); \
*tl++ = txdr_unsigned(NFSX_V3FH); \
bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
} else { \
nfsm_build(cp, caddr_t, NFSX_V2FH); \
bcopy((caddr_t)(f), cp, NFSX_V2FH); \
} }
#define nfsm_mtofh(d,v) \
{ struct nfsnode *np; nfsv2fh_t *fhp; \
nfsm_dissect(fhp,nfsv2fh_t *,NFSX_FH); \
error = nfs_nget((d)->v_mount, fhp, &np); \
if (error) { \
m_freem(mrep); \
goto nfsmout; \
} \
(v) = NFSTOV(np); \
nfsm_loadattr(v, (struct vattr *)0); \
#define nfsm_srvpostop_fh(f) \
{ nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED + NFSX_V3FH); \
*tl++ = nfs_true; \
*tl++ = txdr_unsigned(NFSX_V3FH); \
bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
}
#define nfsm_loadattr(v,a) \
{ struct vnode *tvp = (v); \
error = nfs_loadattrcache(&tvp, &md, &dpos, (a)); \
if (error) { \
#define nfsm_mtofh(d, v, v3, f) \
{ struct nfsnode *ttnp; nfsfh_t *ttfhp; int ttfhsize; \
if (v3) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
(f) = fxdr_unsigned(int, *tl); \
} else \
(f) = 1; \
if (f) { \
nfsm_getfh(ttfhp, ttfhsize, (v3)); \
if (t1 = nfs_nget((d)->v_mount, ttfhp, ttfhsize, \
&ttnp)) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
} \
(v) = NFSTOV(ttnp); \
} \
if (v3) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (f) \
(f) = fxdr_unsigned(int, *tl); \
else if (fxdr_unsigned(int, *tl)) \
nfsm_adv(NFSX_V3FATTR); \
} \
if (f) \
nfsm_loadattr((v), (struct vattr *)0); \
}
#define nfsm_getfh(f, s, v3) \
{ if (v3) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (((s) = fxdr_unsigned(int, *tl)) <= 0 || \
(s) > NFSX_V3FHMAX) { \
m_freem(mrep); \
error = EBADRPC; \
goto nfsmout; \
} \
} else \
(s) = NFSX_V2FH; \
nfsm_dissect((f), nfsfh_t *, nfsm_rndup(s)); }
#define nfsm_loadattr(v, a) \
{ struct vnode *ttvp = (v); \
if (t1 = nfs_loadattrcache(&ttvp, &md, &dpos, (a))) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
} \
(v) = tvp; }
(v) = ttvp; }
#define nfsm_postop_attr(v, f) \
{ struct vnode *ttvp = (v); \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if ((f) = fxdr_unsigned(int, *tl)) { \
if (t1 = nfs_loadattrcache(&ttvp, &md, &dpos, \
(struct vattr *)0)) { \
error = t1; \
(f) = 0; \
m_freem(mrep); \
goto nfsmout; \
} \
(v) = ttvp; \
} }
/* Used as (f) for nfsm_wcc_data() */
#define NFSV3_WCCRATTR 0
#define NFSV3_WCCCHK 1
#define nfsm_wcc_data(v, f) \
{ int ttattrf, ttretf = 0; \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
nfsm_dissect(tl, u_long *, 6 * NFSX_UNSIGNED); \
if (f) \
ttretf = (VTONFS(v)->n_mtime == \
fxdr_unsigned(u_long, *(tl + 2))); \
} \
nfsm_postop_attr((v), ttattrf); \
if (f) { \
(f) = ttretf; \
} else { \
(f) = ttattrf; \
} }
#define nfsm_v3sattr(s, a, u, g) \
{ (s)->sa_modetrue = nfs_true; \
(s)->sa_mode = vtonfsv3_mode((a)->va_mode); \
(s)->sa_uidtrue = nfs_true; \
(s)->sa_uid = txdr_unsigned(u); \
(s)->sa_gidtrue = nfs_true; \
(s)->sa_gid = txdr_unsigned(g); \
(s)->sa_sizefalse = nfs_false; \
(s)->sa_atimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \
txdr_nfsv3time(&(a)->va_atime, &(s)->sa_atime); \
(s)->sa_mtimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \
txdr_nfsv3time(&(a)->va_mtime, &(s)->sa_mtime); \
}
#define nfsm_strsiz(s,m) \
{ nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \
@ -149,16 +254,27 @@ extern struct mbuf *nfsm_reqh();
nfsm_reply(0); \
} }
#define nfsm_srvnamesiz(s) \
{ nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \
if (((s) = fxdr_unsigned(long,*tl)) > NFS_MAXNAMLEN) \
error = NFSERR_NAMETOL; \
if ((s) <= 0) \
error = EBADRPC; \
if (error) \
nfsm_reply(0); \
}
#define nfsm_mtouio(p,s) \
if ((s) > 0 && \
(error = nfsm_mbuftouio(&md,(p),(s),&dpos))) { \
(t1 = nfsm_mbuftouio(&md,(p),(s),&dpos))) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
}
#define nfsm_uiotom(p,s) \
error = nfsm_uiotombuf((p),&mb,(s),&bpos); \
if (error) { \
if (t1 = nfsm_uiotombuf((p),&mb,(s),&bpos)) { \
error = t1; \
m_freem(mreq); \
goto nfsmout; \
}
@ -172,10 +288,13 @@ extern struct mbuf *nfsm_reqh();
#define nfsm_rndup(a) (((a)+3)&(~0x3))
#define nfsm_request(v, t, p, c) \
error = nfs_request((v), mreq, (t), (p), \
(c), &mrep, &md, &dpos); \
if (error) \
goto nfsmout
if (error = nfs_request((v), mreq, (t), (p), \
(c), &mrep, &md, &dpos)) { \
if (error & NFSERR_RETERR) \
error &= ~NFSERR_RETERR; \
else \
goto nfsmout; \
}
#define nfsm_strtom(a,s,m) \
if ((s) > (m)) { \
@ -189,12 +308,10 @@ extern struct mbuf *nfsm_reqh();
*tl++ = txdr_unsigned(s); \
*(tl+((t2>>2)-2)) = 0; \
bcopy((caddr_t)(a), (caddr_t)tl, (s)); \
} else { \
error = nfsm_strtmbuf(&mb, &bpos, (a), (s)); \
if (error) { \
m_freem(mreq); \
goto nfsmout; \
} \
} else if (t2 = nfsm_strtmbuf(&mb, &bpos, (a), (s))) { \
error = t2; \
m_freem(mreq); \
goto nfsmout; \
}
#define nfsm_srvdone \
@ -204,33 +321,53 @@ extern struct mbuf *nfsm_reqh();
#define nfsm_reply(s) \
{ \
nfsd->nd_repstat = error; \
if (error) \
(void) nfs_rephead(0, nfsd, error, cache, &frev, \
if (error && !(nfsd->nd_flag & ND_NFSV3)) \
(void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
mrq, &mb, &bpos); \
else \
(void) nfs_rephead((s), nfsd, error, cache, &frev, \
(void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
mrq, &mb, &bpos); \
m_freem(mrep); \
mreq = *mrq; \
if (error) \
if (error && (!(nfsd->nd_flag & ND_NFSV3) || \
error == EBADRPC)) \
return(0); \
}
#define nfsm_adv(s) \
t1 = mtod(md, caddr_t)+md->m_len-dpos; \
if (t1 >= (s)) { \
dpos += (s); \
} else { \
error = nfs_adv(&md, &dpos, (s), t1); \
if (error) { \
m_freem(mrep); \
goto nfsmout; \
} \
#define nfsm_writereply(s, v3) \
{ \
nfsd->nd_repstat = error; \
if (error && !(v3)) \
(void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
&mreq, &mb, &bpos); \
else \
(void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
&mreq, &mb, &bpos); \
}
#define nfsm_adv(s) \
{ t1 = mtod(md, caddr_t)+md->m_len-dpos; \
if (t1 >= (s)) { \
dpos += (s); \
} else if (t1 = nfs_adv(&md, &dpos, (s), t1)) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
} }
#define nfsm_srvmtofh(f) \
nfsm_dissect(tl, u_long *, NFSX_FH); \
bcopy((caddr_t)tl, (caddr_t)f, NFSX_FH)
{ if (nfsd->nd_flag & ND_NFSV3) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (fxdr_unsigned(int, *tl) != NFSX_V3FH) { \
error = EBADRPC; \
nfsm_reply(0); \
} \
} \
nfsm_dissect(tl, u_long *, NFSX_V3FH); \
bcopy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \
if ((nfsd->nd_flag & ND_NFSV3) == 0) \
nfsm_adv(NFSX_V2FH - NFSX_V3FH); \
}
#define nfsm_clget \
if (bp >= be) { \
@ -246,41 +383,57 @@ extern struct mbuf *nfsm_reqh();
} \
tl = (u_long *)bp
#define nfsm_srvfillattr \
fp->fa_type = vtonfs_type(vap->va_type); \
fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode); \
fp->fa_nlink = txdr_unsigned(vap->va_nlink); \
fp->fa_uid = txdr_unsigned(vap->va_uid); \
fp->fa_gid = txdr_unsigned(vap->va_gid); \
if (nfsd->nd_nqlflag == NQL_NOVAL) { \
fp->fa_nfsblocksize = txdr_unsigned(vap->va_blocksize); \
if (vap->va_type == VFIFO) \
fp->fa_nfsrdev = 0xffffffff; \
else \
fp->fa_nfsrdev = txdr_unsigned(vap->va_rdev); \
fp->fa_nfsfsid = txdr_unsigned(vap->va_fsid); \
fp->fa_nfsfileid = txdr_unsigned(vap->va_fileid); \
fp->fa_nfssize = txdr_unsigned(vap->va_size); \
fp->fa_nfsblocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE); \
txdr_nfstime(&vap->va_atime, &fp->fa_nfsatime); \
txdr_nfstime(&vap->va_mtime, &fp->fa_nfsmtime); \
txdr_nfstime(&vap->va_ctime, &fp->fa_nfsctime); \
} else { \
fp->fa_nqblocksize = txdr_unsigned(vap->va_blocksize); \
if (vap->va_type == VFIFO) \
fp->fa_nqrdev = 0xffffffff; \
else \
fp->fa_nqrdev = txdr_unsigned(vap->va_rdev); \
fp->fa_nqfsid = txdr_unsigned(vap->va_fsid); \
fp->fa_nqfileid = txdr_unsigned(vap->va_fileid); \
txdr_hyper(&vap->va_size, &fp->fa_nqsize); \
txdr_hyper(&vap->va_bytes, &fp->fa_nqbytes); \
txdr_nqtime(&vap->va_atime, &fp->fa_nqatime); \
txdr_nqtime(&vap->va_mtime, &fp->fa_nqmtime); \
txdr_nqtime(&vap->va_ctime, &fp->fa_nqctime); \
fp->fa_nqflags = txdr_unsigned(vap->va_flags); \
fp->fa_nqgen = txdr_unsigned(vap->va_gen); \
txdr_hyper(&vap->va_filerev, &fp->fa_nqfilerev); \
}
#define nfsm_srvfillattr(a, f) \
nfsm_srvfattr(nfsd, (a), (f))
#define nfsm_srvwcc_data(br, b, ar, a) \
nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos)
#define nfsm_srvpostop_attr(r, a) \
nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos)
#define nfsm_srvsattr(a) \
{ nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
(a)->va_mode = nfstov_mode(*tl); \
} \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
(a)->va_uid = fxdr_unsigned(uid_t, *tl); \
} \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
(a)->va_gid = fxdr_unsigned(gid_t, *tl); \
} \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
fxdr_hyper(tl, &(a)->va_size); \
} \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
switch (fxdr_unsigned(int, *tl)) { \
case NFSV3SATTRTIME_TOCLIENT: \
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
fxdr_nfsv3time(tl, &(a)->va_atime); \
break; \
case NFSV3SATTRTIME_TOSERVER: \
(a)->va_atime.ts_sec = time.tv_sec; \
(a)->va_atime.ts_nsec = time.tv_usec * 1000; \
break; \
}; \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
switch (fxdr_unsigned(int, *tl)) { \
case NFSV3SATTRTIME_TOCLIENT: \
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
fxdr_nfsv3time(tl, &(a)->va_mtime); \
break; \
case NFSV3SATTRTIME_TOSERVER: \
(a)->va_mtime.ts_sec = time.tv_sec; \
(a)->va_mtime.ts_nsec = time.tv_usec * 1000; \
break; \
}; }
#endif

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_node.c 8.2 (Berkeley) 12/30/93
* $Id: nfs_node.c,v 1.7 1994/10/17 17:47:33 phk Exp $
* $Id: nfs_node.c,v 1.8 1995/03/16 18:15:36 bde Exp $
*/
#include <sys/param.h>
@ -47,14 +47,12 @@
#include <sys/malloc.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
#include <nfs/nfsnode.h>
#include <nfs/nfsmount.h>
#include <nfs/nqnfs.h>
#define NFSNOHASH(fhsum) \
(&nfsnodehashtbl[(fhsum) & nfsnodehash])
LIST_HEAD(nfsnodehashhead, nfsnode) *nfsnodehashtbl;
u_long nfsnodehash;
@ -79,19 +77,20 @@ nfs_nhinit()
/*
* Compute an entry in the NFS hash table structure
*/
struct nfsnodehashhead *
nfs_hash(fhp)
register nfsv2fh_t *fhp;
u_long
nfs_hash(fhp, fhsize)
register nfsfh_t *fhp;
int fhsize;
{
register u_char *fhpp;
register u_long fhsum;
int i;
register int i;
fhpp = &fhp->fh_bytes[0];
fhsum = 0;
for (i = 0; i < NFSX_FH; i++)
for (i = 0; i < fhsize; i++)
fhsum += *fhpp++;
return (NFSNOHASH(fhsum));
return (fhsum);
}
/*
@ -101,9 +100,10 @@ nfs_hash(fhp)
* nfsnode structure is returned.
*/
int
nfs_nget(mntp, fhp, npp)
nfs_nget(mntp, fhp, fhsize, npp)
struct mount *mntp;
register nfsv2fh_t *fhp;
register nfsfh_t *fhp;
int fhsize;
struct nfsnode **npp;
{
register struct nfsnode *np;
@ -112,11 +112,11 @@ nfs_nget(mntp, fhp, npp)
struct vnode *nvp;
int error;
nhpp = nfs_hash(fhp);
nhpp = NFSNOHASH(nfs_hash(fhp, fhsize));
loop:
for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) {
if (mntp != NFSTOV(np)->v_mount ||
bcmp((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH))
if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize ||
bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize))
continue;
vp = NFSTOV(np);
if (vget(vp, 1))
@ -131,27 +131,26 @@ nfs_nget(mntp, fhp, npp)
}
vp = nvp;
MALLOC(np, struct nfsnode *, sizeof *np, M_NFSNODE, M_WAITOK);
bzero((caddr_t)np, sizeof *np);
vp->v_data = np;
np->n_vnode = vp;
/*
* Insert the nfsnode in the hash queue for its new file handle
*/
np->n_flag = 0;
LIST_INSERT_HEAD(nhpp, np, n_hash);
bcopy((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH);
np->n_attrstamp = 0;
np->n_direofoffset = 0;
np->n_sillyrename = (struct sillyrename *)0;
np->n_size = 0;
np->n_mtime = 0;
np->n_lockf = 0;
if (VFSTONFS(mntp)->nm_flag & NFSMNT_NQNFS) {
np->n_brev = 0;
np->n_lrev = 0;
np->n_expiry = (time_t)0;
np->n_timer.cqe_next = (struct nfsnode *)0;
}
if (fhsize > NFS_SMALLFH) {
MALLOC(np->n_fhp, nfsfh_t *, fhsize, M_NFSBIGFH, M_WAITOK);
} else
np->n_fhp = &np->n_fh;
bcopy((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize);
np->n_fhsize = fhsize;
*npp = np;
/*
* Lock the new nfsnode.
*/
VOP_LOCK(vp);
return (0);
}
@ -168,7 +167,10 @@ nfs_inactive(ap)
np = VTONFS(ap->a_vp);
if (prtactive && ap->a_vp->v_usecount != 0)
vprint("nfs_inactive: pushing active", ap->a_vp);
sp = np->n_sillyrename;
if (ap->a_vp->v_type != VDIR)
sp = np->n_sillyrename;
else
sp = (struct sillyrename *)0;
np->n_sillyrename = (struct sillyrename *)0;
if (sp) {
/*
@ -178,9 +180,7 @@ nfs_inactive(ap)
nfs_removeit(sp);
crfree(sp->s_cred);
vrele(sp->s_dvp);
#ifdef SILLYSEPARATE
free((caddr_t)sp, M_NFSREQ);
#endif
FREE((caddr_t)sp, M_NFSREQ);
}
np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
NQNFSNONCACHE | NQNFSWRITE);
@ -199,6 +199,7 @@ nfs_reclaim(ap)
register struct vnode *vp = ap->a_vp;
register struct nfsnode *np = VTONFS(vp);
register struct nfsmount *nmp = VFSTONFS(vp->v_mount);
register struct nfsdmap *dp, *dp2;
if (prtactive && vp->v_usecount != 0)
vprint("nfs_reclaim: pushing active", vp);
@ -211,6 +212,24 @@ nfs_reclaim(ap)
if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_timer.cqe_next != 0) {
CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
}
/*
* Free up any directory cookie structures and
* large file handle structures that might be associated with
* this nfs node.
*/
if (vp->v_type == VDIR) {
dp = np->n_cookies.lh_first;
while (dp) {
dp2 = dp;
dp = dp->ndm_list.le_next;
FREE((caddr_t)dp2, M_NFSDIROFF);
}
}
if (np->n_fhsize > NFS_SMALLFH) {
FREE((caddr_t)np->n_fhp, M_NFSBIGFH);
}
cache_purge(vp);
FREE(vp->v_data, M_NFSNODE);
vp->v_data = (void *)0;
@ -227,6 +246,7 @@ nfs_lock(ap)
} */ *ap;
{
register struct vnode *vp = ap->a_vp;
struct nfsnode *np = VTONFS(vp);
/*
* Ugh, another place where interruptible mounts will get hung.
@ -239,6 +259,33 @@ nfs_lock(ap)
}
if (vp->v_tag == VT_NON)
return (ENOENT);
#if 0
/*
* Only lock regular files. If a server crashed while we were
* holding a directory lock, we could easily end up sleeping
* until the server rebooted while holding a lock on the root.
* Locks are only needed for protecting critical sections in
* VMIO at the moment.
* New vnodes will have type VNON but they should be locked
* since they may become VREG. This is checked in loadattrcache
* and unwanted locks are released there.
*/
if (vp->v_type == VREG || vp->v_type == VNON) {
while (np->n_flag & NLOCKED) {
np->n_flag |= NWANTED;
(void) tsleep((caddr_t) np, PINOD, "nfslck2", 0);
/*
* If the vnode has transmuted into a VDIR while we
* were asleep, then skip the lock.
*/
if (vp->v_type != VREG && vp->v_type != VNON)
return (0);
}
np->n_flag |= NLOCKED;
}
#endif
return (0);
}
@ -251,6 +298,20 @@ nfs_unlock(ap)
struct vnode *a_vp;
} */ *ap;
{
#if 0
struct vnode* vp = ap->a_vp;
struct nfsnode* np = VTONFS(vp);
if (vp->v_type == VREG || vp->v_type == VNON) {
if (!(np->n_flag & NLOCKED))
panic("nfs_unlock: nfsnode not locked");
np->n_flag &= ~NLOCKED;
if (np->n_flag & NWANTED) {
np->n_flag &= ~NWANTED;
wakeup((caddr_t) np);
}
}
#endif
return (0);
}
@ -264,8 +325,7 @@ nfs_islocked(ap)
struct vnode *a_vp;
} */ *ap;
{
return (0);
return VTONFS(ap->a_vp)->n_flag & NLOCKED ? 1 : 0;
}
/*

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_nqlease.c 8.3 (Berkeley) 1/4/94
* $Id: nfs_nqlease.c,v 1.10 1995/02/15 03:39:58 davidg Exp $
* $Id: nfs_nqlease.c,v 1.11 1995/05/30 08:12:36 rgrimes Exp $
*/
/*
@ -66,7 +66,7 @@
#include <netinet/in.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
#include <nfs/nfsm_subs.h>
#include <nfs/xdr_subs.h>
@ -75,7 +75,6 @@
#include <nfs/nfsmount.h>
time_t nqnfsstarttime = (time_t)0;
u_long nqnfs_prog, nqnfs_vers;
int nqsrv_clockskew = NQ_CLOCKSKEW;
int nqsrv_writeslack = NQ_WRITESLACK;
int nqsrv_maxlease = NQ_MAXLEASE;
@ -91,14 +90,13 @@ struct mbuf *nfsm_rpchead();
*/
int nqnfs_piggy[NFS_NPROCS] = {
0,
NQL_READ,
NQL_WRITE,
0,
NQL_READ,
NQL_READ,
NQL_READ,
ND_WRITE,
ND_READ,
0,
NQL_WRITE,
ND_READ,
ND_READ,
ND_WRITE,
0,
0,
0,
@ -106,24 +104,30 @@ int nqnfs_piggy[NFS_NPROCS] = {
0,
0,
0,
NQL_READ,
0,
NQL_READ,
ND_READ,
ND_READ,
0,
0,
0,
0,
0,
0,
0,
0,
};
extern nfstype nfs_type[9];
extern nfstype nfsv2_type[9];
extern nfstype nfsv3_type[9];
extern struct nfssvc_sock *nfs_udpsock, *nfs_cltpsock;
extern int nfsd_waiting;
extern struct nfsstats nfsstats;
#define TRUE 1
#define FALSE 0
/*
* Get or check for a lease for "vp", based on NQL_CHECK flag.
* Get or check for a lease for "vp", based on ND_CHECK flag.
* The rules are as follows:
* - if a current non-caching lease, reply non-caching
* - if a current lease for same host only, extend lease
@ -146,11 +150,12 @@ extern int nfsd_waiting;
* queue yet. (Ditto for the splsoftclock() and splx(s) calls)
*/
int
nqsrv_getlease(vp, duration, flags, nd, nam, cachablep, frev, cred)
nqsrv_getlease(vp, duration, flags, slp, procp, nam, cachablep, frev, cred)
struct vnode *vp;
u_long *duration;
int flags;
struct nfsd *nd;
struct nfssvc_sock *slp;
struct proc *procp;
struct mbuf *nam;
int *cachablep;
u_quad_t *frev;
@ -169,13 +174,13 @@ nqsrv_getlease(vp, duration, flags, nd, nam, cachablep, frev, cred)
return (0);
if (*duration > nqsrv_maxlease)
*duration = nqsrv_maxlease;
error = VOP_GETATTR(vp, &vattr, cred, nd->nd_procp);
error = VOP_GETATTR(vp, &vattr, cred, procp);
if (error)
return (error);
*frev = vattr.va_filerev;
s = splsoftclock();
tlp = vp->v_lease;
if ((flags & NQL_CHECK) == 0)
if ((flags & ND_CHECK) == 0)
nfsstats.srvnqnfs_getleases++;
if (tlp == (struct nqlease *)0) {
@ -205,12 +210,12 @@ nqsrv_getlease(vp, duration, flags, nd, nam, cachablep, frev, cred)
if (lp) {
if ((lp->lc_flag & LC_NONCACHABLE) ||
(lp->lc_morehosts == (struct nqm *)0 &&
nqsrv_cmpnam(nd->nd_slp, nam, &lp->lc_host)))
nqsrv_cmpnam(slp, nam, &lp->lc_host)))
goto doreply;
if ((flags & NQL_READ) && (lp->lc_flag & LC_WRITE) == 0) {
if (flags & NQL_CHECK)
if ((flags & ND_READ) && (lp->lc_flag & LC_WRITE) == 0) {
if (flags & ND_CHECK)
goto doreply;
if (nqsrv_cmpnam(nd->nd_slp, nam, &lp->lc_host))
if (nqsrv_cmpnam(slp, nam, &lp->lc_host))
goto doreply;
i = 0;
if (lp->lc_morehosts) {
@ -222,7 +227,7 @@ nqsrv_getlease(vp, duration, flags, nd, nam, cachablep, frev, cred)
ok = 0;
}
while (ok && (lph->lph_flag & LC_VALID)) {
if (nqsrv_cmpnam(nd->nd_slp, nam, lph))
if (nqsrv_cmpnam(slp, nam, lph))
goto doreply;
if (++i == LC_MOREHOSTSIZ) {
i = 0;
@ -242,12 +247,12 @@ nqsrv_getlease(vp, duration, flags, nd, nam, cachablep, frev, cred)
bzero((caddr_t)*lphp, sizeof (struct nqm));
lph = (*lphp)->lpm_hosts;
}
nqsrv_addhost(lph, nd->nd_slp, nam);
nqsrv_addhost(lph, slp, nam);
nqsrv_unlocklease(lp);
} else {
lp->lc_flag |= LC_NONCACHABLE;
nqsrv_locklease(lp);
nqsrv_send_eviction(vp, lp, nd->nd_slp, nam, cred);
nqsrv_send_eviction(vp, lp, slp, nam, cred);
nqsrv_waitfor_expiry(lp);
nqsrv_unlocklease(lp);
}
@ -255,20 +260,20 @@ nqsrv_getlease(vp, duration, flags, nd, nam, cachablep, frev, cred)
/*
* Update the lease and return
*/
if ((flags & NQL_CHECK) == 0)
if ((flags & ND_CHECK) == 0)
nqsrv_instimeq(lp, *duration);
if (lp->lc_flag & LC_NONCACHABLE)
*cachablep = 0;
else {
*cachablep = 1;
if (flags & NQL_WRITE)
if (flags & ND_WRITE)
lp->lc_flag |= LC_WRITTEN;
}
splx(s);
return (0);
}
splx(s);
if (flags & NQL_CHECK)
if (flags & ND_CHECK)
return (0);
/*
@ -285,9 +290,9 @@ nqsrv_getlease(vp, duration, flags, nd, nam, cachablep, frev, cred)
}
MALLOC(lp, struct nqlease *, sizeof (struct nqlease), M_NQLEASE, M_WAITOK);
bzero((caddr_t)lp, sizeof (struct nqlease));
if (flags & NQL_WRITE)
if (flags & ND_WRITE)
lp->lc_flag |= (LC_WRITE | LC_WRITTEN);
nqsrv_addhost(&lp->lc_host, nd->nd_slp, nam);
nqsrv_addhost(&lp->lc_host, slp, nam);
lp->lc_vp = vp;
lp->lc_fsid = fh.fh_fsid;
bcopy(fh.fh_fid.fid_data, lp->lc_fiddata,
@ -308,9 +313,12 @@ nqsrv_getlease(vp, duration, flags, nd, nam, cachablep, frev, cred)
/*
* Local lease check for server syscalls.
* Just set up args and let nqsrv_getlease() do the rest.
* nqnfs_vop_lease_check() is the VOP_LEASE() form of the same routine.
* Ifdef'd code in nfsnode.h renames these routines to whatever a particular
* OS needs.
*/
void
nfs_lease_check(vp, p, cred, flag)
nqnfs_lease_check(vp, p, cred, flag)
struct vnode *vp;
struct proc *p;
struct ucred *cred;
@ -318,15 +326,32 @@ nfs_lease_check(vp, p, cred, flag)
{
u_long duration = 0;
int cache;
struct nfsd nfsd;
u_quad_t frev;
nfsd.nd_slp = NQLOCALSLP;
nfsd.nd_procp = p;
(void) nqsrv_getlease(vp, &duration, NQL_CHECK | flag, &nfsd,
(struct mbuf *)0, &cache, &frev, cred);
(void) nqsrv_getlease(vp, &duration, ND_CHECK | flag, NQLOCALSLP,
p, (struct mbuf *)0, &cache, &frev, cred);
}
#ifdef HAS_VOPLEASE
int
nqnfs_vop_lease_check(ap)
struct vop_lease_args /* {
struct vnode *a_vp;
struct proc *a_p;
struct ucred *a_cred;
int a_flag;
} */ *ap;
{
u_long duration = 0;
int cache;
u_quad_t frev;
(void) nqsrv_getlease(ap->a_vp, &duration, ND_CHECK | ap->a_flag,
NQLOCALSLP, ap->a_p, (struct mbuf *)0, &cache, &frev, ap->a_cred);
return (0);
}
#endif
/*
* Add a host to an nqhost structure for a lease.
*/
@ -486,9 +511,9 @@ nqsrv_send_eviction(vp, lp, slp, nam, cred)
else
solockp = (int *)0;
nfsm_reqhead((struct vnode *)0, NQNFSPROC_EVICTED,
NFSX_FH);
nfsm_build(cp, caddr_t, NFSX_FH);
bzero(cp, NFSX_FH);
NFSX_V3FH);
nfsm_build(cp, caddr_t, NFSX_V3FH);
bzero(cp, NFSX_V3FH);
fhp = (fhandle_t *)cp;
fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
VFS_VPTOFH(vp, &fhp->fh_fid);
@ -502,8 +527,9 @@ nqsrv_send_eviction(vp, lp, slp, nam, cred)
printf("mbuf siz=%d\n",siz);
panic("Bad nfs svc reply");
}
m = nfsm_rpchead(cred, TRUE, NQNFSPROC_EVICTED,
RPCAUTH_UNIX, 5*NFSX_UNSIGNED, (char *)0,
m = nfsm_rpchead(cred, (NFSMNT_NFSV3 | NFSMNT_NQNFS),
NQNFSPROC_EVICTED,
RPCAUTH_UNIX, 5 * NFSX_UNSIGNED, (char *)0,
mreq, siz, &mheadend, &xid);
/*
* For stream protocols, prepend a Sun RPC
@ -677,18 +703,21 @@ nqnfs_serverd()
* do the real work.
*/
int
nqnfsrv_getlease(nfsd, mrep, md, dpos, cred, nam, mrq)
struct nfsd *nfsd;
struct mbuf *mrep, *md;
caddr_t dpos;
struct ucred *cred;
struct mbuf *nam, **mrq;
nqnfsrv_getlease(nfsd, slp, procp, mrq)
struct nfsrv_descript *nfsd;
struct nfssvc_sock *slp;
struct proc *procp;
struct mbuf **mrq;
{
register struct nfsv2_fattr *fp;
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct mbuf *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
register struct nfs_fattr *fp;
struct vattr va;
register struct vattr *vap = &va;
struct vnode *vp;
nfsv2fh_t nfh;
nfsfh_t nfh;
fhandle_t *fhp;
register u_long *tl;
register long t1;
@ -701,29 +730,29 @@ nqnfsrv_getlease(nfsd, mrep, md, dpos, cred, nam, mrq)
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED);
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
flags = fxdr_unsigned(int, *tl++);
nfsd->nd_duration = fxdr_unsigned(int, *tl);
error = nfsrv_fhtovp(fhp,
TRUE, &vp, cred, nfsd->nd_slp, nam, &rdonly);
error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
(nfsd->nd_flag & ND_KERBAUTH));
if (error)
nfsm_reply(0);
if (rdonly && flags == NQL_WRITE) {
if (rdonly && flags == ND_WRITE) {
error = EROFS;
nfsrv_vput(vp);
nfsm_reply(0);
}
(void) nqsrv_getlease(vp, &nfsd->nd_duration, flags, nfsd,
(void) nqsrv_getlease(vp, &nfsd->nd_duration, flags, slp, procp,
nam, &cache, &frev, cred);
error = VOP_GETATTR(vp, vap, cred, nfsd->nd_procp);
error = VOP_GETATTR(vp, vap, cred, procp);
nfsrv_vput(vp);
nfsm_reply(NFSX_NQFATTR + 4*NFSX_UNSIGNED);
nfsm_build(tl, u_long *, 4*NFSX_UNSIGNED);
nfsm_reply(NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
nfsm_build(tl, u_long *, 4 * NFSX_UNSIGNED);
*tl++ = txdr_unsigned(cache);
*tl++ = txdr_unsigned(nfsd->nd_duration);
txdr_hyper(&frev, tl);
nfsm_build(fp, struct nfsv2_fattr *, NFSX_NQFATTR);
nfsm_srvfillattr;
nfsm_build(fp, struct nfs_fattr *, NFSX_V3FATTR);
nfsm_srvfillattr(vap, fp);
nfsm_srvdone;
}
@ -732,23 +761,28 @@ nqnfsrv_getlease(nfsd, mrep, md, dpos, cred, nam, mrq)
* client. Find the entry and expire it.
*/
int
nqnfsrv_vacated(nfsd, mrep, md, dpos, cred, nam, mrq)
struct nfsd *nfsd;
struct mbuf *mrep, *md;
caddr_t dpos;
struct ucred *cred;
struct mbuf *nam, **mrq;
nqnfsrv_vacated(nfsd, slp, procp, mrq)
struct nfsrv_descript *nfsd;
struct nfssvc_sock *slp;
struct proc *procp;
struct mbuf **mrq;
{
struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
struct mbuf *nam = nfsd->nd_nam;
caddr_t dpos = nfsd->nd_dpos;
struct ucred *cred = &nfsd->nd_cr;
register struct nqlease *lp;
register struct nqhost *lph;
struct nqlease *tlp = (struct nqlease *)0;
nfsv2fh_t nfh;
nfsfh_t nfh;
fhandle_t *fhp;
register u_long *tl;
register long t1;
struct nqm *lphnext;
int error = 0, i, len, ok, gotit = 0;
char *cp2;
struct mbuf *mreq, *mb;
int error = 0, i, len, ok, gotit = 0, cache = 0;
char *cp2, *bpos;
u_quad_t frev;
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
@ -774,7 +808,7 @@ nqnfsrv_vacated(nfsd, mrep, md, dpos, cred, nam, mrq)
lphnext = lp->lc_morehosts;
ok = 1;
while (ok && (lph->lph_flag & LC_VALID)) {
if (nqsrv_cmpnam(nfsd->nd_slp, nam, lph)) {
if (nqsrv_cmpnam(slp, nam, lph)) {
lph->lph_flag |= LC_VACATED;
gotit++;
break;
@ -812,7 +846,7 @@ nqnfs_getlease(vp, rwflag, cred, p)
{
register u_long *tl;
register caddr_t cp;
register long t1;
register long t1, t2;
register struct nfsnode *np;
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
caddr_t bpos, dpos, cp2;
@ -823,16 +857,16 @@ nqnfs_getlease(vp, rwflag, cred, p)
u_quad_t frev;
nfsstats.rpccnt[NQNFSPROC_GETLEASE]++;
mb = mreq = nfsm_reqh(vp, NQNFSPROC_GETLEASE, NFSX_FH+2*NFSX_UNSIGNED,
mb = mreq = nfsm_reqh(vp, NQNFSPROC_GETLEASE, NFSX_V3FH+2*NFSX_UNSIGNED,
&bpos);
nfsm_fhtom(vp);
nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
nfsm_fhtom(vp, 1);
nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
*tl++ = txdr_unsigned(rwflag);
*tl = txdr_unsigned(nmp->nm_leaseterm);
reqtime = time.tv_sec;
nfsm_request(vp, NQNFSPROC_GETLEASE, p, cred);
np = VTONFS(vp);
nfsm_dissect(tl, u_long *, 4*NFSX_UNSIGNED);
nfsm_dissect(tl, u_long *, 4 * NFSX_UNSIGNED);
cachable = fxdr_unsigned(int, *tl++);
reqtime += fxdr_unsigned(int, *tl++);
if (reqtime > time.tv_sec) {
@ -856,6 +890,8 @@ nqnfs_vacated(vp, cred)
register caddr_t cp;
register struct mbuf *m;
register int i;
register u_long *tl;
register long t1, t2;
caddr_t bpos;
u_long xid;
int error = 0;
@ -865,16 +901,16 @@ nqnfs_vacated(vp, cred)
nmp = VFSTONFS(vp->v_mount);
nfsstats.rpccnt[NQNFSPROC_VACATED]++;
nfsm_reqhead(vp, NQNFSPROC_VACATED, NFSX_FH);
nfsm_fhtom(vp);
nfsm_reqhead(vp, NQNFSPROC_VACATED, NFSX_V3FH);
nfsm_fhtom(vp, 1);
m = mreq;
i = 0;
while (m) {
i += m->m_len;
m = m->m_next;
}
m = nfsm_rpchead(cred, TRUE, NQNFSPROC_VACATED,
RPCAUTH_UNIX, 5*NFSX_UNSIGNED, (char *)0,
m = nfsm_rpchead(cred, nmp->nm_flag, NQNFSPROC_VACATED,
RPCAUTH_UNIX, 5 * NFSX_UNSIGNED, (char *)0,
mreq, i, &mheadend, &xid);
if (nmp->nm_sotype == SOCK_STREAM) {
M_PREPEND(m, NFSX_UNSIGNED, M_WAIT);
@ -888,6 +924,7 @@ nqnfs_vacated(vp, cred)
(void) nfs_send(nmp->nm_so, nmp->nm_nam, m, &myrep);
if (nmp->nm_soflags & PR_CONNREQUIRED)
nfs_sndunlock(&nmp->nm_flag);
nfsmout:
return (error);
}
@ -903,29 +940,37 @@ nqnfs_callback(nmp, mrep, md, dpos)
register struct vnode *vp;
register u_long *tl;
register long t1;
nfsv2fh_t nfh;
nfsfh_t nfh;
fhandle_t *fhp;
struct nfsnode *np;
struct nfsd nd;
int error;
char *cp2;
struct nfsd tnfsd;
struct nfssvc_sock *slp;
struct nfsrv_descript ndesc;
register struct nfsrv_descript *nfsd = &ndesc;
struct mbuf **mrq = (struct mbuf **)0, *mb, *mreq;
int error = 0, cache = 0;
char *cp2, *bpos;
u_quad_t frev;
nd.nd_mrep = mrep;
nd.nd_md = md;
nd.nd_dpos = dpos;
error = nfs_getreq(&nd, FALSE);
#ifndef nolint
slp = NULL;
#endif
nfsd->nd_mrep = mrep;
nfsd->nd_md = md;
nfsd->nd_dpos = dpos;
error = nfs_getreq(nfsd, &tnfsd, FALSE);
if (error)
return (error);
md = nd.nd_md;
dpos = nd.nd_dpos;
if (nd.nd_procnum != NQNFSPROC_EVICTED) {
md = nfsd->nd_md;
dpos = nfsd->nd_dpos;
if (nfsd->nd_procnum != NQNFSPROC_EVICTED) {
m_freem(mrep);
return (EPERM);
}
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
m_freem(mrep);
error = nfs_nget(nmp->nm_mountp, &nfh, &np);
error = nfs_nget(nmp->nm_mountp, (nfsfh_t *)fhp, NFSX_V3FH, &np);
if (error)
return (error);
vp = NFSTOV(np);
@ -937,7 +982,7 @@ nqnfs_callback(nmp, mrep, md, dpos)
CIRCLEQ_INSERT_HEAD(&nmp->nm_timerhead, np, n_timer);
}
}
vrele(vp);
vput(vp);
nfsm_srvdone;
}
@ -960,35 +1005,39 @@ nqnfs_clientd(nmp, cred, ncd, flag, argp, p)
register struct nfsnode *np;
struct vnode *vp;
struct nfsreq myrep;
struct nfsuid *nuidp, *nnuidp;
int error = 0, vpid;
/*
* First initialize some variables
*/
nqnfs_prog = txdr_unsigned(NQNFS_PROG);
nqnfs_vers = txdr_unsigned(NQNFS_VER1);
/*
* If an authorization string is being passed in, get it.
*/
if ((flag & NFSSVC_GOTAUTH) &&
(nmp->nm_flag & (NFSMNT_WAITAUTH | NFSMNT_DISMNT)) == 0) {
if (nmp->nm_flag & NFSMNT_HASAUTH)
panic("cld kerb");
if ((flag & NFSSVC_AUTHINFAIL) == 0) {
if (ncd->ncd_authlen <= RPCAUTH_MAXSIZ &&
copyin(ncd->ncd_authstr, nmp->nm_authstr,
ncd->ncd_authlen) == 0) {
nmp->nm_authtype = ncd->ncd_authtype;
nmp->nm_authlen = ncd->ncd_authlen;
} else
nmp->nm_flag |= NFSMNT_AUTHERR;
(nmp->nm_flag & (NFSMNT_WAITAUTH | NFSMNT_DISMNT)) == 0) {
if (nmp->nm_flag & NFSMNT_HASAUTH)
panic("cld kerb");
if ((flag & NFSSVC_AUTHINFAIL) == 0) {
if (ncd->ncd_authlen <= nmp->nm_authlen &&
ncd->ncd_verflen <= nmp->nm_verflen &&
!copyin(ncd->ncd_authstr,nmp->nm_authstr,ncd->ncd_authlen)&&
!copyin(ncd->ncd_verfstr,nmp->nm_verfstr,ncd->ncd_verflen)){
nmp->nm_authtype = ncd->ncd_authtype;
nmp->nm_authlen = ncd->ncd_authlen;
nmp->nm_verflen = ncd->ncd_verflen;
#ifdef NFSKERB
nmp->nm_key = ncd->ncd_key;
#endif
} else
nmp->nm_flag |= NFSMNT_AUTHERR;
nmp->nm_flag |= NFSMNT_HASAUTH;
wakeup((caddr_t)&nmp->nm_authlen);
nmp->nm_flag |= NFSMNT_AUTHERR;
} else
nmp->nm_flag |= NFSMNT_AUTHERR;
nmp->nm_flag |= NFSMNT_HASAUTH;
wakeup((caddr_t)&nmp->nm_authlen);
} else
nmp->nm_flag |= NFSMNT_WAITAUTH;
nmp->nm_flag |= NFSMNT_WAITAUTH;
/*
* Loop every second updating queue until there is a termination sig.
@ -1016,13 +1065,11 @@ nqnfs_clientd(nmp, cred, ncd, flag, argp, p)
while (np != (void *)&nmp->nm_timerhead &&
(nmp->nm_flag & NFSMNT_DISMINPROG) == 0) {
vp = NFSTOV(np);
if (vp->v_mount->mnt_stat.f_fsid.val[1] != MOUNT_NFS) panic("trash2");
vpid = vp->v_id;
if (np->n_expiry < time.tv_sec) {
if (vget(vp, 1) == 0) {
nmp->nm_inprog = vp;
if (vpid == vp->v_id) {
if (vp->v_mount->mnt_stat.f_fsid.val[1] != MOUNT_NFS) panic("trash3");
CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
np->n_timer.cqe_next = 0;
if ((np->n_flag & (NMODIFIED | NQNFSEVICTED))
@ -1047,9 +1094,8 @@ if (vp->v_mount->mnt_stat.f_fsid.val[1] != MOUNT_NFS) panic("trash3");
== NQNFSWRITE && vp->v_dirtyblkhd.lh_first &&
vget(vp, 1) == 0) {
nmp->nm_inprog = vp;
if (vp->v_mount->mnt_stat.f_fsid.val[1] != MOUNT_NFS) panic("trash4");
if (vpid == vp->v_id &&
nqnfs_getlease(vp, NQL_WRITE, cred, p)==0)
nqnfs_getlease(vp, ND_WRITE, cred, p)==0)
np->n_brev = np->n_lrev;
vrele(vp);
nmp->nm_inprog = NULLVP;
@ -1084,6 +1130,16 @@ if (vp->v_mount->mnt_stat.f_fsid.val[1] != MOUNT_NFS) panic("trash4");
(void) dounmount(nmp->nm_mountp, 0, p);
}
}
/*
* Finally, we can free up the mount structure.
*/
for (nuidp = nmp->nm_uidlruhead.tqh_first; nuidp != 0; nuidp = nnuidp) {
nnuidp = nuidp->nu_lru.tqe_next;
LIST_REMOVE(nuidp, nu_hash);
TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp, nu_lru);
free((caddr_t)nuidp, M_NFSUID);
}
free((caddr_t)nmp, M_NFSMNT);
if (error == EWOULDBLOCK)
error = 0;
@ -1095,7 +1151,7 @@ if (vp->v_mount->mnt_stat.f_fsid.val[1] != MOUNT_NFS) panic("trash4");
* Called from the settimeofday() syscall.
*/
void
nfs_lease_updatetime(deltat)
nqnfs_lease_updatetime(deltat)
register int deltat;
{
register struct nqlease *lp;
@ -1116,8 +1172,17 @@ nfs_lease_updatetime(deltat)
* Search the mount list for all nqnfs mounts and do their timer
* queues.
*/
#if NetBSD >= 1994101
for (mp = mountlist.cqh_first; mp != (void *)&mountlist;
mp = mp->mnt_list.cqe_next) {
#else
for (mp = mountlist.tqh_first; mp != NULL; mp = mp->mnt_list.tqe_next) {
#endif
#ifdef __NetBSD__
if (!strcmp(&mp->mnt_stat.f_fstypename[0], MOUNT_NFS)) {
#else
if (mp->mnt_stat.f_fsid.val[1] == MOUNT_NFS) {
#endif
nmp = VFSTONFS(mp);
if (nmp->nm_flag & NFSMNT_NQNFS) {
for (np = nmp->nm_timerhead.cqh_first;
@ -1174,9 +1239,9 @@ nqnfs_clientlease(nmp, np, rwflag, cachable, expiry, frev)
if (np->n_timer.cqe_next != 0) {
CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
if (rwflag == NQL_WRITE)
if (rwflag == ND_WRITE)
np->n_flag |= NQNFSWRITE;
} else if (rwflag == NQL_READ)
} else if (rwflag == ND_READ)
np->n_flag &= ~NQNFSWRITE;
else
np->n_flag |= NQNFSWRITE;

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_socket.c 8.3 (Berkeley) 1/12/94
* $Id: nfs_socket.c,v 1.6 1995/03/16 18:15:37 bde Exp $
* $Id: nfs_socket.c,v 1.7 1995/05/30 08:12:40 rgrimes Exp $
*/
/*
@ -59,7 +59,7 @@
#include <netinet/tcp.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
#include <nfs/xdr_subs.h>
#include <nfs/nfsm_subs.h>
@ -94,36 +94,13 @@
* External data, mostly RPC constants in XDR form
*/
extern u_long rpc_reply, rpc_msgdenied, rpc_mismatch, rpc_vers, rpc_auth_unix,
rpc_msgaccepted, rpc_call, rpc_autherr, rpc_rejectedcred,
rpc_msgaccepted, rpc_call, rpc_autherr,
rpc_auth_kerb;
extern u_long nfs_prog, nfs_vers, nqnfs_prog, nqnfs_vers;
extern u_long nfs_prog, nqnfs_prog;
extern time_t nqnfsstarttime;
extern int nonidempotent[NFS_NPROCS];
/*
* Maps errno values to nfs error numbers.
* Use NFSERR_IO as the catch all for ones not specifically defined in
* RFC 1094.
*/
static int nfsrv_errmap[ELAST] = {
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,
NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE,
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
NFSERR_IO,
};
extern struct nfsstats nfsstats;
extern int nfsv3_procid[NFS_NPROCS];
extern int nfs_ticks;
/*
* Defines which timer to use for the procnum.
@ -134,7 +111,8 @@ static int nfsrv_errmap[ELAST] = {
* 4 - write
*/
static int proct[NFS_NPROCS] = {
0, 1, 0, 0, 2, 3, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0,
0, 1, 0, 2, 1, 3, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0,
0, 0, 0,
};
/*
@ -164,10 +142,12 @@ int nfsrv_null(),
nfsrv_getattr(),
nfsrv_setattr(),
nfsrv_lookup(),
nfsrv3_access(),
nfsrv_readlink(),
nfsrv_read(),
nfsrv_write(),
nfsrv_create(),
nfsrv_mknod(),
nfsrv_remove(),
nfsrv_rename(),
nfsrv_link(),
@ -175,37 +155,42 @@ int nfsrv_null(),
nfsrv_mkdir(),
nfsrv_rmdir(),
nfsrv_readdir(),
nfsrv_readdirplus(),
nfsrv_statfs(),
nfsrv_fsinfo(),
nfsrv_pathconf(),
nfsrv_commit(),
nfsrv_noop(),
nqnfsrv_readdirlook(),
nqnfsrv_getlease(),
nqnfsrv_vacated(),
nqnfsrv_access();
nqnfsrv_vacated();
int (*nfsrv_procs[NFS_NPROCS])() = {
int (*nfsrv3_procs[NFS_NPROCS])() = {
nfsrv_null,
nfsrv_getattr,
nfsrv_setattr,
nfsrv_noop,
nfsrv_lookup,
nfsrv3_access,
nfsrv_readlink,
nfsrv_read,
nfsrv_noop,
nfsrv_write,
nfsrv_create,
nfsrv_mkdir,
nfsrv_symlink,
nfsrv_mknod,
nfsrv_remove,
nfsrv_rmdir,
nfsrv_rename,
nfsrv_link,
nfsrv_symlink,
nfsrv_mkdir,
nfsrv_rmdir,
nfsrv_readdir,
nfsrv_readdirplus,
nfsrv_statfs,
nqnfsrv_readdirlook,
nfsrv_fsinfo,
nfsrv_pathconf,
nfsrv_commit,
nqnfsrv_getlease,
nqnfsrv_vacated,
nfsrv_noop,
nqnfsrv_access,
nfsrv_noop
};
/*
@ -874,13 +859,16 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
struct nfsmount *nmp;
struct mbuf *md, *mheadend;
struct nfsnode *np;
char nickv[RPCX_NICKVERF];
time_t reqtime, waituntil;
caddr_t dpos, cp2;
int t1, nqlflag, cachable, s, error = 0, mrest_len, auth_len, auth_type;
int trylater_delay = NQ_TRYLATERDEL, trylater_cnt = 0, failed_auth = 0;
int verf_len, verf_type;
u_long xid;
u_quad_t frev;
char *auth_str;
char *auth_str, *verf_str;
NFSKERBKEY_T key; /* save session key */
nmp = VFSTONFS(vp->v_mount);
MALLOC(rep, struct nfsreq *, sizeof(struct nfsreq), M_NFSREQ, M_WAITOK);
@ -900,19 +888,21 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
* Get the RPC header with authorization.
*/
kerbauth:
auth_str = (char *)0;
verf_str = auth_str = (char *)0;
if (nmp->nm_flag & NFSMNT_KERB) {
if (failed_auth) {
error = nfs_getauth(nmp, rep, cred, &auth_type,
&auth_str, &auth_len);
verf_str = nickv;
verf_len = sizeof (nickv);
auth_type = RPCAUTH_KERB4;
bzero((caddr_t)key, sizeof (key));
if (failed_auth || nfs_getnickauth(nmp, cred, &auth_str,
&auth_len, verf_str, verf_len)) {
error = nfs_getauth(nmp, rep, cred, &auth_str,
&auth_len, verf_str, &verf_len, key);
if (error) {
free((caddr_t)rep, M_NFSREQ);
m_freem(mrest);
return (error);
}
} else {
auth_type = RPCAUTH_UNIX;
auth_len = 5 * NFSX_UNSIGNED;
}
} else {
auth_type = RPCAUTH_UNIX;
@ -922,8 +912,8 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
nmp->nm_numgrps : (cred->cr_ngroups - 1)) << 2) +
5 * NFSX_UNSIGNED;
}
m = nfsm_rpchead(cred, (nmp->nm_flag & NFSMNT_NQNFS), procnum,
auth_type, auth_len, auth_str, mrest, mrest_len, &mheadend, &xid);
m = nfsm_rpchead(cred, nmp->nm_flag, procnum, auth_type, auth_len,
auth_str, verf_len, verf_str, mrest, mrest_len, &mheadend, &xid);
if (auth_str)
free(auth_str, M_TEMP);
@ -1029,12 +1019,12 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
/*
* break down the rpc header and check if ok
*/
nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED);
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
if (*tl++ == rpc_msgdenied) {
if (*tl == rpc_mismatch)
error = EOPNOTSUPP;
else if ((nmp->nm_flag & NFSMNT_KERB) && *tl++ == rpc_autherr) {
if (*tl == rpc_rejectedcred && failed_auth == 0) {
if (!failed_auth) {
failed_auth++;
mheadend->m_next = (struct mbuf *)0;
m_freem(mrep);
@ -1051,22 +1041,25 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
}
/*
* skip over the auth_verf, someday we may want to cache auth_short's
* for nfs_reqhead(), but for now just dump it
* Grab any Kerberos verifier, otherwise just throw it away.
*/
if (*++tl != 0) {
i = nfsm_rndup(fxdr_unsigned(long, *tl));
nfsm_adv(i);
}
verf_type = fxdr_unsigned(int, *tl++);
i = fxdr_unsigned(int, *tl);
if ((nmp->nm_flag & NFSMNT_KERB) && verf_type == RPCAUTH_KERB4) {
error = nfs_savenickauth(nmp, cred, i, key, &md, &dpos, mrep);
if (error)
goto nfsmout;
} else if (i > 0)
nfsm_adv(nfsm_rndup(i));
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
/* 0 == ok */
if (*tl == 0) {
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
if (*tl != 0) {
error = fxdr_unsigned(int, *tl);
m_freem(mrep);
if ((nmp->nm_flag & NFSMNT_NQNFS) &&
error == NQNFS_TRYLATER) {
if ((nmp->nm_flag & NFSMNT_NFSV3) &&
error == NFSERR_TRYLATER) {
m_freem(mrep);
error = 0;
waituntil = time.tv_sec + trylater_delay;
while (time.tv_sec < waituntil)
@ -1084,6 +1077,13 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
*/
if (error == ESTALE)
cache_purge(vp);
if (nmp->nm_flag & NFSMNT_NFSV3) {
*mrp = mrep;
*mdp = md;
*dposp = dpos;
error |= NFSERR_RETERR;
} else
m_freem(mrep);
m_freem(rep->r_mreq);
free((caddr_t)rep, M_NFSREQ);
return (error);
@ -1115,10 +1115,10 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
return (0);
}
m_freem(mrep);
m_freem(rep->r_mreq);
free((caddr_t)rep, M_NFSREQ);
error = EPROTONOSUPPORT;
nfsmout:
m_freem(rep->r_mreq);
free((caddr_t)rep, M_NFSREQ);
return (error);
}
@ -1127,9 +1127,10 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
* siz arg. is used to decide if adding a cluster is worthwhile
*/
int
nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
nfs_rephead(siz, nd, slp, err, cache, frev, mrq, mbp, bposp)
int siz;
struct nfsd *nd;
struct nfsrv_descript *nd;
struct nfssvc_sock *slp;
int err;
int cache;
u_quad_t *frev;
@ -1154,47 +1155,98 @@ nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
} else
mreq->m_data += max_hdr;
tl = mtod(mreq, u_long *);
mreq->m_len = 6*NFSX_UNSIGNED;
bpos = ((caddr_t)tl)+mreq->m_len;
mreq->m_len = 6 * NFSX_UNSIGNED;
bpos = ((caddr_t)tl) + mreq->m_len;
*tl++ = txdr_unsigned(nd->nd_retxid);
*tl++ = rpc_reply;
if (err == ERPCMISMATCH || err == NQNFS_AUTHERR) {
if (err == ERPCMISMATCH || (err & NFSERR_AUTHERR)) {
*tl++ = rpc_msgdenied;
if (err == NQNFS_AUTHERR) {
if (err & NFSERR_AUTHERR) {
*tl++ = rpc_autherr;
*tl = rpc_rejectedcred;
*tl = txdr_unsigned(err & ~NFSERR_AUTHERR);
mreq->m_len -= NFSX_UNSIGNED;
bpos -= NFSX_UNSIGNED;
} else {
*tl++ = rpc_mismatch;
*tl++ = txdr_unsigned(2);
*tl = txdr_unsigned(2);
*tl++ = txdr_unsigned(RPC_VER2);
*tl = txdr_unsigned(RPC_VER2);
}
} else {
*tl++ = rpc_msgaccepted;
*tl++ = 0;
*tl++ = 0;
/*
* For Kerberos authentication, we must send the nickname
* verifier back, otherwise just RPCAUTH_NULL.
*/
if (nd->nd_flag & ND_KERBFULL) {
register struct nfsuid *nuidp;
struct timeval ktvin, ktvout;
NFSKERBKEYSCHED_T keys; /* stores key schedule */
for (nuidp = NUIDHASH(slp, nd->nd_cr.cr_uid)->lh_first;
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
if (nuidp->nu_cr.cr_uid == nd->nd_cr.cr_uid &&
(!nd->nd_nam2 || netaddr_match(NU_NETFAM(nuidp),
&nuidp->nu_haddr, nd->nd_nam2)))
break;
}
if (nuidp) {
ktvin.tv_sec =
txdr_unsigned(nuidp->nu_timestamp.tv_sec - 1);
ktvin.tv_usec =
txdr_unsigned(nuidp->nu_timestamp.tv_usec);
/*
* Encrypt the timestamp in ecb mode using the
* session key.
*/
#ifdef NFSKERB
XXX
#endif
*tl++ = rpc_auth_kerb;
*tl++ = txdr_unsigned(3 * NFSX_UNSIGNED);
*tl = ktvout.tv_sec;
nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED);
*tl++ = ktvout.tv_usec;
*tl++ = txdr_unsigned(nuidp->nu_cr.cr_uid);
} else {
*tl++ = 0;
*tl++ = 0;
}
} else {
*tl++ = 0;
*tl++ = 0;
}
switch (err) {
case EPROGUNAVAIL:
*tl = txdr_unsigned(RPC_PROGUNAVAIL);
break;
case EPROGMISMATCH:
*tl = txdr_unsigned(RPC_PROGMISMATCH);
nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
*tl++ = txdr_unsigned(2);
*tl = txdr_unsigned(2); /* someday 3 */
nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
if (nd->nd_flag & ND_NQNFS) {
*tl++ = txdr_unsigned(3);
*tl = txdr_unsigned(3);
} else {
*tl++ = txdr_unsigned(2);
*tl = txdr_unsigned(3);
}
break;
case EPROCUNAVAIL:
*tl = txdr_unsigned(RPC_PROCUNAVAIL);
break;
case EBADRPC:
*tl = txdr_unsigned(RPC_GARBAGE);
break;
default:
*tl = 0;
if (err != VNOVAL) {
if (err != NFSERR_RETVOID) {
nfsm_build(tl, u_long *, NFSX_UNSIGNED);
if (err)
*tl = txdr_unsigned(nfsrv_errmap[err - 1]);
*tl = txdr_unsigned(nfsrv_errmap(nd, err));
else
*tl = 0;
*tl = 0;
}
break;
};
@ -1203,16 +1255,14 @@ nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
/*
* For nqnfs, piggyback lease as requested.
*/
if (nd->nd_nqlflag != NQL_NOVAL && err == 0) {
if (nd->nd_nqlflag) {
nfsm_build(tl, u_long *, 5*NFSX_UNSIGNED);
*tl++ = txdr_unsigned(nd->nd_nqlflag);
if ((nd->nd_flag & ND_NQNFS) && err == 0) {
if (nd->nd_flag & ND_LEASE) {
nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED);
*tl++ = txdr_unsigned(nd->nd_flag & ND_LEASE);
*tl++ = txdr_unsigned(cache);
*tl++ = txdr_unsigned(nd->nd_duration);
txdr_hyper(frev, tl);
} else {
if (nd->nd_nqlflag != 0)
panic("nqreph");
nfsm_build(tl, u_long *, NFSX_UNSIGNED);
*tl = 0;
}
@ -1220,7 +1270,7 @@ nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
*mrq = mreq;
*mbp = mb;
*bposp = bpos;
if (err != 0 && err != VNOVAL)
if (err != 0 && err != NFSERR_RETVOID)
nfsstats.srvrpc_errs++;
return (0);
}
@ -1240,8 +1290,10 @@ nfs_timer(arg)
register struct socket *so;
register struct nfsmount *nmp;
register int timeo;
register struct nfssvc_sock *slp;
static long lasttime = 0;
int s, error;
u_quad_t cur_usec;
s = splnet();
for (rep = nfs_reqq.tqh_first; rep != 0; rep = rep->r_chain.tqe_next) {
@ -1338,8 +1390,19 @@ nfs_timer(arg)
lasttime = time.tv_sec;
nqnfs_serverd();
}
/*
* Scan the write gathering queues for writes that need to be
* completed now.
*/
cur_usec = (u_quad_t)time.tv_sec * 1000000 + (u_quad_t)time.tv_usec;
for (slp = nfssvc_sockhead.tqh_first; slp != 0;
slp = slp->ns_chain.tqe_next) {
if (slp->ns_tq.lh_first && slp->ns_tq.lh_first->nd_time<=cur_usec)
nfsrv_wakenfsd(slp);
}
splx(s);
timeout(nfs_timer, (void *)0, hz / NFS_HZ);
timeout(nfs_timer, (void *)0, nfs_ticks);
}
/*
@ -1673,7 +1736,7 @@ nfsrv_getstream(slp, waitflag)
register struct nfssvc_sock *slp;
int waitflag;
{
register struct mbuf *m;
register struct mbuf *m, **mpp;
register char *cp1, *cp2;
register int len;
struct mbuf *om, *m2, *recm = 0;
@ -1707,7 +1770,12 @@ nfsrv_getstream(slp, waitflag)
}
}
slp->ns_cc -= NFSX_UNSIGNED;
slp->ns_reclen = ntohl(recmark) & ~0x80000000;
recmark = ntohl(recmark);
slp->ns_reclen = recmark & ~0x80000000;
if (recmark & 0x80000000)
slp->ns_flag |= SLP_LASTFRAG;
else
slp->ns_flag &= ~SLP_LASTFRAG;
if (slp->ns_reclen < NFS_MINPACKET || slp->ns_reclen > NFS_MAXPACKET) {
slp->ns_flag &= ~SLP_GETSTREAM;
return (EPERM);
@ -1761,12 +1829,23 @@ nfsrv_getstream(slp, waitflag)
slp->ns_flag &= ~SLP_GETSTREAM;
return (0);
}
nfs_realign(recm, 10 * NFSX_UNSIGNED);
if (slp->ns_recend)
slp->ns_recend->m_nextpkt = recm;
else
slp->ns_rec = recm;
slp->ns_recend = recm;
/*
* Accumulate the fragments into a record.
*/
mpp = &slp->ns_frag;
while (*mpp)
mpp = &((*mpp)->m_next);
*mpp = recm;
if (slp->ns_flag & SLP_LASTFRAG) {
nfs_realign(slp->ns_frag, 10 * NFSX_UNSIGNED);
if (slp->ns_recend)
slp->ns_recend->m_nextpkt = slp->ns_frag;
else
slp->ns_rec = slp->ns_frag;
slp->ns_recend = slp->ns_frag;
slp->ns_frag = (struct mbuf *)0;
}
}
}
@ -1774,13 +1853,16 @@ nfsrv_getstream(slp, waitflag)
* Parse an RPC header.
*/
int
nfsrv_dorec(slp, nd)
nfsrv_dorec(slp, nfsd, ndp)
register struct nfssvc_sock *slp;
register struct nfsd *nd;
struct nfsd *nfsd;
struct nfsrv_descript **ndp;
{
register struct mbuf *m;
register struct mbuf *m, *nam;
register struct nfsrv_descript *nd;
int error;
*ndp = NULL;
if ((slp->ns_flag & SLP_VALID) == 0 ||
(m = slp->ns_rec) == (struct mbuf *)0)
return (ENOBUFS);
@ -1790,19 +1872,24 @@ nfsrv_dorec(slp, nd)
else
slp->ns_recend = (struct mbuf *)0;
if (m->m_type == MT_SONAME) {
nd->nd_nam = m;
nd->nd_md = nd->nd_mrep = m->m_next;
m->m_next = (struct mbuf *)0;
} else {
nd->nd_nam = (struct mbuf *)0;
nd->nd_md = nd->nd_mrep = m;
}
nd->nd_dpos = mtod(nd->nd_md, caddr_t);
error = nfs_getreq(nd, TRUE);
nam = m;
m = m->m_next;
nam->m_next = NULL;
} else
nam = NULL;
MALLOC(nd, struct nfsrv_descript *, sizeof (struct nfsrv_descript),
M_NFSRVDESC, M_WAITOK);
nd->nd_md = nd->nd_mrep = m;
nd->nd_nam2 = nam;
nd->nd_dpos = mtod(m, caddr_t);
error = nfs_getreq(nd, nfsd, TRUE);
if (error) {
m_freem(nd->nd_nam);
m_freem(nam);
free((caddr_t)nd, M_NFSRVDESC);
return (error);
}
*ndp = nd;
nfsd->nfsd_nd = nd;
return (0);
}
@ -1812,8 +1899,9 @@ nfsrv_dorec(slp, nd)
* - fill in the cred struct.
*/
int
nfs_getreq(nd, has_header)
register struct nfsd *nd;
nfs_getreq(nd, nfsd, has_header)
register struct nfsrv_descript *nd;
struct nfsd *nfsd;
int has_header;
{
register int len, i;
@ -1821,57 +1909,67 @@ nfs_getreq(nd, has_header)
register long t1;
struct uio uio;
struct iovec iov;
caddr_t dpos, cp2;
caddr_t dpos, cp2, cp;
u_long nfsvers, auth_type;
int error = 0, nqnfs = 0;
uid_t nickuid;
int error = 0, nqnfs = 0, ticklen;
struct mbuf *mrep, *md;
register struct nfsuid *nuidp;
struct timeval tvin, tvout;
NFSKERBKEYSCHED_T keys; /* stores key schedule */
mrep = nd->nd_mrep;
md = nd->nd_md;
dpos = nd->nd_dpos;
if (has_header) {
nfsm_dissect(tl, u_long *, 10*NFSX_UNSIGNED);
nfsm_dissect(tl, u_long *, 10 * NFSX_UNSIGNED);
nd->nd_retxid = fxdr_unsigned(u_long, *tl++);
if (*tl++ != rpc_call) {
m_freem(mrep);
return (EBADRPC);
}
} else {
nfsm_dissect(tl, u_long *, 8*NFSX_UNSIGNED);
}
} else
nfsm_dissect(tl, u_long *, 8 * NFSX_UNSIGNED);
nd->nd_repstat = 0;
nd->nd_flag = 0;
if (*tl++ != rpc_vers) {
nd->nd_repstat = ERPCMISMATCH;
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
nfsvers = nfs_vers;
if (*tl != nfs_prog) {
if (*tl == nqnfs_prog) {
if (*tl == nqnfs_prog)
nqnfs++;
nfsvers = nqnfs_vers;
} else {
else {
nd->nd_repstat = EPROGUNAVAIL;
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
}
tl++;
if (*tl++ != nfsvers) {
nfsvers = fxdr_unsigned(u_long, *tl++);
if (((nfsvers < NFS_VER2 || nfsvers > NFS_VER3) && !nqnfs) ||
(nfsvers != NQNFS_VER3 && nqnfs)) {
nd->nd_repstat = EPROGMISMATCH;
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
if (nqnfs)
nd->nd_flag = (ND_NFSV3 | ND_NQNFS);
else if (nfsvers == NFS_VER3)
nd->nd_flag = ND_NFSV3;
nd->nd_procnum = fxdr_unsigned(u_long, *tl++);
if (nd->nd_procnum == NFSPROC_NULL)
return (0);
if (nd->nd_procnum >= NFS_NPROCS ||
(!nqnfs && nd->nd_procnum > NFSPROC_STATFS) ||
(*tl != rpc_auth_unix && *tl != rpc_auth_kerb)) {
(!nqnfs && nd->nd_procnum >= NQNFSPROC_GETLEASE) ||
(!nd->nd_flag && nd->nd_procnum > NFSV2PROC_STATFS)) {
nd->nd_repstat = EPROCUNAVAIL;
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
if ((nd->nd_flag & ND_NFSV3) == 0)
nd->nd_procnum = nfsv3_procid[nd->nd_procnum];
auth_type = *tl++;
len = fxdr_unsigned(int, *tl++);
if (len < 0 || len > RPCAUTH_MAXSIZ) {
@ -1879,6 +1977,7 @@ nfs_getreq(nd, has_header)
return (EBADRPC);
}
nd->nd_flag &= ~ND_KERBAUTH;
/*
* Handle auth_unix or auth_kerb.
*/
@ -1889,7 +1988,9 @@ nfs_getreq(nd, has_header)
return (EBADRPC);
}
nfsm_adv(nfsm_rndup(len));
nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED);
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
bzero((caddr_t)&nd->nd_cr, sizeof (struct ucred));
nd->nd_cr.cr_ref = 1;
nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);
nd->nd_cr.cr_gid = fxdr_unsigned(gid_t, *tl++);
len = fxdr_unsigned(int, *tl);
@ -1897,45 +1998,124 @@ nfs_getreq(nd, has_header)
m_freem(mrep);
return (EBADRPC);
}
nfsm_dissect(tl, u_long *, (len + 2)*NFSX_UNSIGNED);
nfsm_dissect(tl, u_long *, (len + 2) * NFSX_UNSIGNED);
for (i = 1; i <= len; i++)
if (i < NGROUPS)
nd->nd_cr.cr_groups[i] = fxdr_unsigned(gid_t, *tl++);
else
tl++;
if (i < NGROUPS)
nd->nd_cr.cr_groups[i] = fxdr_unsigned(gid_t, *tl++);
else
tl++;
nd->nd_cr.cr_ngroups = (len >= NGROUPS) ? NGROUPS : (len + 1);
} else if (auth_type == rpc_auth_kerb) {
nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);
nd->nd_authlen = fxdr_unsigned(int, *tl);
uio.uio_resid = nfsm_rndup(nd->nd_authlen);
if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
if (nd->nd_cr.cr_ngroups > 1)
nfsrvw_sort(nd->nd_cr.cr_groups, nd->nd_cr.cr_ngroups);
len = fxdr_unsigned(int, *++tl);
if (len < 0 || len > RPCAUTH_MAXSIZ) {
m_freem(mrep);
return (EBADRPC);
}
uio.uio_offset = 0;
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
uio.uio_segflg = UIO_SYSSPACE;
iov.iov_base = (caddr_t)nd->nd_authstr;
iov.iov_len = RPCAUTH_MAXSIZ;
nfsm_mtouio(&uio, uio.uio_resid);
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
nd->nd_flag |= NFSD_NEEDAUTH;
}
if (len > 0)
nfsm_adv(nfsm_rndup(len));
} else if (auth_type == rpc_auth_kerb) {
switch (fxdr_unsigned(int, *tl++)) {
case RPCAKN_FULLNAME:
ticklen = fxdr_unsigned(int, *tl);
*((u_long *)nfsd->nfsd_authstr) = *tl;
uio.uio_resid = nfsm_rndup(ticklen) + NFSX_UNSIGNED;
nfsd->nfsd_authlen = uio.uio_resid + NFSX_UNSIGNED;
if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
m_freem(mrep);
return (EBADRPC);
}
uio.uio_offset = 0;
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
uio.uio_segflg = UIO_SYSSPACE;
iov.iov_base = (caddr_t)&nfsd->nfsd_authstr[4];
iov.iov_len = RPCAUTH_MAXSIZ - 4;
nfsm_mtouio(&uio, uio.uio_resid);
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
if (*tl++ != rpc_auth_kerb ||
fxdr_unsigned(int, *tl) != 4 * NFSX_UNSIGNED) {
printf("Bad kerb verifier\n");
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
nfsm_dissect(cp, caddr_t, 4 * NFSX_UNSIGNED);
tl = (u_long *)cp;
if (fxdr_unsigned(int, *tl) != RPCAKN_FULLNAME) {
printf("Not fullname kerb verifier\n");
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
cp += NFSX_UNSIGNED;
bcopy(cp, nfsd->nfsd_verfstr, 3 * NFSX_UNSIGNED);
nfsd->nfsd_verflen = 3 * NFSX_UNSIGNED;
nd->nd_flag |= ND_KERBFULL;
nfsd->nfsd_flag |= NFSD_NEEDAUTH;
break;
case RPCAKN_NICKNAME:
if (len != 2 * NFSX_UNSIGNED) {
printf("Kerb nickname short\n");
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADCRED);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
nickuid = fxdr_unsigned(uid_t, *tl);
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
if (*tl++ != rpc_auth_kerb ||
fxdr_unsigned(int, *tl) != 3 * NFSX_UNSIGNED) {
printf("Kerb nick verifier bad\n");
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
tvin.tv_sec = *tl++;
tvin.tv_usec = *tl;
/*
* Do we have any use for the verifier.
* According to the "Remote Procedure Call Protocol Spec." it
* should be AUTH_NULL, but some clients make it AUTH_UNIX?
* For now, just skip over it
*/
len = fxdr_unsigned(int, *++tl);
if (len < 0 || len > RPCAUTH_MAXSIZ) {
m_freem(mrep);
return (EBADRPC);
}
if (len > 0) {
nfsm_adv(nfsm_rndup(len));
for (nuidp = NUIDHASH(nfsd->nfsd_slp,nickuid)->lh_first;
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
if (nuidp->nu_cr.cr_uid == nickuid &&
(!nd->nd_nam2 ||
netaddr_match(NU_NETFAM(nuidp),
&nuidp->nu_haddr, nd->nd_nam2)))
break;
}
if (!nuidp) {
nd->nd_repstat =
(NFSERR_AUTHERR|AUTH_REJECTCRED);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
/*
* Now, decrypt the timestamp using the session key
* and validate it.
*/
#ifdef NFSKERB
XXX
#endif
tvout.tv_sec = fxdr_unsigned(long, tvout.tv_sec);
tvout.tv_usec = fxdr_unsigned(long, tvout.tv_usec);
if (nuidp->nu_expire < time.tv_sec ||
nuidp->nu_timestamp.tv_sec > tvout.tv_sec ||
(nuidp->nu_timestamp.tv_sec == tvout.tv_sec &&
nuidp->nu_timestamp.tv_usec > tvout.tv_usec)) {
nuidp->nu_expire = 0;
nd->nd_repstat =
(NFSERR_AUTHERR|AUTH_REJECTVERF);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
nfsrv_setcred(&nuidp->nu_cr, &nd->nd_cr);
nd->nd_flag |= ND_KERBNICK;
};
} else {
nd->nd_repstat = (NFSERR_AUTHERR | AUTH_REJECTCRED);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
/*
@ -1943,16 +2123,14 @@ nfs_getreq(nd, has_header)
*/
if (nqnfs && nd->nd_procnum != NQNFSPROC_EVICTED) {
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
nd->nd_nqlflag = fxdr_unsigned(int, *tl);
if (nd->nd_nqlflag) {
nd->nd_flag |= fxdr_unsigned(int, *tl);
if (nd->nd_flag & ND_LEASE) {
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
nd->nd_duration = fxdr_unsigned(int, *tl);
} else
nd->nd_duration = NQ_MINLEASE;
} else {
nd->nd_nqlflag = NQL_NOVAL;
} else
nd->nd_duration = NQ_MINLEASE;
}
nd->nd_md = md;
nd->nd_dpos = dpos;
return (0);
@ -1973,13 +2151,13 @@ nfsrv_wakenfsd(slp)
if ((slp->ns_flag & SLP_VALID) == 0)
return;
for (nd = nfsd_head.tqh_first; nd != 0; nd = nd->nd_chain.tqe_next) {
if (nd->nd_flag & NFSD_WAITING) {
nd->nd_flag &= ~NFSD_WAITING;
if (nd->nd_slp)
for (nd = nfsd_head.tqh_first; nd != 0; nd = nd->nfsd_chain.tqe_next) {
if (nd->nfsd_flag & NFSD_WAITING) {
nd->nfsd_flag &= ~NFSD_WAITING;
if (nd->nfsd_slp)
panic("nfsd wakeup");
slp->ns_sref++;
nd->nd_slp = slp;
nd->nfsd_slp = slp;
wakeup((caddr_t)nd);
return;
}

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_srvcache.c 8.1 (Berkeley) 6/10/93
* $Id: nfs_srvcache.c,v 1.4 1994/10/02 17:27:00 phk Exp $
* $Id: nfs_srvcache.c,v 1.5 1994/10/17 17:47:36 phk Exp $
*/
/*
@ -59,11 +59,13 @@
#endif
#include <nfs/nfsm_subs.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
#include <nfs/nfsrvcache.h>
#include <nfs/nqnfs.h>
extern struct nfsstats nfsstats;
extern int nfsv2_procid[NFS_NPROCS];
long numnfsrvcache, desirednfsrvcache = NFSRVCACHESIZ;
#define NFSRCHASH(xid) \
@ -89,15 +91,18 @@ int nonidempotent[NFS_NPROCS] = {
FALSE,
FALSE,
FALSE,
TRUE,
TRUE,
TRUE,
TRUE,
TRUE,
TRUE,
TRUE,
TRUE,
TRUE,
FALSE,
FALSE,
FALSE,
TRUE,
TRUE,
TRUE,
TRUE,
TRUE,
TRUE,
TRUE,
TRUE,
FALSE,
FALSE,
FALSE,
@ -108,7 +113,7 @@ int nonidempotent[NFS_NPROCS] = {
};
/* True iff the rpc reply is an nfs status ONLY! */
static int repliesstatus[NFS_NPROCS] = {
static int nfsv2_repstat[NFS_NPROCS] = {
FALSE,
FALSE,
FALSE,
@ -127,11 +132,6 @@ static int repliesstatus[NFS_NPROCS] = {
TRUE,
FALSE,
FALSE,
FALSE,
FALSE,
FALSE,
FALSE,
TRUE,
};
/*
@ -160,9 +160,9 @@ nfsrv_initcache()
* Update/add new request at end of lru list
*/
int
nfsrv_getcache(nam, nd, repp)
struct mbuf *nam;
register struct nfsd *nd;
nfsrv_getcache(nd, slp, repp)
register struct nfsrv_descript *nd;
struct nfssvc_sock *slp;
struct mbuf **repp;
{
register struct nfsrvcache *rp;
@ -171,13 +171,17 @@ nfsrv_getcache(nam, nd, repp)
caddr_t bpos;
int ret;
if (nd->nd_nqlflag != NQL_NOVAL)
/*
* Don't cache recent requests for reliable transport protocols.
* (Maybe we should for the case of a reconnect, but..)
*/
if (!nd->nd_nam2)
return (RC_DOIT);
loop:
for (rp = NFSRCHASH(nd->nd_retxid)->lh_first; rp != 0;
rp = rp->rc_hash.le_next) {
if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nam)) {
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) {
if ((rp->rc_flag & RC_LOCKED) != 0) {
rp->rc_flag |= RC_WANTED;
(void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
@ -196,7 +200,7 @@ nfsrv_getcache(nam, nd, repp)
ret = RC_DROPIT;
} else if (rp->rc_flag & RC_REPSTATUS) {
nfsstats.srvcache_nonidemdonehits++;
nfs_rephead(0, nd, rp->rc_status,
nfs_rephead(0, nd, slp, rp->rc_status,
0, (u_quad_t *)0, repp, &mb, &bpos);
ret = RC_REPLY;
} else if (rp->rc_flag & RC_REPMBUF) {
@ -243,7 +247,7 @@ nfsrv_getcache(nam, nd, repp)
TAILQ_INSERT_TAIL(&nfsrvlruhead, rp, rc_lru);
rp->rc_state = RC_INPROG;
rp->rc_xid = nd->nd_retxid;
saddr = mtod(nam, struct sockaddr_in *);
saddr = mtod(nd->nd_nam, struct sockaddr_in *);
switch (saddr->sin_family) {
case AF_INET:
rp->rc_flag |= RC_INETADDR;
@ -252,7 +256,7 @@ nfsrv_getcache(nam, nd, repp)
case AF_ISO:
default:
rp->rc_flag |= RC_NAM;
rp->rc_nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
rp->rc_nam = m_copym(nd->nd_nam, 0, M_COPYALL, M_WAIT);
break;
};
rp->rc_proc = nd->nd_procnum;
@ -269,21 +273,20 @@ nfsrv_getcache(nam, nd, repp)
* Update a request cache entry after the rpc has been done
*/
void
nfsrv_updatecache(nam, nd, repvalid, repmbuf)
struct mbuf *nam;
register struct nfsd *nd;
nfsrv_updatecache(nd, repvalid, repmbuf)
register struct nfsrv_descript *nd;
int repvalid;
struct mbuf *repmbuf;
{
register struct nfsrvcache *rp;
if (nd->nd_nqlflag != NQL_NOVAL)
if (!nd->nd_nam2)
return;
loop:
for (rp = NFSRCHASH(nd->nd_retxid)->lh_first; rp != 0;
rp = rp->rc_hash.le_next) {
if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nam)) {
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) {
if ((rp->rc_flag & RC_LOCKED) != 0) {
rp->rc_flag |= RC_WANTED;
(void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
@ -296,7 +299,8 @@ nfsrv_updatecache(nam, nd, repvalid, repmbuf)
* the reply for non-idempotent rpc's.
*/
if (repvalid && nonidempotent[nd->nd_procnum]) {
if (repliesstatus[nd->nd_procnum]) {
if ((nd->nd_flag & ND_NFSV3) == 0 &&
nfsv2_repstat[nfsv2_procid[nd->nd_procnum]]) {
rp->rc_status = nd->nd_repstat;
rp->rc_flag |= RC_REPSTATUS;
} else {

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_syscalls.c 8.3 (Berkeley) 1/4/94
* $Id: nfs_syscalls.c,v 1.5 1994/10/17 17:47:38 phk Exp $
* $Id: nfs_syscalls.c,v 1.6 1995/05/30 08:12:45 rgrimes Exp $
*/
#include <sys/param.h>
@ -61,9 +61,11 @@
#ifdef ISO
#include <netiso/iso.h>
#endif
#include <nfs/xdr_subs.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
#include <nfs/nfsm_subs.h>
#include <nfs/nfsrvcache.h>
#include <nfs/nfsmount.h>
#include <nfs/nfsnode.h>
@ -73,13 +75,14 @@
void nfsrv_zapsock __P((struct nfssvc_sock *));
/* Global defs. */
extern u_long nfs_prog, nfs_vers;
extern int (*nfsrv_procs[NFS_NPROCS])();
extern int (*nfsrv3_procs[NFS_NPROCS])();
extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
extern int nfs_numasync;
extern time_t nqnfsstarttime;
extern int nqsrv_writeslack;
extern int nfsrtton;
extern struct nfsstats nfsstats;
extern int nfsrvw_procrastinate;
struct nfssvc_sock *nfs_udpsock, *nfs_cltpsock;
int nuidhash_max = NFS_MAXUIDHASH;
static int nfs_numnfsd = 0;
@ -225,19 +228,25 @@ nfssvc(p, uap, retval)
if (error)
return (error);
if ((uap->flag & NFSSVC_AUTHIN) && ((nfsd = nsd->nsd_nfsd)) &&
(nfsd->nd_slp->ns_flag & SLP_VALID)) {
slp = nfsd->nd_slp;
(nfsd->nfsd_slp->ns_flag & SLP_VALID)) {
slp = nfsd->nfsd_slp;
/*
* First check to see if another nfsd has already
* added this credential.
*/
for (nuidp = NUIDHASH(slp, nsd->nsd_uid)->lh_first;
for (nuidp = NUIDHASH(slp,nsd->nsd_cr.cr_uid)->lh_first;
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
if (nuidp->nu_uid == nsd->nsd_uid)
if (nuidp->nu_cr.cr_uid == nsd->nsd_cr.cr_uid &&
(!nfsd->nfsd_nd->nd_nam2 ||
netaddr_match(NU_NETFAM(nuidp),
&nuidp->nu_haddr, nfsd->nfsd_nd->nd_nam2)))
break;
}
if (!nuidp) {
if (nuidp) {
nfsrv_setcred(&nuidp->nu_cr,&nfsd->nfsd_nd->nd_cr);
nfsd->nfsd_nd->nd_flag |= ND_KERBFULL;
} else {
/*
* Nope, so we will.
*/
@ -257,22 +266,53 @@ nfssvc(p, uap, retval)
LIST_REMOVE(nuidp, nu_hash);
TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp,
nu_lru);
if (nuidp->nu_flag & NU_NAM)
m_freem(nuidp->nu_nam);
}
nuidp->nu_flag = 0;
nuidp->nu_cr = nsd->nsd_cr;
if (nuidp->nu_cr.cr_ngroups > NGROUPS)
nuidp->nu_cr.cr_ngroups = NGROUPS;
nuidp->nu_cr.cr_ngroups = NGROUPS;
nuidp->nu_cr.cr_ref = 1;
nuidp->nu_uid = nsd->nsd_uid;
nuidp->nu_timestamp = nsd->nsd_timestamp;
nuidp->nu_expire = time.tv_sec + nsd->nsd_ttl;
/*
* and save the session key in nu_key.
*/
bcopy(nsd->nsd_key, nuidp->nu_key,
sizeof (nsd->nsd_key));
if (nfsd->nfsd_nd->nd_nam2) {
struct sockaddr_in *saddr;
saddr = mtod(nfsd->nfsd_nd->nd_nam2,
struct sockaddr_in *);
switch (saddr->sin_family) {
case AF_INET:
nuidp->nu_flag |= NU_INETADDR;
nuidp->nu_inetaddr =
saddr->sin_addr.s_addr;
break;
case AF_ISO:
default:
nuidp->nu_flag |= NU_NAM;
nuidp->nu_nam = m_copym(
nfsd->nfsd_nd->nd_nam2, 0,
M_COPYALL, M_WAIT);
break;
};
}
TAILQ_INSERT_TAIL(&slp->ns_uidlruhead, nuidp,
nu_lru);
LIST_INSERT_HEAD(NUIDHASH(slp, nsd->nsd_uid),
nuidp, nu_hash);
nfsrv_setcred(&nuidp->nu_cr,
&nfsd->nfsd_nd->nd_cr);
nfsd->nfsd_nd->nd_flag |= ND_KERBFULL;
}
}
}
if ((uap->flag & NFSSVC_AUTHINFAIL) && (nfsd = nsd->nsd_nfsd))
nfsd->nd_flag |= NFSD_AUTHFAIL;
nfsd->nfsd_flag |= NFSD_AUTHFAIL;
error = nfssvc_nfsd(nsd, uap->argp, p);
}
if (error == EINTR || error == ERESTART)
@ -353,8 +393,6 @@ nfssvc_addsock(fp, mynam)
slp = (struct nfssvc_sock *)
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
bzero((caddr_t)slp, sizeof (struct nfssvc_sock));
slp->ns_uidhashtbl =
hashinit(NUIDHASHSIZ, M_NFSSVC, &slp->ns_uidhash);
TAILQ_INIT(&slp->ns_uidlruhead);
TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain);
}
@ -381,44 +419,47 @@ nfssvc_nfsd(nsd, argp, p)
caddr_t argp;
struct proc *p;
{
register struct mbuf *m, *nam2;
register struct mbuf *m;
register int siz;
register struct nfssvc_sock *slp;
register struct socket *so;
register int *solockp;
struct nfsd *nd = nsd->nsd_nfsd;
struct mbuf *mreq, *nam;
struct timeval starttime;
struct nfsd *nfsd = nsd->nsd_nfsd;
struct nfsrv_descript *nd = NULL;
struct mbuf *mreq;
struct nfsuid *uidp;
int error = 0, cacherep, s;
int sotype;
int error = 0, cacherep, s, sotype, writes_todo;
u_quad_t cur_usec;
#ifndef nolint
cacherep = RC_DOIT;
writes_todo = 0;
#endif
s = splnet();
if (nd == (struct nfsd *)0) {
nsd->nsd_nfsd = nd = (struct nfsd *)
if (nfsd == (struct nfsd *)0) {
nsd->nsd_nfsd = nfsd = (struct nfsd *)
malloc(sizeof (struct nfsd), M_NFSD, M_WAITOK);
bzero((caddr_t)nd, sizeof (struct nfsd));
nd->nd_procp = p;
nd->nd_cr.cr_ref = 1;
TAILQ_INSERT_TAIL(&nfsd_head, nd, nd_chain);
nd->nd_nqlflag = NQL_NOVAL;
bzero((caddr_t)nfsd, sizeof (struct nfsd));
nfsd->nfsd_procp = p;
TAILQ_INSERT_TAIL(&nfsd_head, nfsd, nfsd_chain);
nfs_numnfsd++;
}
/*
* Loop getting rpc requests until SIGKILL.
*/
for (;;) {
if ((nd->nd_flag & NFSD_REQINPROG) == 0) {
while (nd->nd_slp == (struct nfssvc_sock *)0 &&
if ((nfsd->nfsd_flag & NFSD_REQINPROG) == 0) {
while (nfsd->nfsd_slp == (struct nfssvc_sock *)0 &&
(nfsd_head_flag & NFSD_CHECKSLP) == 0) {
nd->nd_flag |= NFSD_WAITING;
nfsd->nfsd_flag |= NFSD_WAITING;
nfsd_waiting++;
error = tsleep((caddr_t)nd, PSOCK | PCATCH, "nfsd", 0);
error = tsleep((caddr_t)nfsd, PSOCK | PCATCH,
"nfsd", 0);
nfsd_waiting--;
if (error)
goto done;
}
if (nd->nd_slp == (struct nfssvc_sock *)0 &&
if (nfsd->nfsd_slp == (struct nfssvc_sock *)0 &&
(nfsd_head_flag & NFSD_CHECKSLP) != 0) {
for (slp = nfssvc_sockhead.tqh_first; slp != 0;
slp = slp->ns_chain.tqe_next) {
@ -426,14 +467,14 @@ nfssvc_nfsd(nsd, argp, p)
== (SLP_VALID | SLP_DOREC)) {
slp->ns_flag &= ~SLP_DOREC;
slp->ns_sref++;
nd->nd_slp = slp;
nfsd->nfsd_slp = slp;
break;
}
}
if (slp == 0)
nfsd_head_flag &= ~NFSD_CHECKSLP;
}
if ((slp = nd->nd_slp) == (struct nfssvc_sock *)0)
if ((slp = nfsd->nfsd_slp) == (struct nfssvc_sock *)0)
continue;
if (slp->ns_flag & SLP_VALID) {
if (slp->ns_flag & SLP_DISCONN)
@ -446,86 +487,78 @@ nfssvc_nfsd(nsd, argp, p)
M_WAIT);
nfs_sndunlock(&slp->ns_solock);
}
error = nfsrv_dorec(slp, nd);
nd->nd_flag |= NFSD_REQINPROG;
error = nfsrv_dorec(slp, nfsd, &nd);
cur_usec = (u_quad_t)time.tv_sec * 1000000 +
(u_quad_t)time.tv_usec;
if (error && slp->ns_tq.lh_first &&
slp->ns_tq.lh_first->nd_time <= cur_usec) {
error = 0;
cacherep = RC_DOIT;
writes_todo = 1;
} else
writes_todo = 0;
nfsd->nfsd_flag |= NFSD_REQINPROG;
}
} else {
error = 0;
slp = nd->nd_slp;
slp = nfsd->nfsd_slp;
}
if (error || (slp->ns_flag & SLP_VALID) == 0) {
nd->nd_slp = (struct nfssvc_sock *)0;
nd->nd_flag &= ~NFSD_REQINPROG;
if (nd) {
free((caddr_t)nd, M_NFSRVDESC);
nd = NULL;
}
nfsd->nfsd_slp = (struct nfssvc_sock *)0;
nfsd->nfsd_flag &= ~NFSD_REQINPROG;
nfsrv_slpderef(slp);
continue;
}
splx(s);
so = slp->ns_so;
sotype = so->so_type;
starttime = time;
if (so->so_proto->pr_flags & PR_CONNREQUIRED)
solockp = &slp->ns_solock;
else
solockp = (int *)0;
/*
* nam == nam2 for connectionless protocols such as UDP
* nam2 == NULL for connection based protocols to disable
* recent request caching.
*/
nam2 = nd->nd_nam;
if (nam2) {
nam = nam2;
cacherep = RC_CHECKIT;
} else {
nam = slp->ns_nam;
cacherep = RC_DOIT;
}
if (nd) {
nd->nd_starttime = time;
if (nd->nd_nam2)
nd->nd_nam = nd->nd_nam2;
else
nd->nd_nam = slp->ns_nam;
/*
* Check to see if authorization is needed.
*/
if (nd->nd_flag & NFSD_NEEDAUTH) {
static int logauth = 0;
/*
* Check to see if authorization is needed.
*/
if (nfsd->nfsd_flag & NFSD_NEEDAUTH) {
nfsd->nfsd_flag &= ~NFSD_NEEDAUTH;
nsd->nsd_haddr = mtod(nd->nd_nam,
struct sockaddr_in *)->sin_addr.s_addr;
nsd->nsd_authlen = nfsd->nfsd_authlen;
nsd->nsd_verflen = nfsd->nfsd_verflen;
if (!copyout(nfsd->nfsd_authstr,nsd->nsd_authstr,
nfsd->nfsd_authlen) &&
!copyout(nfsd->nfsd_verfstr, nsd->nsd_verfstr,
nfsd->nfsd_verflen) &&
!copyout((caddr_t)nsd, argp, sizeof (*nsd)))
return (ENEEDAUTH);
cacherep = RC_DROPIT;
} else
cacherep = nfsrv_getcache(nd, slp, &mreq);
nd->nd_flag &= ~NFSD_NEEDAUTH;
/*
* Check for a mapping already installed.
*/
for (uidp = NUIDHASH(slp, nd->nd_cr.cr_uid)->lh_first;
uidp != 0; uidp = uidp->nu_hash.le_next) {
if (uidp->nu_uid == nd->nd_cr.cr_uid)
break;
}
if (!uidp) {
nsd->nsd_uid = nd->nd_cr.cr_uid;
if (nam2 && logauth++ == 0)
log(LOG_WARNING, "Kerberized NFS using UDP\n");
nsd->nsd_haddr =
mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
nsd->nsd_authlen = nd->nd_authlen;
if (copyout(nd->nd_authstr, nsd->nsd_authstr,
nd->nd_authlen) == 0 &&
copyout((caddr_t)nsd, argp, sizeof (*nsd)) == 0)
return (ENEEDAUTH);
cacherep = RC_DROPIT;
}
}
if (cacherep == RC_CHECKIT)
cacherep = nfsrv_getcache(nam2, nd, &mreq);
/*
* Check for just starting up for NQNFS and send
* fake "try again later" replies to the NQNFS clients.
*/
if (notstarted && nqnfsstarttime <= time.tv_sec) {
/*
* Check for just starting up for NQNFS and send
* fake "try again later" replies to the NQNFS clients.
*/
if (notstarted && nqnfsstarttime <= time.tv_sec) {
if (modify_flag) {
nqnfsstarttime = time.tv_sec + nqsrv_writeslack;
modify_flag = 0;
} else
notstarted = 0;
}
if (notstarted) {
if (nd->nd_nqlflag == NQL_NOVAL)
}
if (notstarted) {
if ((nd->nd_flag & ND_NQNFS) == 0)
cacherep = RC_DROPIT;
else if (nd->nd_procnum != NFSPROC_WRITE) {
nd->nd_procnum = NFSPROC_NOOP;
@ -533,36 +566,42 @@ nfssvc_nfsd(nsd, argp, p)
cacherep = RC_DOIT;
} else
modify_flag = 1;
} else if (nd->nd_flag & NFSD_AUTHFAIL) {
nd->nd_flag &= ~NFSD_AUTHFAIL;
} else if (nfsd->nfsd_flag & NFSD_AUTHFAIL) {
nfsd->nfsd_flag &= ~NFSD_AUTHFAIL;
nd->nd_procnum = NFSPROC_NOOP;
nd->nd_repstat = NQNFS_AUTHERR;
nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK);
cacherep = RC_DOIT;
}
}
switch (cacherep) {
case RC_DOIT:
error = (*(nfsrv_procs[nd->nd_procnum]))(nd,
nd->nd_mrep, nd->nd_md, nd->nd_dpos, &nd->nd_cr,
nam, &mreq);
if (nd->nd_cr.cr_ref != 1) {
printf("nfssvc cref=%d\n", nd->nd_cr.cr_ref);
panic("nfssvc cref");
}
/*
* Loop to get all the write rpc relies that have been
* gathered together.
*/
do {
switch (cacherep) {
case RC_DOIT:
if (writes_todo || (nd->nd_procnum == NFSPROC_WRITE &&
nfsrvw_procrastinate > 0 && !notstarted))
error = nfsrv_writegather(&nd, slp,
nfsd->nfsd_procp, &mreq);
else
error = (*(nfsrv3_procs[nd->nd_procnum]))(nd,
slp, nfsd->nfsd_procp, &mreq);
if (mreq == NULL)
break;
if (error) {
if (nd->nd_procnum != NQNFSPROC_VACATED)
nfsstats.srv_errs++;
if (nam2) {
nfsrv_updatecache(nam2, nd, FALSE, mreq);
m_freem(nam2);
}
nfsrv_updatecache(nd, FALSE, mreq);
if (nd->nd_nam2)
m_freem(nd->nd_nam2);
break;
}
nfsstats.srvrpccnt[nd->nd_procnum]++;
if (nam2)
nfsrv_updatecache(nam2, nd, TRUE, mreq);
nfsrv_updatecache(nd, TRUE, mreq);
nd->nd_mrep = (struct mbuf *)0;
case RC_REPLY:
case RC_REPLY:
m = mreq;
siz = 0;
while (m) {
@ -587,15 +626,15 @@ nfssvc_nfsd(nsd, argp, p)
if (solockp)
(void) nfs_sndlock(solockp, (struct nfsreq *)0);
if (slp->ns_flag & SLP_VALID)
error = nfs_send(so, nam2, m, (struct nfsreq *)0);
error = nfs_send(so, nd->nd_nam2, m, NULL);
else {
error = EPIPE;
m_freem(m);
}
if (nfsrtton)
nfsd_rt(&starttime, sotype, nd, nam, cacherep);
if (nam2)
MFREE(nam2, m);
nfsd_rt(sotype, nd, cacherep);
if (nd->nd_nam2)
MFREE(nd->nd_nam2, m);
if (nd->nd_mrep)
m_freem(nd->nd_mrep);
if (error == EPIPE)
@ -603,29 +642,50 @@ nfssvc_nfsd(nsd, argp, p)
if (solockp)
nfs_sndunlock(solockp);
if (error == EINTR || error == ERESTART) {
free((caddr_t)nd, M_NFSRVDESC);
nfsrv_slpderef(slp);
s = splnet();
goto done;
}
break;
case RC_DROPIT:
case RC_DROPIT:
if (nfsrtton)
nfsd_rt(&starttime, sotype, nd, nam, cacherep);
nfsd_rt(sotype, nd, cacherep);
m_freem(nd->nd_mrep);
m_freem(nam2);
m_freem(nd->nd_nam2);
break;
};
};
if (nd) {
FREE((caddr_t)nd, M_NFSRVDESC);
nd = NULL;
}
/*
* Check to see if there are outstanding writes that
* need to be serviced.
*/
cur_usec = (u_quad_t)time.tv_sec * 1000000 +
(u_quad_t)time.tv_usec;
s = splsoftclock();
if (slp->ns_tq.lh_first &&
slp->ns_tq.lh_first->nd_time <= cur_usec) {
cacherep = RC_DOIT;
writes_todo = 1;
} else
writes_todo = 0;
splx(s);
} while (writes_todo);
s = splnet();
if (nfsrv_dorec(slp, nd)) {
nd->nd_flag &= ~NFSD_REQINPROG;
nd->nd_slp = (struct nfssvc_sock *)0;
if (nfsrv_dorec(slp, nfsd, &nd)) {
nfsd->nfsd_flag &= ~NFSD_REQINPROG;
nfsd->nfsd_slp = NULL;
nfsrv_slpderef(slp);
}
}
done:
TAILQ_REMOVE(&nfsd_head, nd, nd_chain);
TAILQ_REMOVE(&nfsd_head, nfsd, nfsd_chain);
splx(s);
free((caddr_t)nd, M_NFSD);
free((caddr_t)nfsd, M_NFSD);
nsd->nsd_nfsd = (struct nfsd *)0;
if (--nfs_numnfsd == 0)
nfsrv_init(TRUE); /* Reinitialize everything */
@ -641,9 +701,10 @@ int
nfssvc_iod(p)
struct proc *p;
{
register struct buf *bp;
register struct buf *bp, *nbp;
register int i, myiod;
int error = 0;
struct vnode *vp;
int error = 0, s;
/*
* Assign my position or return error if too many already running
@ -662,24 +723,53 @@ nfssvc_iod(p)
* Just loop around doin our stuff until SIGKILL
*/
for (;;) {
while (nfs_bufq.tqh_first == NULL && error == 0) {
nfs_iodwant[myiod] = p;
error = tsleep((caddr_t)&nfs_iodwant[myiod],
PWAIT | PCATCH, "nfsidl", 0);
}
while ((bp = nfs_bufq.tqh_first) != NULL) {
/* Take one off the front of the list */
TAILQ_REMOVE(&nfs_bufq, bp, b_freelist);
if (bp->b_flags & B_READ)
(void) nfs_doio(bp, bp->b_rcred, (struct proc *)0);
else
(void) nfs_doio(bp, bp->b_wcred, (struct proc *)0);
}
if (error) {
nfs_asyncdaemon[myiod] = 0;
nfs_numasync--;
return (error);
}
while (nfs_bufq.tqh_first == NULL && error == 0) {
nfs_iodwant[myiod] = p;
error = tsleep((caddr_t)&nfs_iodwant[myiod],
PWAIT | PCATCH, "nfsidl", 0);
}
while ((bp = nfs_bufq.tqh_first) != NULL) {
/* Take one off the front of the list */
TAILQ_REMOVE(&nfs_bufq, bp, b_freelist);
if (bp->b_flags & B_READ)
(void) nfs_doio(bp, bp->b_rcred, (struct proc *)0);
else do {
/*
* Look for a delayed write for the same vnode, so I can do
* it now. We must grab it before calling nfs_doio() to
* avoid any risk of the vnode getting vclean()'d while
* we are doing the write rpc.
*/
vp = bp->b_vp;
s = splbio();
for (nbp = vp->v_dirtyblkhd.lh_first; nbp;
nbp = nbp->b_vnbufs.le_next) {
if ((nbp->b_flags &
(B_BUSY|B_DELWRI|B_NEEDCOMMIT|B_NOCACHE))!=B_DELWRI)
continue;
bremfree(nbp);
vfs_busy_pages(nbp, 1);
nbp->b_flags |= (B_BUSY|B_ASYNC);
break;
}
splx(s);
/*
* For the delayed write, do the first part of nfs_bwrite()
* up to, but not including nfs_strategy().
*/
if (nbp) {
nbp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI);
reassignbuf(nbp, nbp->b_vp);
nbp->b_vp->v_numoutput++;
}
(void) nfs_doio(bp, bp->b_wcred, (struct proc *)0);
} while (bp = nbp);
}
if (error) {
nfs_asyncdaemon[myiod] = 0;
nfs_numasync--;
return (error);
}
}
}
@ -695,9 +785,11 @@ nfsrv_zapsock(slp)
register struct nfssvc_sock *slp;
{
register struct nfsuid *nuidp, *nnuidp;
register struct nfsrv_descript *nwp, *nnwp;
struct socket *so;
struct file *fp;
struct mbuf *m;
int s;
slp->ns_flag &= ~SLP_ALLFLAGS;
fp = slp->ns_fp;
@ -716,8 +808,18 @@ nfsrv_zapsock(slp)
nnuidp = nuidp->nu_lru.tqe_next;
LIST_REMOVE(nuidp, nu_hash);
TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp, nu_lru);
if (nuidp->nu_flag & NU_NAM)
m_freem(nuidp->nu_nam);
free((caddr_t)nuidp, M_NFSUID);
}
s = splsoftclock();
for (nwp = slp->ns_tq.lh_first; nwp; nwp = nnwp) {
nnwp = nwp->nd_tq.le_next;
LIST_REMOVE(nwp, nd_tq);
free((caddr_t)nwp, M_NFSRVDESC);
}
LIST_INIT(&slp->ns_tq);
splx(s);
}
}
@ -726,13 +828,15 @@ nfsrv_zapsock(slp)
* on this mount point porpous out of the kernel and do it.
*/
int
nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
nfs_getauth(nmp, rep, cred, auth_str, auth_len, verf_str, verf_len, key)
register struct nfsmount *nmp;
struct nfsreq *rep;
struct ucred *cred;
int *auth_type;
char **auth_str;
int *auth_len;
char *verf_str;
int *verf_len;
NFSKERBKEY_T key; /* return session key */
{
int error = 0;
@ -748,6 +852,9 @@ nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
}
nmp->nm_flag &= ~(NFSMNT_WAITAUTH | NFSMNT_WANTAUTH);
nmp->nm_authstr = *auth_str = (char *)malloc(RPCAUTH_MAXSIZ, M_TEMP, M_WAITOK);
nmp->nm_authlen = RPCAUTH_MAXSIZ;
nmp->nm_verfstr = verf_str;
nmp->nm_verflen = *verf_len;
nmp->nm_authuid = cred->cr_uid;
wakeup((caddr_t)&nmp->nm_authstr);
@ -766,8 +873,9 @@ nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
if (error)
free((caddr_t)*auth_str, M_TEMP);
else {
*auth_type = nmp->nm_authtype;
*auth_len = nmp->nm_authlen;
*verf_len = nmp->nm_verflen;
bcopy((caddr_t)nmp->nm_key, (caddr_t)key, sizeof (key));
}
nmp->nm_flag &= ~NFSMNT_HASAUTH;
nmp->nm_flag |= NFSMNT_WAITAUTH;
@ -778,6 +886,149 @@ nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
return (error);
}
/*
* Get a nickname authenticator and verifier.
*/
int
nfs_getnickauth(nmp, cred, auth_str, auth_len, verf_str, verf_len)
struct nfsmount *nmp;
struct ucred *cred;
char **auth_str;
int *auth_len;
char *verf_str;
int verf_len;
{
register struct nfsuid *nuidp;
register u_long *nickp, *verfp;
struct timeval ktvin, ktvout;
NFSKERBKEYSCHED_T keys; /* stores key schedule */
#ifdef DIAGNOSTIC
if (verf_len < (4 * NFSX_UNSIGNED))
panic("nfs_getnickauth verf too small");
#endif
for (nuidp = NMUIDHASH(nmp, cred->cr_uid)->lh_first;
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
if (nuidp->nu_cr.cr_uid == cred->cr_uid)
break;
}
if (!nuidp || nuidp->nu_expire < time.tv_sec)
return (EACCES);
/*
* Move to the end of the lru list (end of lru == most recently used).
*/
TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp, nu_lru);
TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp, nu_lru);
nickp = (u_long *)malloc(2 * NFSX_UNSIGNED, M_TEMP, M_WAITOK);
*nickp++ = txdr_unsigned(RPCAKN_NICKNAME);
*nickp = txdr_unsigned(nuidp->nu_nickname);
*auth_str = (char *)nickp;
*auth_len = 2 * NFSX_UNSIGNED;
/*
* Now we must encrypt the verifier and package it up.
*/
verfp = (u_long *)verf_str;
*verfp++ = txdr_unsigned(RPCAKN_NICKNAME);
if (time.tv_sec > nuidp->nu_timestamp.tv_sec ||
(time.tv_sec == nuidp->nu_timestamp.tv_sec &&
time.tv_usec > nuidp->nu_timestamp.tv_usec))
nuidp->nu_timestamp = time;
else
nuidp->nu_timestamp.tv_usec++;
ktvin.tv_sec = txdr_unsigned(nuidp->nu_timestamp.tv_sec);
ktvin.tv_usec = txdr_unsigned(nuidp->nu_timestamp.tv_usec);
/*
* Now encrypt the timestamp verifier in ecb mode using the session
* key.
*/
#ifdef NFSKERB
XXX
#endif
*verfp++ = ktvout.tv_sec;
*verfp++ = ktvout.tv_usec;
*verfp = 0;
return (0);
}
/*
* Save the current nickname in a hash list entry on the mount point.
*/
int
nfs_savenickauth(nmp, cred, len, key, mdp, dposp, mrep)
register struct nfsmount *nmp;
struct ucred *cred;
int len;
NFSKERBKEY_T key;
struct mbuf **mdp;
char **dposp;
struct mbuf *mrep;
{
register struct nfsuid *nuidp;
register u_long *tl;
register long t1;
struct mbuf *md = *mdp;
struct timeval ktvin, ktvout;
u_long nick;
NFSKERBKEYSCHED_T keys;
char *dpos = *dposp, *cp2;
int deltasec, error = 0;
if (len == (3 * NFSX_UNSIGNED)) {
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
ktvin.tv_sec = *tl++;
ktvin.tv_usec = *tl++;
nick = fxdr_unsigned(u_long, *tl);
/*
* Decrypt the timestamp in ecb mode.
*/
#ifdef NFSKERB
XXX
#endif
ktvout.tv_sec = fxdr_unsigned(long, ktvout.tv_sec);
ktvout.tv_usec = fxdr_unsigned(long, ktvout.tv_usec);
deltasec = time.tv_sec - ktvout.tv_sec;
if (deltasec < 0)
deltasec = -deltasec;
/*
* If ok, add it to the hash list for the mount point.
*/
if (deltasec <= NFS_KERBCLOCKSKEW) {
if (nmp->nm_numuids < nuidhash_max) {
nmp->nm_numuids++;
nuidp = (struct nfsuid *)
malloc(sizeof (struct nfsuid), M_NFSUID,
M_WAITOK);
} else {
nuidp = nmp->nm_uidlruhead.tqh_first;
LIST_REMOVE(nuidp, nu_hash);
TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp,
nu_lru);
}
nuidp->nu_flag = 0;
nuidp->nu_cr.cr_uid = cred->cr_uid;
nuidp->nu_expire = time.tv_sec + NFS_KERBTTL;
nuidp->nu_timestamp = ktvout;
nuidp->nu_nickname = nick;
bcopy(key, nuidp->nu_key, sizeof (key));
TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp,
nu_lru);
LIST_INSERT_HEAD(NMUIDHASH(nmp, cred->cr_uid),
nuidp, nu_hash);
}
} else
nfsm_adv(nfsm_rndup(len));
nfsmout:
*mdp = md;
*dposp = dpos;
return (error);
}
/*
* Derefence a server socket structure. If it has no more references and
* is no longer valid, you can throw it away.
@ -830,16 +1081,12 @@ nfsrv_init(terminating)
nfs_udpsock = (struct nfssvc_sock *)
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
bzero((caddr_t)nfs_udpsock, sizeof (struct nfssvc_sock));
nfs_udpsock->ns_uidhashtbl =
hashinit(NUIDHASHSIZ, M_NFSSVC, &nfs_udpsock->ns_uidhash);
TAILQ_INIT(&nfs_udpsock->ns_uidlruhead);
TAILQ_INSERT_HEAD(&nfssvc_sockhead, nfs_udpsock, ns_chain);
nfs_cltpsock = (struct nfssvc_sock *)
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
bzero((caddr_t)nfs_cltpsock, sizeof (struct nfssvc_sock));
nfs_cltpsock->ns_uidhashtbl =
hashinit(NUIDHASHSIZ, M_NFSSVC, &nfs_cltpsock->ns_uidhash);
TAILQ_INIT(&nfs_cltpsock->ns_uidlruhead);
TAILQ_INSERT_TAIL(&nfssvc_sockhead, nfs_cltpsock, ns_chain);
}
@ -848,11 +1095,9 @@ nfsrv_init(terminating)
* Add entries to the server monitor log.
*/
static void
nfsd_rt(startp, sotype, nd, nam, cacherep)
struct timeval *startp;
nfsd_rt(sotype, nd, cacherep)
int sotype;
register struct nfsd *nd;
struct mbuf *nam;
register struct nfsrv_descript *nd;
int cacherep;
{
register struct drt *rt;
@ -866,15 +1111,17 @@ nfsd_rt(startp, sotype, nd, nam, cacherep)
rt->flag = DRT_CACHEDROP;
if (sotype == SOCK_STREAM)
rt->flag |= DRT_TCP;
if (nd->nd_nqlflag != NQL_NOVAL)
if (nd->nd_flag & ND_NQNFS)
rt->flag |= DRT_NQNFS;
else if (nd->nd_flag & ND_NFSV3)
rt->flag |= DRT_NFSV3;
rt->proc = nd->nd_procnum;
if (mtod(nam, struct sockaddr *)->sa_family == AF_INET)
rt->ipadr = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
if (mtod(nd->nd_nam, struct sockaddr *)->sa_family == AF_INET)
rt->ipadr = mtod(nd->nd_nam, struct sockaddr_in *)->sin_addr.s_addr;
else
rt->ipadr = INADDR_ANY;
rt->resptime = ((time.tv_sec - startp->tv_sec) * 1000000) +
(time.tv_usec - startp->tv_usec);
rt->ipadr = INADDR_ANY;
rt->resptime = ((time.tv_sec - nd->nd_starttime.tv_sec) * 1000000) +
(time.tv_usec - nd->nd_starttime.tv_usec);
rt->tstamp = time;
nfsdrt.pos = (nfsdrt.pos + 1) % NFSRTTLOGSIZ;
}

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_vfsops.c 8.3 (Berkeley) 1/4/94
* $Id: nfs_vfsops.c,v 1.14.2.1 1995/06/02 11:13:15 davidg Exp $
* $Id: nfs_vfsops.c,v 1.15 1995/06/11 19:31:46 rgrimes Exp $
*/
#include <sys/param.h>
@ -59,10 +59,10 @@
#include <netinet/in.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfsnode.h>
#include <nfs/nfsmount.h>
#include <nfs/nfs.h>
#include <nfs/nfsmount.h>
#include <nfs/xdr_subs.h>
#include <nfs/nfsm_subs.h>
#include <nfs/nfsdiskless.h>
@ -71,11 +71,15 @@
struct nfsstats nfsstats;
static int nfs_sysctl(int *, u_int, void *, size_t *, void *, size_t,
struct proc *);
extern int nfs_ticks;
/*
* nfs vfs operations.
*/
struct vfsops nfs_vfsops = {
#ifdef __NetBSD__
MOUNT_NFS,
#endif
nfs_mount,
nfs_start,
nfs_unmount,
@ -87,9 +91,13 @@ struct vfsops nfs_vfsops = {
nfs_fhtovp,
nfs_vptofh,
nfs_init,
#ifdef __FreeBSD__
nfs_sysctl
#endif
};
#ifdef __FreeBSD__
VFS_SET(nfs_vfsops, nfs, MOUNT_NFS, VFCF_NETWORK);
#endif
/*
* This structure must be filled in by a primary bootstrap or bootstrap
@ -99,16 +107,11 @@ VFS_SET(nfs_vfsops, nfs, MOUNT_NFS, VFCF_NETWORK);
struct nfs_diskless nfs_diskless = { 0 };
int nfs_diskless_valid = 0;
extern u_long nfs_procids[NFS_NPROCS];
extern u_long nfs_prog, nfs_vers;
void nfs_disconnect __P((struct nfsmount *));
void nfsargs_ntoh __P((struct nfs_args *));
static struct mount *nfs_mountdiskless __P((char *, char *, int,
struct sockaddr_in *, struct nfs_args *, register struct vnode **));
#define TRUE 1
#define FALSE 0
/*
* nfs statfs call
*/
@ -119,40 +122,65 @@ nfs_statfs(mp, sbp, p)
struct proc *p;
{
register struct vnode *vp;
register struct nfsv2_statfs *sfp;
register struct nfs_statfs *sfp;
register caddr_t cp;
register long t1;
register u_long *tl;
register long t1, t2;
caddr_t bpos, dpos, cp2;
int error = 0, isnq;
struct nfsmount *nmp = VFSTONFS(mp);
int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
struct mbuf *mreq, *mrep, *md, *mb, *mb2;
struct nfsmount *nmp;
struct ucred *cred;
struct nfsnode *np;
u_quad_t tquad;
nmp = VFSTONFS(mp);
isnq = (nmp->nm_flag & NFSMNT_NQNFS);
error = nfs_nget(mp, &nmp->nm_fh, &np);
#ifndef nolint
sfp = (struct nfs_statfs *)0;
#endif
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
if (error)
return (error);
vp = NFSTOV(np);
nfsstats.rpccnt[NFSPROC_STATFS]++;
cred = crget();
cred->cr_ngroups = 1;
nfsm_reqhead(vp, NFSPROC_STATFS, NFSX_FH);
nfsm_fhtom(vp);
nfsm_request(vp, NFSPROC_STATFS, p, cred);
nfsm_dissect(sfp, struct nfsv2_statfs *, NFSX_STATFS(isnq));
if (v3 && (nmp->nm_flag & NFSMNT_GOTFSINFO) == 0)
(void)nfs_fsinfo(nmp, vp, cred, p);
nfsstats.rpccnt[NFSPROC_FSSTAT]++;
nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3));
nfsm_fhtom(vp, v3);
nfsm_request(vp, NFSPROC_FSSTAT, p, cred);
if (v3)
nfsm_postop_attr(vp, retattr);
if (!error)
nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
#ifdef __NetBSD__
#ifdef COMPAT_09
sbp->f_type = 2;
#else
sbp->f_type = 0;
#endif
#else
sbp->f_type = MOUNT_NFS;
#endif
sbp->f_flags = nmp->nm_flag;
sbp->f_iosize = NFS_MAXDGRAMDATA;
sbp->f_bsize = fxdr_unsigned(long, sfp->sf_bsize);
sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks);
sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree);
sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail);
if (isnq) {
sbp->f_files = fxdr_unsigned(long, sfp->sf_files);
sbp->f_ffree = fxdr_unsigned(long, sfp->sf_ffree);
sbp->f_iosize = min(nmp->nm_rsize, nmp->nm_wsize);
if (v3) {
sbp->f_bsize = NFS_FABLKSIZE;
fxdr_hyper(&sfp->sf_tbytes, &tquad);
sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
fxdr_hyper(&sfp->sf_fbytes, &tquad);
sbp->f_bfree = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
fxdr_hyper(&sfp->sf_abytes, &tquad);
sbp->f_bavail = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
sbp->f_files = (fxdr_unsigned(long, sfp->sf_tfiles.nfsuquad[1])
& 0x7fffffff);
sbp->f_ffree = (fxdr_unsigned(long, sfp->sf_ffiles.nfsuquad[1])
& 0x7fffffff);
} else {
sbp->f_bsize = fxdr_unsigned(long, sfp->sf_bsize);
sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks);
sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree);
sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail);
sbp->f_files = 0;
sbp->f_ffree = 0;
}
@ -161,11 +189,71 @@ nfs_statfs(mp, sbp, p)
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
}
nfsm_reqdone;
vrele(vp);
vput(vp);
crfree(cred);
return (error);
}
/*
* nfs version 3 fsinfo rpc call
*/
int
nfs_fsinfo(nmp, vp, cred, p)
register struct nfsmount *nmp;
register struct vnode *vp;
struct ucred *cred;
struct proc *p;
{
register struct nfsv3_fsinfo *fsp;
register caddr_t cp;
register long t1, t2;
register u_long *tl, pref, max;
caddr_t bpos, dpos, cp2;
int error = 0, retattr;
struct mbuf *mreq, *mrep, *md, *mb, *mb2;
nfsstats.rpccnt[NFSPROC_FSINFO]++;
nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
nfsm_fhtom(vp, 1);
nfsm_request(vp, NFSPROC_FSINFO, p, cred);
nfsm_postop_attr(vp, retattr);
if (!error) {
nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
pref = fxdr_unsigned(u_long, fsp->fs_wtpref);
if (pref < nmp->nm_wsize)
nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
~(NFS_FABLKSIZE - 1);
max = fxdr_unsigned(u_long, fsp->fs_wtmax);
if (max < nmp->nm_wsize) {
nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
if (nmp->nm_wsize == 0)
nmp->nm_wsize = max;
}
pref = fxdr_unsigned(u_long, fsp->fs_rtpref);
if (pref < nmp->nm_rsize)
nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
~(NFS_FABLKSIZE - 1);
max = fxdr_unsigned(u_long, fsp->fs_rtmax);
if (max < nmp->nm_rsize) {
nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
if (nmp->nm_rsize == 0)
nmp->nm_rsize = max;
}
pref = fxdr_unsigned(u_long, fsp->fs_dtpref);
if (pref < nmp->nm_readdirsize)
nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) &
~(NFS_DIRBLKSIZ - 1);
if (max < nmp->nm_readdirsize) {
nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
if (nmp->nm_readdirsize == 0)
nmp->nm_readdirsize = max;
}
nmp->nm_flag |= NFSMNT_GOTFSINFO;
}
nfsm_reqdone;
return (error);
}
/*
* Mount a remote root fs via. nfs. This depends on the info in the
* nfs_diskless structure that has been filled in properly by some primary
@ -268,7 +356,12 @@ nfs_mountroot()
* Create a fake mount point just for the swap vnode so that the
* swap file can be on a different server from the rootfs.
*/
nd->swap_args.fh = (nfsv2fh_t *)nd->swap_fh;
nd->swap_args.fh = nd->swap_fh;
/*
* If using nfsv3_diskless, replace NFSX_V2FH with
* nd->swap_fhsize.
*/
nd->swap_args.fhsize = NFSX_V2FH;
l = ntohl(nd->swap_saddr.sin_addr.s_addr);
sprintf(buf,"%ld.%ld.%ld.%ld:%s",
(l >> 24) & 0xff, (l >> 16) & 0xff,
@ -293,8 +386,12 @@ nfs_mountroot()
/*
* Create the rootfs mount point.
*/
nd->root_args.fh = (nfsv2fh_t *)nd->root_fh;
l = ntohl(nd->root_saddr.sin_addr.s_addr);
nd->root_args.fh = nd->root_fh;
/*
* If using nfsv3_diskless, replace NFSX_V2FH with nd->root_fhsize.
*/
nd->root_args.fhsize = NFSX_V2FH;
l = ntohl(nd->swap_saddr.sin_addr.s_addr);
sprintf(buf,"%ld.%ld.%ld.%ld:%s",
(l >> 24) & 0xff, (l >> 16) & 0xff,
(l >> 8) & 0xff, (l >> 0) & 0xff,nd->root_hostnam);
@ -304,7 +401,11 @@ nfs_mountroot()
if (vfs_lock(mp))
panic("nfs_mountroot: vfs_lock");
#if NetBSD >= 1994101
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
#else
TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
#endif
mp->mnt_flag |= MNT_ROOTFS;
mp->mnt_vnodecovered = NULLVP;
vfs_unlock(mp);
@ -386,12 +487,12 @@ nfs_mount(mp, path, data, ndp, p)
struct vnode *vp;
char pth[MNAMELEN], hst[MNAMELEN];
u_int len;
nfsv2fh_t nfh;
u_char nfh[NFSX_V3FHMAX];
error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
if (error)
return (error);
error = copyin((caddr_t)args.fh, (caddr_t)&nfh, sizeof (nfsv2fh_t));
error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
if (error)
return (error);
error = copyinstr(path, pth, MNAMELEN-1, &len);
@ -406,7 +507,7 @@ nfs_mount(mp, path, data, ndp, p)
error = sockargs(&nam, (caddr_t)args.addr, args.addrlen, MT_SONAME);
if (error)
return (error);
args.fh = &nfh;
args.fh = nfh;
error = mountnfs(&args, mp, nam, pth, hst, &vp);
return (error);
}
@ -424,7 +525,7 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
{
register struct nfsmount *nmp;
struct nfsnode *np;
int error;
int error, maxio;
if (mp->mnt_flag & MNT_UPDATE) {
nmp = VFSTONFS(mp);
@ -435,16 +536,12 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount),
M_NFSMNT, M_WAITOK);
bzero((caddr_t)nmp, sizeof (struct nfsmount));
TAILQ_INIT(&nmp->nm_uidlruhead);
mp->mnt_data = (qaddr_t)nmp;
}
getnewfsid(mp, MOUNT_NFS);
nmp->nm_mountp = mp;
nmp->nm_flag = argp->flags;
if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_MYWRITE)) ==
(NFSMNT_NQNFS | NFSMNT_MYWRITE)) {
error = EPERM;
goto bad;
}
if (nmp->nm_flag & NFSMNT_NQNFS)
/*
* We have to set mnt_maxsymlink to a non-zero value so
@ -457,14 +554,24 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
nmp->nm_retry = NFS_RETRANS;
nmp->nm_wsize = NFS_WSIZE;
nmp->nm_rsize = NFS_RSIZE;
nmp->nm_readdirsize = NFS_READDIRSIZE;
nmp->nm_numgrps = NFS_MAXGRPS;
nmp->nm_readahead = NFS_DEFRAHEAD;
nmp->nm_leaseterm = NQ_DEFLEASE;
nmp->nm_deadthresh = NQ_DEADTHRESH;
CIRCLEQ_INIT(&nmp->nm_timerhead);
nmp->nm_inprog = NULLVP;
bcopy((caddr_t)argp->fh, (caddr_t)&nmp->nm_fh, sizeof(nfsv2fh_t));
nmp->nm_fhsize = argp->fhsize;
bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
#ifdef __NetBSD__
#ifdef COMPAT_09
mp->mnt_stat.f_type = 2;
#else
mp->mnt_stat.f_type = 0;
#endif
#else
mp->mnt_stat.f_type = MOUNT_NFS;
#endif
bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
nmp->nm_nam = nam;
@ -483,29 +590,48 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
nmp->nm_retry = NFS_MAXREXMIT;
}
if (argp->flags & NFSMNT_NFSV3) {
if (argp->sotype == SOCK_DGRAM)
maxio = NFS_MAXDGRAMDATA;
else
maxio = NFS_MAXDATA;
} else
maxio = NFS_V2MAXDATA;
if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
nmp->nm_wsize = argp->wsize;
/* Round down to multiple of blocksize */
nmp->nm_wsize &= ~0x1ff;
nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
if (nmp->nm_wsize <= 0)
nmp->nm_wsize = 512;
else if (nmp->nm_wsize > NFS_MAXDATA)
nmp->nm_wsize = NFS_MAXDATA;
nmp->nm_wsize = NFS_FABLKSIZE;
}
if (nmp->nm_wsize > maxio)
nmp->nm_wsize = maxio;
if (nmp->nm_wsize > MAXBSIZE)
nmp->nm_wsize = MAXBSIZE;
if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
nmp->nm_rsize = argp->rsize;
/* Round down to multiple of blocksize */
nmp->nm_rsize &= ~0x1ff;
nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
if (nmp->nm_rsize <= 0)
nmp->nm_rsize = 512;
else if (nmp->nm_rsize > NFS_MAXDATA)
nmp->nm_rsize = NFS_MAXDATA;
nmp->nm_rsize = NFS_FABLKSIZE;
}
if (nmp->nm_rsize > maxio)
nmp->nm_rsize = maxio;
if (nmp->nm_rsize > MAXBSIZE)
nmp->nm_rsize = MAXBSIZE;
if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
nmp->nm_readdirsize = argp->readdirsize;
/* Round down to multiple of blocksize */
nmp->nm_readdirsize &= ~(NFS_DIRBLKSIZ - 1);
if (nmp->nm_readdirsize < NFS_DIRBLKSIZ)
nmp->nm_readdirsize = NFS_DIRBLKSIZ;
}
if (nmp->nm_readdirsize > maxio)
nmp->nm_readdirsize = maxio;
if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 &&
argp->maxgrouplist <= NFS_MAXGRPS)
nmp->nm_numgrps = argp->maxgrouplist;
@ -536,7 +662,7 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
* stuck on a dead server and we are holding a lock on the mount
* point.
*/
mp->mnt_stat.f_iosize = NFS_MAXDGRAMDATA;
mp->mnt_stat.f_iosize = min(nmp->nm_rsize, nmp->nm_wsize);
/*
* A reference count is needed on the nfsnode representing the
* remote root. If this object is not persistent, then backward
@ -545,11 +671,16 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
* this problem, because one can identify root inodes by their
* number == ROOTINO (2).
*/
error = nfs_nget(mp, &nmp->nm_fh, &np);
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
if (error)
goto bad;
*vpp = NFSTOV(np);
/*
* Lose the lock but keep the ref.
*/
VOP_UNLOCK(*vpp);
return (0);
bad:
nfs_disconnect(nmp);
@ -592,7 +723,7 @@ nfs_unmount(mp, mntflags, p)
* the remote root. See comment in mountnfs(). The VFS unmount()
* has done vput on this vnode, otherwise we would get deadlock!
*/
error = nfs_nget(mp, &nmp->nm_fh, &np);
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
if (error)
return(error);
vp = NFSTOV(np);
@ -622,9 +753,9 @@ nfs_unmount(mp, mntflags, p)
nmp->nm_flag |= NFSMNT_DISMNT;
/*
* There are two reference counts to get rid of here.
* There are two reference counts and one lock to get rid of here.
*/
vrele(vp);
vput(vp);
vrele(vp);
vgone(vp);
nfs_disconnect(nmp);
@ -649,10 +780,11 @@ nfs_root(mp, vpp)
int error;
nmp = VFSTONFS(mp);
error = nfs_nget(mp, &nmp->nm_fh, &np);
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
if (error)
return (error);
vp = NFSTOV(np);
VOP_UNLOCK(vp);
vp->v_type = VDIR;
vp->v_flag = VROOT;
*vpp = vp;

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfsdiskless.h 8.1 (Berkeley) 6/10/93
* $Id: nfsdiskless.h,v 1.3 1994/08/05 09:28:49 davidg Exp $
* $Id: nfsdiskless.h,v 1.4 1994/08/21 06:50:09 paul Exp $
*/
#ifndef _NFS_NFSDISKLESS_H_
@ -52,17 +52,45 @@
* NB: All fields are stored in net byte order to avoid hassles with
* client/server byte ordering differences.
*/
struct nfs_diskless {
/*
* I have defined a new structure that can handle an NFS Version 3 file handle
* but the kernel still expects the old Version 2 one to be provided. The
* changes required in nfs_vfsops.c for using the new are documented there in
* comments. (I felt that breaking network booting code by changing this
* structure would not be prudent at this time, since almost all servers are
* still Version 2 anyhow.)
*/
struct nfsv3_diskless {
struct ifaliasreq myif; /* Default interface */
struct sockaddr_in mygateway; /* Default gateway */
struct nfs_args swap_args; /* Mount args for swap file */
u_char swap_fh[NFS_FHSIZE]; /* Swap file's file handle */
int swap_fhsize; /* Size of file handle */
u_char swap_fh[NFSX_V3FHMAX]; /* Swap file's file handle */
struct sockaddr_in swap_saddr; /* Address of swap server */
char swap_hostnam[MNAMELEN]; /* Host name for mount pt */
int swap_nblks; /* Size of server swap file */
struct ucred swap_ucred; /* Swap credentials */
struct nfs_args root_args; /* Mount args for root fs */
u_char root_fh[NFS_FHSIZE]; /* File handle of root dir */
int root_fhsize; /* Size of root file handle */
u_char root_fh[NFSX_V3FHMAX]; /* File handle of root dir */
struct sockaddr_in root_saddr; /* Address of root server */
char root_hostnam[MNAMELEN]; /* Host name for mount pt */
long root_time; /* Timestamp of root fs */
char my_hostnam[MAXHOSTNAMELEN]; /* Client host name */
};
struct nfs_diskless {
struct ifaliasreq myif; /* Default interface */
struct sockaddr_in mygateway; /* Default gateway */
struct nfs_args swap_args; /* Mount args for swap file */
u_char swap_fh[NFSX_V2FH]; /* Swap file's file handle */
struct sockaddr_in swap_saddr; /* Address of swap server */
char swap_hostnam[MNAMELEN]; /* Host name for mount pt */
int swap_nblks; /* Size of server swap file */
struct ucred swap_ucred; /* Swap credentials */
struct nfs_args root_args; /* Mount args for root fs */
u_char root_fh[NFSX_V2FH]; /* File handle of root dir */
struct sockaddr_in root_saddr; /* Address of root server */
char root_hostnam[MNAMELEN]; /* Host name for mount pt */
long root_time; /* Timestamp of root fs */

View File

@ -34,12 +34,13 @@
* SUCH DAMAGE.
*
* @(#)nfsm_subs.h 8.1 (Berkeley) 6/16/93
* $Id: nfsm_subs.h,v 1.5 1994/10/17 17:47:42 phk Exp $
* $Id: nfsm_subs.h,v 1.6 1995/05/30 08:12:51 rgrimes Exp $
*/
#ifndef _NFS_NFSM_SUBS_H_
#define _NFS_NFSM_SUBS_H_
/*
* These macros do strange and peculiar things to mbuf chains for
* the assistance of the nfs code. To attempt to use them for any
@ -90,49 +91,153 @@ extern struct mbuf *nfsm_reqh();
mb->m_len += (s); \
bpos += (s); }
#define nfsm_dissect(a,c,s) \
#define nfsm_dissect(a, c, s) \
{ t1 = mtod(md, caddr_t)+md->m_len-dpos; \
if (t1 >= (s)) { \
(a) = (c)(dpos); \
dpos += (s); \
} else if (t1 = nfsm_disct(&md, &dpos, (s), t1, &cp2)) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
} else { \
error = nfsm_disct(&md, &dpos, (s), t1, &cp2); \
if (error) { \
m_freem(mrep); \
goto nfsmout; \
} else { \
(a) = (c)cp2; \
} \
(a) = (c)cp2; \
} }
#define nfsm_fhtom(v) \
nfsm_build(cp,caddr_t,NFSX_FH); \
bcopy((caddr_t)&(VTONFS(v)->n_fh), cp, NFSX_FH)
#define nfsm_fhtom(v, v3) \
{ if (v3) { \
t2 = nfsm_rndup(VTONFS(v)->n_fhsize) + NFSX_UNSIGNED; \
if (t2 <= M_TRAILINGSPACE(mb)) { \
nfsm_build(tl, u_long *, t2); \
*tl++ = txdr_unsigned(VTONFS(v)->n_fhsize); \
*(tl + ((t2>>2) - 2)) = 0; \
bcopy((caddr_t)VTONFS(v)->n_fhp,(caddr_t)tl, \
VTONFS(v)->n_fhsize); \
} else if (t2 = nfsm_strtmbuf(&mb, &bpos, \
(caddr_t)VTONFS(v)->n_fhp, VTONFS(v)->n_fhsize)) { \
error = t2; \
m_freem(mreq); \
goto nfsmout; \
} \
} else { \
nfsm_build(cp, caddr_t, NFSX_V2FH); \
bcopy((caddr_t)VTONFS(v)->n_fhp, cp, NFSX_V2FH); \
} }
#define nfsm_srvfhtom(f) \
nfsm_build(cp,caddr_t,NFSX_FH); \
bcopy((caddr_t)(f), cp, NFSX_FH)
#define nfsm_srvfhtom(f, v3) \
{ if (v3) { \
nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3FH); \
*tl++ = txdr_unsigned(NFSX_V3FH); \
bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
} else { \
nfsm_build(cp, caddr_t, NFSX_V2FH); \
bcopy((caddr_t)(f), cp, NFSX_V2FH); \
} }
#define nfsm_mtofh(d,v) \
{ struct nfsnode *np; nfsv2fh_t *fhp; \
nfsm_dissect(fhp,nfsv2fh_t *,NFSX_FH); \
error = nfs_nget((d)->v_mount, fhp, &np); \
if (error) { \
m_freem(mrep); \
goto nfsmout; \
} \
(v) = NFSTOV(np); \
nfsm_loadattr(v, (struct vattr *)0); \
#define nfsm_srvpostop_fh(f) \
{ nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED + NFSX_V3FH); \
*tl++ = nfs_true; \
*tl++ = txdr_unsigned(NFSX_V3FH); \
bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
}
#define nfsm_loadattr(v,a) \
{ struct vnode *tvp = (v); \
error = nfs_loadattrcache(&tvp, &md, &dpos, (a)); \
if (error) { \
#define nfsm_mtofh(d, v, v3, f) \
{ struct nfsnode *ttnp; nfsfh_t *ttfhp; int ttfhsize; \
if (v3) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
(f) = fxdr_unsigned(int, *tl); \
} else \
(f) = 1; \
if (f) { \
nfsm_getfh(ttfhp, ttfhsize, (v3)); \
if (t1 = nfs_nget((d)->v_mount, ttfhp, ttfhsize, \
&ttnp)) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
} \
(v) = NFSTOV(ttnp); \
} \
if (v3) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (f) \
(f) = fxdr_unsigned(int, *tl); \
else if (fxdr_unsigned(int, *tl)) \
nfsm_adv(NFSX_V3FATTR); \
} \
if (f) \
nfsm_loadattr((v), (struct vattr *)0); \
}
#define nfsm_getfh(f, s, v3) \
{ if (v3) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (((s) = fxdr_unsigned(int, *tl)) <= 0 || \
(s) > NFSX_V3FHMAX) { \
m_freem(mrep); \
error = EBADRPC; \
goto nfsmout; \
} \
} else \
(s) = NFSX_V2FH; \
nfsm_dissect((f), nfsfh_t *, nfsm_rndup(s)); }
#define nfsm_loadattr(v, a) \
{ struct vnode *ttvp = (v); \
if (t1 = nfs_loadattrcache(&ttvp, &md, &dpos, (a))) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
} \
(v) = tvp; }
(v) = ttvp; }
#define nfsm_postop_attr(v, f) \
{ struct vnode *ttvp = (v); \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if ((f) = fxdr_unsigned(int, *tl)) { \
if (t1 = nfs_loadattrcache(&ttvp, &md, &dpos, \
(struct vattr *)0)) { \
error = t1; \
(f) = 0; \
m_freem(mrep); \
goto nfsmout; \
} \
(v) = ttvp; \
} }
/* Used as (f) for nfsm_wcc_data() */
#define NFSV3_WCCRATTR 0
#define NFSV3_WCCCHK 1
#define nfsm_wcc_data(v, f) \
{ int ttattrf, ttretf = 0; \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
nfsm_dissect(tl, u_long *, 6 * NFSX_UNSIGNED); \
if (f) \
ttretf = (VTONFS(v)->n_mtime == \
fxdr_unsigned(u_long, *(tl + 2))); \
} \
nfsm_postop_attr((v), ttattrf); \
if (f) { \
(f) = ttretf; \
} else { \
(f) = ttattrf; \
} }
#define nfsm_v3sattr(s, a, u, g) \
{ (s)->sa_modetrue = nfs_true; \
(s)->sa_mode = vtonfsv3_mode((a)->va_mode); \
(s)->sa_uidtrue = nfs_true; \
(s)->sa_uid = txdr_unsigned(u); \
(s)->sa_gidtrue = nfs_true; \
(s)->sa_gid = txdr_unsigned(g); \
(s)->sa_sizefalse = nfs_false; \
(s)->sa_atimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \
txdr_nfsv3time(&(a)->va_atime, &(s)->sa_atime); \
(s)->sa_mtimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \
txdr_nfsv3time(&(a)->va_mtime, &(s)->sa_mtime); \
}
#define nfsm_strsiz(s,m) \
{ nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \
@ -149,16 +254,27 @@ extern struct mbuf *nfsm_reqh();
nfsm_reply(0); \
} }
#define nfsm_srvnamesiz(s) \
{ nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \
if (((s) = fxdr_unsigned(long,*tl)) > NFS_MAXNAMLEN) \
error = NFSERR_NAMETOL; \
if ((s) <= 0) \
error = EBADRPC; \
if (error) \
nfsm_reply(0); \
}
#define nfsm_mtouio(p,s) \
if ((s) > 0 && \
(error = nfsm_mbuftouio(&md,(p),(s),&dpos))) { \
(t1 = nfsm_mbuftouio(&md,(p),(s),&dpos))) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
}
#define nfsm_uiotom(p,s) \
error = nfsm_uiotombuf((p),&mb,(s),&bpos); \
if (error) { \
if (t1 = nfsm_uiotombuf((p),&mb,(s),&bpos)) { \
error = t1; \
m_freem(mreq); \
goto nfsmout; \
}
@ -172,10 +288,13 @@ extern struct mbuf *nfsm_reqh();
#define nfsm_rndup(a) (((a)+3)&(~0x3))
#define nfsm_request(v, t, p, c) \
error = nfs_request((v), mreq, (t), (p), \
(c), &mrep, &md, &dpos); \
if (error) \
goto nfsmout
if (error = nfs_request((v), mreq, (t), (p), \
(c), &mrep, &md, &dpos)) { \
if (error & NFSERR_RETERR) \
error &= ~NFSERR_RETERR; \
else \
goto nfsmout; \
}
#define nfsm_strtom(a,s,m) \
if ((s) > (m)) { \
@ -189,12 +308,10 @@ extern struct mbuf *nfsm_reqh();
*tl++ = txdr_unsigned(s); \
*(tl+((t2>>2)-2)) = 0; \
bcopy((caddr_t)(a), (caddr_t)tl, (s)); \
} else { \
error = nfsm_strtmbuf(&mb, &bpos, (a), (s)); \
if (error) { \
m_freem(mreq); \
goto nfsmout; \
} \
} else if (t2 = nfsm_strtmbuf(&mb, &bpos, (a), (s))) { \
error = t2; \
m_freem(mreq); \
goto nfsmout; \
}
#define nfsm_srvdone \
@ -204,33 +321,53 @@ extern struct mbuf *nfsm_reqh();
#define nfsm_reply(s) \
{ \
nfsd->nd_repstat = error; \
if (error) \
(void) nfs_rephead(0, nfsd, error, cache, &frev, \
if (error && !(nfsd->nd_flag & ND_NFSV3)) \
(void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
mrq, &mb, &bpos); \
else \
(void) nfs_rephead((s), nfsd, error, cache, &frev, \
(void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
mrq, &mb, &bpos); \
m_freem(mrep); \
mreq = *mrq; \
if (error) \
if (error && (!(nfsd->nd_flag & ND_NFSV3) || \
error == EBADRPC)) \
return(0); \
}
#define nfsm_adv(s) \
t1 = mtod(md, caddr_t)+md->m_len-dpos; \
if (t1 >= (s)) { \
dpos += (s); \
} else { \
error = nfs_adv(&md, &dpos, (s), t1); \
if (error) { \
m_freem(mrep); \
goto nfsmout; \
} \
#define nfsm_writereply(s, v3) \
{ \
nfsd->nd_repstat = error; \
if (error && !(v3)) \
(void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
&mreq, &mb, &bpos); \
else \
(void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
&mreq, &mb, &bpos); \
}
#define nfsm_adv(s) \
{ t1 = mtod(md, caddr_t)+md->m_len-dpos; \
if (t1 >= (s)) { \
dpos += (s); \
} else if (t1 = nfs_adv(&md, &dpos, (s), t1)) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
} }
#define nfsm_srvmtofh(f) \
nfsm_dissect(tl, u_long *, NFSX_FH); \
bcopy((caddr_t)tl, (caddr_t)f, NFSX_FH)
{ if (nfsd->nd_flag & ND_NFSV3) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (fxdr_unsigned(int, *tl) != NFSX_V3FH) { \
error = EBADRPC; \
nfsm_reply(0); \
} \
} \
nfsm_dissect(tl, u_long *, NFSX_V3FH); \
bcopy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \
if ((nfsd->nd_flag & ND_NFSV3) == 0) \
nfsm_adv(NFSX_V2FH - NFSX_V3FH); \
}
#define nfsm_clget \
if (bp >= be) { \
@ -246,41 +383,57 @@ extern struct mbuf *nfsm_reqh();
} \
tl = (u_long *)bp
#define nfsm_srvfillattr \
fp->fa_type = vtonfs_type(vap->va_type); \
fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode); \
fp->fa_nlink = txdr_unsigned(vap->va_nlink); \
fp->fa_uid = txdr_unsigned(vap->va_uid); \
fp->fa_gid = txdr_unsigned(vap->va_gid); \
if (nfsd->nd_nqlflag == NQL_NOVAL) { \
fp->fa_nfsblocksize = txdr_unsigned(vap->va_blocksize); \
if (vap->va_type == VFIFO) \
fp->fa_nfsrdev = 0xffffffff; \
else \
fp->fa_nfsrdev = txdr_unsigned(vap->va_rdev); \
fp->fa_nfsfsid = txdr_unsigned(vap->va_fsid); \
fp->fa_nfsfileid = txdr_unsigned(vap->va_fileid); \
fp->fa_nfssize = txdr_unsigned(vap->va_size); \
fp->fa_nfsblocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE); \
txdr_nfstime(&vap->va_atime, &fp->fa_nfsatime); \
txdr_nfstime(&vap->va_mtime, &fp->fa_nfsmtime); \
txdr_nfstime(&vap->va_ctime, &fp->fa_nfsctime); \
} else { \
fp->fa_nqblocksize = txdr_unsigned(vap->va_blocksize); \
if (vap->va_type == VFIFO) \
fp->fa_nqrdev = 0xffffffff; \
else \
fp->fa_nqrdev = txdr_unsigned(vap->va_rdev); \
fp->fa_nqfsid = txdr_unsigned(vap->va_fsid); \
fp->fa_nqfileid = txdr_unsigned(vap->va_fileid); \
txdr_hyper(&vap->va_size, &fp->fa_nqsize); \
txdr_hyper(&vap->va_bytes, &fp->fa_nqbytes); \
txdr_nqtime(&vap->va_atime, &fp->fa_nqatime); \
txdr_nqtime(&vap->va_mtime, &fp->fa_nqmtime); \
txdr_nqtime(&vap->va_ctime, &fp->fa_nqctime); \
fp->fa_nqflags = txdr_unsigned(vap->va_flags); \
fp->fa_nqgen = txdr_unsigned(vap->va_gen); \
txdr_hyper(&vap->va_filerev, &fp->fa_nqfilerev); \
}
#define nfsm_srvfillattr(a, f) \
nfsm_srvfattr(nfsd, (a), (f))
#define nfsm_srvwcc_data(br, b, ar, a) \
nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos)
#define nfsm_srvpostop_attr(r, a) \
nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos)
#define nfsm_srvsattr(a) \
{ nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
(a)->va_mode = nfstov_mode(*tl); \
} \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
(a)->va_uid = fxdr_unsigned(uid_t, *tl); \
} \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
(a)->va_gid = fxdr_unsigned(gid_t, *tl); \
} \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
fxdr_hyper(tl, &(a)->va_size); \
} \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
switch (fxdr_unsigned(int, *tl)) { \
case NFSV3SATTRTIME_TOCLIENT: \
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
fxdr_nfsv3time(tl, &(a)->va_atime); \
break; \
case NFSV3SATTRTIME_TOSERVER: \
(a)->va_atime.ts_sec = time.tv_sec; \
(a)->va_atime.ts_nsec = time.tv_usec * 1000; \
break; \
}; \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
switch (fxdr_unsigned(int, *tl)) { \
case NFSV3SATTRTIME_TOCLIENT: \
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
fxdr_nfsv3time(tl, &(a)->va_mtime); \
break; \
case NFSV3SATTRTIME_TOSERVER: \
(a)->va_mtime.ts_sec = time.tv_sec; \
(a)->va_mtime.ts_nsec = time.tv_usec * 1000; \
break; \
}; }
#endif

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfsmount.h 8.1 (Berkeley) 6/10/93
* $Id: nfsmount.h,v 1.3 1994/08/21 06:50:10 paul Exp $
* $Id: nfsmount.h,v 1.4 1994/10/17 17:47:43 phk Exp $
*/
#ifndef _NFS_NFSMOUNT_H_
@ -49,7 +49,8 @@ struct nfsmount {
int nm_flag; /* Flags for soft/hard... */
struct mount *nm_mountp; /* Vfs structure for this filesystem */
int nm_numgrps; /* Max. size of groupslist */
nfsv2fh_t nm_fh; /* File handle of root dir */
u_char nm_fh[NFSX_V3FHMAX]; /* File handle of root dir */
int nm_fhsize; /* Size of root file handle */
struct socket *nm_so; /* Rpc socket */
int nm_sotype; /* Type of socket */
int nm_soproto; /* and protocol */
@ -65,6 +66,7 @@ struct nfsmount {
int nm_deadthresh; /* Threshold of timeouts-->dead server*/
int nm_rsize; /* Max size of read rpc */
int nm_wsize; /* Max size of write rpc */
int nm_readdirsize; /* Size of a readdir rpc */
int nm_readahead; /* Num. of blocks to readahead */
int nm_leaseterm; /* Term (sec) for NQNFS lease */
CIRCLEQ_HEAD(, nfsnode) nm_timerhead; /* Head of lease timer queue */
@ -73,9 +75,16 @@ struct nfsmount {
int nm_authtype; /* Authenticator type */
int nm_authlen; /* and length */
char *nm_authstr; /* Authenticator string */
char *nm_verfstr; /* and the verifier */
int nm_verflen;
u_char nm_verf[NFSX_V3WRITEVERF]; /* V3 write verifier */
NFSKERBKEY_T nm_key; /* and the session key */
int nm_numuids; /* Number of nfsuid mappings */
TAILQ_HEAD(, nfsuid) nm_uidlruhead; /* Lists of nfsuid mappings */
LIST_HEAD(, nfsuid) nm_uidhashtbl[NFS_MUIDHASHSIZ];
};
#ifdef KERNEL
#if defined(KERNEL) || defined(_KERNEL)
/*
* Convert mount ptr to nfsmount ptr.
*/

View File

@ -34,12 +34,16 @@
* SUCH DAMAGE.
*
* @(#)nfsnode.h 8.4 (Berkeley) 2/13/94
* $Id: nfsnode.h,v 1.8 1994/10/17 17:47:44 phk Exp $
* $Id: nfsnode.h,v 1.9 1995/03/16 18:15:42 bde Exp $
*/
#ifndef _NFS_NFSNODE_H_
#define _NFS_NFSNODE_H_
#ifndef _NFS_NFS_H_
#include <nfs/nfs.h>
#endif
/*
* Silly rename structure that hangs off the nfsnode until the name
* can be removed by nfs_inactive()
@ -51,37 +55,74 @@ struct sillyrename {
char s_name[20];
};
/*
* This structure is used to save the logical directory offset to
* NFS cookie mappings.
* The mappings are stored in a list headed
* by n_cookies, as required.
* There is one mapping for each NFS_DIRBLKSIZ bytes of directory information
* stored in increasing logical offset byte order.
*/
#define NFSNUMCOOKIES 31
struct nfsdmap {
LIST_ENTRY(nfsdmap) ndm_list;
int ndm_eocookie;
nfsuint64 ndm_cookies[NFSNUMCOOKIES];
};
/*
* The nfsnode is the nfs equivalent to ufs's inode. Any similarity
* is purely coincidental.
* There is a unique nfsnode allocated for each active file,
* each current directory, each mounted-on file, text file, and the root.
* An nfsnode is 'named' by its file handle. (nget/nfs_node.c)
* If this structure exceeds 256 bytes (it is currently 256 using 4.4BSD-Lite
* type definitions), file handles of > 32 bytes should probably be split out
* into a separate MALLOC()'d data structure. (Reduce the size of nfsfh_t by
* changing the definition in sys/mount.h of NFS_SMALLFH.)
* NB: Hopefully the current order of the fields is such that everything will
* be well aligned and, therefore, tightly packed.
*/
struct nfsnode {
LIST_ENTRY(nfsnode) n_hash; /* Hash chain */
CIRCLEQ_ENTRY(nfsnode) n_timer; /* Nqnfs timer chain */
nfsv2fh_t n_fh; /* NFS File Handle */
long n_flag; /* Flag for locking.. */
struct vnode *n_vnode; /* vnode associated with this node */
struct vattr n_vattr; /* Vnode attribute cache */
time_t n_attrstamp; /* Time stamp for cached attributes */
struct sillyrename *n_sillyrename; /* Ptr to silly rename struct */
u_quad_t n_size; /* Current size of file */
struct lockf *n_lockf; /* Locking record of file */
int n_error; /* Save write error value */
u_long n_direofoffset; /* Dir. EOF offset cache */
time_t n_mtime; /* Prev modify time. */
time_t n_ctime; /* Prev create time. */
u_quad_t n_brev; /* Modify rev when cached */
u_quad_t n_lrev; /* Modify rev for lease */
time_t n_expiry; /* Lease expiry time */
struct sillyrename n_silly; /* Silly rename struct */
struct timeval n_atim; /* Special file times */
struct timeval n_mtim;
LIST_ENTRY(nfsnode) n_hash; /* Hash chain */
CIRCLEQ_ENTRY(nfsnode) n_timer; /* Nqnfs timer chain */
u_quad_t n_size; /* Current size of file */
u_quad_t n_brev; /* Modify rev when cached */
u_quad_t n_lrev; /* Modify rev for lease */
struct vattr n_vattr; /* Vnode attribute cache */
time_t n_attrstamp; /* Attr. cache timestamp */
time_t n_mtime; /* Prev modify time. */
time_t n_ctime; /* Prev create time. */
time_t n_expiry; /* Lease expiry time */
nfsfh_t *n_fhp; /* NFS File Handle */
struct vnode *n_vnode; /* associated vnode */
struct lockf *n_lockf; /* Locking record of file */
int n_error; /* Save write error value */
union {
struct timespec nf_atim; /* Special file times */
nfsuint64 nd_cookieverf; /* Cookie verifier (dir only) */
} n_un1;
union {
struct timespec nf_mtim;
off_t nd_direof; /* Dir. EOF offset cache */
} n_un2;
union {
struct sillyrename *nf_silly; /* Ptr to silly rename struct */
LIST_HEAD(, nfsdmap) nd_cook; /* cookies */
} n_un3;
short n_fhsize; /* size in bytes, of fh */
short n_flag; /* Flag for locking.. */
nfsfh_t n_fh; /* Small File Handle */
};
#define n_atim n_un1.nf_atim
#define n_mtim n_un2.nf_mtim
#define n_sillyrename n_un3.nf_silly
#define n_cookieverf n_un1.nd_cookieverf
#define n_direofoffset n_un2.nd_direof
#define n_cookies n_un3.nd_cook
/*
* Flags for n_flag
*/
@ -95,6 +136,8 @@ struct nfsnode {
#define NACC 0x0100 /* Special file accessed */
#define NUPD 0x0200 /* Special file updated */
#define NCHG 0x0400 /* Special file times changed */
#define NLOCKED 0x0800 /* node is locked */
#define NWANTED 0x0100 /* someone wants to lock */
/*
* Convert between nfsnode pointers and vnode pointers
@ -107,7 +150,7 @@ struct nfsnode {
*/
TAILQ_HEAD(, buf) nfs_bufq;
#ifdef KERNEL
#if defined(KERNEL) || defined(_KERNEL)
extern int (**fifo_nfsv2nodeop_p)();
extern int (**nfsv2_vnodeop_p)();
extern int (**spec_nfsv2nodeop_p)();
@ -128,12 +171,25 @@ int nfs_getattr __P((struct vop_getattr_args *));
int nfs_setattr __P((struct vop_setattr_args *));
int nfs_read __P((struct vop_read_args *));
int nfs_write __P((struct vop_write_args *));
#ifdef HAS_VOPLEASE
#define nfs_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
#define nqnfs_vop_lease_check lease_check
#else
#ifdef __FreeBSD__
#define nqnfs_lease_check nfs_lease_check
#else
#define nqnfs_lease_check lease_check
#endif
#endif
int nfsspec_read __P((struct vop_read_args *));
int nfsspec_write __P((struct vop_write_args *));
int nfsfifo_read __P((struct vop_read_args *));
int nfsfifo_write __P((struct vop_write_args *));
#define nfs_ioctl ((int (*) __P((struct vop_ioctl_args *)))enoioctl)
#define nfs_select ((int (*) __P((struct vop_select_args *)))seltrue)
#ifdef HAS_VOPREVOKE
#define nfs_revoke vop_revoke
#endif
int nfs_mmap __P((struct vop_mmap_args *));
int nfs_fsync __P((struct vop_fsync_args *));
#define nfs_seek ((int (*) __P((struct vop_seek_args *)))nullop)
@ -157,6 +213,7 @@ int nfs_islocked __P((struct vop_islocked_args *));
int nfs_pathconf __P((struct vop_pathconf_args *));
int nfs_advlock __P((struct vop_advlock_args *));
int nfs_blkatoff __P((struct vop_blkatoff_args *));
int nfs_bwrite __P((struct vop_bwrite_args *));
int nfs_vget __P((struct mount *, ino_t, struct vnode **));
int nfs_valloc __P((struct vop_valloc_args *));
#define nfs_reallocblks \
@ -164,13 +221,20 @@ int nfs_valloc __P((struct vop_valloc_args *));
int nfs_vfree __P((struct vop_vfree_args *));
int nfs_truncate __P((struct vop_truncate_args *));
int nfs_update __P((struct vop_update_args *));
int nfs_bwrite __P((struct vop_bwrite_args *));
/* other stuff */
int nfs_removeit __P((struct sillyrename *));
int nfs_nget __P((struct mount *,nfsv2fh_t *,struct nfsnode **));
int nfs_lookitup __P((struct sillyrename *,nfsv2fh_t *,struct proc *));
int nfs_nget __P((struct mount *,nfsfh_t *,int,struct nfsnode **));
int nfs_lookitup __P((struct vnode *,char *,int,struct ucred *,struct proc *,struct nfsnode **));
int nfs_sillyrename __P((struct vnode *,struct vnode *,struct componentname *));
nfsuint64 *nfs_getcookie __P((struct nfsnode *, off_t, int));
void nfs_invaldir __P((struct vnode *));
#ifdef __FreeBSD__
#define nqnfs_lease_updatetime nfs_lease_updatetime
#else
#define nqnfs_lease_updatetime lease_updatetime
#endif
#endif /* KERNEL */

441
sys/nfs/nfsproto.h Normal file
View File

@ -0,0 +1,441 @@
/*
* 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* 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.
*
* @(#)nfsproto.h 8.1 (Berkeley) 6/10/93
* $Id: nfsproto.h,v 1.4 1994/08/21 06:50:13 paul Exp $
*/
#ifndef _NFS_NFSPROTO_H_
#define _NFS_NFSPROTO_H_
/*
* nfs definitions as per the Version 2 and 3 specs
*/
/*
* Constants as defined in the Sun NFS Version 2 and 3 specs.
* "NFS: Network File System Protocol Specification" RFC1094
* and in the "NFS: Network File System Version 3 Protocol
* Specification"
*/
#define NFS_PORT 2049
#define NFS_PROG 100003
#define NFS_VER2 2
#define NFS_VER3 3
#define NFS_V2MAXDATA 8192
#define NFS_MAXDGRAMDATA 16384
#define NFS_MAXDATA 32768
#define NFS_MAXPATHLEN 1024
#define NFS_MAXNAMLEN 255
#define NFS_MAXPKTHDR 404
#define NFS_MAXPACKET (NFS_MAXPKTHDR + NFS_MAXDATA)
#define NFS_MINPACKET 20
#define NFS_FABLKSIZE 512 /* Size in bytes of a block wrt fa_blocks */
/* Stat numbers for rpc returns (version 2 and 3) */
#define NFS_OK 0
#define NFSERR_PERM 1
#define NFSERR_NOENT 2
#define NFSERR_IO 5
#define NFSERR_NXIO 6
#define NFSERR_ACCES 13
#define NFSERR_EXIST 17
#define NFSERR_XDEV 18 /* Version 3 only */
#define NFSERR_NODEV 19
#define NFSERR_NOTDIR 20
#define NFSERR_ISDIR 21
#define NFSERR_INVAL 22 /* Version 3 only */
#define NFSERR_FBIG 27
#define NFSERR_NOSPC 28
#define NFSERR_ROFS 30
#define NFSERR_MLINK 31 /* Version 3 only */
#define NFSERR_NAMETOL 63
#define NFSERR_NOTEMPTY 66
#define NFSERR_DQUOT 69
#define NFSERR_STALE 70
#define NFSERR_REMOTE 71 /* Version 3 only */
#define NFSERR_WFLUSH 99 /* Version 2 only */
#define NFSERR_BADHANDLE 10001 /* The rest Version 3 only */
#define NFSERR_NOT_SYNC 10002
#define NFSERR_BAD_COOKIE 10003
#define NFSERR_NOTSUPP 10004
#define NFSERR_TOOSMALL 10005
#define NFSERR_SERVERFAULT 10006
#define NFSERR_BADTYPE 10007
#define NFSERR_JUKEBOX 10008
#define NFSERR_TRYLATER NFSERR_JUKEBOX
#define NFSERR_STALEWRITEVERF 30001 /* Fake return for nfs_commit() */
#define NFSERR_RETVOID 0x20000000 /* Return void, not error */
#define NFSERR_AUTHERR 0x40000000 /* Mark an authentication error */
#define NFSERR_RETERR 0x80000000 /* Mark an error return for V3 */
/* Sizes in bytes of various nfs rpc components */
#define NFSX_UNSIGNED 4
/* specific to NFS Version 2 */
#define NFSX_V2FH 32
#define NFSX_V2FATTR 68
#define NFSX_V2SATTR 32
#define NFSX_V2COOKIE 4
#define NFSX_V2STATFS 20
/* specific to NFS Version 3 */
#define NFSX_V3FH (sizeof (fhandle_t)) /* size this server uses */
#define NFSX_V3FHMAX 64 /* max. allowed by protocol */
#define NFSX_V3FATTR 84
#define NFSX_V3SATTR 60 /* max. all fields filled in */
#define NFSX_V3SRVSATTR (sizeof (struct nfsv3_sattr))
#define NFSX_V3POSTOPATTR (NFSX_V3FATTR + NFSX_UNSIGNED)
#define NFSX_V3WCCDATA (NFSX_V3POSTOPATTR + 8 * NFSX_UNSIGNED)
#define NFSX_V3COOKIEVERF 8
#define NFSX_V3WRITEVERF 8
#define NFSX_V3CREATEVERF 8
#define NFSX_V3STATFS 52
#define NFSX_V3FSINFO 48
#define NFSX_V3PATHCONF 24
/* variants for both versions */
#define NFSX_FH(v3) ((v3) ? (NFSX_V3FHMAX + NFSX_UNSIGNED) : \
NFSX_V2FH)
#define NFSX_SRVFH(v3) ((v3) ? NFSX_V3FH : NFSX_V2FH)
#define NFSX_FATTR(v3) ((v3) ? NFSX_V3FATTR : NFSX_V2FATTR)
#define NFSX_PREOPATTR(v3) ((v3) ? (7 * NFSX_UNSIGNED) : 0)
#define NFSX_POSTOPATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : 0)
#define NFSX_POSTOPORFATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : \
NFSX_V2FATTR)
#define NFSX_WCCDATA(v3) ((v3) ? NFSX_V3WCCDATA : 0)
#define NFSX_WCCORFATTR(v3) ((v3) ? NFSX_V3WCCDATA : NFSX_V2FATTR)
#define NFSX_SATTR(v3) ((v3) ? NFSX_V3SATTR : NFSX_V2SATTR)
#define NFSX_COOKIEVERF(v3) ((v3) ? NFSX_V3COOKIEVERF : 0)
#define NFSX_WRITEVERF(v3) ((v3) ? NFSX_V3WRITEVERF : 0)
#define NFSX_READDIR(v3) ((v3) ? (5 * NFSX_UNSIGNED) : \
(2 * NFSX_UNSIGNED))
#define NFSX_STATFS(v3) ((v3) ? NFSX_V3STATFS : NFSX_V2STATFS)
/* nfs rpc procedure numbers (before version mapping) */
#define NFSPROC_NULL 0
#define NFSPROC_GETATTR 1
#define NFSPROC_SETATTR 2
#define NFSPROC_LOOKUP 3
#define NFSPROC_ACCESS 4
#define NFSPROC_READLINK 5
#define NFSPROC_READ 6
#define NFSPROC_WRITE 7
#define NFSPROC_CREATE 8
#define NFSPROC_MKDIR 9
#define NFSPROC_SYMLINK 10
#define NFSPROC_MKNOD 11
#define NFSPROC_REMOVE 12
#define NFSPROC_RMDIR 13
#define NFSPROC_RENAME 14
#define NFSPROC_LINK 15
#define NFSPROC_READDIR 16
#define NFSPROC_READDIRPLUS 17
#define NFSPROC_FSSTAT 18
#define NFSPROC_FSINFO 19
#define NFSPROC_PATHCONF 20
#define NFSPROC_COMMIT 21
/* And leasing (nqnfs) procedure numbers (must be last) */
#define NQNFSPROC_GETLEASE 22
#define NQNFSPROC_VACATED 23
#define NQNFSPROC_EVICTED 24
#define NFSPROC_NOOP 25
#define NFS_NPROCS 26
/* Actual Version 2 procedure numbers */
#define NFSV2PROC_NULL 0
#define NFSV2PROC_GETATTR 1
#define NFSV2PROC_SETATTR 2
#define NFSV2PROC_NOOP 3
#define NFSV2PROC_ROOT NFSV2PROC_NOOP /* Obsolete */
#define NFSV2PROC_LOOKUP 4
#define NFSV2PROC_READLINK 5
#define NFSV2PROC_READ 6
#define NFSV2PROC_WRITECACHE NFSV2PROC_NOOP /* Obsolete */
#define NFSV2PROC_WRITE 8
#define NFSV2PROC_CREATE 9
#define NFSV2PROC_REMOVE 10
#define NFSV2PROC_RENAME 11
#define NFSV2PROC_LINK 12
#define NFSV2PROC_SYMLINK 13
#define NFSV2PROC_MKDIR 14
#define NFSV2PROC_RMDIR 15
#define NFSV2PROC_READDIR 16
#define NFSV2PROC_STATFS 17
/*
* Constants used by the Version 3 protocol for various RPCs
*/
#define NFSV3SATTRTIME_DONTCHANGE 0
#define NFSV3SATTRTIME_TOSERVER 1
#define NFSV3SATTRTIME_TOCLIENT 2
#define NFSV3ACCESS_READ 0x01
#define NFSV3ACCESS_LOOKUP 0x02
#define NFSV3ACCESS_MODIFY 0x04
#define NFSV3ACCESS_EXTEND 0x08
#define NFSV3ACCESS_DELETE 0x10
#define NFSV3ACCESS_EXECUTE 0x20
#define NFSV3WRITE_UNSTABLE 0
#define NFSV3WRITE_DATASYNC 1
#define NFSV3WRITE_FILESYNC 2
#define NFSV3CREATE_UNCHECKED 0
#define NFSV3CREATE_GUARDED 1
#define NFSV3CREATE_EXCLUSIVE 2
#define NFSV3FSINFO_LINK 0x01
#define NFSV3FSINFO_SYMLINK 0x02
#define NFSV3FSINFO_HOMOGENEOUS 0x08
#define NFSV3FSINFO_CANSETTIME 0x10
/* Conversion macros */
#define vtonfsv2_mode(t,m) \
txdr_unsigned(((t) == VFIFO) ? MAKEIMODE(VCHR, (m)) : \
MAKEIMODE((t), (m)))
#define vtonfsv3_mode(m) txdr_unsigned((m) & 07777)
#define nfstov_mode(a) (fxdr_unsigned(u_short, (a))&07777)
#define vtonfsv2_type(a) txdr_unsigned(nfsv2_type[((long)(a))])
#define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((long)(a))])
#define nfsv2tov_type(a) nv2tov_type[fxdr_unsigned(u_long,(a))&0x7]
#define nfsv3tov_type(a) nv3tov_type[fxdr_unsigned(u_long,(a))&0x7]
/* File types */
typedef enum { NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5,
NFSOCK=6, NFFIFO=7 } nfstype;
/* Structs for common parts of the rpc's */
/*
* File Handle (32 bytes for version 2), variable up to 64 for version 3.
* File Handles of up to NFS_SMALLFH in size are stored directly in the
* nfs node, whereas larger ones are malloc'd. (This never happens when
* NFS_SMALLFH is set to 64.)
* NFS_SMALLFH should be in the range of 32 to 64 and be divisible by 4.
*/
#ifndef NFS_SMALLFH
#define NFS_SMALLFH 64
#endif
union nfsfh {
fhandle_t fh_generic;
u_char fh_bytes[NFS_SMALLFH];
};
typedef union nfsfh nfsfh_t;
struct nfsv2_time {
u_long nfsv2_sec;
u_long nfsv2_usec;
};
typedef struct nfsv2_time nfstime2;
struct nfsv3_time {
u_long nfsv3_sec;
u_long nfsv3_nsec;
};
typedef struct nfsv3_time nfstime3;
/*
* Quads are defined as arrays of 2 longs to ensure dense packing for the
* protocol and to facilitate xdr conversion.
*/
struct nfs_uquad {
u_long nfsuquad[2];
};
typedef struct nfs_uquad nfsuint64;
/*
* Used to convert between two u_longs and a u_quad_t.
*/
union nfs_quadconvert {
u_long lval[2];
u_quad_t qval;
};
typedef union nfs_quadconvert nfsquad_t;
/*
* NFS Version 3 special file number.
*/
struct nfsv3_spec {
u_long specdata1;
u_long specdata2;
};
typedef struct nfsv3_spec nfsv3spec;
/*
* File attributes and setable attributes. These structures cover both
* NFS version 2 and the version 3 protocol. Note that the union is only
* used so that one pointer can refer to both variants. These structures
* go out on the wire and must be densely packed, so no quad data types
* are used. (all fields are longs or u_longs or structures of same)
* NB: You can't do sizeof(struct nfs_fattr), you must use the
* NFSX_FATTR(v3) macro.
*/
struct nfs_fattr {
u_long fa_type;
u_long fa_mode;
u_long fa_nlink;
u_long fa_uid;
u_long fa_gid;
union {
struct {
u_long nfsv2fa_size;
u_long nfsv2fa_blocksize;
u_long nfsv2fa_rdev;
u_long nfsv2fa_blocks;
u_long nfsv2fa_fsid;
u_long nfsv2fa_fileid;
nfstime2 nfsv2fa_atime;
nfstime2 nfsv2fa_mtime;
nfstime2 nfsv2fa_ctime;
} fa_nfsv2;
struct {
nfsuint64 nfsv3fa_size;
nfsuint64 nfsv3fa_used;
nfsv3spec nfsv3fa_rdev;
nfsuint64 nfsv3fa_fsid;
nfsuint64 nfsv3fa_fileid;
nfstime3 nfsv3fa_atime;
nfstime3 nfsv3fa_mtime;
nfstime3 nfsv3fa_ctime;
} fa_nfsv3;
} fa_un;
};
/* and some ugly defines for accessing union components */
#define fa2_size fa_un.fa_nfsv2.nfsv2fa_size
#define fa2_blocksize fa_un.fa_nfsv2.nfsv2fa_blocksize
#define fa2_rdev fa_un.fa_nfsv2.nfsv2fa_rdev
#define fa2_blocks fa_un.fa_nfsv2.nfsv2fa_blocks
#define fa2_fsid fa_un.fa_nfsv2.nfsv2fa_fsid
#define fa2_fileid fa_un.fa_nfsv2.nfsv2fa_fileid
#define fa2_atime fa_un.fa_nfsv2.nfsv2fa_atime
#define fa2_mtime fa_un.fa_nfsv2.nfsv2fa_mtime
#define fa2_ctime fa_un.fa_nfsv2.nfsv2fa_ctime
#define fa3_size fa_un.fa_nfsv3.nfsv3fa_size
#define fa3_used fa_un.fa_nfsv3.nfsv3fa_used
#define fa3_rdev fa_un.fa_nfsv3.nfsv3fa_rdev
#define fa3_fsid fa_un.fa_nfsv3.nfsv3fa_fsid
#define fa3_fileid fa_un.fa_nfsv3.nfsv3fa_fileid
#define fa3_atime fa_un.fa_nfsv3.nfsv3fa_atime
#define fa3_mtime fa_un.fa_nfsv3.nfsv3fa_mtime
#define fa3_ctime fa_un.fa_nfsv3.nfsv3fa_ctime
struct nfsv2_sattr {
u_long sa_mode;
u_long sa_uid;
u_long sa_gid;
u_long sa_size;
nfstime2 sa_atime;
nfstime2 sa_mtime;
};
/*
* NFS Version 3 sattr structure for the new node creation case.
*/
struct nfsv3_sattr {
u_long sa_modetrue;
u_long sa_mode;
u_long sa_uidtrue;
u_long sa_uid;
u_long sa_gidtrue;
u_long sa_gid;
u_long sa_sizefalse;
u_long sa_atimetype;
nfstime3 sa_atime;
u_long sa_mtimetype;
nfstime3 sa_mtime;
};
struct nfs_statfs {
union {
struct {
u_long nfsv2sf_tsize;
u_long nfsv2sf_bsize;
u_long nfsv2sf_blocks;
u_long nfsv2sf_bfree;
u_long nfsv2sf_bavail;
} sf_nfsv2;
struct {
nfsuint64 nfsv3sf_tbytes;
nfsuint64 nfsv3sf_fbytes;
nfsuint64 nfsv3sf_abytes;
nfsuint64 nfsv3sf_tfiles;
nfsuint64 nfsv3sf_ffiles;
nfsuint64 nfsv3sf_afiles;
u_long nfsv3sf_invarsec;
} sf_nfsv3;
} sf_un;
};
#define sf_tsize sf_un.sf_nfsv2.nfsv2sf_tsize
#define sf_bsize sf_un.sf_nfsv2.nfsv2sf_bsize
#define sf_blocks sf_un.sf_nfsv2.nfsv2sf_blocks
#define sf_bfree sf_un.sf_nfsv2.nfsv2sf_bfree
#define sf_bavail sf_un.sf_nfsv2.nfsv2sf_bavail
#define sf_tbytes sf_un.sf_nfsv3.nfsv3sf_tbytes
#define sf_fbytes sf_un.sf_nfsv3.nfsv3sf_fbytes
#define sf_abytes sf_un.sf_nfsv3.nfsv3sf_abytes
#define sf_tfiles sf_un.sf_nfsv3.nfsv3sf_tfiles
#define sf_ffiles sf_un.sf_nfsv3.nfsv3sf_ffiles
#define sf_afiles sf_un.sf_nfsv3.nfsv3sf_afiles
#define sf_invarsec sf_un.sf_nfsv3.nfsv3sf_invarsec
struct nfsv3_fsinfo {
u_long fs_rtmax;
u_long fs_rtpref;
u_long fs_rtmult;
u_long fs_wtmax;
u_long fs_wtpref;
u_long fs_wtmult;
u_long fs_dtpref;
nfsuint64 fs_maxfilesize;
nfstime3 fs_timedelta;
u_long fs_properties;
};
struct nfsv3_pathconf {
u_long pc_linkmax;
u_long pc_namemax;
u_long pc_notrunc;
u_long pc_chownrestricted;
u_long pc_caseinsensitive;
u_long pc_casepreserving;
};
#endif

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfsrtt.h 8.1 (Berkeley) 6/10/93
* $Id: nfsrtt.h,v 1.2 1994/08/02 07:52:24 davidg Exp $
* $Id: nfsrtt.h,v 1.3 1994/08/21 06:50:12 paul Exp $
*/
#ifndef _NFS_NFSRTT_H_
@ -82,6 +82,7 @@ struct nfsrtt {
#define DRT_TCP 0x02 /* Client used TCP transport */
#define DRT_CACHEREPLY 0x04 /* Reply was from recent request cache */
#define DRT_CACHEDROP 0x08 /* Rpc request dropped, due to recent reply */
#define DRT_NFSV3 0x10 /* Rpc used NFS Version 3 */
/*
* Server log structure

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfsrvcache.h 8.1 (Berkeley) 6/10/93
* $Id: nfsrvcache.h,v 1.3 1994/08/21 06:50:13 paul Exp $
* $Id: nfsrvcache.h,v 1.4 1994/10/17 17:47:44 phk Exp $
*/
#ifndef _NFS_NFSRVCACHE_H_
@ -44,7 +44,7 @@
* Definitions for the server recent request cache
*/
#define NFSRVCACHESIZ 256
#define NFSRVCACHESIZ 64
struct nfsrvcache {
TAILQ_ENTRY(nfsrvcache) rc_lru; /* LRU chain */

View File

@ -34,129 +34,201 @@
* SUCH DAMAGE.
*
* @(#)nfsv2.h 8.1 (Berkeley) 6/10/93
* $Id: nfsv2.h,v 1.3 1994/08/18 22:35:37 wollman Exp $
* $Id: nfsv2.h,v 1.4 1994/08/21 06:50:13 paul Exp $
*/
#ifndef _NFS_NFSV2_H_
#define _NFS_NFSV2_H_
#include <nfs/nfsproto.h>
#if 0
/*
* nfs definitions as per the version 2 specs
* nfs definitions as per the Version 2 and 3 specs
*/
/*
* Constants as defined in the Sun NFS Version 2 spec.
* Constants as defined in the Sun NFS Version 2 and 3 specs.
* "NFS: Network File System Protocol Specification" RFC1094
* and in the "NFS: Network File System Version 3 Protocol
* Specification"
*/
#define NFS_PORT 2049
#define NFS_PROG 100003
#define NFS_VER2 2
#define NFS_VER3 3
#define NFS_MAXDGRAMDATA 8192
#define NFS_MAXDATA 32768
#define NFS_MAXPATHLEN 1024
#define NFS_MAXNAMLEN 255
#define NFS_FHSIZE 32
#define NFS_MAXPKTHDR 404
#define NFS_MAXPACKET (NFS_MAXPKTHDR+NFS_MAXDATA)
#define NFS_MAXPACKET (NFS_MAXPKTHDR + NFS_MAXDATA)
#define NFS_MINPACKET 20
#define NFS_FABLKSIZE 512 /* Size in bytes of a block wrt fa_blocks */
/* Stat numbers for rpc returns */
#define NFS_OK 0
#define NFSERR_PERM 1
#define NFSERR_NOENT 2
#define NFSERR_IO 5
#define NFSERR_NXIO 6
#define NFSERR_ACCES 13
#define NFSERR_EXIST 17
#define NFSERR_NODEV 19
#define NFSERR_NOTDIR 20
#define NFSERR_ISDIR 21
#define NFSERR_FBIG 27
#define NFSERR_NOSPC 28
#define NFSERR_ROFS 30
#define NFSERR_NAMETOL 63
#define NFSERR_NOTEMPTY 66
#define NFSERR_DQUOT 69
#define NFSERR_STALE 70
#define NFSERR_WFLUSH 99
/* Stat numbers for rpc returns (version 2 and 3) */
#define NFS_OK 0
#define NFSERR_PERM 1
#define NFSERR_NOENT 2
#define NFSERR_IO 5
#define NFSERR_NXIO 6
#define NFSERR_ACCES 13
#define NFSERR_EXIST 17
#define NFSERR_XDEV 18 /* Version 3 only */
#define NFSERR_NODEV 19
#define NFSERR_NOTDIR 20
#define NFSERR_ISDIR 21
#define NFSERR_INVAL 22 /* Version 3 only */
#define NFSERR_FBIG 27
#define NFSERR_NOSPC 28
#define NFSERR_ROFS 30
#define NFSERR_MLINK 31 /* Version 3 only */
#define NFSERR_NAMETOL 63
#define NFSERR_NOTEMPTY 66
#define NFSERR_DQUOT 69
#define NFSERR_STALE 70
#define NFSERR_REMOTE 71 /* Version 3 only */
#define NFSERR_WFLUSH 99 /* Version 2 only */
#define NFSERR_BADHANDLE 10001 /* The rest Version 3 only */
#define NFSERR_NOT_SYNC 10002
#define NFSERR_BAD_COOKIE 10003
#define NFSERR_NOTSUPP 10004
#define NFSERR_TOOSMALL 10005
#define NFSERR_SERVERFAULT 10006
#define NFSERR_BADTYPE 10007
#define NFSERR_JUKEBOX 10008
/* Sizes in bytes of various nfs rpc components */
#define NFSX_FH 32
#define NFSX_UNSIGNED 4
#define NFSX_NFSFATTR 68
#define NFSX_NQFATTR 92
#define NFSX_NFSSATTR 32
#define NFSX_NQSATTR 44
#define NFSX_COOKIE 4
#define NFSX_NFSSTATFS 20
#define NFSX_NQSTATFS 28
#define NFSX_FATTR(isnq) ((isnq) ? NFSX_NQFATTR : NFSX_NFSFATTR)
#define NFSX_SATTR(isnq) ((isnq) ? NFSX_NQSATTR : NFSX_NFSSATTR)
#define NFSX_STATFS(isnq) ((isnq) ? NFSX_NQSTATFS : NFSX_NFSSTATFS)
/* nfs rpc procedure numbers */
/* specific to NFS Version 2 */
#define NFSX_V2FH 32
#define NFSX_V2FATTR 68
#define NFSX_V2SATTR 32
#define NFSX_V2COOKIE 4
#define NFSX_V2STATFS 20
/* specific to NFS Version 3 */
#define NFSX_V3FH 16 /* size this server uses */
#define NFSX_V3FHMAX 64 /* max. allowed by protocol */
#define NFSX_V3FATTR 84
#define NFSX_V3SATTR 60 /* max. all fields filled in */
#define NFSX_V3COOKIEVERF 8
/* variants for both versions */
#define NFSX_FH(v3) ((v3) ? (NFSX_V3FHMAX + NFSX_UNSIGNED) : \
NFSX_V2FH)
#define NFSX_SRVFH(v3) ((v3) ? NFSX_V3FH : NFSX_V2FH)
#define NFSX_FATTR(v3) ((v3) ? NFSX_V3FATTR : NFSX_V2FATTR)
#define NFSX_POSTOPATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : 0)
#define NFSX_POSTOPORFATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : \
NFSX_V2FATTR)
#define NFSX_WCCDATA(v3) ((v3) ? (NFSX_V3FATTR + 32) : 0)
#define NFSX_WCCORFATTR(v3) ((v3) ? (NFSX_V3FATTR + 32) : NFSX_V2FATTR)
#define NFSX_SATTR(v3) ((v3) ? NFSX_V3SATTR : NFSX_V2SATTR)
#define NFSX_COOKIEVERF(v3) ((v3) ? NFSX_V3COOKIEVERF : 0)
#define NFSX_STATFS(isv3) ((isv3) ? NFSX_NFSV3STATFS : NFSX_NFSSTATFS)
/* nfs rpc procedure numbers (before version mapping) */
#define NFSPROC_NULL 0
#define NFSPROC_GETATTR 1
#define NFSPROC_SETATTR 2
#define NFSPROC_NOOP 3
#define NFSPROC_ROOT NFSPROC_NOOP /* Obsolete */
#define NFSPROC_LOOKUP 4
#define NFSPROC_LOOKUP 3
#define NFSPROC_ACCESS 4
#define NFSPROC_READLINK 5
#define NFSPROC_READ 6
#define NFSPROC_WRITECACHE NFSPROC_NOOP /* Obsolete */
#define NFSPROC_WRITE 8
#define NFSPROC_CREATE 9
#define NFSPROC_REMOVE 10
#define NFSPROC_RENAME 11
#define NFSPROC_LINK 12
#define NFSPROC_SYMLINK 13
#define NFSPROC_MKDIR 14
#define NFSPROC_RMDIR 15
#define NFSPROC_WRITE 7
#define NFSPROC_CREATE 8
#define NFSPROC_MKDIR 9
#define NFSPROC_SYMLINK 10
#define NFSPROC_MKNOD 11
#define NFSPROC_REMOVE 12
#define NFSPROC_RMDIR 13
#define NFSPROC_RENAME 14
#define NFSPROC_LINK 15
#define NFSPROC_READDIR 16
#define NFSPROC_STATFS 17
#define NFSPROC_READDIRPLUS 17
#define NFSPROC_FSSTAT 18
#define NFSPROC_FSINFO 19
#define NFSPROC_PATHCONF 20
#define NFSPROC_COMMIT 21
/* NQ nfs numbers */
#define NQNFSPROC_READDIRLOOK 18
#define NQNFSPROC_GETLEASE 19
#define NQNFSPROC_VACATED 20
#define NQNFSPROC_EVICTED 21
#define NQNFSPROC_ACCESS 22
/* And leasing (nqnfs) procedure numbers */
#define NQNFSPROC_GETLEASE 22
#define NQNFSPROC_VACATED 23
#define NQNFSPROC_EVICTED 24
#define NFS_NPROCS 25
/* Actual Version 2 procedure numbers */
#define NFSV2PROC_NULL 0
#define NFSV2PROC_GETATTR 1
#define NFSV2PROC_SETATTR 2
#define NFSV2PROC_NOOP 3
#define NFSV2PROC_ROOT NFSV2PROC_NOOP /* Obsolete */
#define NFSV2PROC_LOOKUP 4
#define NFSV2PROC_READLINK 5
#define NFSV2PROC_READ 6
#define NFSV2PROC_WRITECACHE NFSV2PROC_NOOP /* Obsolete */
#define NFSV2PROC_WRITE 8
#define NFSV2PROC_CREATE 9
#define NFSV2PROC_REMOVE 10
#define NFSV2PROC_RENAME 11
#define NFSV2PROC_LINK 12
#define NFSV2PROC_SYMLINK 13
#define NFSV2PROC_MKDIR 14
#define NFSV2PROC_RMDIR 15
#define NFSV2PROC_READDIR 16
#define NFSV2PROC_STATFS 17
#define NFS_NPROCS 23
/* Conversion macros */
#define vtonfs_mode(t,m) \
extern int vttoif_tab[];
#define vtonfsv2_mode(t,m) \
txdr_unsigned(((t) == VFIFO) ? MAKEIMODE(VCHR, (m)) : \
MAKEIMODE((t), (m)))
#define nfstov_mode(a) (fxdr_unsigned(u_short, (a))&07777)
#define vtonfs_type(a) txdr_unsigned(nfs_type[((long)(a))])
#define nfstov_type(a) ntov_type[fxdr_unsigned(u_long,(a))&0x7]
#define vtonfsv3_mode(m) txdr_unsigned((m) & 07777)
#define nfstov_mode(a) (fxdr_unsigned(u_short, (a))&07777)
#define vtonfsv2_type(a) txdr_unsigned(nfsv2_type[((long)(a))])
#define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((long)(a))])
#define nfsv2tov_type(a) nv2tov_type[fxdr_unsigned(u_long,(a))&0x7]
#define nfsv3tov_type(a) nv3tov_type[fxdr_unsigned(u_long,(a))&0x7]
/* File types */
typedef enum { NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5 } nfstype;
typedef enum { NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5,
NFSOCK=6, NFFIFO=7 } nfstype;
/* Structs for common parts of the rpc's */
struct nfsv2_time {
u_long nfs_sec;
u_long nfs_usec;
u_long nfsv2_sec;
u_long nfsv2_usec;
};
typedef struct nfsv2_time nfstime2;
struct nqnfs_time {
u_long nq_sec;
u_long nq_nsec;
struct nfsv3_time {
u_long nfsv3_sec;
u_long nfsv3_nsec;
};
typedef struct nfsv3_time nfstime3;
/*
* Quads are defined as arrays of 2 longs to ensure dense packing for the
* protocol and to facilitate xdr conversion.
*/
struct nfs_uquad {
u_long nfsuquad[2];
};
typedef struct nfs_uquad nfsuint64;
/*
* File attributes and setable attributes. These structures cover both
* NFS version 2 and the NQNFS protocol. Note that the union is only
* used to that one pointer can refer to both variants. These structures
* NFS version 2 and the version 3 protocol. Note that the union is only
* used so that one pointer can refer to both variants. These structures
* go out on the wire and must be densely packed, so no quad data types
* are used. (all fields are longs or u_longs or structures of same)
* NB: You can't do sizeof(struct nfsv2_fattr), you must use the
* NFSX_FATTR(isnq) macro.
* NB: You can't do sizeof(struct nfs_fattr), you must use the
* NFSX_FATTR(v3) macro.
*/
struct nfsv2_fattr {
struct nfs_fattr {
u_long fa_type;
u_long fa_mode;
u_long fa_nlink;
@ -164,102 +236,85 @@ struct nfsv2_fattr {
u_long fa_gid;
union {
struct {
u_long nfsfa_size;
u_long nfsfa_blocksize;
u_long nfsfa_rdev;
u_long nfsfa_blocks;
u_long nfsfa_fsid;
u_long nfsfa_fileid;
struct nfsv2_time nfsfa_atime;
struct nfsv2_time nfsfa_mtime;
struct nfsv2_time nfsfa_ctime;
u_long nfsv2fa_size;
u_long nfsv2fa_blocksize;
u_long nfsv2fa_rdev;
u_long nfsv2fa_blocks;
u_long nfsv2fa_fsid;
u_long nfsv2fa_fileid;
nfstime2 nfsv2fa_atime;
nfstime2 nfsv2fa_mtime;
nfstime2 nfsv2fa_ctime;
} fa_nfsv2;
struct {
struct {
u_long nqfa_qsize[2];
} nqfa_size;
u_long nqfa_blocksize;
u_long nqfa_rdev;
struct {
u_long nqfa_qbytes[2];
} nqfa_bytes;
u_long nqfa_fsid;
u_long nqfa_fileid;
struct nqnfs_time nqfa_atime;
struct nqnfs_time nqfa_mtime;
struct nqnfs_time nqfa_ctime;
u_long nqfa_flags;
u_long nqfa_gen;
struct {
u_long nqfa_qfilerev[2];
} nqfa_filerev;
} fa_nqnfs;
nfsuint64 nfsv3fa_size;
nfsuint64 nfsv3fa_used;
nfsuint64 nfsv3fa_rdev;
nfsuint64 nfsv3fa_fsid;
nfsuint64 nfsv3fa_fileid;
nfstime3 nfsv3fa_atime;
nfstime3 nfsv3fa_mtime;
nfstime3 nfsv3fa_ctime;
} fa_nfsv3;
} fa_un;
};
/* and some ugly defines for accessing union components */
#define fa_nfssize fa_un.fa_nfsv2.nfsfa_size
#define fa_nfsblocksize fa_un.fa_nfsv2.nfsfa_blocksize
#define fa_nfsrdev fa_un.fa_nfsv2.nfsfa_rdev
#define fa_nfsblocks fa_un.fa_nfsv2.nfsfa_blocks
#define fa_nfsfsid fa_un.fa_nfsv2.nfsfa_fsid
#define fa_nfsfileid fa_un.fa_nfsv2.nfsfa_fileid
#define fa_nfsatime fa_un.fa_nfsv2.nfsfa_atime
#define fa_nfsmtime fa_un.fa_nfsv2.nfsfa_mtime
#define fa_nfsctime fa_un.fa_nfsv2.nfsfa_ctime
#define fa_nqsize fa_un.fa_nqnfs.nqfa_size
#define fa_nqblocksize fa_un.fa_nqnfs.nqfa_blocksize
#define fa_nqrdev fa_un.fa_nqnfs.nqfa_rdev
#define fa_nqbytes fa_un.fa_nqnfs.nqfa_bytes
#define fa_nqfsid fa_un.fa_nqnfs.nqfa_fsid
#define fa_nqfileid fa_un.fa_nqnfs.nqfa_fileid
#define fa_nqatime fa_un.fa_nqnfs.nqfa_atime
#define fa_nqmtime fa_un.fa_nqnfs.nqfa_mtime
#define fa_nqctime fa_un.fa_nqnfs.nqfa_ctime
#define fa_nqflags fa_un.fa_nqnfs.nqfa_flags
#define fa_nqgen fa_un.fa_nqnfs.nqfa_gen
#define fa_nqfilerev fa_un.fa_nqnfs.nqfa_filerev
#define fa2_size fa_un.fa_nfsv2.nfsv2fa_size
#define fa2_blocksize fa_un.fa_nfsv2.nfsv2fa_blocksize
#define fa2_rdev fa_un.fa_nfsv2.nfsv2fa_rdev
#define fa2_blocks fa_un.fa_nfsv2.nfsv2fa_blocks
#define fa2_fsid fa_un.fa_nfsv2.nfsv2fa_fsid
#define fa2_fileid fa_un.fa_nfsv2.nfsv2fa_fileid
#define fa2_atime fa_un.fa_nfsv2.nfsv2fa_atime
#define fa2_mtime fa_un.fa_nfsv2.nfsv2fa_mtime
#define fa2_ctime fa_un.fa_nfsv2.nfsv2fa_ctime
#define fa3_size fa_un.fa_nfsv3.nfsv3fa_size
#define fa3_used fa_un.fa_nfsv3.nfsv3fa_used
#define fa3_rdev fa_un.fa_nfsv3.nfsv3fa_rdev
#define fa3_fsid fa_un.fa_nfsv3.nfsv3fa_fsid
#define fa3_fileid fa_un.fa_nfsv3.nfsv3fa_fileid
#define fa3_atime fa_un.fa_nfsv3.nfsv3fa_atime
#define fa3_mtime fa_un.fa_nfsv3.nfsv3fa_mtime
#define fa3_ctime fa_un.fa_nfsv3.nfsv3fa_ctime
struct nfsv2_sattr {
u_long sa_mode;
u_long sa_uid;
u_long sa_gid;
union {
struct {
u_long nfssa_size;
struct nfsv2_time nfssa_atime;
struct nfsv2_time nfssa_mtime;
} sa_nfsv2;
struct {
struct {
u_long nqsa_qsize[2];
} nqsa_size;
struct nqnfs_time nqsa_atime;
struct nqnfs_time nqsa_mtime;
u_long nqsa_flags;
u_long nqsa_rdev;
} sa_nqnfs;
} sa_un;
u_long sa_mode;
u_long sa_uid;
u_long sa_gid;
u_long sa_size;
nfstime2 sa_atime;
nfstime2 sa_mtime;
};
/* and some ugly defines for accessing the unions */
#define sa_nfssize sa_un.sa_nfsv2.nfssa_size
#define sa_nfsatime sa_un.sa_nfsv2.nfssa_atime
#define sa_nfsmtime sa_un.sa_nfsv2.nfssa_mtime
#define sa_nqsize sa_un.sa_nqnfs.nqsa_size
#define sa_nqatime sa_un.sa_nqnfs.nqsa_atime
#define sa_nqmtime sa_un.sa_nqnfs.nqsa_mtime
#define sa_nqflags sa_un.sa_nqnfs.nqsa_flags
#define sa_nqrdev sa_un.sa_nqnfs.nqsa_rdev
struct nfsv2_statfs {
u_long sf_tsize;
u_long sf_bsize;
u_long sf_blocks;
u_long sf_bfree;
u_long sf_bavail;
u_long sf_files; /* Nqnfs only */
u_long sf_ffree; /* ditto */
};
struct nfsv3_fsstat {
nfsuint64 sf_tbytes;
nfsuint64 sf_fbytes;
nfsuint64 sf_abytes;
nfsuint64 sf_tfiles;
nfsuint64 sf_ffiles;
nfsuint64 sf_afiles;
u_long sf_invarsec;
};
struct nfsv3_fsinfo {
u_long fs_rtmax;
u_long fs_rtpref;
u_long fs_rtmult;
u_long fs_wtmax;
u_long fs_wtpref;
u_long fs_wtmult;
u_long fs_dtpref;
nfsuint64 fs_maxfilesize;
nfstime3 fs_time_delta;
u_long fs_properties;
};
#endif

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nqnfs.h 8.1 (Berkeley) 6/10/93
* $Id: nqnfs.h,v 1.5 1994/10/02 17:27:07 phk Exp $
* $Id: nqnfs.h,v 1.6 1994/10/17 17:47:45 phk Exp $
*/
#ifndef _NFS_NQNFS_H_
@ -58,7 +58,7 @@
#define NQLCHSZ 256 /* Server hash table size */
#define NQNFS_PROG 300105 /* As assigned by Sun */
#define NQNFS_VER1 1
#define NQNFS_VER3 3
#define NQNFS_EVICTSIZ 156 /* Size of eviction request in bytes */
/*
@ -142,14 +142,6 @@ struct nqm {
struct nqhost lpm_hosts[LC_MOREHOSTSIZ];
};
/*
* Flag bits for flags argument to nqsrv_getlease.
*/
#define NQL_READ LEASE_READ /* Read Request */
#define NQL_WRITE LEASE_WRITE /* Write Request */
#define NQL_CHECK 0x4 /* Check for lease */
#define NQL_NOVAL 0xffffffff /* Invalid */
/*
* Special value for slp for local server calls.
*/
@ -160,9 +152,9 @@ struct nqm {
*/
#define nqsrv_getl(v, l) \
(void) nqsrv_getlease((v), &nfsd->nd_duration, \
((nfsd->nd_nqlflag != 0 && nfsd->nd_nqlflag != NQL_NOVAL) ? nfsd->nd_nqlflag : \
((l) | NQL_CHECK)), \
nfsd, nam, &cache, &frev, cred)
((nfsd->nd_flag & ND_LEASE) ? (nfsd->nd_flag & ND_LEASE) : \
((l) | ND_CHECK)), \
slp, procp, nfsd->nd_nam, &cache, &frev, cred)
/*
* Client side macros that check for a valid lease.
@ -170,13 +162,13 @@ struct nqm {
#define NQNFS_CKINVALID(v, n, f) \
((time.tv_sec > (n)->n_expiry && \
VFSTONFS((v)->v_mount)->nm_timeouts < VFSTONFS((v)->v_mount)->nm_deadthresh) \
|| ((f) == NQL_WRITE && ((n)->n_flag & NQNFSWRITE) == 0))
|| ((f) == ND_WRITE && ((n)->n_flag & NQNFSWRITE) == 0))
#define NQNFS_CKCACHABLE(v, f) \
((time.tv_sec <= VTONFS(v)->n_expiry || \
VFSTONFS((v)->v_mount)->nm_timeouts >= VFSTONFS((v)->v_mount)->nm_deadthresh) \
&& (VTONFS(v)->n_flag & NQNFSNONCACHE) == 0 && \
((f) == NQL_READ || (VTONFS(v)->n_flag & NQNFSWRITE)))
((f) == ND_READ || (VTONFS(v)->n_flag & NQNFSWRITE)))
#define NQNFS_NEEDLEASE(v, p) \
(time.tv_sec > VTONFS(v)->n_expiry ? \
@ -184,7 +176,7 @@ struct nqm {
(((time.tv_sec + NQ_RENEWAL) > VTONFS(v)->n_expiry && \
nqnfs_piggy[p]) ? \
((VTONFS(v)->n_flag & NQNFSWRITE) ? \
NQL_WRITE : nqnfs_piggy[p]) : 0))
ND_WRITE : nqnfs_piggy[p]) : 0))
/*
* List head for timer queue.
@ -204,13 +196,12 @@ u_long nqfhhash;
*/
#define NQNFS_EXPIRED 500
#define NQNFS_TRYLATER 501
#define NQNFS_AUTHERR 502
#ifdef KERNEL
void nfs_lease_check __P((struct vnode *, struct proc *, struct ucred *, int));
void nfs_lease_updatetime __P((int));
#if defined(KERNEL) || defined(_KERNEL)
void nqnfs_lease_check __P((struct vnode *, struct proc *, struct ucred *, int));
void nqnfs_lease_updatetime __P((int));
int nqsrv_cmpnam __P((struct nfssvc_sock *,struct mbuf *,struct nqhost *));
int nqsrv_getlease __P((struct vnode *,u_long *,int,struct nfsd *,struct mbuf *,int *,u_quad_t *,struct ucred *));
int nqsrv_getlease __P((struct vnode *,u_long *,int,struct nfssvc_sock *,struct proc *,struct mbuf *,int *,u_quad_t *,struct ucred *));
int nqnfs_getlease __P((struct vnode *,int,struct ucred *,struct proc *));
int nqnfs_callback __P((struct nfsmount *,struct mbuf *,struct mbuf *,caddr_t));
int nqnfs_clientd __P((struct nfsmount *,struct ucred *,struct nfsd_cargs *,int,caddr_t,struct proc *));

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)rpcv2.h 8.1 (Berkeley) 6/10/93
* $Id: rpcv2.h,v 1.2 1994/08/02 07:52:29 davidg Exp $
* $Id: rpcv2.h,v 1.3 1994/08/21 06:50:15 paul Exp $
*/
#ifndef _NFS_RPCV2_H_
@ -52,10 +52,18 @@
#define RPCAUTH_NULL 0
#define RPCAUTH_UNIX 1
#define RPCAUTH_SHORT 2
#define RPCAUTH_KERB4 4
#define RPCAUTH_NQNFS 300000
#define RPCAUTH_MAXSIZ 400
#define RPCVERF_MAXSIZ 12 /* For Kerb, can actually be 400 */
#define RPCAUTH_UNIXGIDS 16
/*
* Constants associated with authentication flavours.
*/
#define RPCAKN_FULLNAME 0
#define RPCAKN_NICKNAME 1
/* Rpc Constants */
#define RPC_CALL 0
#define RPC_REPLY 1
@ -91,4 +99,43 @@
#define RPCMNT_PATHLEN 1024
#define RPCPROG_NFS 100003
/*
* Structures used for RPCAUTH_KERB4.
*/
struct nfsrpc_fullverf {
u_long t1;
u_long t2;
u_long w2;
};
struct nfsrpc_fullblock {
u_long t1;
u_long t2;
u_long w1;
u_long w2;
};
struct nfsrpc_nickverf {
u_long kind;
struct nfsrpc_fullverf verf;
};
/*
* and their sizes in bytes.. If sizeof (struct nfsrpc_xx) != these
* constants, well then things will break in mount_nfs and nfsd.
*/
#define RPCX_FULLVERF 12
#define RPCX_FULLBLOCK 16
#define RPCX_NICKVERF 16
#ifdef NFSKERB
XXX
#else
typedef u_char NFSKERBKEY_T[2];
typedef u_char NFSKERBKEYSCHED_T[2];
#endif
#define NFS_KERBSRV "rcmd" /* Kerberos Service for NFS */
#define NFS_KERBTTL (30 * 60) /* Credential ttl (sec) */
#define NFS_KERBCLOCKSKEW (5 * 60) /* Clock skew (sec) */
#define NFS_KERBW1(t) (*((u_long *)(&((t).dat[((t).length + 3) & ~0x3]))))
#endif

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)xdr_subs.h 8.1 (Berkeley) 6/10/93
* $Id: xdr_subs.h,v 1.3 1994/08/21 06:50:16 paul Exp $
* $Id: xdr_subs.h,v 1.4 1995/01/10 13:11:42 davidg Exp $
*/
#ifndef _NFS_XDR_SUBS_H_
@ -54,28 +54,28 @@
#define fxdr_unsigned(t, v) ((t)ntohl((long)(v)))
#define txdr_unsigned(v) (htonl((long)(v)))
#define fxdr_nfstime(f, t) { \
(t)->ts_sec = ntohl(((struct nfsv2_time *)(f))->nfs_sec); \
if (((struct nfsv2_time *)(f))->nfs_usec != 0xffffffff) \
(t)->ts_nsec = 1000 * ntohl(((struct nfsv2_time *)(f))->nfs_usec); \
#define fxdr_nfsv2time(f, t) { \
(t)->ts_sec = ntohl(((struct nfsv2_time *)(f))->nfsv2_sec); \
if (((struct nfsv2_time *)(f))->nfsv2_usec != 0xffffffff) \
(t)->ts_nsec = 1000 * ntohl(((struct nfsv2_time *)(f))->nfsv2_usec); \
else \
(t)->ts_nsec = -1; \
(t)->ts_nsec = 0; \
}
#define txdr_nfstime(f, t) { \
((struct nfsv2_time *)(t))->nfs_sec = htonl((f)->ts_sec); \
#define txdr_nfsv2time(f, t) { \
((struct nfsv2_time *)(t))->nfsv2_sec = htonl((f)->ts_sec); \
if ((f)->ts_nsec != -1) \
((struct nfsv2_time *)(t))->nfs_usec = htonl((f)->ts_nsec / 1000); \
((struct nfsv2_time *)(t))->nfsv2_usec = htonl((f)->ts_nsec / 1000); \
else \
((struct nfsv2_time *)(t))->nfs_usec = 0xffffffff; \
((struct nfsv2_time *)(t))->nfsv2_usec = 0xffffffff; \
}
#define fxdr_nqtime(f, t) { \
(t)->ts_sec = ntohl(((struct nqnfs_time *)(f))->nq_sec); \
(t)->ts_nsec = ntohl(((struct nqnfs_time *)(f))->nq_nsec); \
#define fxdr_nfsv3time(f, t) { \
(t)->ts_sec = ntohl(((struct nfsv3_time *)(f))->nfsv3_sec); \
(t)->ts_nsec = ntohl(((struct nfsv3_time *)(f))->nfsv3_nsec); \
}
#define txdr_nqtime(f, t) { \
((struct nqnfs_time *)(t))->nq_sec = htonl((f)->ts_sec); \
((struct nqnfs_time *)(t))->nq_nsec = htonl((f)->ts_nsec); \
#define txdr_nfsv3time(f, t) { \
((struct nfsv3_time *)(t))->nfsv3_sec = htonl((f)->ts_sec); \
((struct nfsv3_time *)(t))->nfsv3_nsec = htonl((f)->ts_nsec); \
}
#define fxdr_hyper(f, t) { \

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs.h 8.1 (Berkeley) 6/10/93
* $Id: nfs.h,v 1.8 1994/11/02 00:11:00 wollman Exp $
* $Id: nfs.h,v 1.9 1995/02/14 06:22:18 phk Exp $
*/
#ifndef _NFS_NFS_H_
@ -45,11 +45,12 @@
*/
#define NFS_MAXIOVEC 34
#define NFS_HZ 25 /* Ticks per second for NFS timeouts */
#define NFS_TIMEO (1*NFS_HZ) /* Default timeout = 1 second */
#define NFS_MINTIMEO (1*NFS_HZ) /* Min timeout to use */
#define NFS_MAXTIMEO (60*NFS_HZ) /* Max timeout to backoff to */
#define NFS_MINIDEMTIMEO (5*NFS_HZ) /* Min timeout for non-idempotent ops*/
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
#define NFS_MINIDEMTIMEO (5 * NFS_HZ) /* Min timeout for non-idempotent ops*/
#define NFS_MAXREXMIT 100 /* Stop counting after this many */
#define NFS_MAXWINDOW 1024 /* Max number of outstanding requests */
#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
@ -62,13 +63,81 @@
#endif
#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
#define NFS_READDIRSIZE 8192 /* Def. readdir size */
#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
#define NFS_MAXREADDIR NFS_MAXDATA /* Max. size of directory read */
#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
#define NFS_DIRBLKSIZ 1024 /* Size of an NFS directory block */
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
#ifndef NFS_GATHERDELAY
#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
#endif
#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
/*
* Oddballs
*/
#define NMOD(a) ((a) % nfs_asyncdaemons)
#define NFS_CMPFH(n, f, s) \
((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s)))
#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3)
#define NFS_SRVMAXDATA(n) \
(((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \
NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA)
/*
* XXX
* sys/buf.h should be editted to change B_APPENDWRITE --> B_NEEDCOMMIT, but
* until then...
* Same goes for sys/malloc.h, which needs M_NFSDIROFF,
* M_NFSRVDESC and M_NFSBIGFH added.
* The VA_EXCLUSIVE flag should be added for va_vaflags and set for an
* exclusive create.
* The B_INVAFTERWRITE flag should be set to whatever is required by the
* buffer cache code to say "Invalidate the block after it is written back".
*/
#ifndef B_NEEDCOMMIT
#define B_NEEDCOMMIT B_APPENDWRITE
#endif
#ifndef M_NFSRVDESC
#define M_NFSRVDESC M_TEMP
#endif
#ifndef M_NFSDIROFF
#define M_NFSDIROFF M_TEMP
#endif
#ifndef M_NFSBIGFH
#define M_NFSBIGFH M_TEMP
#endif
#ifndef VA_EXCLUSIVE
#define VA_EXCLUSIVE 0
#endif
#ifdef __FreeBSD__
#define B_INVAFTERWRITE B_NOCACHE
#else
#define B_INVAFTERWRITE B_INVAL
#endif
/*
* These ifdefs try to handle the differences between the various 4.4BSD-Lite
* based vfs interfaces.
* btw: NetBSD-current does have a VOP_LEASDE(), but I don't know how to
* differentiate between NetBSD-1.0 and NetBSD-current, so..
* I also don't know about BSDi's 2.0 release.
*/
#if !defined(HAS_VOPLEASE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
#define HAS_VOPLEASE 1
#endif
#if !defined(HAS_VOPREVOKE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
#define HAS_VOPREVOKE 1
#endif
/*
* The IO_METASYNC flag should be implemented for local file systems.
* (Until then, it is nothin at all.)
*/
#ifndef IO_METASYNC
#define IO_METASYNC 0
#endif
/*
* Set the attribute timeout based on how recently the file has been modified.
@ -79,6 +148,20 @@
((time.tv_sec - (np)->n_mtime) / 10 > NFS_MAXATTRTIMO ? NFS_MAXATTRTIMO : \
(time.tv_sec - (np)->n_mtime) / 10))
/*
* Expected allocation sizes for major data structures. If the actual size
* of the structure exceeds these sizes, then malloc() will be allocating
* almost twice the memory required. This is used in nfs_init() to warn
* the sysadmin that the size of a structure should be reduced.
* (These sizes are always a power of 2. If the kernel malloc() changes
* to one that does not allocate space in powers of 2 size, then this all
* becomes bunk!)
*/
#define NFS_NODEALLOC 256
#define NFS_MNTALLOC 512
#define NFS_SVCALLOC 256
#define NFS_UIDALLOC 128
/*
* Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
* should ever try and use it.
@ -95,7 +178,12 @@ struct nfsd_srvargs {
u_long nsd_haddr; /* Ip address of client */
struct ucred nsd_cr; /* Cred. uid maps to */
int nsd_authlen; /* Length of auth string (ret) */
char *nsd_authstr; /* Auth string (ret) */
u_char *nsd_authstr; /* Auth string (ret) */
int nsd_verflen; /* and the verfier */
u_char *nsd_verfstr;
struct timeval nsd_timestamp; /* timestamp from verifier */
u_long nsd_ttl; /* credential ttl (sec) */
NFSKERBKEY_T nsd_key; /* Session key */
};
struct nfsd_cargs {
@ -103,7 +191,10 @@ struct nfsd_cargs {
uid_t ncd_authuid; /* Effective uid */
int ncd_authtype; /* Type of authenticator */
int ncd_authlen; /* Length of authenticator string */
char *ncd_authstr; /* Authenticator string */
u_char *ncd_authstr; /* Authenticator string */
int ncd_verflen; /* and the verifier */
u_char *ncd_verfstr;
NFSKERBKEY_T ncd_key; /* Session key */
};
/*
@ -142,6 +233,7 @@ struct nfsstats {
int srvnqnfs_leases;
int srvnqnfs_maxleases;
int srvnqnfs_getleases;
int srvvop_writes;
};
/*
@ -173,7 +265,7 @@ struct nfsstats {
* such as SIGALRM will not expect file I/O system calls to be interrupted
* by them and break.
*/
#ifdef KERNEL
#if defined(KERNEL) || defined(_KERNEL)
struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
@ -224,17 +316,29 @@ TAILQ_HEAD(, nfsreq) nfs_reqq;
#define R_MUSTRESEND 0x40 /* Must resend request */
#define R_GETONEREP 0x80 /* Probe for one reply only */
extern struct nfsstats nfsstats;
/*
* A list of nfssvc_sock structures is maintained with all the sockets
* that require service by the nfsd.
* The nfsuid structs hang off of the nfssvc_sock structs in both lru
* and uid hash lists.
*/
#define NUIDHASHSIZ 32
#ifndef NFS_UIDHASHSIZ
#define NFS_UIDHASHSIZ 29 /* Tune the size of nfssvc_sock with this */
#endif
#define NUIDHASH(sock, uid) \
(&(sock)->ns_uidhashtbl[(uid) & (sock)->ns_uidhash])
(&(sock)->ns_uidhashtbl[(uid) % NFS_UIDHASHSIZ])
#ifndef NFS_WDELAYHASHSIZ
#define NFS_WDELAYHASHSIZ 16 /* and with this */
#endif
#define NWDELAYHASH(sock, f) \
(&(sock)->ns_wdelayhashtbl[(*((u_long *)(f))) % NFS_WDELAYHASHSIZ])
#ifndef NFS_MUIDHASHSIZ
#define NFS_MUIDHASHSIZ 67 /* Tune the size of nfsmount with this */
#endif
#define NMUIDHASH(nmp, uid) \
(&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
#define NFSNOHASH(fhsum) \
(&nfsnodehashtbl[(fhsum) & nfsnodehash])
/*
* Network address hash list element
@ -248,35 +352,41 @@ struct nfsuid {
TAILQ_ENTRY(nfsuid) nu_lru; /* LRU chain */
LIST_ENTRY(nfsuid) nu_hash; /* Hash list */
int nu_flag; /* Flags */
uid_t nu_uid; /* Uid mapped by this entry */
union nethostaddr nu_haddr; /* Host addr. for dgram sockets */
struct ucred nu_cr; /* Cred uid mapped to */
int nu_expire; /* Expiry time (sec) */
struct timeval nu_timestamp; /* Kerb. timestamp */
u_long nu_nickname; /* Nickname on server */
NFSKERBKEY_T nu_key; /* and session key */
};
#define nu_inetaddr nu_haddr.had_inetaddr
#define nu_nam nu_haddr.had_nam
/* Bits for nu_flag */
#define NU_INETADDR 0x1
#define NU_NAM 0x2
#define NU_NETFAM(u) (((u)->nu_flag & NU_INETADDR) ? AF_INET : AF_ISO)
struct nfssvc_sock {
TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
TAILQ_HEAD(, nfsuid) ns_uidlruhead;
LIST_HEAD(, nfsuid) *ns_uidhashtbl;
u_long ns_uidhash;
int ns_flag;
u_long ns_sref;
struct file *ns_fp;
struct socket *ns_so;
int ns_solock;
struct mbuf *ns_nam;
int ns_cc;
struct mbuf *ns_raw;
struct mbuf *ns_rawend;
int ns_reclen;
struct mbuf *ns_rec;
struct mbuf *ns_recend;
struct mbuf *ns_frag;
int ns_flag;
int ns_solock;
int ns_cc;
int ns_reclen;
int ns_numuids;
u_long ns_sref;
LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
LIST_HEAD(, nfsuid) ns_uidhashtbl[NFS_UIDHASHSIZ];
LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
};
/* Bits for "ns_flag" */
@ -285,6 +395,7 @@ struct nfssvc_sock {
#define SLP_NEEDQ 0x04
#define SLP_DISCONN 0x08
#define SLP_GETSTREAM 0x10
#define SLP_LASTFRAG 0x20
#define SLP_ALLFLAGS 0xff
TAILQ_HEAD(, nfssvc_sock) nfssvc_sockhead;
@ -296,73 +407,124 @@ int nfssvc_sockhead_flag;
* One of these structures is allocated for each nfsd.
*/
struct nfsd {
TAILQ_ENTRY(nfsd) nd_chain; /* List of all nfsd's */
int nd_flag; /* NFSD_ flags */
struct nfssvc_sock *nd_slp; /* Current socket */
struct mbuf *nd_nam; /* Client addr for datagram req. */
struct mbuf *nd_mrep; /* Req. mbuf list */
struct mbuf *nd_md;
caddr_t nd_dpos; /* Position in list */
int nd_procnum; /* RPC procedure number */
u_long nd_retxid; /* RPC xid */
int nd_repstat; /* Reply status value */
struct ucred nd_cr; /* Credentials for req. */
int nd_nqlflag; /* Leasing flag */
u_long nd_duration; /* Lease duration */
int nd_authlen; /* Authenticator len */
u_char nd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
struct proc *nd_procp; /* Proc ptr */
TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
int nfsd_flag; /* NFSD_ flags */
struct nfssvc_sock *nfsd_slp; /* Current socket */
int nfsd_authlen; /* Authenticator len */
u_char nfsd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
int nfsd_verflen; /* and the Verifier */
u_char nfsd_verfstr[RPCVERF_MAXSIZ];
struct proc *nfsd_procp; /* Proc ptr */
struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
};
/* Bits for "nd_flag" */
/* Bits for "nfsd_flag" */
#define NFSD_WAITING 0x01
#define NFSD_REQINPROG 0x02
#define NFSD_NEEDAUTH 0x04
#define NFSD_AUTHFAIL 0x08
/*
* This structure is used by the server for describing each request.
* Some fields are used only when write request gathering is performed.
*/
struct nfsrv_descript {
u_quad_t nd_time; /* Write deadline (usec) */
off_t nd_off; /* Start byte offset */
off_t nd_eoff; /* and end byte offset */
LIST_ENTRY(nfsrv_descript) nd_hash; /* Hash list */
LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
LIST_HEAD(,nfsrv_descript) nd_coalesce; /* coalesced writes */
struct mbuf *nd_mrep; /* Request mbuf list */
struct mbuf *nd_md; /* Current dissect mbuf */
struct mbuf *nd_mreq; /* Reply mbuf list */
struct mbuf *nd_nam; /* and socket addr */
struct mbuf *nd_nam2; /* return socket addr */
caddr_t nd_dpos; /* Current dissect pos */
int nd_procnum; /* RPC # */
int nd_stable; /* storage type */
int nd_flag; /* nd_flag */
int nd_len; /* Length of this write */
int nd_repstat; /* Reply status */
u_long nd_retxid; /* Reply xid */
u_long nd_duration; /* Lease duration */
struct timeval nd_starttime; /* Time RPC initiated */
fhandle_t nd_fh; /* File handle */
struct ucred nd_cr; /* Credentials */
};
/* Bits for "nd_flag" */
#define ND_READ LEASE_READ
#define ND_WRITE LEASE_WRITE
#define ND_CHECK 0x04
#define ND_LEASE (ND_READ | ND_WRITE | ND_CHECK)
#define ND_NFSV3 0x08
#define ND_NQNFS 0x10
#define ND_KERBNICK 0x20
#define ND_KERBFULL 0x40
#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
TAILQ_HEAD(, nfsd) nfsd_head;
int nfsd_head_flag;
#define NFSD_CHECKSLP 0x01
/*
* These macros compare nfsrv_descript structures.
*/
#define NFSW_CONTIG(o, n) \
((o)->nd_eoff >= (n)->nd_off && \
!bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH))
#define NFSW_SAMECRED(o, n) \
(((o)->nd_flag & ND_KERBAUTH) == ((n)->nd_flag & ND_KERBAUTH) && \
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
sizeof (struct ucred)))
int nfs_reply __P((struct nfsreq *));
int nfs_getreq __P((struct nfsd *,int));
int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
int nfs_send __P((struct socket *,struct mbuf *,struct mbuf *,struct nfsreq *));
int nfs_rephead __P((int,struct nfsd *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_rephead __P((int,struct nfsrv_descript *,struct nfssvc_sock *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_sndlock __P((int *,struct nfsreq *));
int nfs_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
int nfs_vinvalbuf __P((struct vnode *,int,struct ucred *,struct proc *,int));
int nfs_readrpc __P((struct vnode *,struct uio *,struct ucred *));
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int));
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int *,int *));
int nfs_readdirrpc __P((register struct vnode *,struct uio *,struct ucred *));
int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct proc *));
int nfs_asyncio __P((struct buf *,struct ucred *));
int nfs_doio __P((struct buf *,struct ucred *,struct proc *));
int nfs_readlinkrpc __P((struct vnode *,struct uio *,struct ucred *));
int nfs_sigintr __P((struct nfsmount *,struct nfsreq *r,struct proc *));
int nfs_readdirlookrpc __P((struct vnode *,register struct uio *,struct ucred *));
int nfs_readdirplusrpc __P((struct vnode *,register struct uio *,struct ucred *));
int nfsm_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *));
void nfsm_srvfattr __P((struct nfsrv_descript *,struct vattr *,struct nfs_fattr *));
void nfsm_srvwcc __P((struct nfsrv_descript *,int,struct vattr *,int,struct vattr *,struct mbuf **,char **));
void nfsm_srvpostopattr __P((struct nfsrv_descript *,int,struct vattr *,struct mbuf **,char **));
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *,int));
int nfsrv_access __P((struct vnode *,int,struct ucred *,int,struct proc *));
int netaddr_match __P((int,union nethostaddr *,struct mbuf *));
int nfs_request __P((struct vnode *,struct mbuf *,int,struct proc *,struct ucred *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_loadattrcache __P((struct vnode **,struct mbuf **,caddr_t *,struct vattr *));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct proc *));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int));
void nfsm_adj __P((struct mbuf *,int,int));
int nfsm_mbuftouio __P((struct mbuf **,struct uio *,int,caddr_t *));
void nfsrv_initcache __P((void));
int nfs_rcvlock __P((struct nfsreq *));
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,int *,char **,int *));
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,char **,int *,char *,int *,NFSKERBKEY_T));
int nfs_getnickauth __P((struct nfsmount *,struct ucred *,char **,int *,char *,int));
int nfs_savenickauth __P((struct nfsmount *,struct ucred *,int,NFSKERBKEY_T,struct mbuf **,char **,struct mbuf *));
int nfs_msg __P((struct proc *,char *,char *));
int nfs_adv __P((struct mbuf **,caddr_t *,int,int));
int nfsrv_getstream __P((struct nfssvc_sock *,int));
void nfs_nhinit __P((void));
void nfs_timer __P((void*));
struct nfsnodehashhead * nfs_hash __P((nfsv2fh_t *));
u_long nfs_hash __P((nfsfh_t *,int));
int nfssvc_iod __P((struct proc *));
int nfssvc_nfsd __P((struct nfsd_srvargs *,caddr_t,struct proc *));
int nfssvc_addsock __P((struct file *,struct mbuf *));
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *));
int nfsrv_getcache __P((struct mbuf *,struct nfsd *,struct mbuf **));
void nfsrv_updatecache __P((struct mbuf *,struct nfsd *,int,struct mbuf *));
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *,struct nfsrv_descript **));
int nfsrv_getcache __P((struct nfsrv_descript *,struct nfssvc_sock *,struct mbuf **));
void nfsrv_updatecache __P((struct nfsrv_descript *,int,struct mbuf *));
int mountnfs __P((struct nfs_args *,struct mount *,struct mbuf *,char *,char *,struct vnode **));
int nfs_connect __P((struct nfsmount *,struct nfsreq *));
int nfs_getattrcache __P((struct vnode *,struct vattr *));
@ -370,9 +532,20 @@ int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long));
int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *));
int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *));
void nfsrv_init __P((int));
void nfs_clearcommit __P((struct mount *));
int nfsrv_errmap __P((struct nfsrv_descript *, int));
void nfsrvw_coalesce __P((struct nfsrv_descript *,struct nfsrv_descript *));
void nfsrvw_sort __P((gid_t [],int));
void nfsrv_setcred __P((struct ucred *,struct ucred *));
int nfs_flush __P((struct vnode *,struct ucred *,int,struct proc *,int));
int nfs_writebp __P((struct buf *,int));
int nfsrv_vput __P(( struct vnode * ));
int nfsrv_vrele __P(( struct vnode * ));
int nfsrv_vmio __P(( struct vnode * ));
int nfsrv_writegather __P((struct nfsrv_descript **, struct nfssvc_sock *,
struct proc *, struct mbuf **));
int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
struct proc *p));
#endif /* KERNEL */

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_bio.c 8.5 (Berkeley) 1/4/94
* $Id: nfs_bio.c,v 1.13 1995/05/21 21:39:21 davidg Exp $
* $Id: nfs_bio.c,v 1.14 1995/05/30 08:12:35 rgrimes Exp $
*/
#include <sys/param.h>
@ -49,16 +49,30 @@
#include <vm/vm.h>
#include <nfs/nfsnode.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
#include <nfs/nfsmount.h>
#include <nfs/nqnfs.h>
#include <nfs/nfsnode.h>
struct buf *nfs_getcacheblk();
extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
extern int nfs_numasync;
extern struct nfsstats nfsstats;
/*
* Ifdefs for FreeBSD-current's merged VM/buffer cache. It is unfortunate
* that this isn't done inside getblk() and brelse() so these calls
* wouldn't need to be here.
*/
#ifdef B_VMIO
#define vnode_pager_uncache(vp)
#else
#define vfs_busy_pages(bp, f)
#define vfs_unbusy_pages(bp)
#define vfs_dirty_pages(bp)
#endif
/*
* Vnode op for read using bio
@ -72,29 +86,28 @@ nfs_bioread(vp, uio, ioflag, cred)
struct ucred *cred;
{
register struct nfsnode *np = VTONFS(vp);
register int biosize, diff;
register int biosize, diff, i;
struct buf *bp = 0, *rabp;
struct vattr vattr;
struct proc *p;
struct nfsmount *nmp;
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
daddr_t lbn, rabn;
int bufsize;
int nra, error = 0, n = 0, on = 0, not_readin;
nfsquad_t tquad;
#ifdef lint
ioflag = ioflag;
#endif /* lint */
#ifdef DIAGNOSTIC
if (uio->uio_rw != UIO_READ)
panic("nfs_read mode");
#endif
if (uio->uio_resid == 0)
return (0);
if (uio->uio_offset < 0 && vp->v_type != VDIR)
if (uio->uio_offset < 0)
return (EINVAL);
nmp = VFSTONFS(vp->v_mount);
biosize = NFS_MAXDGRAMDATA;
p = uio->uio_procp;
if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
(void)nfs_fsinfo(nmp, vp, cred, p);
biosize = nmp->nm_rsize;
/*
* For nfs, cache consistency can only be maintained approximately.
* Although RFC1094 does not specify the criteria, the following is
@ -107,8 +120,6 @@ nfs_bioread(vp, uio, ioflag, cred)
* server, so flush all of the file's data out of the cache.
* Then force a getattr rpc to ensure that you have up to date
* attributes.
* The mount flag NFSMNT_MYWRITE says "Assume that my writes are
* the ones changing the modify time.
* NB: This implies that cache data can be read when up to
* NFS_ATTRTIMEO seconds out of date. If you find that you need current
* attributes this could be forced by setting n_attrstamp to 0 before
@ -116,14 +127,15 @@ nfs_bioread(vp, uio, ioflag, cred)
*/
if ((nmp->nm_flag & NFSMNT_NQNFS) == 0 && vp->v_type != VLNK) {
if (np->n_flag & NMODIFIED) {
if ((nmp->nm_flag & NFSMNT_MYWRITE) == 0 ||
vp->v_type != VREG) {
if (vp->v_type != VREG) {
if (vp->v_type != VDIR)
panic("nfs: bioread, not dir");
nfs_invaldir(vp);
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
if (error)
return (error);
}
np->n_attrstamp = 0;
np->n_direofoffset = 0;
error = VOP_GETATTR(vp, &vattr, cred, p);
if (error)
return (error);
@ -133,7 +145,8 @@ nfs_bioread(vp, uio, ioflag, cred)
if (error)
return (error);
if (np->n_mtime != vattr.va_mtime.ts_sec) {
np->n_direofoffset = 0;
if (vp->v_type == VDIR)
nfs_invaldir(vp);
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
if (error)
return (error);
@ -147,27 +160,24 @@ nfs_bioread(vp, uio, ioflag, cred)
* Get a valid lease. If cached data is stale, flush it.
*/
if (nmp->nm_flag & NFSMNT_NQNFS) {
if (NQNFS_CKINVALID(vp, np, NQL_READ)) {
if (NQNFS_CKINVALID(vp, np, ND_READ)) {
do {
error = nqnfs_getlease(vp, NQL_READ, cred, p);
error = nqnfs_getlease(vp, ND_READ, cred, p);
} while (error == NQNFS_EXPIRED);
if (error)
return (error);
if (np->n_lrev != np->n_brev ||
(np->n_flag & NQNFSNONCACHE) ||
((np->n_flag & NMODIFIED) && vp->v_type == VDIR)) {
if (vp->v_type == VDIR) {
np->n_direofoffset = 0;
cache_purge(vp);
}
if (vp->v_type == VDIR)
nfs_invaldir(vp);
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
if (error)
return (error);
np->n_brev = np->n_lrev;
}
} else if (vp->v_type == VDIR && (np->n_flag & NMODIFIED)) {
np->n_direofoffset = 0;
cache_purge(vp);
nfs_invaldir(vp);
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
if (error)
return (error);
@ -176,33 +186,27 @@ nfs_bioread(vp, uio, ioflag, cred)
if (np->n_flag & NQNFSNONCACHE) {
switch (vp->v_type) {
case VREG:
error = nfs_readrpc(vp, uio, cred);
break;
return (nfs_readrpc(vp, uio, cred));
case VLNK:
error = nfs_readlinkrpc(vp, uio, cred);
break;
return (nfs_readlinkrpc(vp, uio, cred));
case VDIR:
error = nfs_readdirrpc(vp, uio, cred);
break;
default:
printf(" NQNFSNONCACHE: type %x unexpected\n",
vp->v_type);
break;
};
return (error);
}
switch (vp->v_type) {
case VREG:
nfsstats.biocache_reads++;
lbn = uio->uio_offset / biosize;
on = uio->uio_offset & (biosize-1);
on = uio->uio_offset & (biosize - 1);
not_readin = 1;
/*
* Start the read ahead(s), as required.
*/
if (nfs_numasync > 0 && nmp->nm_readahead > 0 &&
lbn == vp->v_lastr + 1) {
if (nfs_numasync > 0 && nmp->nm_readahead > 0) {
for (nra = 0; nra < nmp->nm_readahead &&
(lbn + 1 + nra) * biosize < np->n_size; nra++) {
rabn = lbn + 1 + nra;
@ -296,32 +300,55 @@ nfs_bioread(vp, uio, ioflag, cred)
break;
case VDIR:
nfsstats.biocache_readdirs++;
lbn = (daddr_t)uio->uio_offset;
lbn = uio->uio_offset / NFS_DIRBLKSIZ;
on = uio->uio_offset & (NFS_DIRBLKSIZ - 1);
bp = nfs_getcacheblk(vp, lbn, NFS_DIRBLKSIZ, p);
if (!bp)
return (EINTR);
return (EINTR);
if ((bp->b_flags & B_CACHE) == 0) {
bp->b_flags |= B_READ;
vfs_busy_pages(bp, 0);
error = nfs_doio(bp, cred, p);
if (error) {
bp->b_flags |= B_ERROR;
brelse(bp);
return (error);
bp->b_flags |= B_READ;
vfs_busy_pages(bp, 0);
error = nfs_doio(bp, cred, p);
if (error) {
brelse(bp);
while (error == NFSERR_BAD_COOKIE) {
nfs_invaldir(vp);
error = nfs_vinvalbuf(vp, 0, cred, p, 1);
/*
* Yuck! The directory has been modified on the
* server. The only way to get the block is by
* reading from the beginning to get all the
* offset cookies.
*/
for (i = 0; i <= lbn && !error; i++) {
bp = nfs_getcacheblk(vp, i, NFS_DIRBLKSIZ, p);
if (!bp)
return (EINTR);
if ((bp->b_flags & B_DONE) == 0) {
bp->b_flags |= B_READ;
vfs_busy_pages(bp, 0);
error = nfs_doio(bp, cred, p);
if (error)
brelse(bp);
}
}
}
if (error)
return (error);
}
}
/*
* If not eof and read aheads are enabled, start one.
* (You need the current block first, so that you have the
* directory offset cookie of the next block.
* directory offset cookie of the next block.)
*/
rabn = bp->b_blkno;
if (nfs_numasync > 0 && nmp->nm_readahead > 0 &&
rabn != 0 && rabn != np->n_direofoffset &&
!incore(vp, rabn)) {
rabp = nfs_getcacheblk(vp, rabn, NFS_DIRBLKSIZ, p);
(np->n_direofoffset == 0 ||
(lbn + 1) * NFS_DIRBLKSIZ < np->n_direofoffset) &&
!(np->n_flag & NQNFSNONCACHE) &&
!incore(vp, lbn + 1)) {
rabp = nfs_getcacheblk(vp, lbn + 1, NFS_DIRBLKSIZ, p);
if (rabp) {
if ((rabp->b_flags & (B_CACHE|B_DELWRI)) == 0) {
rabp->b_flags |= (B_READ | B_ASYNC);
@ -336,11 +363,10 @@ nfs_bioread(vp, uio, ioflag, cred)
}
}
}
on = 0;
n = min(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid);
n = min(uio->uio_resid, NFS_DIRBLKSIZ - bp->b_resid - on);
break;
default:
printf(" nfsbioread: type %x unexpected\n",vp->v_type);
printf(" nfs_bioread: type %x unexpected\n",vp->v_type);
break;
};
@ -354,11 +380,11 @@ nfs_bioread(vp, uio, ioflag, cred)
n = 0;
break;
case VDIR:
uio->uio_offset = bp->b_blkno;
if (np->n_flag & NQNFSNONCACHE)
bp->b_flags |= B_INVAL;
break;
default:
printf(" nfsbioread: type %x unexpected\n",vp->v_type);
break;
printf(" nfs_bioread: type %x unexpected\n",vp->v_type);
}
brelse(bp);
} while (error == 0 && uio->uio_resid > 0 && n > 0);
@ -386,10 +412,10 @@ nfs_write(ap)
int ioflag = ap->a_ioflag;
struct buf *bp;
struct vattr vattr;
struct nfsmount *nmp;
daddr_t lbn;
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
daddr_t lbn, bn;
int bufsize;
int n, on, error = 0;
int n, on, error = 0, iomode, must_commit;
#ifdef DIAGNOSTIC
if (uio->uio_rw != UIO_WRITE)
@ -403,6 +429,8 @@ nfs_write(ap)
np->n_flag &= ~NWRITEERR;
return (np->n_error);
}
if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3)
(void)nfs_fsinfo(nmp, vp, cred, p);
if (ioflag & (IO_APPEND | IO_SYNC)) {
if (np->n_flag & NMODIFIED) {
np->n_attrstamp = 0;
@ -418,7 +446,6 @@ nfs_write(ap)
uio->uio_offset = np->n_size;
}
}
nmp = VFSTONFS(vp->v_mount);
if (uio->uio_offset < 0)
return (EINVAL);
if (uio->uio_resid == 0)
@ -437,7 +464,7 @@ nfs_write(ap)
* will be the same size within a filesystem. nfs_writerpc will
* still use nm_wsize when sizing the rpc's.
*/
biosize = NFS_MAXDGRAMDATA;
biosize = nmp->nm_rsize;
do {
/*
@ -445,12 +472,11 @@ nfs_write(ap)
*/
/*
* Check for a valid write lease.
* If non-cachable, just do the rpc
*/
if ((nmp->nm_flag & NFSMNT_NQNFS) &&
NQNFS_CKINVALID(vp, np, NQL_WRITE)) {
NQNFS_CKINVALID(vp, np, ND_WRITE)) {
do {
error = nqnfs_getlease(vp, NQL_WRITE, cred, p);
error = nqnfs_getlease(vp, ND_WRITE, cred, p);
} while (error == NQNFS_EXPIRED);
if (error)
return (error);
@ -462,8 +488,13 @@ nfs_write(ap)
np->n_brev = np->n_lrev;
}
}
if (np->n_flag & NQNFSNONCACHE)
return (nfs_writerpc(vp, uio, cred, ioflag));
if ((np->n_flag & NQNFSNONCACHE) && uio->uio_iovcnt == 1) {
iomode = NFSV3WRITE_FILESYNC;
error = nfs_writerpc(vp, uio, cred, &iomode, &must_commit);
if (must_commit)
nfs_clearcommit(vp->v_mount);
return (error);
}
nfsstats.biocache_writes++;
lbn = uio->uio_offset / biosize;
on = uio->uio_offset & (biosize-1);
@ -509,9 +540,9 @@ nfs_write(ap)
* In case getblk() and/or bwrite() delayed us.
*/
if ((nmp->nm_flag & NFSMNT_NQNFS) &&
NQNFS_CKINVALID(vp, np, NQL_WRITE)) {
NQNFS_CKINVALID(vp, np, ND_WRITE)) {
do {
error = nqnfs_getlease(vp, NQL_WRITE, cred, p);
error = nqnfs_getlease(vp, ND_WRITE, cred, p);
} while (error == NQNFS_EXPIRED);
if (error) {
brelse(bp);
@ -540,7 +571,6 @@ nfs_write(ap)
bp->b_dirtyoff = on;
bp->b_dirtyend = on + n;
}
#ifndef notdef
if (bp->b_validend == 0 || bp->b_validend < bp->b_dirtyoff ||
bp->b_validoff > bp->b_dirtyend) {
bp->b_validoff = bp->b_dirtyoff;
@ -549,13 +579,6 @@ nfs_write(ap)
bp->b_validoff = min(bp->b_validoff, bp->b_dirtyoff);
bp->b_validend = max(bp->b_validend, bp->b_dirtyend);
}
#else
bp->b_validoff = bp->b_dirtyoff;
bp->b_validend = bp->b_dirtyend;
#endif
if (ioflag & IO_APPEND)
bp->b_flags |= B_APPENDWRITE;
/*
* If the lease is non-cachable or IO_SYNC do bwrite().
*/
@ -564,10 +587,16 @@ nfs_write(ap)
error = VOP_BWRITE(bp);
if (error)
return (error);
if (np->n_flag & NQNFSNONCACHE) {
error = nfs_vinvalbuf(vp, V_SAVE, cred, p, 1);
if (error)
return (error);
}
} else if ((n + on) == biosize &&
(nmp->nm_flag & NFSMNT_NQNFS) == 0) {
bp->b_proc = (struct proc *)0;
bawrite(bp);
bp->b_flags |= B_ASYNC;
(void)nfs_writebp(bp, 0);
} else
bdwrite(bp);
} while (uio->uio_resid > 0 && n > 0);
@ -590,6 +619,7 @@ nfs_getcacheblk(vp, bn, size, p)
{
register struct buf *bp;
struct nfsmount *nmp = VFSTONFS(vp->v_mount);
int biosize = nmp->nm_rsize;
if (nmp->nm_flag & NFSMNT_INT) {
bp = getblk(vp, bn, size, PCATCH, 0);
@ -602,7 +632,7 @@ nfs_getcacheblk(vp, bn, size, p)
bp = getblk(vp, bn, size, 0, 0);
if( vp->v_type == VREG)
bp->b_blkno = (bn * NFS_MAXDGRAMDATA) / DEV_BSIZE;
bp->b_blkno = (bn * biosize) / DEV_BSIZE;
return (bp);
}
@ -689,6 +719,7 @@ nfs_asyncio(bp, cred)
bp->b_rcred = cred;
}
} else {
bp->b_flags |= B_WRITEINPROG;
if (bp->b_wcred == NOCRED && cred != NOCRED) {
crhold(cred);
bp->b_wcred = cred;
@ -700,7 +731,25 @@ nfs_asyncio(bp, cred)
wakeup((caddr_t)&nfs_iodwant[i]);
return (0);
}
return (EIO);
/*
* If it is a read or a write already marked B_WRITEINPROG or B_NOCACHE
* return EIO so the process will call nfs_doio() and do it
* synchronously.
*/
if (bp->b_flags & (B_READ | B_WRITEINPROG | B_NOCACHE))
return (EIO);
/*
* Just turn the async write into a delayed write, instead of
* doing in synchronously. Hopefully, at least one of the nfsiods
* is currently doing a write for this file and will pick up the
* delayed writes before going back to sleep.
*/
bp->b_flags |= B_DELWRI;
reassignbuf(bp, bp->b_vp);
biodone(bp);
return (0);
}
/*
@ -717,9 +766,10 @@ nfs_doio(bp, cr, p)
register struct vnode *vp;
struct nfsnode *np;
struct nfsmount *nmp;
int error = 0, diff, len;
int error = 0, diff, len, iomode, must_commit = 0;
struct uio uio;
struct iovec io;
nfsquad_t tquad;
vp = bp->b_vp;
np = VTONFS(vp);
@ -740,15 +790,18 @@ nfs_doio(bp, cr, p)
io.iov_len = uiop->uio_resid = bp->b_bcount;
/* mapping was done by vmapbuf() */
io.iov_base = bp->b_data;
uiop->uio_offset = bp->b_blkno * DEV_BSIZE;
uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE;
if (bp->b_flags & B_READ) {
uiop->uio_rw = UIO_READ;
nfsstats.read_physios++;
error = nfs_readrpc(vp, uiop, cr);
} else {
int com;
iomode = NFSV3WRITE_DATASYNC;
uiop->uio_rw = UIO_WRITE;
nfsstats.write_physios++;
error = nfs_writerpc(vp, uiop, cr,0);
error = nfs_writerpc(vp, uiop, cr, &iomode, &com);
}
if (error) {
bp->b_flags |= B_ERROR;
@ -760,7 +813,7 @@ nfs_doio(bp, cr, p)
uiop->uio_rw = UIO_READ;
switch (vp->v_type) {
case VREG:
uiop->uio_offset = bp->b_blkno * DEV_BSIZE;
uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE;
nfsstats.read_bios++;
error = nfs_readrpc(vp, uiop, cr);
if (!error) {
@ -773,7 +826,7 @@ nfs_doio(bp, cr, p)
* Just zero fill the rest of the valid area.
*/
diff = bp->b_bcount - uiop->uio_resid;
len = np->n_size - (bp->b_blkno * DEV_BSIZE
len = np->n_size - (((u_quad_t)bp->b_blkno) * DEV_BSIZE
+ diff);
if (len > 0) {
len = min(len, uiop->uio_resid);
@ -786,31 +839,34 @@ nfs_doio(bp, cr, p)
}
if (p && (vp->v_flag & VTEXT) &&
(((nmp->nm_flag & NFSMNT_NQNFS) &&
NQNFS_CKINVALID(vp, np, NQL_READ) &&
NQNFS_CKINVALID(vp, np, ND_READ) &&
np->n_lrev != np->n_brev) ||
(!(nmp->nm_flag & NFSMNT_NQNFS) &&
np->n_mtime != np->n_vattr.va_mtime.ts_sec))) {
uprintf("Process killed due to text file modification\n");
psignal(p, SIGKILL);
#ifdef __NetBSD__
p->p_holdcnt++;
#else
p->p_flag |= P_NOSWAP;
#endif
}
break;
case VLNK:
uiop->uio_offset = 0;
uiop->uio_offset = (off_t)0;
nfsstats.readlink_bios++;
error = nfs_readlinkrpc(vp, uiop, cr);
break;
case VDIR:
uiop->uio_offset = bp->b_lblkno;
nfsstats.readdir_bios++;
if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS)
error = nfs_readdirlookrpc(vp, uiop, cr);
else
error = nfs_readdirrpc(vp, uiop, cr);
/*
* Save offset cookie in b_blkno.
*/
bp->b_blkno = uiop->uio_offset;
uiop->uio_offset = ((u_quad_t)bp->b_lblkno) * NFS_DIRBLKSIZ;
if (nmp->nm_flag & NFSMNT_RDIRPLUS) {
error = nfs_readdirplusrpc(vp, uiop, cr);
if (error == NFSERR_NOTSUPP)
nmp->nm_flag &= ~NFSMNT_RDIRPLUS;
}
if ((nmp->nm_flag & NFSMNT_RDIRPLUS) == 0)
error = nfs_readdirrpc(vp, uiop, cr);
break;
default:
printf("nfs_doio: type %x unexpected\n",vp->v_type);
@ -821,32 +877,44 @@ nfs_doio(bp, cr, p)
bp->b_error = error;
}
} else {
if (((bp->b_blkno * DEV_BSIZE) + bp->b_dirtyend) > np->n_size)
bp->b_dirtyend = np->n_size - (bp->b_blkno * DEV_BSIZE);
if (bp->b_dirtyend > bp->b_dirtyoff) {
io.iov_len = uiop->uio_resid = bp->b_dirtyend
- bp->b_dirtyoff;
uiop->uio_offset = (bp->b_blkno * DEV_BSIZE)
+ bp->b_dirtyoff;
- bp->b_dirtyoff;
uiop->uio_offset = ((off_t)bp->b_blkno) * DEV_BSIZE
+ bp->b_dirtyoff;
io.iov_base = (char *)bp->b_data + bp->b_dirtyoff;
uiop->uio_rw = UIO_WRITE;
nfsstats.write_bios++;
if (bp->b_flags & B_APPENDWRITE)
error = nfs_writerpc(vp, uiop, cr, IO_APPEND);
if ((bp->b_flags & (B_ASYNC | B_NEEDCOMMIT | B_NOCACHE)) == B_ASYNC)
iomode = NFSV3WRITE_UNSTABLE;
else
error = nfs_writerpc(vp, uiop, cr, 0);
bp->b_flags &= ~(B_WRITEINPROG | B_APPENDWRITE);
iomode = NFSV3WRITE_FILESYNC;
bp->b_flags |= B_WRITEINPROG;
error = nfs_writerpc(vp, uiop, cr, &iomode, &must_commit);
if (!error && iomode == NFSV3WRITE_UNSTABLE)
bp->b_flags |= B_NEEDCOMMIT;
else
bp->b_flags &= ~B_NEEDCOMMIT;
bp->b_flags &= ~B_WRITEINPROG;
/*
* For an interrupted write, the buffer is still valid and the
* write hasn't been pushed to the server yet, so we can't set
* B_ERROR and report the interruption by setting B_EINTR. For
* the B_ASYNC case, B_EINTR is not relevant, so the rpc attempt
* is essentially a noop.
*/
if (error == EINTR) {
/*
* For an interrupted write, the buffer is still valid
* and the write hasn't been pushed to the server yet,
* so we can't set B_ERROR and report the interruption
* by setting B_EINTR. For the B_ASYNC case, B_EINTR
* is not relevant, so the rpc attempt is essentially
* a noop. For the case of a V3 write rpc not being
* committed to stable storage, the block is still
* dirty and requires either a commit rpc or another
* write rpc with iomode == NFSV3WRITE_FILESYNC before
* the block is reused. This is indicated by setting
* the B_DELWRI and B_NEEDCOMMIT flags.
*/
if (error == EINTR
|| (!error && (bp->b_flags & B_NEEDCOMMIT))) {
bp->b_flags &= ~(B_INVAL|B_NOCACHE);
bp->b_flags |= B_DELWRI;
@ -874,6 +942,8 @@ nfs_doio(bp, cr, p)
}
}
bp->b_resid = uiop->uio_resid;
if (must_commit)
nfs_clearcommit(vp->v_mount);
biodone(bp);
return (error);
}

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_syscalls.c 8.3 (Berkeley) 1/4/94
* $Id: nfs_syscalls.c,v 1.5 1994/10/17 17:47:38 phk Exp $
* $Id: nfs_syscalls.c,v 1.6 1995/05/30 08:12:45 rgrimes Exp $
*/
#include <sys/param.h>
@ -61,9 +61,11 @@
#ifdef ISO
#include <netiso/iso.h>
#endif
#include <nfs/xdr_subs.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
#include <nfs/nfsm_subs.h>
#include <nfs/nfsrvcache.h>
#include <nfs/nfsmount.h>
#include <nfs/nfsnode.h>
@ -73,13 +75,14 @@
void nfsrv_zapsock __P((struct nfssvc_sock *));
/* Global defs. */
extern u_long nfs_prog, nfs_vers;
extern int (*nfsrv_procs[NFS_NPROCS])();
extern int (*nfsrv3_procs[NFS_NPROCS])();
extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
extern int nfs_numasync;
extern time_t nqnfsstarttime;
extern int nqsrv_writeslack;
extern int nfsrtton;
extern struct nfsstats nfsstats;
extern int nfsrvw_procrastinate;
struct nfssvc_sock *nfs_udpsock, *nfs_cltpsock;
int nuidhash_max = NFS_MAXUIDHASH;
static int nfs_numnfsd = 0;
@ -225,19 +228,25 @@ nfssvc(p, uap, retval)
if (error)
return (error);
if ((uap->flag & NFSSVC_AUTHIN) && ((nfsd = nsd->nsd_nfsd)) &&
(nfsd->nd_slp->ns_flag & SLP_VALID)) {
slp = nfsd->nd_slp;
(nfsd->nfsd_slp->ns_flag & SLP_VALID)) {
slp = nfsd->nfsd_slp;
/*
* First check to see if another nfsd has already
* added this credential.
*/
for (nuidp = NUIDHASH(slp, nsd->nsd_uid)->lh_first;
for (nuidp = NUIDHASH(slp,nsd->nsd_cr.cr_uid)->lh_first;
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
if (nuidp->nu_uid == nsd->nsd_uid)
if (nuidp->nu_cr.cr_uid == nsd->nsd_cr.cr_uid &&
(!nfsd->nfsd_nd->nd_nam2 ||
netaddr_match(NU_NETFAM(nuidp),
&nuidp->nu_haddr, nfsd->nfsd_nd->nd_nam2)))
break;
}
if (!nuidp) {
if (nuidp) {
nfsrv_setcred(&nuidp->nu_cr,&nfsd->nfsd_nd->nd_cr);
nfsd->nfsd_nd->nd_flag |= ND_KERBFULL;
} else {
/*
* Nope, so we will.
*/
@ -257,22 +266,53 @@ nfssvc(p, uap, retval)
LIST_REMOVE(nuidp, nu_hash);
TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp,
nu_lru);
if (nuidp->nu_flag & NU_NAM)
m_freem(nuidp->nu_nam);
}
nuidp->nu_flag = 0;
nuidp->nu_cr = nsd->nsd_cr;
if (nuidp->nu_cr.cr_ngroups > NGROUPS)
nuidp->nu_cr.cr_ngroups = NGROUPS;
nuidp->nu_cr.cr_ngroups = NGROUPS;
nuidp->nu_cr.cr_ref = 1;
nuidp->nu_uid = nsd->nsd_uid;
nuidp->nu_timestamp = nsd->nsd_timestamp;
nuidp->nu_expire = time.tv_sec + nsd->nsd_ttl;
/*
* and save the session key in nu_key.
*/
bcopy(nsd->nsd_key, nuidp->nu_key,
sizeof (nsd->nsd_key));
if (nfsd->nfsd_nd->nd_nam2) {
struct sockaddr_in *saddr;
saddr = mtod(nfsd->nfsd_nd->nd_nam2,
struct sockaddr_in *);
switch (saddr->sin_family) {
case AF_INET:
nuidp->nu_flag |= NU_INETADDR;
nuidp->nu_inetaddr =
saddr->sin_addr.s_addr;
break;
case AF_ISO:
default:
nuidp->nu_flag |= NU_NAM;
nuidp->nu_nam = m_copym(
nfsd->nfsd_nd->nd_nam2, 0,
M_COPYALL, M_WAIT);
break;
};
}
TAILQ_INSERT_TAIL(&slp->ns_uidlruhead, nuidp,
nu_lru);
LIST_INSERT_HEAD(NUIDHASH(slp, nsd->nsd_uid),
nuidp, nu_hash);
nfsrv_setcred(&nuidp->nu_cr,
&nfsd->nfsd_nd->nd_cr);
nfsd->nfsd_nd->nd_flag |= ND_KERBFULL;
}
}
}
if ((uap->flag & NFSSVC_AUTHINFAIL) && (nfsd = nsd->nsd_nfsd))
nfsd->nd_flag |= NFSD_AUTHFAIL;
nfsd->nfsd_flag |= NFSD_AUTHFAIL;
error = nfssvc_nfsd(nsd, uap->argp, p);
}
if (error == EINTR || error == ERESTART)
@ -353,8 +393,6 @@ nfssvc_addsock(fp, mynam)
slp = (struct nfssvc_sock *)
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
bzero((caddr_t)slp, sizeof (struct nfssvc_sock));
slp->ns_uidhashtbl =
hashinit(NUIDHASHSIZ, M_NFSSVC, &slp->ns_uidhash);
TAILQ_INIT(&slp->ns_uidlruhead);
TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain);
}
@ -381,44 +419,47 @@ nfssvc_nfsd(nsd, argp, p)
caddr_t argp;
struct proc *p;
{
register struct mbuf *m, *nam2;
register struct mbuf *m;
register int siz;
register struct nfssvc_sock *slp;
register struct socket *so;
register int *solockp;
struct nfsd *nd = nsd->nsd_nfsd;
struct mbuf *mreq, *nam;
struct timeval starttime;
struct nfsd *nfsd = nsd->nsd_nfsd;
struct nfsrv_descript *nd = NULL;
struct mbuf *mreq;
struct nfsuid *uidp;
int error = 0, cacherep, s;
int sotype;
int error = 0, cacherep, s, sotype, writes_todo;
u_quad_t cur_usec;
#ifndef nolint
cacherep = RC_DOIT;
writes_todo = 0;
#endif
s = splnet();
if (nd == (struct nfsd *)0) {
nsd->nsd_nfsd = nd = (struct nfsd *)
if (nfsd == (struct nfsd *)0) {
nsd->nsd_nfsd = nfsd = (struct nfsd *)
malloc(sizeof (struct nfsd), M_NFSD, M_WAITOK);
bzero((caddr_t)nd, sizeof (struct nfsd));
nd->nd_procp = p;
nd->nd_cr.cr_ref = 1;
TAILQ_INSERT_TAIL(&nfsd_head, nd, nd_chain);
nd->nd_nqlflag = NQL_NOVAL;
bzero((caddr_t)nfsd, sizeof (struct nfsd));
nfsd->nfsd_procp = p;
TAILQ_INSERT_TAIL(&nfsd_head, nfsd, nfsd_chain);
nfs_numnfsd++;
}
/*
* Loop getting rpc requests until SIGKILL.
*/
for (;;) {
if ((nd->nd_flag & NFSD_REQINPROG) == 0) {
while (nd->nd_slp == (struct nfssvc_sock *)0 &&
if ((nfsd->nfsd_flag & NFSD_REQINPROG) == 0) {
while (nfsd->nfsd_slp == (struct nfssvc_sock *)0 &&
(nfsd_head_flag & NFSD_CHECKSLP) == 0) {
nd->nd_flag |= NFSD_WAITING;
nfsd->nfsd_flag |= NFSD_WAITING;
nfsd_waiting++;
error = tsleep((caddr_t)nd, PSOCK | PCATCH, "nfsd", 0);
error = tsleep((caddr_t)nfsd, PSOCK | PCATCH,
"nfsd", 0);
nfsd_waiting--;
if (error)
goto done;
}
if (nd->nd_slp == (struct nfssvc_sock *)0 &&
if (nfsd->nfsd_slp == (struct nfssvc_sock *)0 &&
(nfsd_head_flag & NFSD_CHECKSLP) != 0) {
for (slp = nfssvc_sockhead.tqh_first; slp != 0;
slp = slp->ns_chain.tqe_next) {
@ -426,14 +467,14 @@ nfssvc_nfsd(nsd, argp, p)
== (SLP_VALID | SLP_DOREC)) {
slp->ns_flag &= ~SLP_DOREC;
slp->ns_sref++;
nd->nd_slp = slp;
nfsd->nfsd_slp = slp;
break;
}
}
if (slp == 0)
nfsd_head_flag &= ~NFSD_CHECKSLP;
}
if ((slp = nd->nd_slp) == (struct nfssvc_sock *)0)
if ((slp = nfsd->nfsd_slp) == (struct nfssvc_sock *)0)
continue;
if (slp->ns_flag & SLP_VALID) {
if (slp->ns_flag & SLP_DISCONN)
@ -446,86 +487,78 @@ nfssvc_nfsd(nsd, argp, p)
M_WAIT);
nfs_sndunlock(&slp->ns_solock);
}
error = nfsrv_dorec(slp, nd);
nd->nd_flag |= NFSD_REQINPROG;
error = nfsrv_dorec(slp, nfsd, &nd);
cur_usec = (u_quad_t)time.tv_sec * 1000000 +
(u_quad_t)time.tv_usec;
if (error && slp->ns_tq.lh_first &&
slp->ns_tq.lh_first->nd_time <= cur_usec) {
error = 0;
cacherep = RC_DOIT;
writes_todo = 1;
} else
writes_todo = 0;
nfsd->nfsd_flag |= NFSD_REQINPROG;
}
} else {
error = 0;
slp = nd->nd_slp;
slp = nfsd->nfsd_slp;
}
if (error || (slp->ns_flag & SLP_VALID) == 0) {
nd->nd_slp = (struct nfssvc_sock *)0;
nd->nd_flag &= ~NFSD_REQINPROG;
if (nd) {
free((caddr_t)nd, M_NFSRVDESC);
nd = NULL;
}
nfsd->nfsd_slp = (struct nfssvc_sock *)0;
nfsd->nfsd_flag &= ~NFSD_REQINPROG;
nfsrv_slpderef(slp);
continue;
}
splx(s);
so = slp->ns_so;
sotype = so->so_type;
starttime = time;
if (so->so_proto->pr_flags & PR_CONNREQUIRED)
solockp = &slp->ns_solock;
else
solockp = (int *)0;
/*
* nam == nam2 for connectionless protocols such as UDP
* nam2 == NULL for connection based protocols to disable
* recent request caching.
*/
nam2 = nd->nd_nam;
if (nam2) {
nam = nam2;
cacherep = RC_CHECKIT;
} else {
nam = slp->ns_nam;
cacherep = RC_DOIT;
}
if (nd) {
nd->nd_starttime = time;
if (nd->nd_nam2)
nd->nd_nam = nd->nd_nam2;
else
nd->nd_nam = slp->ns_nam;
/*
* Check to see if authorization is needed.
*/
if (nd->nd_flag & NFSD_NEEDAUTH) {
static int logauth = 0;
/*
* Check to see if authorization is needed.
*/
if (nfsd->nfsd_flag & NFSD_NEEDAUTH) {
nfsd->nfsd_flag &= ~NFSD_NEEDAUTH;
nsd->nsd_haddr = mtod(nd->nd_nam,
struct sockaddr_in *)->sin_addr.s_addr;
nsd->nsd_authlen = nfsd->nfsd_authlen;
nsd->nsd_verflen = nfsd->nfsd_verflen;
if (!copyout(nfsd->nfsd_authstr,nsd->nsd_authstr,
nfsd->nfsd_authlen) &&
!copyout(nfsd->nfsd_verfstr, nsd->nsd_verfstr,
nfsd->nfsd_verflen) &&
!copyout((caddr_t)nsd, argp, sizeof (*nsd)))
return (ENEEDAUTH);
cacherep = RC_DROPIT;
} else
cacherep = nfsrv_getcache(nd, slp, &mreq);
nd->nd_flag &= ~NFSD_NEEDAUTH;
/*
* Check for a mapping already installed.
*/
for (uidp = NUIDHASH(slp, nd->nd_cr.cr_uid)->lh_first;
uidp != 0; uidp = uidp->nu_hash.le_next) {
if (uidp->nu_uid == nd->nd_cr.cr_uid)
break;
}
if (!uidp) {
nsd->nsd_uid = nd->nd_cr.cr_uid;
if (nam2 && logauth++ == 0)
log(LOG_WARNING, "Kerberized NFS using UDP\n");
nsd->nsd_haddr =
mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
nsd->nsd_authlen = nd->nd_authlen;
if (copyout(nd->nd_authstr, nsd->nsd_authstr,
nd->nd_authlen) == 0 &&
copyout((caddr_t)nsd, argp, sizeof (*nsd)) == 0)
return (ENEEDAUTH);
cacherep = RC_DROPIT;
}
}
if (cacherep == RC_CHECKIT)
cacherep = nfsrv_getcache(nam2, nd, &mreq);
/*
* Check for just starting up for NQNFS and send
* fake "try again later" replies to the NQNFS clients.
*/
if (notstarted && nqnfsstarttime <= time.tv_sec) {
/*
* Check for just starting up for NQNFS and send
* fake "try again later" replies to the NQNFS clients.
*/
if (notstarted && nqnfsstarttime <= time.tv_sec) {
if (modify_flag) {
nqnfsstarttime = time.tv_sec + nqsrv_writeslack;
modify_flag = 0;
} else
notstarted = 0;
}
if (notstarted) {
if (nd->nd_nqlflag == NQL_NOVAL)
}
if (notstarted) {
if ((nd->nd_flag & ND_NQNFS) == 0)
cacherep = RC_DROPIT;
else if (nd->nd_procnum != NFSPROC_WRITE) {
nd->nd_procnum = NFSPROC_NOOP;
@ -533,36 +566,42 @@ nfssvc_nfsd(nsd, argp, p)
cacherep = RC_DOIT;
} else
modify_flag = 1;
} else if (nd->nd_flag & NFSD_AUTHFAIL) {
nd->nd_flag &= ~NFSD_AUTHFAIL;
} else if (nfsd->nfsd_flag & NFSD_AUTHFAIL) {
nfsd->nfsd_flag &= ~NFSD_AUTHFAIL;
nd->nd_procnum = NFSPROC_NOOP;
nd->nd_repstat = NQNFS_AUTHERR;
nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK);
cacherep = RC_DOIT;
}
}
switch (cacherep) {
case RC_DOIT:
error = (*(nfsrv_procs[nd->nd_procnum]))(nd,
nd->nd_mrep, nd->nd_md, nd->nd_dpos, &nd->nd_cr,
nam, &mreq);
if (nd->nd_cr.cr_ref != 1) {
printf("nfssvc cref=%d\n", nd->nd_cr.cr_ref);
panic("nfssvc cref");
}
/*
* Loop to get all the write rpc relies that have been
* gathered together.
*/
do {
switch (cacherep) {
case RC_DOIT:
if (writes_todo || (nd->nd_procnum == NFSPROC_WRITE &&
nfsrvw_procrastinate > 0 && !notstarted))
error = nfsrv_writegather(&nd, slp,
nfsd->nfsd_procp, &mreq);
else
error = (*(nfsrv3_procs[nd->nd_procnum]))(nd,
slp, nfsd->nfsd_procp, &mreq);
if (mreq == NULL)
break;
if (error) {
if (nd->nd_procnum != NQNFSPROC_VACATED)
nfsstats.srv_errs++;
if (nam2) {
nfsrv_updatecache(nam2, nd, FALSE, mreq);
m_freem(nam2);
}
nfsrv_updatecache(nd, FALSE, mreq);
if (nd->nd_nam2)
m_freem(nd->nd_nam2);
break;
}
nfsstats.srvrpccnt[nd->nd_procnum]++;
if (nam2)
nfsrv_updatecache(nam2, nd, TRUE, mreq);
nfsrv_updatecache(nd, TRUE, mreq);
nd->nd_mrep = (struct mbuf *)0;
case RC_REPLY:
case RC_REPLY:
m = mreq;
siz = 0;
while (m) {
@ -587,15 +626,15 @@ nfssvc_nfsd(nsd, argp, p)
if (solockp)
(void) nfs_sndlock(solockp, (struct nfsreq *)0);
if (slp->ns_flag & SLP_VALID)
error = nfs_send(so, nam2, m, (struct nfsreq *)0);
error = nfs_send(so, nd->nd_nam2, m, NULL);
else {
error = EPIPE;
m_freem(m);
}
if (nfsrtton)
nfsd_rt(&starttime, sotype, nd, nam, cacherep);
if (nam2)
MFREE(nam2, m);
nfsd_rt(sotype, nd, cacherep);
if (nd->nd_nam2)
MFREE(nd->nd_nam2, m);
if (nd->nd_mrep)
m_freem(nd->nd_mrep);
if (error == EPIPE)
@ -603,29 +642,50 @@ nfssvc_nfsd(nsd, argp, p)
if (solockp)
nfs_sndunlock(solockp);
if (error == EINTR || error == ERESTART) {
free((caddr_t)nd, M_NFSRVDESC);
nfsrv_slpderef(slp);
s = splnet();
goto done;
}
break;
case RC_DROPIT:
case RC_DROPIT:
if (nfsrtton)
nfsd_rt(&starttime, sotype, nd, nam, cacherep);
nfsd_rt(sotype, nd, cacherep);
m_freem(nd->nd_mrep);
m_freem(nam2);
m_freem(nd->nd_nam2);
break;
};
};
if (nd) {
FREE((caddr_t)nd, M_NFSRVDESC);
nd = NULL;
}
/*
* Check to see if there are outstanding writes that
* need to be serviced.
*/
cur_usec = (u_quad_t)time.tv_sec * 1000000 +
(u_quad_t)time.tv_usec;
s = splsoftclock();
if (slp->ns_tq.lh_first &&
slp->ns_tq.lh_first->nd_time <= cur_usec) {
cacherep = RC_DOIT;
writes_todo = 1;
} else
writes_todo = 0;
splx(s);
} while (writes_todo);
s = splnet();
if (nfsrv_dorec(slp, nd)) {
nd->nd_flag &= ~NFSD_REQINPROG;
nd->nd_slp = (struct nfssvc_sock *)0;
if (nfsrv_dorec(slp, nfsd, &nd)) {
nfsd->nfsd_flag &= ~NFSD_REQINPROG;
nfsd->nfsd_slp = NULL;
nfsrv_slpderef(slp);
}
}
done:
TAILQ_REMOVE(&nfsd_head, nd, nd_chain);
TAILQ_REMOVE(&nfsd_head, nfsd, nfsd_chain);
splx(s);
free((caddr_t)nd, M_NFSD);
free((caddr_t)nfsd, M_NFSD);
nsd->nsd_nfsd = (struct nfsd *)0;
if (--nfs_numnfsd == 0)
nfsrv_init(TRUE); /* Reinitialize everything */
@ -641,9 +701,10 @@ int
nfssvc_iod(p)
struct proc *p;
{
register struct buf *bp;
register struct buf *bp, *nbp;
register int i, myiod;
int error = 0;
struct vnode *vp;
int error = 0, s;
/*
* Assign my position or return error if too many already running
@ -662,24 +723,53 @@ nfssvc_iod(p)
* Just loop around doin our stuff until SIGKILL
*/
for (;;) {
while (nfs_bufq.tqh_first == NULL && error == 0) {
nfs_iodwant[myiod] = p;
error = tsleep((caddr_t)&nfs_iodwant[myiod],
PWAIT | PCATCH, "nfsidl", 0);
}
while ((bp = nfs_bufq.tqh_first) != NULL) {
/* Take one off the front of the list */
TAILQ_REMOVE(&nfs_bufq, bp, b_freelist);
if (bp->b_flags & B_READ)
(void) nfs_doio(bp, bp->b_rcred, (struct proc *)0);
else
(void) nfs_doio(bp, bp->b_wcred, (struct proc *)0);
}
if (error) {
nfs_asyncdaemon[myiod] = 0;
nfs_numasync--;
return (error);
}
while (nfs_bufq.tqh_first == NULL && error == 0) {
nfs_iodwant[myiod] = p;
error = tsleep((caddr_t)&nfs_iodwant[myiod],
PWAIT | PCATCH, "nfsidl", 0);
}
while ((bp = nfs_bufq.tqh_first) != NULL) {
/* Take one off the front of the list */
TAILQ_REMOVE(&nfs_bufq, bp, b_freelist);
if (bp->b_flags & B_READ)
(void) nfs_doio(bp, bp->b_rcred, (struct proc *)0);
else do {
/*
* Look for a delayed write for the same vnode, so I can do
* it now. We must grab it before calling nfs_doio() to
* avoid any risk of the vnode getting vclean()'d while
* we are doing the write rpc.
*/
vp = bp->b_vp;
s = splbio();
for (nbp = vp->v_dirtyblkhd.lh_first; nbp;
nbp = nbp->b_vnbufs.le_next) {
if ((nbp->b_flags &
(B_BUSY|B_DELWRI|B_NEEDCOMMIT|B_NOCACHE))!=B_DELWRI)
continue;
bremfree(nbp);
vfs_busy_pages(nbp, 1);
nbp->b_flags |= (B_BUSY|B_ASYNC);
break;
}
splx(s);
/*
* For the delayed write, do the first part of nfs_bwrite()
* up to, but not including nfs_strategy().
*/
if (nbp) {
nbp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI);
reassignbuf(nbp, nbp->b_vp);
nbp->b_vp->v_numoutput++;
}
(void) nfs_doio(bp, bp->b_wcred, (struct proc *)0);
} while (bp = nbp);
}
if (error) {
nfs_asyncdaemon[myiod] = 0;
nfs_numasync--;
return (error);
}
}
}
@ -695,9 +785,11 @@ nfsrv_zapsock(slp)
register struct nfssvc_sock *slp;
{
register struct nfsuid *nuidp, *nnuidp;
register struct nfsrv_descript *nwp, *nnwp;
struct socket *so;
struct file *fp;
struct mbuf *m;
int s;
slp->ns_flag &= ~SLP_ALLFLAGS;
fp = slp->ns_fp;
@ -716,8 +808,18 @@ nfsrv_zapsock(slp)
nnuidp = nuidp->nu_lru.tqe_next;
LIST_REMOVE(nuidp, nu_hash);
TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp, nu_lru);
if (nuidp->nu_flag & NU_NAM)
m_freem(nuidp->nu_nam);
free((caddr_t)nuidp, M_NFSUID);
}
s = splsoftclock();
for (nwp = slp->ns_tq.lh_first; nwp; nwp = nnwp) {
nnwp = nwp->nd_tq.le_next;
LIST_REMOVE(nwp, nd_tq);
free((caddr_t)nwp, M_NFSRVDESC);
}
LIST_INIT(&slp->ns_tq);
splx(s);
}
}
@ -726,13 +828,15 @@ nfsrv_zapsock(slp)
* on this mount point porpous out of the kernel and do it.
*/
int
nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
nfs_getauth(nmp, rep, cred, auth_str, auth_len, verf_str, verf_len, key)
register struct nfsmount *nmp;
struct nfsreq *rep;
struct ucred *cred;
int *auth_type;
char **auth_str;
int *auth_len;
char *verf_str;
int *verf_len;
NFSKERBKEY_T key; /* return session key */
{
int error = 0;
@ -748,6 +852,9 @@ nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
}
nmp->nm_flag &= ~(NFSMNT_WAITAUTH | NFSMNT_WANTAUTH);
nmp->nm_authstr = *auth_str = (char *)malloc(RPCAUTH_MAXSIZ, M_TEMP, M_WAITOK);
nmp->nm_authlen = RPCAUTH_MAXSIZ;
nmp->nm_verfstr = verf_str;
nmp->nm_verflen = *verf_len;
nmp->nm_authuid = cred->cr_uid;
wakeup((caddr_t)&nmp->nm_authstr);
@ -766,8 +873,9 @@ nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
if (error)
free((caddr_t)*auth_str, M_TEMP);
else {
*auth_type = nmp->nm_authtype;
*auth_len = nmp->nm_authlen;
*verf_len = nmp->nm_verflen;
bcopy((caddr_t)nmp->nm_key, (caddr_t)key, sizeof (key));
}
nmp->nm_flag &= ~NFSMNT_HASAUTH;
nmp->nm_flag |= NFSMNT_WAITAUTH;
@ -778,6 +886,149 @@ nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
return (error);
}
/*
* Get a nickname authenticator and verifier.
*/
int
nfs_getnickauth(nmp, cred, auth_str, auth_len, verf_str, verf_len)
struct nfsmount *nmp;
struct ucred *cred;
char **auth_str;
int *auth_len;
char *verf_str;
int verf_len;
{
register struct nfsuid *nuidp;
register u_long *nickp, *verfp;
struct timeval ktvin, ktvout;
NFSKERBKEYSCHED_T keys; /* stores key schedule */
#ifdef DIAGNOSTIC
if (verf_len < (4 * NFSX_UNSIGNED))
panic("nfs_getnickauth verf too small");
#endif
for (nuidp = NMUIDHASH(nmp, cred->cr_uid)->lh_first;
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
if (nuidp->nu_cr.cr_uid == cred->cr_uid)
break;
}
if (!nuidp || nuidp->nu_expire < time.tv_sec)
return (EACCES);
/*
* Move to the end of the lru list (end of lru == most recently used).
*/
TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp, nu_lru);
TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp, nu_lru);
nickp = (u_long *)malloc(2 * NFSX_UNSIGNED, M_TEMP, M_WAITOK);
*nickp++ = txdr_unsigned(RPCAKN_NICKNAME);
*nickp = txdr_unsigned(nuidp->nu_nickname);
*auth_str = (char *)nickp;
*auth_len = 2 * NFSX_UNSIGNED;
/*
* Now we must encrypt the verifier and package it up.
*/
verfp = (u_long *)verf_str;
*verfp++ = txdr_unsigned(RPCAKN_NICKNAME);
if (time.tv_sec > nuidp->nu_timestamp.tv_sec ||
(time.tv_sec == nuidp->nu_timestamp.tv_sec &&
time.tv_usec > nuidp->nu_timestamp.tv_usec))
nuidp->nu_timestamp = time;
else
nuidp->nu_timestamp.tv_usec++;
ktvin.tv_sec = txdr_unsigned(nuidp->nu_timestamp.tv_sec);
ktvin.tv_usec = txdr_unsigned(nuidp->nu_timestamp.tv_usec);
/*
* Now encrypt the timestamp verifier in ecb mode using the session
* key.
*/
#ifdef NFSKERB
XXX
#endif
*verfp++ = ktvout.tv_sec;
*verfp++ = ktvout.tv_usec;
*verfp = 0;
return (0);
}
/*
* Save the current nickname in a hash list entry on the mount point.
*/
int
nfs_savenickauth(nmp, cred, len, key, mdp, dposp, mrep)
register struct nfsmount *nmp;
struct ucred *cred;
int len;
NFSKERBKEY_T key;
struct mbuf **mdp;
char **dposp;
struct mbuf *mrep;
{
register struct nfsuid *nuidp;
register u_long *tl;
register long t1;
struct mbuf *md = *mdp;
struct timeval ktvin, ktvout;
u_long nick;
NFSKERBKEYSCHED_T keys;
char *dpos = *dposp, *cp2;
int deltasec, error = 0;
if (len == (3 * NFSX_UNSIGNED)) {
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
ktvin.tv_sec = *tl++;
ktvin.tv_usec = *tl++;
nick = fxdr_unsigned(u_long, *tl);
/*
* Decrypt the timestamp in ecb mode.
*/
#ifdef NFSKERB
XXX
#endif
ktvout.tv_sec = fxdr_unsigned(long, ktvout.tv_sec);
ktvout.tv_usec = fxdr_unsigned(long, ktvout.tv_usec);
deltasec = time.tv_sec - ktvout.tv_sec;
if (deltasec < 0)
deltasec = -deltasec;
/*
* If ok, add it to the hash list for the mount point.
*/
if (deltasec <= NFS_KERBCLOCKSKEW) {
if (nmp->nm_numuids < nuidhash_max) {
nmp->nm_numuids++;
nuidp = (struct nfsuid *)
malloc(sizeof (struct nfsuid), M_NFSUID,
M_WAITOK);
} else {
nuidp = nmp->nm_uidlruhead.tqh_first;
LIST_REMOVE(nuidp, nu_hash);
TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp,
nu_lru);
}
nuidp->nu_flag = 0;
nuidp->nu_cr.cr_uid = cred->cr_uid;
nuidp->nu_expire = time.tv_sec + NFS_KERBTTL;
nuidp->nu_timestamp = ktvout;
nuidp->nu_nickname = nick;
bcopy(key, nuidp->nu_key, sizeof (key));
TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp,
nu_lru);
LIST_INSERT_HEAD(NMUIDHASH(nmp, cred->cr_uid),
nuidp, nu_hash);
}
} else
nfsm_adv(nfsm_rndup(len));
nfsmout:
*mdp = md;
*dposp = dpos;
return (error);
}
/*
* Derefence a server socket structure. If it has no more references and
* is no longer valid, you can throw it away.
@ -830,16 +1081,12 @@ nfsrv_init(terminating)
nfs_udpsock = (struct nfssvc_sock *)
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
bzero((caddr_t)nfs_udpsock, sizeof (struct nfssvc_sock));
nfs_udpsock->ns_uidhashtbl =
hashinit(NUIDHASHSIZ, M_NFSSVC, &nfs_udpsock->ns_uidhash);
TAILQ_INIT(&nfs_udpsock->ns_uidlruhead);
TAILQ_INSERT_HEAD(&nfssvc_sockhead, nfs_udpsock, ns_chain);
nfs_cltpsock = (struct nfssvc_sock *)
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
bzero((caddr_t)nfs_cltpsock, sizeof (struct nfssvc_sock));
nfs_cltpsock->ns_uidhashtbl =
hashinit(NUIDHASHSIZ, M_NFSSVC, &nfs_cltpsock->ns_uidhash);
TAILQ_INIT(&nfs_cltpsock->ns_uidlruhead);
TAILQ_INSERT_TAIL(&nfssvc_sockhead, nfs_cltpsock, ns_chain);
}
@ -848,11 +1095,9 @@ nfsrv_init(terminating)
* Add entries to the server monitor log.
*/
static void
nfsd_rt(startp, sotype, nd, nam, cacherep)
struct timeval *startp;
nfsd_rt(sotype, nd, cacherep)
int sotype;
register struct nfsd *nd;
struct mbuf *nam;
register struct nfsrv_descript *nd;
int cacherep;
{
register struct drt *rt;
@ -866,15 +1111,17 @@ nfsd_rt(startp, sotype, nd, nam, cacherep)
rt->flag = DRT_CACHEDROP;
if (sotype == SOCK_STREAM)
rt->flag |= DRT_TCP;
if (nd->nd_nqlflag != NQL_NOVAL)
if (nd->nd_flag & ND_NQNFS)
rt->flag |= DRT_NQNFS;
else if (nd->nd_flag & ND_NFSV3)
rt->flag |= DRT_NFSV3;
rt->proc = nd->nd_procnum;
if (mtod(nam, struct sockaddr *)->sa_family == AF_INET)
rt->ipadr = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
if (mtod(nd->nd_nam, struct sockaddr *)->sa_family == AF_INET)
rt->ipadr = mtod(nd->nd_nam, struct sockaddr_in *)->sin_addr.s_addr;
else
rt->ipadr = INADDR_ANY;
rt->resptime = ((time.tv_sec - startp->tv_sec) * 1000000) +
(time.tv_usec - startp->tv_usec);
rt->ipadr = INADDR_ANY;
rt->resptime = ((time.tv_sec - nd->nd_starttime.tv_sec) * 1000000) +
(time.tv_usec - nd->nd_starttime.tv_usec);
rt->tstamp = time;
nfsdrt.pos = (nfsdrt.pos + 1) % NFSRTTLOGSIZ;
}

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_node.c 8.2 (Berkeley) 12/30/93
* $Id: nfs_node.c,v 1.7 1994/10/17 17:47:33 phk Exp $
* $Id: nfs_node.c,v 1.8 1995/03/16 18:15:36 bde Exp $
*/
#include <sys/param.h>
@ -47,14 +47,12 @@
#include <sys/malloc.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
#include <nfs/nfsnode.h>
#include <nfs/nfsmount.h>
#include <nfs/nqnfs.h>
#define NFSNOHASH(fhsum) \
(&nfsnodehashtbl[(fhsum) & nfsnodehash])
LIST_HEAD(nfsnodehashhead, nfsnode) *nfsnodehashtbl;
u_long nfsnodehash;
@ -79,19 +77,20 @@ nfs_nhinit()
/*
* Compute an entry in the NFS hash table structure
*/
struct nfsnodehashhead *
nfs_hash(fhp)
register nfsv2fh_t *fhp;
u_long
nfs_hash(fhp, fhsize)
register nfsfh_t *fhp;
int fhsize;
{
register u_char *fhpp;
register u_long fhsum;
int i;
register int i;
fhpp = &fhp->fh_bytes[0];
fhsum = 0;
for (i = 0; i < NFSX_FH; i++)
for (i = 0; i < fhsize; i++)
fhsum += *fhpp++;
return (NFSNOHASH(fhsum));
return (fhsum);
}
/*
@ -101,9 +100,10 @@ nfs_hash(fhp)
* nfsnode structure is returned.
*/
int
nfs_nget(mntp, fhp, npp)
nfs_nget(mntp, fhp, fhsize, npp)
struct mount *mntp;
register nfsv2fh_t *fhp;
register nfsfh_t *fhp;
int fhsize;
struct nfsnode **npp;
{
register struct nfsnode *np;
@ -112,11 +112,11 @@ nfs_nget(mntp, fhp, npp)
struct vnode *nvp;
int error;
nhpp = nfs_hash(fhp);
nhpp = NFSNOHASH(nfs_hash(fhp, fhsize));
loop:
for (np = nhpp->lh_first; np != 0; np = np->n_hash.le_next) {
if (mntp != NFSTOV(np)->v_mount ||
bcmp((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH))
if (mntp != NFSTOV(np)->v_mount || np->n_fhsize != fhsize ||
bcmp((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize))
continue;
vp = NFSTOV(np);
if (vget(vp, 1))
@ -131,27 +131,26 @@ nfs_nget(mntp, fhp, npp)
}
vp = nvp;
MALLOC(np, struct nfsnode *, sizeof *np, M_NFSNODE, M_WAITOK);
bzero((caddr_t)np, sizeof *np);
vp->v_data = np;
np->n_vnode = vp;
/*
* Insert the nfsnode in the hash queue for its new file handle
*/
np->n_flag = 0;
LIST_INSERT_HEAD(nhpp, np, n_hash);
bcopy((caddr_t)fhp, (caddr_t)&np->n_fh, NFSX_FH);
np->n_attrstamp = 0;
np->n_direofoffset = 0;
np->n_sillyrename = (struct sillyrename *)0;
np->n_size = 0;
np->n_mtime = 0;
np->n_lockf = 0;
if (VFSTONFS(mntp)->nm_flag & NFSMNT_NQNFS) {
np->n_brev = 0;
np->n_lrev = 0;
np->n_expiry = (time_t)0;
np->n_timer.cqe_next = (struct nfsnode *)0;
}
if (fhsize > NFS_SMALLFH) {
MALLOC(np->n_fhp, nfsfh_t *, fhsize, M_NFSBIGFH, M_WAITOK);
} else
np->n_fhp = &np->n_fh;
bcopy((caddr_t)fhp, (caddr_t)np->n_fhp, fhsize);
np->n_fhsize = fhsize;
*npp = np;
/*
* Lock the new nfsnode.
*/
VOP_LOCK(vp);
return (0);
}
@ -168,7 +167,10 @@ nfs_inactive(ap)
np = VTONFS(ap->a_vp);
if (prtactive && ap->a_vp->v_usecount != 0)
vprint("nfs_inactive: pushing active", ap->a_vp);
sp = np->n_sillyrename;
if (ap->a_vp->v_type != VDIR)
sp = np->n_sillyrename;
else
sp = (struct sillyrename *)0;
np->n_sillyrename = (struct sillyrename *)0;
if (sp) {
/*
@ -178,9 +180,7 @@ nfs_inactive(ap)
nfs_removeit(sp);
crfree(sp->s_cred);
vrele(sp->s_dvp);
#ifdef SILLYSEPARATE
free((caddr_t)sp, M_NFSREQ);
#endif
FREE((caddr_t)sp, M_NFSREQ);
}
np->n_flag &= (NMODIFIED | NFLUSHINPROG | NFLUSHWANT | NQNFSEVICTED |
NQNFSNONCACHE | NQNFSWRITE);
@ -199,6 +199,7 @@ nfs_reclaim(ap)
register struct vnode *vp = ap->a_vp;
register struct nfsnode *np = VTONFS(vp);
register struct nfsmount *nmp = VFSTONFS(vp->v_mount);
register struct nfsdmap *dp, *dp2;
if (prtactive && vp->v_usecount != 0)
vprint("nfs_reclaim: pushing active", vp);
@ -211,6 +212,24 @@ nfs_reclaim(ap)
if ((nmp->nm_flag & NFSMNT_NQNFS) && np->n_timer.cqe_next != 0) {
CIRCLEQ_REMOVE(&nmp->nm_timerhead, np, n_timer);
}
/*
* Free up any directory cookie structures and
* large file handle structures that might be associated with
* this nfs node.
*/
if (vp->v_type == VDIR) {
dp = np->n_cookies.lh_first;
while (dp) {
dp2 = dp;
dp = dp->ndm_list.le_next;
FREE((caddr_t)dp2, M_NFSDIROFF);
}
}
if (np->n_fhsize > NFS_SMALLFH) {
FREE((caddr_t)np->n_fhp, M_NFSBIGFH);
}
cache_purge(vp);
FREE(vp->v_data, M_NFSNODE);
vp->v_data = (void *)0;
@ -227,6 +246,7 @@ nfs_lock(ap)
} */ *ap;
{
register struct vnode *vp = ap->a_vp;
struct nfsnode *np = VTONFS(vp);
/*
* Ugh, another place where interruptible mounts will get hung.
@ -239,6 +259,33 @@ nfs_lock(ap)
}
if (vp->v_tag == VT_NON)
return (ENOENT);
#if 0
/*
* Only lock regular files. If a server crashed while we were
* holding a directory lock, we could easily end up sleeping
* until the server rebooted while holding a lock on the root.
* Locks are only needed for protecting critical sections in
* VMIO at the moment.
* New vnodes will have type VNON but they should be locked
* since they may become VREG. This is checked in loadattrcache
* and unwanted locks are released there.
*/
if (vp->v_type == VREG || vp->v_type == VNON) {
while (np->n_flag & NLOCKED) {
np->n_flag |= NWANTED;
(void) tsleep((caddr_t) np, PINOD, "nfslck2", 0);
/*
* If the vnode has transmuted into a VDIR while we
* were asleep, then skip the lock.
*/
if (vp->v_type != VREG && vp->v_type != VNON)
return (0);
}
np->n_flag |= NLOCKED;
}
#endif
return (0);
}
@ -251,6 +298,20 @@ nfs_unlock(ap)
struct vnode *a_vp;
} */ *ap;
{
#if 0
struct vnode* vp = ap->a_vp;
struct nfsnode* np = VTONFS(vp);
if (vp->v_type == VREG || vp->v_type == VNON) {
if (!(np->n_flag & NLOCKED))
panic("nfs_unlock: nfsnode not locked");
np->n_flag &= ~NLOCKED;
if (np->n_flag & NWANTED) {
np->n_flag &= ~NWANTED;
wakeup((caddr_t) np);
}
}
#endif
return (0);
}
@ -264,8 +325,7 @@ nfs_islocked(ap)
struct vnode *a_vp;
} */ *ap;
{
return (0);
return VTONFS(ap->a_vp)->n_flag & NLOCKED ? 1 : 0;
}
/*

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_socket.c 8.3 (Berkeley) 1/12/94
* $Id: nfs_socket.c,v 1.6 1995/03/16 18:15:37 bde Exp $
* $Id: nfs_socket.c,v 1.7 1995/05/30 08:12:40 rgrimes Exp $
*/
/*
@ -59,7 +59,7 @@
#include <netinet/tcp.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
#include <nfs/xdr_subs.h>
#include <nfs/nfsm_subs.h>
@ -94,36 +94,13 @@
* External data, mostly RPC constants in XDR form
*/
extern u_long rpc_reply, rpc_msgdenied, rpc_mismatch, rpc_vers, rpc_auth_unix,
rpc_msgaccepted, rpc_call, rpc_autherr, rpc_rejectedcred,
rpc_msgaccepted, rpc_call, rpc_autherr,
rpc_auth_kerb;
extern u_long nfs_prog, nfs_vers, nqnfs_prog, nqnfs_vers;
extern u_long nfs_prog, nqnfs_prog;
extern time_t nqnfsstarttime;
extern int nonidempotent[NFS_NPROCS];
/*
* Maps errno values to nfs error numbers.
* Use NFSERR_IO as the catch all for ones not specifically defined in
* RFC 1094.
*/
static int nfsrv_errmap[ELAST] = {
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,
NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE,
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
NFSERR_IO,
};
extern struct nfsstats nfsstats;
extern int nfsv3_procid[NFS_NPROCS];
extern int nfs_ticks;
/*
* Defines which timer to use for the procnum.
@ -134,7 +111,8 @@ static int nfsrv_errmap[ELAST] = {
* 4 - write
*/
static int proct[NFS_NPROCS] = {
0, 1, 0, 0, 2, 3, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0,
0, 1, 0, 2, 1, 3, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0,
0, 0, 0,
};
/*
@ -164,10 +142,12 @@ int nfsrv_null(),
nfsrv_getattr(),
nfsrv_setattr(),
nfsrv_lookup(),
nfsrv3_access(),
nfsrv_readlink(),
nfsrv_read(),
nfsrv_write(),
nfsrv_create(),
nfsrv_mknod(),
nfsrv_remove(),
nfsrv_rename(),
nfsrv_link(),
@ -175,37 +155,42 @@ int nfsrv_null(),
nfsrv_mkdir(),
nfsrv_rmdir(),
nfsrv_readdir(),
nfsrv_readdirplus(),
nfsrv_statfs(),
nfsrv_fsinfo(),
nfsrv_pathconf(),
nfsrv_commit(),
nfsrv_noop(),
nqnfsrv_readdirlook(),
nqnfsrv_getlease(),
nqnfsrv_vacated(),
nqnfsrv_access();
nqnfsrv_vacated();
int (*nfsrv_procs[NFS_NPROCS])() = {
int (*nfsrv3_procs[NFS_NPROCS])() = {
nfsrv_null,
nfsrv_getattr,
nfsrv_setattr,
nfsrv_noop,
nfsrv_lookup,
nfsrv3_access,
nfsrv_readlink,
nfsrv_read,
nfsrv_noop,
nfsrv_write,
nfsrv_create,
nfsrv_mkdir,
nfsrv_symlink,
nfsrv_mknod,
nfsrv_remove,
nfsrv_rmdir,
nfsrv_rename,
nfsrv_link,
nfsrv_symlink,
nfsrv_mkdir,
nfsrv_rmdir,
nfsrv_readdir,
nfsrv_readdirplus,
nfsrv_statfs,
nqnfsrv_readdirlook,
nfsrv_fsinfo,
nfsrv_pathconf,
nfsrv_commit,
nqnfsrv_getlease,
nqnfsrv_vacated,
nfsrv_noop,
nqnfsrv_access,
nfsrv_noop
};
/*
@ -874,13 +859,16 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
struct nfsmount *nmp;
struct mbuf *md, *mheadend;
struct nfsnode *np;
char nickv[RPCX_NICKVERF];
time_t reqtime, waituntil;
caddr_t dpos, cp2;
int t1, nqlflag, cachable, s, error = 0, mrest_len, auth_len, auth_type;
int trylater_delay = NQ_TRYLATERDEL, trylater_cnt = 0, failed_auth = 0;
int verf_len, verf_type;
u_long xid;
u_quad_t frev;
char *auth_str;
char *auth_str, *verf_str;
NFSKERBKEY_T key; /* save session key */
nmp = VFSTONFS(vp->v_mount);
MALLOC(rep, struct nfsreq *, sizeof(struct nfsreq), M_NFSREQ, M_WAITOK);
@ -900,19 +888,21 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
* Get the RPC header with authorization.
*/
kerbauth:
auth_str = (char *)0;
verf_str = auth_str = (char *)0;
if (nmp->nm_flag & NFSMNT_KERB) {
if (failed_auth) {
error = nfs_getauth(nmp, rep, cred, &auth_type,
&auth_str, &auth_len);
verf_str = nickv;
verf_len = sizeof (nickv);
auth_type = RPCAUTH_KERB4;
bzero((caddr_t)key, sizeof (key));
if (failed_auth || nfs_getnickauth(nmp, cred, &auth_str,
&auth_len, verf_str, verf_len)) {
error = nfs_getauth(nmp, rep, cred, &auth_str,
&auth_len, verf_str, &verf_len, key);
if (error) {
free((caddr_t)rep, M_NFSREQ);
m_freem(mrest);
return (error);
}
} else {
auth_type = RPCAUTH_UNIX;
auth_len = 5 * NFSX_UNSIGNED;
}
} else {
auth_type = RPCAUTH_UNIX;
@ -922,8 +912,8 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
nmp->nm_numgrps : (cred->cr_ngroups - 1)) << 2) +
5 * NFSX_UNSIGNED;
}
m = nfsm_rpchead(cred, (nmp->nm_flag & NFSMNT_NQNFS), procnum,
auth_type, auth_len, auth_str, mrest, mrest_len, &mheadend, &xid);
m = nfsm_rpchead(cred, nmp->nm_flag, procnum, auth_type, auth_len,
auth_str, verf_len, verf_str, mrest, mrest_len, &mheadend, &xid);
if (auth_str)
free(auth_str, M_TEMP);
@ -1029,12 +1019,12 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
/*
* break down the rpc header and check if ok
*/
nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED);
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
if (*tl++ == rpc_msgdenied) {
if (*tl == rpc_mismatch)
error = EOPNOTSUPP;
else if ((nmp->nm_flag & NFSMNT_KERB) && *tl++ == rpc_autherr) {
if (*tl == rpc_rejectedcred && failed_auth == 0) {
if (!failed_auth) {
failed_auth++;
mheadend->m_next = (struct mbuf *)0;
m_freem(mrep);
@ -1051,22 +1041,25 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
}
/*
* skip over the auth_verf, someday we may want to cache auth_short's
* for nfs_reqhead(), but for now just dump it
* Grab any Kerberos verifier, otherwise just throw it away.
*/
if (*++tl != 0) {
i = nfsm_rndup(fxdr_unsigned(long, *tl));
nfsm_adv(i);
}
verf_type = fxdr_unsigned(int, *tl++);
i = fxdr_unsigned(int, *tl);
if ((nmp->nm_flag & NFSMNT_KERB) && verf_type == RPCAUTH_KERB4) {
error = nfs_savenickauth(nmp, cred, i, key, &md, &dpos, mrep);
if (error)
goto nfsmout;
} else if (i > 0)
nfsm_adv(nfsm_rndup(i));
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
/* 0 == ok */
if (*tl == 0) {
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
if (*tl != 0) {
error = fxdr_unsigned(int, *tl);
m_freem(mrep);
if ((nmp->nm_flag & NFSMNT_NQNFS) &&
error == NQNFS_TRYLATER) {
if ((nmp->nm_flag & NFSMNT_NFSV3) &&
error == NFSERR_TRYLATER) {
m_freem(mrep);
error = 0;
waituntil = time.tv_sec + trylater_delay;
while (time.tv_sec < waituntil)
@ -1084,6 +1077,13 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
*/
if (error == ESTALE)
cache_purge(vp);
if (nmp->nm_flag & NFSMNT_NFSV3) {
*mrp = mrep;
*mdp = md;
*dposp = dpos;
error |= NFSERR_RETERR;
} else
m_freem(mrep);
m_freem(rep->r_mreq);
free((caddr_t)rep, M_NFSREQ);
return (error);
@ -1115,10 +1115,10 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
return (0);
}
m_freem(mrep);
m_freem(rep->r_mreq);
free((caddr_t)rep, M_NFSREQ);
error = EPROTONOSUPPORT;
nfsmout:
m_freem(rep->r_mreq);
free((caddr_t)rep, M_NFSREQ);
return (error);
}
@ -1127,9 +1127,10 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
* siz arg. is used to decide if adding a cluster is worthwhile
*/
int
nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
nfs_rephead(siz, nd, slp, err, cache, frev, mrq, mbp, bposp)
int siz;
struct nfsd *nd;
struct nfsrv_descript *nd;
struct nfssvc_sock *slp;
int err;
int cache;
u_quad_t *frev;
@ -1154,47 +1155,98 @@ nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
} else
mreq->m_data += max_hdr;
tl = mtod(mreq, u_long *);
mreq->m_len = 6*NFSX_UNSIGNED;
bpos = ((caddr_t)tl)+mreq->m_len;
mreq->m_len = 6 * NFSX_UNSIGNED;
bpos = ((caddr_t)tl) + mreq->m_len;
*tl++ = txdr_unsigned(nd->nd_retxid);
*tl++ = rpc_reply;
if (err == ERPCMISMATCH || err == NQNFS_AUTHERR) {
if (err == ERPCMISMATCH || (err & NFSERR_AUTHERR)) {
*tl++ = rpc_msgdenied;
if (err == NQNFS_AUTHERR) {
if (err & NFSERR_AUTHERR) {
*tl++ = rpc_autherr;
*tl = rpc_rejectedcred;
*tl = txdr_unsigned(err & ~NFSERR_AUTHERR);
mreq->m_len -= NFSX_UNSIGNED;
bpos -= NFSX_UNSIGNED;
} else {
*tl++ = rpc_mismatch;
*tl++ = txdr_unsigned(2);
*tl = txdr_unsigned(2);
*tl++ = txdr_unsigned(RPC_VER2);
*tl = txdr_unsigned(RPC_VER2);
}
} else {
*tl++ = rpc_msgaccepted;
*tl++ = 0;
*tl++ = 0;
/*
* For Kerberos authentication, we must send the nickname
* verifier back, otherwise just RPCAUTH_NULL.
*/
if (nd->nd_flag & ND_KERBFULL) {
register struct nfsuid *nuidp;
struct timeval ktvin, ktvout;
NFSKERBKEYSCHED_T keys; /* stores key schedule */
for (nuidp = NUIDHASH(slp, nd->nd_cr.cr_uid)->lh_first;
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
if (nuidp->nu_cr.cr_uid == nd->nd_cr.cr_uid &&
(!nd->nd_nam2 || netaddr_match(NU_NETFAM(nuidp),
&nuidp->nu_haddr, nd->nd_nam2)))
break;
}
if (nuidp) {
ktvin.tv_sec =
txdr_unsigned(nuidp->nu_timestamp.tv_sec - 1);
ktvin.tv_usec =
txdr_unsigned(nuidp->nu_timestamp.tv_usec);
/*
* Encrypt the timestamp in ecb mode using the
* session key.
*/
#ifdef NFSKERB
XXX
#endif
*tl++ = rpc_auth_kerb;
*tl++ = txdr_unsigned(3 * NFSX_UNSIGNED);
*tl = ktvout.tv_sec;
nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED);
*tl++ = ktvout.tv_usec;
*tl++ = txdr_unsigned(nuidp->nu_cr.cr_uid);
} else {
*tl++ = 0;
*tl++ = 0;
}
} else {
*tl++ = 0;
*tl++ = 0;
}
switch (err) {
case EPROGUNAVAIL:
*tl = txdr_unsigned(RPC_PROGUNAVAIL);
break;
case EPROGMISMATCH:
*tl = txdr_unsigned(RPC_PROGMISMATCH);
nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
*tl++ = txdr_unsigned(2);
*tl = txdr_unsigned(2); /* someday 3 */
nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
if (nd->nd_flag & ND_NQNFS) {
*tl++ = txdr_unsigned(3);
*tl = txdr_unsigned(3);
} else {
*tl++ = txdr_unsigned(2);
*tl = txdr_unsigned(3);
}
break;
case EPROCUNAVAIL:
*tl = txdr_unsigned(RPC_PROCUNAVAIL);
break;
case EBADRPC:
*tl = txdr_unsigned(RPC_GARBAGE);
break;
default:
*tl = 0;
if (err != VNOVAL) {
if (err != NFSERR_RETVOID) {
nfsm_build(tl, u_long *, NFSX_UNSIGNED);
if (err)
*tl = txdr_unsigned(nfsrv_errmap[err - 1]);
*tl = txdr_unsigned(nfsrv_errmap(nd, err));
else
*tl = 0;
*tl = 0;
}
break;
};
@ -1203,16 +1255,14 @@ nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
/*
* For nqnfs, piggyback lease as requested.
*/
if (nd->nd_nqlflag != NQL_NOVAL && err == 0) {
if (nd->nd_nqlflag) {
nfsm_build(tl, u_long *, 5*NFSX_UNSIGNED);
*tl++ = txdr_unsigned(nd->nd_nqlflag);
if ((nd->nd_flag & ND_NQNFS) && err == 0) {
if (nd->nd_flag & ND_LEASE) {
nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED);
*tl++ = txdr_unsigned(nd->nd_flag & ND_LEASE);
*tl++ = txdr_unsigned(cache);
*tl++ = txdr_unsigned(nd->nd_duration);
txdr_hyper(frev, tl);
} else {
if (nd->nd_nqlflag != 0)
panic("nqreph");
nfsm_build(tl, u_long *, NFSX_UNSIGNED);
*tl = 0;
}
@ -1220,7 +1270,7 @@ nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
*mrq = mreq;
*mbp = mb;
*bposp = bpos;
if (err != 0 && err != VNOVAL)
if (err != 0 && err != NFSERR_RETVOID)
nfsstats.srvrpc_errs++;
return (0);
}
@ -1240,8 +1290,10 @@ nfs_timer(arg)
register struct socket *so;
register struct nfsmount *nmp;
register int timeo;
register struct nfssvc_sock *slp;
static long lasttime = 0;
int s, error;
u_quad_t cur_usec;
s = splnet();
for (rep = nfs_reqq.tqh_first; rep != 0; rep = rep->r_chain.tqe_next) {
@ -1338,8 +1390,19 @@ nfs_timer(arg)
lasttime = time.tv_sec;
nqnfs_serverd();
}
/*
* Scan the write gathering queues for writes that need to be
* completed now.
*/
cur_usec = (u_quad_t)time.tv_sec * 1000000 + (u_quad_t)time.tv_usec;
for (slp = nfssvc_sockhead.tqh_first; slp != 0;
slp = slp->ns_chain.tqe_next) {
if (slp->ns_tq.lh_first && slp->ns_tq.lh_first->nd_time<=cur_usec)
nfsrv_wakenfsd(slp);
}
splx(s);
timeout(nfs_timer, (void *)0, hz / NFS_HZ);
timeout(nfs_timer, (void *)0, nfs_ticks);
}
/*
@ -1673,7 +1736,7 @@ nfsrv_getstream(slp, waitflag)
register struct nfssvc_sock *slp;
int waitflag;
{
register struct mbuf *m;
register struct mbuf *m, **mpp;
register char *cp1, *cp2;
register int len;
struct mbuf *om, *m2, *recm = 0;
@ -1707,7 +1770,12 @@ nfsrv_getstream(slp, waitflag)
}
}
slp->ns_cc -= NFSX_UNSIGNED;
slp->ns_reclen = ntohl(recmark) & ~0x80000000;
recmark = ntohl(recmark);
slp->ns_reclen = recmark & ~0x80000000;
if (recmark & 0x80000000)
slp->ns_flag |= SLP_LASTFRAG;
else
slp->ns_flag &= ~SLP_LASTFRAG;
if (slp->ns_reclen < NFS_MINPACKET || slp->ns_reclen > NFS_MAXPACKET) {
slp->ns_flag &= ~SLP_GETSTREAM;
return (EPERM);
@ -1761,12 +1829,23 @@ nfsrv_getstream(slp, waitflag)
slp->ns_flag &= ~SLP_GETSTREAM;
return (0);
}
nfs_realign(recm, 10 * NFSX_UNSIGNED);
if (slp->ns_recend)
slp->ns_recend->m_nextpkt = recm;
else
slp->ns_rec = recm;
slp->ns_recend = recm;
/*
* Accumulate the fragments into a record.
*/
mpp = &slp->ns_frag;
while (*mpp)
mpp = &((*mpp)->m_next);
*mpp = recm;
if (slp->ns_flag & SLP_LASTFRAG) {
nfs_realign(slp->ns_frag, 10 * NFSX_UNSIGNED);
if (slp->ns_recend)
slp->ns_recend->m_nextpkt = slp->ns_frag;
else
slp->ns_rec = slp->ns_frag;
slp->ns_recend = slp->ns_frag;
slp->ns_frag = (struct mbuf *)0;
}
}
}
@ -1774,13 +1853,16 @@ nfsrv_getstream(slp, waitflag)
* Parse an RPC header.
*/
int
nfsrv_dorec(slp, nd)
nfsrv_dorec(slp, nfsd, ndp)
register struct nfssvc_sock *slp;
register struct nfsd *nd;
struct nfsd *nfsd;
struct nfsrv_descript **ndp;
{
register struct mbuf *m;
register struct mbuf *m, *nam;
register struct nfsrv_descript *nd;
int error;
*ndp = NULL;
if ((slp->ns_flag & SLP_VALID) == 0 ||
(m = slp->ns_rec) == (struct mbuf *)0)
return (ENOBUFS);
@ -1790,19 +1872,24 @@ nfsrv_dorec(slp, nd)
else
slp->ns_recend = (struct mbuf *)0;
if (m->m_type == MT_SONAME) {
nd->nd_nam = m;
nd->nd_md = nd->nd_mrep = m->m_next;
m->m_next = (struct mbuf *)0;
} else {
nd->nd_nam = (struct mbuf *)0;
nd->nd_md = nd->nd_mrep = m;
}
nd->nd_dpos = mtod(nd->nd_md, caddr_t);
error = nfs_getreq(nd, TRUE);
nam = m;
m = m->m_next;
nam->m_next = NULL;
} else
nam = NULL;
MALLOC(nd, struct nfsrv_descript *, sizeof (struct nfsrv_descript),
M_NFSRVDESC, M_WAITOK);
nd->nd_md = nd->nd_mrep = m;
nd->nd_nam2 = nam;
nd->nd_dpos = mtod(m, caddr_t);
error = nfs_getreq(nd, nfsd, TRUE);
if (error) {
m_freem(nd->nd_nam);
m_freem(nam);
free((caddr_t)nd, M_NFSRVDESC);
return (error);
}
*ndp = nd;
nfsd->nfsd_nd = nd;
return (0);
}
@ -1812,8 +1899,9 @@ nfsrv_dorec(slp, nd)
* - fill in the cred struct.
*/
int
nfs_getreq(nd, has_header)
register struct nfsd *nd;
nfs_getreq(nd, nfsd, has_header)
register struct nfsrv_descript *nd;
struct nfsd *nfsd;
int has_header;
{
register int len, i;
@ -1821,57 +1909,67 @@ nfs_getreq(nd, has_header)
register long t1;
struct uio uio;
struct iovec iov;
caddr_t dpos, cp2;
caddr_t dpos, cp2, cp;
u_long nfsvers, auth_type;
int error = 0, nqnfs = 0;
uid_t nickuid;
int error = 0, nqnfs = 0, ticklen;
struct mbuf *mrep, *md;
register struct nfsuid *nuidp;
struct timeval tvin, tvout;
NFSKERBKEYSCHED_T keys; /* stores key schedule */
mrep = nd->nd_mrep;
md = nd->nd_md;
dpos = nd->nd_dpos;
if (has_header) {
nfsm_dissect(tl, u_long *, 10*NFSX_UNSIGNED);
nfsm_dissect(tl, u_long *, 10 * NFSX_UNSIGNED);
nd->nd_retxid = fxdr_unsigned(u_long, *tl++);
if (*tl++ != rpc_call) {
m_freem(mrep);
return (EBADRPC);
}
} else {
nfsm_dissect(tl, u_long *, 8*NFSX_UNSIGNED);
}
} else
nfsm_dissect(tl, u_long *, 8 * NFSX_UNSIGNED);
nd->nd_repstat = 0;
nd->nd_flag = 0;
if (*tl++ != rpc_vers) {
nd->nd_repstat = ERPCMISMATCH;
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
nfsvers = nfs_vers;
if (*tl != nfs_prog) {
if (*tl == nqnfs_prog) {
if (*tl == nqnfs_prog)
nqnfs++;
nfsvers = nqnfs_vers;
} else {
else {
nd->nd_repstat = EPROGUNAVAIL;
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
}
tl++;
if (*tl++ != nfsvers) {
nfsvers = fxdr_unsigned(u_long, *tl++);
if (((nfsvers < NFS_VER2 || nfsvers > NFS_VER3) && !nqnfs) ||
(nfsvers != NQNFS_VER3 && nqnfs)) {
nd->nd_repstat = EPROGMISMATCH;
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
if (nqnfs)
nd->nd_flag = (ND_NFSV3 | ND_NQNFS);
else if (nfsvers == NFS_VER3)
nd->nd_flag = ND_NFSV3;
nd->nd_procnum = fxdr_unsigned(u_long, *tl++);
if (nd->nd_procnum == NFSPROC_NULL)
return (0);
if (nd->nd_procnum >= NFS_NPROCS ||
(!nqnfs && nd->nd_procnum > NFSPROC_STATFS) ||
(*tl != rpc_auth_unix && *tl != rpc_auth_kerb)) {
(!nqnfs && nd->nd_procnum >= NQNFSPROC_GETLEASE) ||
(!nd->nd_flag && nd->nd_procnum > NFSV2PROC_STATFS)) {
nd->nd_repstat = EPROCUNAVAIL;
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
if ((nd->nd_flag & ND_NFSV3) == 0)
nd->nd_procnum = nfsv3_procid[nd->nd_procnum];
auth_type = *tl++;
len = fxdr_unsigned(int, *tl++);
if (len < 0 || len > RPCAUTH_MAXSIZ) {
@ -1879,6 +1977,7 @@ nfs_getreq(nd, has_header)
return (EBADRPC);
}
nd->nd_flag &= ~ND_KERBAUTH;
/*
* Handle auth_unix or auth_kerb.
*/
@ -1889,7 +1988,9 @@ nfs_getreq(nd, has_header)
return (EBADRPC);
}
nfsm_adv(nfsm_rndup(len));
nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED);
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
bzero((caddr_t)&nd->nd_cr, sizeof (struct ucred));
nd->nd_cr.cr_ref = 1;
nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);
nd->nd_cr.cr_gid = fxdr_unsigned(gid_t, *tl++);
len = fxdr_unsigned(int, *tl);
@ -1897,45 +1998,124 @@ nfs_getreq(nd, has_header)
m_freem(mrep);
return (EBADRPC);
}
nfsm_dissect(tl, u_long *, (len + 2)*NFSX_UNSIGNED);
nfsm_dissect(tl, u_long *, (len + 2) * NFSX_UNSIGNED);
for (i = 1; i <= len; i++)
if (i < NGROUPS)
nd->nd_cr.cr_groups[i] = fxdr_unsigned(gid_t, *tl++);
else
tl++;
if (i < NGROUPS)
nd->nd_cr.cr_groups[i] = fxdr_unsigned(gid_t, *tl++);
else
tl++;
nd->nd_cr.cr_ngroups = (len >= NGROUPS) ? NGROUPS : (len + 1);
} else if (auth_type == rpc_auth_kerb) {
nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);
nd->nd_authlen = fxdr_unsigned(int, *tl);
uio.uio_resid = nfsm_rndup(nd->nd_authlen);
if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
if (nd->nd_cr.cr_ngroups > 1)
nfsrvw_sort(nd->nd_cr.cr_groups, nd->nd_cr.cr_ngroups);
len = fxdr_unsigned(int, *++tl);
if (len < 0 || len > RPCAUTH_MAXSIZ) {
m_freem(mrep);
return (EBADRPC);
}
uio.uio_offset = 0;
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
uio.uio_segflg = UIO_SYSSPACE;
iov.iov_base = (caddr_t)nd->nd_authstr;
iov.iov_len = RPCAUTH_MAXSIZ;
nfsm_mtouio(&uio, uio.uio_resid);
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
nd->nd_flag |= NFSD_NEEDAUTH;
}
if (len > 0)
nfsm_adv(nfsm_rndup(len));
} else if (auth_type == rpc_auth_kerb) {
switch (fxdr_unsigned(int, *tl++)) {
case RPCAKN_FULLNAME:
ticklen = fxdr_unsigned(int, *tl);
*((u_long *)nfsd->nfsd_authstr) = *tl;
uio.uio_resid = nfsm_rndup(ticklen) + NFSX_UNSIGNED;
nfsd->nfsd_authlen = uio.uio_resid + NFSX_UNSIGNED;
if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
m_freem(mrep);
return (EBADRPC);
}
uio.uio_offset = 0;
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
uio.uio_segflg = UIO_SYSSPACE;
iov.iov_base = (caddr_t)&nfsd->nfsd_authstr[4];
iov.iov_len = RPCAUTH_MAXSIZ - 4;
nfsm_mtouio(&uio, uio.uio_resid);
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
if (*tl++ != rpc_auth_kerb ||
fxdr_unsigned(int, *tl) != 4 * NFSX_UNSIGNED) {
printf("Bad kerb verifier\n");
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
nfsm_dissect(cp, caddr_t, 4 * NFSX_UNSIGNED);
tl = (u_long *)cp;
if (fxdr_unsigned(int, *tl) != RPCAKN_FULLNAME) {
printf("Not fullname kerb verifier\n");
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
cp += NFSX_UNSIGNED;
bcopy(cp, nfsd->nfsd_verfstr, 3 * NFSX_UNSIGNED);
nfsd->nfsd_verflen = 3 * NFSX_UNSIGNED;
nd->nd_flag |= ND_KERBFULL;
nfsd->nfsd_flag |= NFSD_NEEDAUTH;
break;
case RPCAKN_NICKNAME:
if (len != 2 * NFSX_UNSIGNED) {
printf("Kerb nickname short\n");
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADCRED);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
nickuid = fxdr_unsigned(uid_t, *tl);
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
if (*tl++ != rpc_auth_kerb ||
fxdr_unsigned(int, *tl) != 3 * NFSX_UNSIGNED) {
printf("Kerb nick verifier bad\n");
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
tvin.tv_sec = *tl++;
tvin.tv_usec = *tl;
/*
* Do we have any use for the verifier.
* According to the "Remote Procedure Call Protocol Spec." it
* should be AUTH_NULL, but some clients make it AUTH_UNIX?
* For now, just skip over it
*/
len = fxdr_unsigned(int, *++tl);
if (len < 0 || len > RPCAUTH_MAXSIZ) {
m_freem(mrep);
return (EBADRPC);
}
if (len > 0) {
nfsm_adv(nfsm_rndup(len));
for (nuidp = NUIDHASH(nfsd->nfsd_slp,nickuid)->lh_first;
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
if (nuidp->nu_cr.cr_uid == nickuid &&
(!nd->nd_nam2 ||
netaddr_match(NU_NETFAM(nuidp),
&nuidp->nu_haddr, nd->nd_nam2)))
break;
}
if (!nuidp) {
nd->nd_repstat =
(NFSERR_AUTHERR|AUTH_REJECTCRED);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
/*
* Now, decrypt the timestamp using the session key
* and validate it.
*/
#ifdef NFSKERB
XXX
#endif
tvout.tv_sec = fxdr_unsigned(long, tvout.tv_sec);
tvout.tv_usec = fxdr_unsigned(long, tvout.tv_usec);
if (nuidp->nu_expire < time.tv_sec ||
nuidp->nu_timestamp.tv_sec > tvout.tv_sec ||
(nuidp->nu_timestamp.tv_sec == tvout.tv_sec &&
nuidp->nu_timestamp.tv_usec > tvout.tv_usec)) {
nuidp->nu_expire = 0;
nd->nd_repstat =
(NFSERR_AUTHERR|AUTH_REJECTVERF);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
nfsrv_setcred(&nuidp->nu_cr, &nd->nd_cr);
nd->nd_flag |= ND_KERBNICK;
};
} else {
nd->nd_repstat = (NFSERR_AUTHERR | AUTH_REJECTCRED);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
/*
@ -1943,16 +2123,14 @@ nfs_getreq(nd, has_header)
*/
if (nqnfs && nd->nd_procnum != NQNFSPROC_EVICTED) {
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
nd->nd_nqlflag = fxdr_unsigned(int, *tl);
if (nd->nd_nqlflag) {
nd->nd_flag |= fxdr_unsigned(int, *tl);
if (nd->nd_flag & ND_LEASE) {
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
nd->nd_duration = fxdr_unsigned(int, *tl);
} else
nd->nd_duration = NQ_MINLEASE;
} else {
nd->nd_nqlflag = NQL_NOVAL;
} else
nd->nd_duration = NQ_MINLEASE;
}
nd->nd_md = md;
nd->nd_dpos = dpos;
return (0);
@ -1973,13 +2151,13 @@ nfsrv_wakenfsd(slp)
if ((slp->ns_flag & SLP_VALID) == 0)
return;
for (nd = nfsd_head.tqh_first; nd != 0; nd = nd->nd_chain.tqe_next) {
if (nd->nd_flag & NFSD_WAITING) {
nd->nd_flag &= ~NFSD_WAITING;
if (nd->nd_slp)
for (nd = nfsd_head.tqh_first; nd != 0; nd = nd->nfsd_chain.tqe_next) {
if (nd->nfsd_flag & NFSD_WAITING) {
nd->nfsd_flag &= ~NFSD_WAITING;
if (nd->nfsd_slp)
panic("nfsd wakeup");
slp->ns_sref++;
nd->nd_slp = slp;
nd->nfsd_slp = slp;
wakeup((caddr_t)nd);
return;
}

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_vfsops.c 8.3 (Berkeley) 1/4/94
* $Id: nfs_vfsops.c,v 1.14.2.1 1995/06/02 11:13:15 davidg Exp $
* $Id: nfs_vfsops.c,v 1.15 1995/06/11 19:31:46 rgrimes Exp $
*/
#include <sys/param.h>
@ -59,10 +59,10 @@
#include <netinet/in.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfsnode.h>
#include <nfs/nfsmount.h>
#include <nfs/nfs.h>
#include <nfs/nfsmount.h>
#include <nfs/xdr_subs.h>
#include <nfs/nfsm_subs.h>
#include <nfs/nfsdiskless.h>
@ -71,11 +71,15 @@
struct nfsstats nfsstats;
static int nfs_sysctl(int *, u_int, void *, size_t *, void *, size_t,
struct proc *);
extern int nfs_ticks;
/*
* nfs vfs operations.
*/
struct vfsops nfs_vfsops = {
#ifdef __NetBSD__
MOUNT_NFS,
#endif
nfs_mount,
nfs_start,
nfs_unmount,
@ -87,9 +91,13 @@ struct vfsops nfs_vfsops = {
nfs_fhtovp,
nfs_vptofh,
nfs_init,
#ifdef __FreeBSD__
nfs_sysctl
#endif
};
#ifdef __FreeBSD__
VFS_SET(nfs_vfsops, nfs, MOUNT_NFS, VFCF_NETWORK);
#endif
/*
* This structure must be filled in by a primary bootstrap or bootstrap
@ -99,16 +107,11 @@ VFS_SET(nfs_vfsops, nfs, MOUNT_NFS, VFCF_NETWORK);
struct nfs_diskless nfs_diskless = { 0 };
int nfs_diskless_valid = 0;
extern u_long nfs_procids[NFS_NPROCS];
extern u_long nfs_prog, nfs_vers;
void nfs_disconnect __P((struct nfsmount *));
void nfsargs_ntoh __P((struct nfs_args *));
static struct mount *nfs_mountdiskless __P((char *, char *, int,
struct sockaddr_in *, struct nfs_args *, register struct vnode **));
#define TRUE 1
#define FALSE 0
/*
* nfs statfs call
*/
@ -119,40 +122,65 @@ nfs_statfs(mp, sbp, p)
struct proc *p;
{
register struct vnode *vp;
register struct nfsv2_statfs *sfp;
register struct nfs_statfs *sfp;
register caddr_t cp;
register long t1;
register u_long *tl;
register long t1, t2;
caddr_t bpos, dpos, cp2;
int error = 0, isnq;
struct nfsmount *nmp = VFSTONFS(mp);
int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr;
struct mbuf *mreq, *mrep, *md, *mb, *mb2;
struct nfsmount *nmp;
struct ucred *cred;
struct nfsnode *np;
u_quad_t tquad;
nmp = VFSTONFS(mp);
isnq = (nmp->nm_flag & NFSMNT_NQNFS);
error = nfs_nget(mp, &nmp->nm_fh, &np);
#ifndef nolint
sfp = (struct nfs_statfs *)0;
#endif
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
if (error)
return (error);
vp = NFSTOV(np);
nfsstats.rpccnt[NFSPROC_STATFS]++;
cred = crget();
cred->cr_ngroups = 1;
nfsm_reqhead(vp, NFSPROC_STATFS, NFSX_FH);
nfsm_fhtom(vp);
nfsm_request(vp, NFSPROC_STATFS, p, cred);
nfsm_dissect(sfp, struct nfsv2_statfs *, NFSX_STATFS(isnq));
if (v3 && (nmp->nm_flag & NFSMNT_GOTFSINFO) == 0)
(void)nfs_fsinfo(nmp, vp, cred, p);
nfsstats.rpccnt[NFSPROC_FSSTAT]++;
nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3));
nfsm_fhtom(vp, v3);
nfsm_request(vp, NFSPROC_FSSTAT, p, cred);
if (v3)
nfsm_postop_attr(vp, retattr);
if (!error)
nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
#ifdef __NetBSD__
#ifdef COMPAT_09
sbp->f_type = 2;
#else
sbp->f_type = 0;
#endif
#else
sbp->f_type = MOUNT_NFS;
#endif
sbp->f_flags = nmp->nm_flag;
sbp->f_iosize = NFS_MAXDGRAMDATA;
sbp->f_bsize = fxdr_unsigned(long, sfp->sf_bsize);
sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks);
sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree);
sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail);
if (isnq) {
sbp->f_files = fxdr_unsigned(long, sfp->sf_files);
sbp->f_ffree = fxdr_unsigned(long, sfp->sf_ffree);
sbp->f_iosize = min(nmp->nm_rsize, nmp->nm_wsize);
if (v3) {
sbp->f_bsize = NFS_FABLKSIZE;
fxdr_hyper(&sfp->sf_tbytes, &tquad);
sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
fxdr_hyper(&sfp->sf_fbytes, &tquad);
sbp->f_bfree = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
fxdr_hyper(&sfp->sf_abytes, &tquad);
sbp->f_bavail = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE));
sbp->f_files = (fxdr_unsigned(long, sfp->sf_tfiles.nfsuquad[1])
& 0x7fffffff);
sbp->f_ffree = (fxdr_unsigned(long, sfp->sf_ffiles.nfsuquad[1])
& 0x7fffffff);
} else {
sbp->f_bsize = fxdr_unsigned(long, sfp->sf_bsize);
sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks);
sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree);
sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail);
sbp->f_files = 0;
sbp->f_ffree = 0;
}
@ -161,11 +189,71 @@ nfs_statfs(mp, sbp, p)
bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN);
}
nfsm_reqdone;
vrele(vp);
vput(vp);
crfree(cred);
return (error);
}
/*
* nfs version 3 fsinfo rpc call
*/
int
nfs_fsinfo(nmp, vp, cred, p)
register struct nfsmount *nmp;
register struct vnode *vp;
struct ucred *cred;
struct proc *p;
{
register struct nfsv3_fsinfo *fsp;
register caddr_t cp;
register long t1, t2;
register u_long *tl, pref, max;
caddr_t bpos, dpos, cp2;
int error = 0, retattr;
struct mbuf *mreq, *mrep, *md, *mb, *mb2;
nfsstats.rpccnt[NFSPROC_FSINFO]++;
nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1));
nfsm_fhtom(vp, 1);
nfsm_request(vp, NFSPROC_FSINFO, p, cred);
nfsm_postop_attr(vp, retattr);
if (!error) {
nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
pref = fxdr_unsigned(u_long, fsp->fs_wtpref);
if (pref < nmp->nm_wsize)
nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) &
~(NFS_FABLKSIZE - 1);
max = fxdr_unsigned(u_long, fsp->fs_wtmax);
if (max < nmp->nm_wsize) {
nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1);
if (nmp->nm_wsize == 0)
nmp->nm_wsize = max;
}
pref = fxdr_unsigned(u_long, fsp->fs_rtpref);
if (pref < nmp->nm_rsize)
nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) &
~(NFS_FABLKSIZE - 1);
max = fxdr_unsigned(u_long, fsp->fs_rtmax);
if (max < nmp->nm_rsize) {
nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1);
if (nmp->nm_rsize == 0)
nmp->nm_rsize = max;
}
pref = fxdr_unsigned(u_long, fsp->fs_dtpref);
if (pref < nmp->nm_readdirsize)
nmp->nm_readdirsize = (pref + NFS_DIRBLKSIZ - 1) &
~(NFS_DIRBLKSIZ - 1);
if (max < nmp->nm_readdirsize) {
nmp->nm_readdirsize = max & ~(NFS_DIRBLKSIZ - 1);
if (nmp->nm_readdirsize == 0)
nmp->nm_readdirsize = max;
}
nmp->nm_flag |= NFSMNT_GOTFSINFO;
}
nfsm_reqdone;
return (error);
}
/*
* Mount a remote root fs via. nfs. This depends on the info in the
* nfs_diskless structure that has been filled in properly by some primary
@ -268,7 +356,12 @@ nfs_mountroot()
* Create a fake mount point just for the swap vnode so that the
* swap file can be on a different server from the rootfs.
*/
nd->swap_args.fh = (nfsv2fh_t *)nd->swap_fh;
nd->swap_args.fh = nd->swap_fh;
/*
* If using nfsv3_diskless, replace NFSX_V2FH with
* nd->swap_fhsize.
*/
nd->swap_args.fhsize = NFSX_V2FH;
l = ntohl(nd->swap_saddr.sin_addr.s_addr);
sprintf(buf,"%ld.%ld.%ld.%ld:%s",
(l >> 24) & 0xff, (l >> 16) & 0xff,
@ -293,8 +386,12 @@ nfs_mountroot()
/*
* Create the rootfs mount point.
*/
nd->root_args.fh = (nfsv2fh_t *)nd->root_fh;
l = ntohl(nd->root_saddr.sin_addr.s_addr);
nd->root_args.fh = nd->root_fh;
/*
* If using nfsv3_diskless, replace NFSX_V2FH with nd->root_fhsize.
*/
nd->root_args.fhsize = NFSX_V2FH;
l = ntohl(nd->swap_saddr.sin_addr.s_addr);
sprintf(buf,"%ld.%ld.%ld.%ld:%s",
(l >> 24) & 0xff, (l >> 16) & 0xff,
(l >> 8) & 0xff, (l >> 0) & 0xff,nd->root_hostnam);
@ -304,7 +401,11 @@ nfs_mountroot()
if (vfs_lock(mp))
panic("nfs_mountroot: vfs_lock");
#if NetBSD >= 1994101
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
#else
TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
#endif
mp->mnt_flag |= MNT_ROOTFS;
mp->mnt_vnodecovered = NULLVP;
vfs_unlock(mp);
@ -386,12 +487,12 @@ nfs_mount(mp, path, data, ndp, p)
struct vnode *vp;
char pth[MNAMELEN], hst[MNAMELEN];
u_int len;
nfsv2fh_t nfh;
u_char nfh[NFSX_V3FHMAX];
error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
if (error)
return (error);
error = copyin((caddr_t)args.fh, (caddr_t)&nfh, sizeof (nfsv2fh_t));
error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
if (error)
return (error);
error = copyinstr(path, pth, MNAMELEN-1, &len);
@ -406,7 +507,7 @@ nfs_mount(mp, path, data, ndp, p)
error = sockargs(&nam, (caddr_t)args.addr, args.addrlen, MT_SONAME);
if (error)
return (error);
args.fh = &nfh;
args.fh = nfh;
error = mountnfs(&args, mp, nam, pth, hst, &vp);
return (error);
}
@ -424,7 +525,7 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
{
register struct nfsmount *nmp;
struct nfsnode *np;
int error;
int error, maxio;
if (mp->mnt_flag & MNT_UPDATE) {
nmp = VFSTONFS(mp);
@ -435,16 +536,12 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
MALLOC(nmp, struct nfsmount *, sizeof (struct nfsmount),
M_NFSMNT, M_WAITOK);
bzero((caddr_t)nmp, sizeof (struct nfsmount));
TAILQ_INIT(&nmp->nm_uidlruhead);
mp->mnt_data = (qaddr_t)nmp;
}
getnewfsid(mp, MOUNT_NFS);
nmp->nm_mountp = mp;
nmp->nm_flag = argp->flags;
if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_MYWRITE)) ==
(NFSMNT_NQNFS | NFSMNT_MYWRITE)) {
error = EPERM;
goto bad;
}
if (nmp->nm_flag & NFSMNT_NQNFS)
/*
* We have to set mnt_maxsymlink to a non-zero value so
@ -457,14 +554,24 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
nmp->nm_retry = NFS_RETRANS;
nmp->nm_wsize = NFS_WSIZE;
nmp->nm_rsize = NFS_RSIZE;
nmp->nm_readdirsize = NFS_READDIRSIZE;
nmp->nm_numgrps = NFS_MAXGRPS;
nmp->nm_readahead = NFS_DEFRAHEAD;
nmp->nm_leaseterm = NQ_DEFLEASE;
nmp->nm_deadthresh = NQ_DEADTHRESH;
CIRCLEQ_INIT(&nmp->nm_timerhead);
nmp->nm_inprog = NULLVP;
bcopy((caddr_t)argp->fh, (caddr_t)&nmp->nm_fh, sizeof(nfsv2fh_t));
nmp->nm_fhsize = argp->fhsize;
bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
#ifdef __NetBSD__
#ifdef COMPAT_09
mp->mnt_stat.f_type = 2;
#else
mp->mnt_stat.f_type = 0;
#endif
#else
mp->mnt_stat.f_type = MOUNT_NFS;
#endif
bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
nmp->nm_nam = nam;
@ -483,29 +590,48 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
nmp->nm_retry = NFS_MAXREXMIT;
}
if (argp->flags & NFSMNT_NFSV3) {
if (argp->sotype == SOCK_DGRAM)
maxio = NFS_MAXDGRAMDATA;
else
maxio = NFS_MAXDATA;
} else
maxio = NFS_V2MAXDATA;
if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) {
nmp->nm_wsize = argp->wsize;
/* Round down to multiple of blocksize */
nmp->nm_wsize &= ~0x1ff;
nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1);
if (nmp->nm_wsize <= 0)
nmp->nm_wsize = 512;
else if (nmp->nm_wsize > NFS_MAXDATA)
nmp->nm_wsize = NFS_MAXDATA;
nmp->nm_wsize = NFS_FABLKSIZE;
}
if (nmp->nm_wsize > maxio)
nmp->nm_wsize = maxio;
if (nmp->nm_wsize > MAXBSIZE)
nmp->nm_wsize = MAXBSIZE;
if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) {
nmp->nm_rsize = argp->rsize;
/* Round down to multiple of blocksize */
nmp->nm_rsize &= ~0x1ff;
nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1);
if (nmp->nm_rsize <= 0)
nmp->nm_rsize = 512;
else if (nmp->nm_rsize > NFS_MAXDATA)
nmp->nm_rsize = NFS_MAXDATA;
nmp->nm_rsize = NFS_FABLKSIZE;
}
if (nmp->nm_rsize > maxio)
nmp->nm_rsize = maxio;
if (nmp->nm_rsize > MAXBSIZE)
nmp->nm_rsize = MAXBSIZE;
if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) {
nmp->nm_readdirsize = argp->readdirsize;
/* Round down to multiple of blocksize */
nmp->nm_readdirsize &= ~(NFS_DIRBLKSIZ - 1);
if (nmp->nm_readdirsize < NFS_DIRBLKSIZ)
nmp->nm_readdirsize = NFS_DIRBLKSIZ;
}
if (nmp->nm_readdirsize > maxio)
nmp->nm_readdirsize = maxio;
if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 &&
argp->maxgrouplist <= NFS_MAXGRPS)
nmp->nm_numgrps = argp->maxgrouplist;
@ -536,7 +662,7 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
* stuck on a dead server and we are holding a lock on the mount
* point.
*/
mp->mnt_stat.f_iosize = NFS_MAXDGRAMDATA;
mp->mnt_stat.f_iosize = min(nmp->nm_rsize, nmp->nm_wsize);
/*
* A reference count is needed on the nfsnode representing the
* remote root. If this object is not persistent, then backward
@ -545,11 +671,16 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
* this problem, because one can identify root inodes by their
* number == ROOTINO (2).
*/
error = nfs_nget(mp, &nmp->nm_fh, &np);
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
if (error)
goto bad;
*vpp = NFSTOV(np);
/*
* Lose the lock but keep the ref.
*/
VOP_UNLOCK(*vpp);
return (0);
bad:
nfs_disconnect(nmp);
@ -592,7 +723,7 @@ nfs_unmount(mp, mntflags, p)
* the remote root. See comment in mountnfs(). The VFS unmount()
* has done vput on this vnode, otherwise we would get deadlock!
*/
error = nfs_nget(mp, &nmp->nm_fh, &np);
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
if (error)
return(error);
vp = NFSTOV(np);
@ -622,9 +753,9 @@ nfs_unmount(mp, mntflags, p)
nmp->nm_flag |= NFSMNT_DISMNT;
/*
* There are two reference counts to get rid of here.
* There are two reference counts and one lock to get rid of here.
*/
vrele(vp);
vput(vp);
vrele(vp);
vgone(vp);
nfs_disconnect(nmp);
@ -649,10 +780,11 @@ nfs_root(mp, vpp)
int error;
nmp = VFSTONFS(mp);
error = nfs_nget(mp, &nmp->nm_fh, &np);
error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np);
if (error)
return (error);
vp = NFSTOV(np);
VOP_UNLOCK(vp);
vp->v_type = VDIR;
vp->v_flag = VROOT;
*vpp = vp;

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs.h 8.1 (Berkeley) 6/10/93
* $Id: nfs.h,v 1.8 1994/11/02 00:11:00 wollman Exp $
* $Id: nfs.h,v 1.9 1995/02/14 06:22:18 phk Exp $
*/
#ifndef _NFS_NFS_H_
@ -45,11 +45,12 @@
*/
#define NFS_MAXIOVEC 34
#define NFS_HZ 25 /* Ticks per second for NFS timeouts */
#define NFS_TIMEO (1*NFS_HZ) /* Default timeout = 1 second */
#define NFS_MINTIMEO (1*NFS_HZ) /* Min timeout to use */
#define NFS_MAXTIMEO (60*NFS_HZ) /* Max timeout to backoff to */
#define NFS_MINIDEMTIMEO (5*NFS_HZ) /* Min timeout for non-idempotent ops*/
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
#define NFS_MINIDEMTIMEO (5 * NFS_HZ) /* Min timeout for non-idempotent ops*/
#define NFS_MAXREXMIT 100 /* Stop counting after this many */
#define NFS_MAXWINDOW 1024 /* Max number of outstanding requests */
#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
@ -62,13 +63,81 @@
#endif
#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
#define NFS_READDIRSIZE 8192 /* Def. readdir size */
#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
#define NFS_MAXREADDIR NFS_MAXDATA /* Max. size of directory read */
#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
#define NFS_DIRBLKSIZ 1024 /* Size of an NFS directory block */
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
#ifndef NFS_GATHERDELAY
#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
#endif
#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
/*
* Oddballs
*/
#define NMOD(a) ((a) % nfs_asyncdaemons)
#define NFS_CMPFH(n, f, s) \
((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s)))
#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3)
#define NFS_SRVMAXDATA(n) \
(((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \
NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA)
/*
* XXX
* sys/buf.h should be editted to change B_APPENDWRITE --> B_NEEDCOMMIT, but
* until then...
* Same goes for sys/malloc.h, which needs M_NFSDIROFF,
* M_NFSRVDESC and M_NFSBIGFH added.
* The VA_EXCLUSIVE flag should be added for va_vaflags and set for an
* exclusive create.
* The B_INVAFTERWRITE flag should be set to whatever is required by the
* buffer cache code to say "Invalidate the block after it is written back".
*/
#ifndef B_NEEDCOMMIT
#define B_NEEDCOMMIT B_APPENDWRITE
#endif
#ifndef M_NFSRVDESC
#define M_NFSRVDESC M_TEMP
#endif
#ifndef M_NFSDIROFF
#define M_NFSDIROFF M_TEMP
#endif
#ifndef M_NFSBIGFH
#define M_NFSBIGFH M_TEMP
#endif
#ifndef VA_EXCLUSIVE
#define VA_EXCLUSIVE 0
#endif
#ifdef __FreeBSD__
#define B_INVAFTERWRITE B_NOCACHE
#else
#define B_INVAFTERWRITE B_INVAL
#endif
/*
* These ifdefs try to handle the differences between the various 4.4BSD-Lite
* based vfs interfaces.
* btw: NetBSD-current does have a VOP_LEASDE(), but I don't know how to
* differentiate between NetBSD-1.0 and NetBSD-current, so..
* I also don't know about BSDi's 2.0 release.
*/
#if !defined(HAS_VOPLEASE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
#define HAS_VOPLEASE 1
#endif
#if !defined(HAS_VOPREVOKE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
#define HAS_VOPREVOKE 1
#endif
/*
* The IO_METASYNC flag should be implemented for local file systems.
* (Until then, it is nothin at all.)
*/
#ifndef IO_METASYNC
#define IO_METASYNC 0
#endif
/*
* Set the attribute timeout based on how recently the file has been modified.
@ -79,6 +148,20 @@
((time.tv_sec - (np)->n_mtime) / 10 > NFS_MAXATTRTIMO ? NFS_MAXATTRTIMO : \
(time.tv_sec - (np)->n_mtime) / 10))
/*
* Expected allocation sizes for major data structures. If the actual size
* of the structure exceeds these sizes, then malloc() will be allocating
* almost twice the memory required. This is used in nfs_init() to warn
* the sysadmin that the size of a structure should be reduced.
* (These sizes are always a power of 2. If the kernel malloc() changes
* to one that does not allocate space in powers of 2 size, then this all
* becomes bunk!)
*/
#define NFS_NODEALLOC 256
#define NFS_MNTALLOC 512
#define NFS_SVCALLOC 256
#define NFS_UIDALLOC 128
/*
* Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
* should ever try and use it.
@ -95,7 +178,12 @@ struct nfsd_srvargs {
u_long nsd_haddr; /* Ip address of client */
struct ucred nsd_cr; /* Cred. uid maps to */
int nsd_authlen; /* Length of auth string (ret) */
char *nsd_authstr; /* Auth string (ret) */
u_char *nsd_authstr; /* Auth string (ret) */
int nsd_verflen; /* and the verfier */
u_char *nsd_verfstr;
struct timeval nsd_timestamp; /* timestamp from verifier */
u_long nsd_ttl; /* credential ttl (sec) */
NFSKERBKEY_T nsd_key; /* Session key */
};
struct nfsd_cargs {
@ -103,7 +191,10 @@ struct nfsd_cargs {
uid_t ncd_authuid; /* Effective uid */
int ncd_authtype; /* Type of authenticator */
int ncd_authlen; /* Length of authenticator string */
char *ncd_authstr; /* Authenticator string */
u_char *ncd_authstr; /* Authenticator string */
int ncd_verflen; /* and the verifier */
u_char *ncd_verfstr;
NFSKERBKEY_T ncd_key; /* Session key */
};
/*
@ -142,6 +233,7 @@ struct nfsstats {
int srvnqnfs_leases;
int srvnqnfs_maxleases;
int srvnqnfs_getleases;
int srvvop_writes;
};
/*
@ -173,7 +265,7 @@ struct nfsstats {
* such as SIGALRM will not expect file I/O system calls to be interrupted
* by them and break.
*/
#ifdef KERNEL
#if defined(KERNEL) || defined(_KERNEL)
struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
@ -224,17 +316,29 @@ TAILQ_HEAD(, nfsreq) nfs_reqq;
#define R_MUSTRESEND 0x40 /* Must resend request */
#define R_GETONEREP 0x80 /* Probe for one reply only */
extern struct nfsstats nfsstats;
/*
* A list of nfssvc_sock structures is maintained with all the sockets
* that require service by the nfsd.
* The nfsuid structs hang off of the nfssvc_sock structs in both lru
* and uid hash lists.
*/
#define NUIDHASHSIZ 32
#ifndef NFS_UIDHASHSIZ
#define NFS_UIDHASHSIZ 29 /* Tune the size of nfssvc_sock with this */
#endif
#define NUIDHASH(sock, uid) \
(&(sock)->ns_uidhashtbl[(uid) & (sock)->ns_uidhash])
(&(sock)->ns_uidhashtbl[(uid) % NFS_UIDHASHSIZ])
#ifndef NFS_WDELAYHASHSIZ
#define NFS_WDELAYHASHSIZ 16 /* and with this */
#endif
#define NWDELAYHASH(sock, f) \
(&(sock)->ns_wdelayhashtbl[(*((u_long *)(f))) % NFS_WDELAYHASHSIZ])
#ifndef NFS_MUIDHASHSIZ
#define NFS_MUIDHASHSIZ 67 /* Tune the size of nfsmount with this */
#endif
#define NMUIDHASH(nmp, uid) \
(&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
#define NFSNOHASH(fhsum) \
(&nfsnodehashtbl[(fhsum) & nfsnodehash])
/*
* Network address hash list element
@ -248,35 +352,41 @@ struct nfsuid {
TAILQ_ENTRY(nfsuid) nu_lru; /* LRU chain */
LIST_ENTRY(nfsuid) nu_hash; /* Hash list */
int nu_flag; /* Flags */
uid_t nu_uid; /* Uid mapped by this entry */
union nethostaddr nu_haddr; /* Host addr. for dgram sockets */
struct ucred nu_cr; /* Cred uid mapped to */
int nu_expire; /* Expiry time (sec) */
struct timeval nu_timestamp; /* Kerb. timestamp */
u_long nu_nickname; /* Nickname on server */
NFSKERBKEY_T nu_key; /* and session key */
};
#define nu_inetaddr nu_haddr.had_inetaddr
#define nu_nam nu_haddr.had_nam
/* Bits for nu_flag */
#define NU_INETADDR 0x1
#define NU_NAM 0x2
#define NU_NETFAM(u) (((u)->nu_flag & NU_INETADDR) ? AF_INET : AF_ISO)
struct nfssvc_sock {
TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
TAILQ_HEAD(, nfsuid) ns_uidlruhead;
LIST_HEAD(, nfsuid) *ns_uidhashtbl;
u_long ns_uidhash;
int ns_flag;
u_long ns_sref;
struct file *ns_fp;
struct socket *ns_so;
int ns_solock;
struct mbuf *ns_nam;
int ns_cc;
struct mbuf *ns_raw;
struct mbuf *ns_rawend;
int ns_reclen;
struct mbuf *ns_rec;
struct mbuf *ns_recend;
struct mbuf *ns_frag;
int ns_flag;
int ns_solock;
int ns_cc;
int ns_reclen;
int ns_numuids;
u_long ns_sref;
LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
LIST_HEAD(, nfsuid) ns_uidhashtbl[NFS_UIDHASHSIZ];
LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
};
/* Bits for "ns_flag" */
@ -285,6 +395,7 @@ struct nfssvc_sock {
#define SLP_NEEDQ 0x04
#define SLP_DISCONN 0x08
#define SLP_GETSTREAM 0x10
#define SLP_LASTFRAG 0x20
#define SLP_ALLFLAGS 0xff
TAILQ_HEAD(, nfssvc_sock) nfssvc_sockhead;
@ -296,73 +407,124 @@ int nfssvc_sockhead_flag;
* One of these structures is allocated for each nfsd.
*/
struct nfsd {
TAILQ_ENTRY(nfsd) nd_chain; /* List of all nfsd's */
int nd_flag; /* NFSD_ flags */
struct nfssvc_sock *nd_slp; /* Current socket */
struct mbuf *nd_nam; /* Client addr for datagram req. */
struct mbuf *nd_mrep; /* Req. mbuf list */
struct mbuf *nd_md;
caddr_t nd_dpos; /* Position in list */
int nd_procnum; /* RPC procedure number */
u_long nd_retxid; /* RPC xid */
int nd_repstat; /* Reply status value */
struct ucred nd_cr; /* Credentials for req. */
int nd_nqlflag; /* Leasing flag */
u_long nd_duration; /* Lease duration */
int nd_authlen; /* Authenticator len */
u_char nd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
struct proc *nd_procp; /* Proc ptr */
TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
int nfsd_flag; /* NFSD_ flags */
struct nfssvc_sock *nfsd_slp; /* Current socket */
int nfsd_authlen; /* Authenticator len */
u_char nfsd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
int nfsd_verflen; /* and the Verifier */
u_char nfsd_verfstr[RPCVERF_MAXSIZ];
struct proc *nfsd_procp; /* Proc ptr */
struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
};
/* Bits for "nd_flag" */
/* Bits for "nfsd_flag" */
#define NFSD_WAITING 0x01
#define NFSD_REQINPROG 0x02
#define NFSD_NEEDAUTH 0x04
#define NFSD_AUTHFAIL 0x08
/*
* This structure is used by the server for describing each request.
* Some fields are used only when write request gathering is performed.
*/
struct nfsrv_descript {
u_quad_t nd_time; /* Write deadline (usec) */
off_t nd_off; /* Start byte offset */
off_t nd_eoff; /* and end byte offset */
LIST_ENTRY(nfsrv_descript) nd_hash; /* Hash list */
LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
LIST_HEAD(,nfsrv_descript) nd_coalesce; /* coalesced writes */
struct mbuf *nd_mrep; /* Request mbuf list */
struct mbuf *nd_md; /* Current dissect mbuf */
struct mbuf *nd_mreq; /* Reply mbuf list */
struct mbuf *nd_nam; /* and socket addr */
struct mbuf *nd_nam2; /* return socket addr */
caddr_t nd_dpos; /* Current dissect pos */
int nd_procnum; /* RPC # */
int nd_stable; /* storage type */
int nd_flag; /* nd_flag */
int nd_len; /* Length of this write */
int nd_repstat; /* Reply status */
u_long nd_retxid; /* Reply xid */
u_long nd_duration; /* Lease duration */
struct timeval nd_starttime; /* Time RPC initiated */
fhandle_t nd_fh; /* File handle */
struct ucred nd_cr; /* Credentials */
};
/* Bits for "nd_flag" */
#define ND_READ LEASE_READ
#define ND_WRITE LEASE_WRITE
#define ND_CHECK 0x04
#define ND_LEASE (ND_READ | ND_WRITE | ND_CHECK)
#define ND_NFSV3 0x08
#define ND_NQNFS 0x10
#define ND_KERBNICK 0x20
#define ND_KERBFULL 0x40
#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
TAILQ_HEAD(, nfsd) nfsd_head;
int nfsd_head_flag;
#define NFSD_CHECKSLP 0x01
/*
* These macros compare nfsrv_descript structures.
*/
#define NFSW_CONTIG(o, n) \
((o)->nd_eoff >= (n)->nd_off && \
!bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH))
#define NFSW_SAMECRED(o, n) \
(((o)->nd_flag & ND_KERBAUTH) == ((n)->nd_flag & ND_KERBAUTH) && \
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
sizeof (struct ucred)))
int nfs_reply __P((struct nfsreq *));
int nfs_getreq __P((struct nfsd *,int));
int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
int nfs_send __P((struct socket *,struct mbuf *,struct mbuf *,struct nfsreq *));
int nfs_rephead __P((int,struct nfsd *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_rephead __P((int,struct nfsrv_descript *,struct nfssvc_sock *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_sndlock __P((int *,struct nfsreq *));
int nfs_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
int nfs_vinvalbuf __P((struct vnode *,int,struct ucred *,struct proc *,int));
int nfs_readrpc __P((struct vnode *,struct uio *,struct ucred *));
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int));
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int *,int *));
int nfs_readdirrpc __P((register struct vnode *,struct uio *,struct ucred *));
int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct proc *));
int nfs_asyncio __P((struct buf *,struct ucred *));
int nfs_doio __P((struct buf *,struct ucred *,struct proc *));
int nfs_readlinkrpc __P((struct vnode *,struct uio *,struct ucred *));
int nfs_sigintr __P((struct nfsmount *,struct nfsreq *r,struct proc *));
int nfs_readdirlookrpc __P((struct vnode *,register struct uio *,struct ucred *));
int nfs_readdirplusrpc __P((struct vnode *,register struct uio *,struct ucred *));
int nfsm_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *));
void nfsm_srvfattr __P((struct nfsrv_descript *,struct vattr *,struct nfs_fattr *));
void nfsm_srvwcc __P((struct nfsrv_descript *,int,struct vattr *,int,struct vattr *,struct mbuf **,char **));
void nfsm_srvpostopattr __P((struct nfsrv_descript *,int,struct vattr *,struct mbuf **,char **));
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *,int));
int nfsrv_access __P((struct vnode *,int,struct ucred *,int,struct proc *));
int netaddr_match __P((int,union nethostaddr *,struct mbuf *));
int nfs_request __P((struct vnode *,struct mbuf *,int,struct proc *,struct ucred *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_loadattrcache __P((struct vnode **,struct mbuf **,caddr_t *,struct vattr *));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct proc *));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int));
void nfsm_adj __P((struct mbuf *,int,int));
int nfsm_mbuftouio __P((struct mbuf **,struct uio *,int,caddr_t *));
void nfsrv_initcache __P((void));
int nfs_rcvlock __P((struct nfsreq *));
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,int *,char **,int *));
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,char **,int *,char *,int *,NFSKERBKEY_T));
int nfs_getnickauth __P((struct nfsmount *,struct ucred *,char **,int *,char *,int));
int nfs_savenickauth __P((struct nfsmount *,struct ucred *,int,NFSKERBKEY_T,struct mbuf **,char **,struct mbuf *));
int nfs_msg __P((struct proc *,char *,char *));
int nfs_adv __P((struct mbuf **,caddr_t *,int,int));
int nfsrv_getstream __P((struct nfssvc_sock *,int));
void nfs_nhinit __P((void));
void nfs_timer __P((void*));
struct nfsnodehashhead * nfs_hash __P((nfsv2fh_t *));
u_long nfs_hash __P((nfsfh_t *,int));
int nfssvc_iod __P((struct proc *));
int nfssvc_nfsd __P((struct nfsd_srvargs *,caddr_t,struct proc *));
int nfssvc_addsock __P((struct file *,struct mbuf *));
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *));
int nfsrv_getcache __P((struct mbuf *,struct nfsd *,struct mbuf **));
void nfsrv_updatecache __P((struct mbuf *,struct nfsd *,int,struct mbuf *));
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *,struct nfsrv_descript **));
int nfsrv_getcache __P((struct nfsrv_descript *,struct nfssvc_sock *,struct mbuf **));
void nfsrv_updatecache __P((struct nfsrv_descript *,int,struct mbuf *));
int mountnfs __P((struct nfs_args *,struct mount *,struct mbuf *,char *,char *,struct vnode **));
int nfs_connect __P((struct nfsmount *,struct nfsreq *));
int nfs_getattrcache __P((struct vnode *,struct vattr *));
@ -370,9 +532,20 @@ int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long));
int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *));
int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *));
void nfsrv_init __P((int));
void nfs_clearcommit __P((struct mount *));
int nfsrv_errmap __P((struct nfsrv_descript *, int));
void nfsrvw_coalesce __P((struct nfsrv_descript *,struct nfsrv_descript *));
void nfsrvw_sort __P((gid_t [],int));
void nfsrv_setcred __P((struct ucred *,struct ucred *));
int nfs_flush __P((struct vnode *,struct ucred *,int,struct proc *,int));
int nfs_writebp __P((struct buf *,int));
int nfsrv_vput __P(( struct vnode * ));
int nfsrv_vrele __P(( struct vnode * ));
int nfsrv_vmio __P(( struct vnode * ));
int nfsrv_writegather __P((struct nfsrv_descript **, struct nfssvc_sock *,
struct proc *, struct mbuf **));
int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
struct proc *p));
#endif /* KERNEL */

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfsdiskless.h 8.1 (Berkeley) 6/10/93
* $Id: nfsdiskless.h,v 1.3 1994/08/05 09:28:49 davidg Exp $
* $Id: nfsdiskless.h,v 1.4 1994/08/21 06:50:09 paul Exp $
*/
#ifndef _NFS_NFSDISKLESS_H_
@ -52,17 +52,45 @@
* NB: All fields are stored in net byte order to avoid hassles with
* client/server byte ordering differences.
*/
struct nfs_diskless {
/*
* I have defined a new structure that can handle an NFS Version 3 file handle
* but the kernel still expects the old Version 2 one to be provided. The
* changes required in nfs_vfsops.c for using the new are documented there in
* comments. (I felt that breaking network booting code by changing this
* structure would not be prudent at this time, since almost all servers are
* still Version 2 anyhow.)
*/
struct nfsv3_diskless {
struct ifaliasreq myif; /* Default interface */
struct sockaddr_in mygateway; /* Default gateway */
struct nfs_args swap_args; /* Mount args for swap file */
u_char swap_fh[NFS_FHSIZE]; /* Swap file's file handle */
int swap_fhsize; /* Size of file handle */
u_char swap_fh[NFSX_V3FHMAX]; /* Swap file's file handle */
struct sockaddr_in swap_saddr; /* Address of swap server */
char swap_hostnam[MNAMELEN]; /* Host name for mount pt */
int swap_nblks; /* Size of server swap file */
struct ucred swap_ucred; /* Swap credentials */
struct nfs_args root_args; /* Mount args for root fs */
u_char root_fh[NFS_FHSIZE]; /* File handle of root dir */
int root_fhsize; /* Size of root file handle */
u_char root_fh[NFSX_V3FHMAX]; /* File handle of root dir */
struct sockaddr_in root_saddr; /* Address of root server */
char root_hostnam[MNAMELEN]; /* Host name for mount pt */
long root_time; /* Timestamp of root fs */
char my_hostnam[MAXHOSTNAMELEN]; /* Client host name */
};
struct nfs_diskless {
struct ifaliasreq myif; /* Default interface */
struct sockaddr_in mygateway; /* Default gateway */
struct nfs_args swap_args; /* Mount args for swap file */
u_char swap_fh[NFSX_V2FH]; /* Swap file's file handle */
struct sockaddr_in swap_saddr; /* Address of swap server */
char swap_hostnam[MNAMELEN]; /* Host name for mount pt */
int swap_nblks; /* Size of server swap file */
struct ucred swap_ucred; /* Swap credentials */
struct nfs_args root_args; /* Mount args for root fs */
u_char root_fh[NFSX_V2FH]; /* File handle of root dir */
struct sockaddr_in root_saddr; /* Address of root server */
char root_hostnam[MNAMELEN]; /* Host name for mount pt */
long root_time; /* Timestamp of root fs */

View File

@ -34,12 +34,13 @@
* SUCH DAMAGE.
*
* @(#)nfsm_subs.h 8.1 (Berkeley) 6/16/93
* $Id: nfsm_subs.h,v 1.5 1994/10/17 17:47:42 phk Exp $
* $Id: nfsm_subs.h,v 1.6 1995/05/30 08:12:51 rgrimes Exp $
*/
#ifndef _NFS_NFSM_SUBS_H_
#define _NFS_NFSM_SUBS_H_
/*
* These macros do strange and peculiar things to mbuf chains for
* the assistance of the nfs code. To attempt to use them for any
@ -90,49 +91,153 @@ extern struct mbuf *nfsm_reqh();
mb->m_len += (s); \
bpos += (s); }
#define nfsm_dissect(a,c,s) \
#define nfsm_dissect(a, c, s) \
{ t1 = mtod(md, caddr_t)+md->m_len-dpos; \
if (t1 >= (s)) { \
(a) = (c)(dpos); \
dpos += (s); \
} else if (t1 = nfsm_disct(&md, &dpos, (s), t1, &cp2)) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
} else { \
error = nfsm_disct(&md, &dpos, (s), t1, &cp2); \
if (error) { \
m_freem(mrep); \
goto nfsmout; \
} else { \
(a) = (c)cp2; \
} \
(a) = (c)cp2; \
} }
#define nfsm_fhtom(v) \
nfsm_build(cp,caddr_t,NFSX_FH); \
bcopy((caddr_t)&(VTONFS(v)->n_fh), cp, NFSX_FH)
#define nfsm_fhtom(v, v3) \
{ if (v3) { \
t2 = nfsm_rndup(VTONFS(v)->n_fhsize) + NFSX_UNSIGNED; \
if (t2 <= M_TRAILINGSPACE(mb)) { \
nfsm_build(tl, u_long *, t2); \
*tl++ = txdr_unsigned(VTONFS(v)->n_fhsize); \
*(tl + ((t2>>2) - 2)) = 0; \
bcopy((caddr_t)VTONFS(v)->n_fhp,(caddr_t)tl, \
VTONFS(v)->n_fhsize); \
} else if (t2 = nfsm_strtmbuf(&mb, &bpos, \
(caddr_t)VTONFS(v)->n_fhp, VTONFS(v)->n_fhsize)) { \
error = t2; \
m_freem(mreq); \
goto nfsmout; \
} \
} else { \
nfsm_build(cp, caddr_t, NFSX_V2FH); \
bcopy((caddr_t)VTONFS(v)->n_fhp, cp, NFSX_V2FH); \
} }
#define nfsm_srvfhtom(f) \
nfsm_build(cp,caddr_t,NFSX_FH); \
bcopy((caddr_t)(f), cp, NFSX_FH)
#define nfsm_srvfhtom(f, v3) \
{ if (v3) { \
nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3FH); \
*tl++ = txdr_unsigned(NFSX_V3FH); \
bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
} else { \
nfsm_build(cp, caddr_t, NFSX_V2FH); \
bcopy((caddr_t)(f), cp, NFSX_V2FH); \
} }
#define nfsm_mtofh(d,v) \
{ struct nfsnode *np; nfsv2fh_t *fhp; \
nfsm_dissect(fhp,nfsv2fh_t *,NFSX_FH); \
error = nfs_nget((d)->v_mount, fhp, &np); \
if (error) { \
m_freem(mrep); \
goto nfsmout; \
} \
(v) = NFSTOV(np); \
nfsm_loadattr(v, (struct vattr *)0); \
#define nfsm_srvpostop_fh(f) \
{ nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED + NFSX_V3FH); \
*tl++ = nfs_true; \
*tl++ = txdr_unsigned(NFSX_V3FH); \
bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
}
#define nfsm_loadattr(v,a) \
{ struct vnode *tvp = (v); \
error = nfs_loadattrcache(&tvp, &md, &dpos, (a)); \
if (error) { \
#define nfsm_mtofh(d, v, v3, f) \
{ struct nfsnode *ttnp; nfsfh_t *ttfhp; int ttfhsize; \
if (v3) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
(f) = fxdr_unsigned(int, *tl); \
} else \
(f) = 1; \
if (f) { \
nfsm_getfh(ttfhp, ttfhsize, (v3)); \
if (t1 = nfs_nget((d)->v_mount, ttfhp, ttfhsize, \
&ttnp)) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
} \
(v) = NFSTOV(ttnp); \
} \
if (v3) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (f) \
(f) = fxdr_unsigned(int, *tl); \
else if (fxdr_unsigned(int, *tl)) \
nfsm_adv(NFSX_V3FATTR); \
} \
if (f) \
nfsm_loadattr((v), (struct vattr *)0); \
}
#define nfsm_getfh(f, s, v3) \
{ if (v3) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (((s) = fxdr_unsigned(int, *tl)) <= 0 || \
(s) > NFSX_V3FHMAX) { \
m_freem(mrep); \
error = EBADRPC; \
goto nfsmout; \
} \
} else \
(s) = NFSX_V2FH; \
nfsm_dissect((f), nfsfh_t *, nfsm_rndup(s)); }
#define nfsm_loadattr(v, a) \
{ struct vnode *ttvp = (v); \
if (t1 = nfs_loadattrcache(&ttvp, &md, &dpos, (a))) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
} \
(v) = tvp; }
(v) = ttvp; }
#define nfsm_postop_attr(v, f) \
{ struct vnode *ttvp = (v); \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if ((f) = fxdr_unsigned(int, *tl)) { \
if (t1 = nfs_loadattrcache(&ttvp, &md, &dpos, \
(struct vattr *)0)) { \
error = t1; \
(f) = 0; \
m_freem(mrep); \
goto nfsmout; \
} \
(v) = ttvp; \
} }
/* Used as (f) for nfsm_wcc_data() */
#define NFSV3_WCCRATTR 0
#define NFSV3_WCCCHK 1
#define nfsm_wcc_data(v, f) \
{ int ttattrf, ttretf = 0; \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
nfsm_dissect(tl, u_long *, 6 * NFSX_UNSIGNED); \
if (f) \
ttretf = (VTONFS(v)->n_mtime == \
fxdr_unsigned(u_long, *(tl + 2))); \
} \
nfsm_postop_attr((v), ttattrf); \
if (f) { \
(f) = ttretf; \
} else { \
(f) = ttattrf; \
} }
#define nfsm_v3sattr(s, a, u, g) \
{ (s)->sa_modetrue = nfs_true; \
(s)->sa_mode = vtonfsv3_mode((a)->va_mode); \
(s)->sa_uidtrue = nfs_true; \
(s)->sa_uid = txdr_unsigned(u); \
(s)->sa_gidtrue = nfs_true; \
(s)->sa_gid = txdr_unsigned(g); \
(s)->sa_sizefalse = nfs_false; \
(s)->sa_atimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \
txdr_nfsv3time(&(a)->va_atime, &(s)->sa_atime); \
(s)->sa_mtimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \
txdr_nfsv3time(&(a)->va_mtime, &(s)->sa_mtime); \
}
#define nfsm_strsiz(s,m) \
{ nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \
@ -149,16 +254,27 @@ extern struct mbuf *nfsm_reqh();
nfsm_reply(0); \
} }
#define nfsm_srvnamesiz(s) \
{ nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \
if (((s) = fxdr_unsigned(long,*tl)) > NFS_MAXNAMLEN) \
error = NFSERR_NAMETOL; \
if ((s) <= 0) \
error = EBADRPC; \
if (error) \
nfsm_reply(0); \
}
#define nfsm_mtouio(p,s) \
if ((s) > 0 && \
(error = nfsm_mbuftouio(&md,(p),(s),&dpos))) { \
(t1 = nfsm_mbuftouio(&md,(p),(s),&dpos))) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
}
#define nfsm_uiotom(p,s) \
error = nfsm_uiotombuf((p),&mb,(s),&bpos); \
if (error) { \
if (t1 = nfsm_uiotombuf((p),&mb,(s),&bpos)) { \
error = t1; \
m_freem(mreq); \
goto nfsmout; \
}
@ -172,10 +288,13 @@ extern struct mbuf *nfsm_reqh();
#define nfsm_rndup(a) (((a)+3)&(~0x3))
#define nfsm_request(v, t, p, c) \
error = nfs_request((v), mreq, (t), (p), \
(c), &mrep, &md, &dpos); \
if (error) \
goto nfsmout
if (error = nfs_request((v), mreq, (t), (p), \
(c), &mrep, &md, &dpos)) { \
if (error & NFSERR_RETERR) \
error &= ~NFSERR_RETERR; \
else \
goto nfsmout; \
}
#define nfsm_strtom(a,s,m) \
if ((s) > (m)) { \
@ -189,12 +308,10 @@ extern struct mbuf *nfsm_reqh();
*tl++ = txdr_unsigned(s); \
*(tl+((t2>>2)-2)) = 0; \
bcopy((caddr_t)(a), (caddr_t)tl, (s)); \
} else { \
error = nfsm_strtmbuf(&mb, &bpos, (a), (s)); \
if (error) { \
m_freem(mreq); \
goto nfsmout; \
} \
} else if (t2 = nfsm_strtmbuf(&mb, &bpos, (a), (s))) { \
error = t2; \
m_freem(mreq); \
goto nfsmout; \
}
#define nfsm_srvdone \
@ -204,33 +321,53 @@ extern struct mbuf *nfsm_reqh();
#define nfsm_reply(s) \
{ \
nfsd->nd_repstat = error; \
if (error) \
(void) nfs_rephead(0, nfsd, error, cache, &frev, \
if (error && !(nfsd->nd_flag & ND_NFSV3)) \
(void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
mrq, &mb, &bpos); \
else \
(void) nfs_rephead((s), nfsd, error, cache, &frev, \
(void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
mrq, &mb, &bpos); \
m_freem(mrep); \
mreq = *mrq; \
if (error) \
if (error && (!(nfsd->nd_flag & ND_NFSV3) || \
error == EBADRPC)) \
return(0); \
}
#define nfsm_adv(s) \
t1 = mtod(md, caddr_t)+md->m_len-dpos; \
if (t1 >= (s)) { \
dpos += (s); \
} else { \
error = nfs_adv(&md, &dpos, (s), t1); \
if (error) { \
m_freem(mrep); \
goto nfsmout; \
} \
#define nfsm_writereply(s, v3) \
{ \
nfsd->nd_repstat = error; \
if (error && !(v3)) \
(void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
&mreq, &mb, &bpos); \
else \
(void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
&mreq, &mb, &bpos); \
}
#define nfsm_adv(s) \
{ t1 = mtod(md, caddr_t)+md->m_len-dpos; \
if (t1 >= (s)) { \
dpos += (s); \
} else if (t1 = nfs_adv(&md, &dpos, (s), t1)) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
} }
#define nfsm_srvmtofh(f) \
nfsm_dissect(tl, u_long *, NFSX_FH); \
bcopy((caddr_t)tl, (caddr_t)f, NFSX_FH)
{ if (nfsd->nd_flag & ND_NFSV3) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (fxdr_unsigned(int, *tl) != NFSX_V3FH) { \
error = EBADRPC; \
nfsm_reply(0); \
} \
} \
nfsm_dissect(tl, u_long *, NFSX_V3FH); \
bcopy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \
if ((nfsd->nd_flag & ND_NFSV3) == 0) \
nfsm_adv(NFSX_V2FH - NFSX_V3FH); \
}
#define nfsm_clget \
if (bp >= be) { \
@ -246,41 +383,57 @@ extern struct mbuf *nfsm_reqh();
} \
tl = (u_long *)bp
#define nfsm_srvfillattr \
fp->fa_type = vtonfs_type(vap->va_type); \
fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode); \
fp->fa_nlink = txdr_unsigned(vap->va_nlink); \
fp->fa_uid = txdr_unsigned(vap->va_uid); \
fp->fa_gid = txdr_unsigned(vap->va_gid); \
if (nfsd->nd_nqlflag == NQL_NOVAL) { \
fp->fa_nfsblocksize = txdr_unsigned(vap->va_blocksize); \
if (vap->va_type == VFIFO) \
fp->fa_nfsrdev = 0xffffffff; \
else \
fp->fa_nfsrdev = txdr_unsigned(vap->va_rdev); \
fp->fa_nfsfsid = txdr_unsigned(vap->va_fsid); \
fp->fa_nfsfileid = txdr_unsigned(vap->va_fileid); \
fp->fa_nfssize = txdr_unsigned(vap->va_size); \
fp->fa_nfsblocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE); \
txdr_nfstime(&vap->va_atime, &fp->fa_nfsatime); \
txdr_nfstime(&vap->va_mtime, &fp->fa_nfsmtime); \
txdr_nfstime(&vap->va_ctime, &fp->fa_nfsctime); \
} else { \
fp->fa_nqblocksize = txdr_unsigned(vap->va_blocksize); \
if (vap->va_type == VFIFO) \
fp->fa_nqrdev = 0xffffffff; \
else \
fp->fa_nqrdev = txdr_unsigned(vap->va_rdev); \
fp->fa_nqfsid = txdr_unsigned(vap->va_fsid); \
fp->fa_nqfileid = txdr_unsigned(vap->va_fileid); \
txdr_hyper(&vap->va_size, &fp->fa_nqsize); \
txdr_hyper(&vap->va_bytes, &fp->fa_nqbytes); \
txdr_nqtime(&vap->va_atime, &fp->fa_nqatime); \
txdr_nqtime(&vap->va_mtime, &fp->fa_nqmtime); \
txdr_nqtime(&vap->va_ctime, &fp->fa_nqctime); \
fp->fa_nqflags = txdr_unsigned(vap->va_flags); \
fp->fa_nqgen = txdr_unsigned(vap->va_gen); \
txdr_hyper(&vap->va_filerev, &fp->fa_nqfilerev); \
}
#define nfsm_srvfillattr(a, f) \
nfsm_srvfattr(nfsd, (a), (f))
#define nfsm_srvwcc_data(br, b, ar, a) \
nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos)
#define nfsm_srvpostop_attr(r, a) \
nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos)
#define nfsm_srvsattr(a) \
{ nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
(a)->va_mode = nfstov_mode(*tl); \
} \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
(a)->va_uid = fxdr_unsigned(uid_t, *tl); \
} \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
(a)->va_gid = fxdr_unsigned(gid_t, *tl); \
} \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
fxdr_hyper(tl, &(a)->va_size); \
} \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
switch (fxdr_unsigned(int, *tl)) { \
case NFSV3SATTRTIME_TOCLIENT: \
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
fxdr_nfsv3time(tl, &(a)->va_atime); \
break; \
case NFSV3SATTRTIME_TOSERVER: \
(a)->va_atime.ts_sec = time.tv_sec; \
(a)->va_atime.ts_nsec = time.tv_usec * 1000; \
break; \
}; \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
switch (fxdr_unsigned(int, *tl)) { \
case NFSV3SATTRTIME_TOCLIENT: \
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
fxdr_nfsv3time(tl, &(a)->va_mtime); \
break; \
case NFSV3SATTRTIME_TOSERVER: \
(a)->va_mtime.ts_sec = time.tv_sec; \
(a)->va_mtime.ts_nsec = time.tv_usec * 1000; \
break; \
}; }
#endif

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfsmount.h 8.1 (Berkeley) 6/10/93
* $Id: nfsmount.h,v 1.3 1994/08/21 06:50:10 paul Exp $
* $Id: nfsmount.h,v 1.4 1994/10/17 17:47:43 phk Exp $
*/
#ifndef _NFS_NFSMOUNT_H_
@ -49,7 +49,8 @@ struct nfsmount {
int nm_flag; /* Flags for soft/hard... */
struct mount *nm_mountp; /* Vfs structure for this filesystem */
int nm_numgrps; /* Max. size of groupslist */
nfsv2fh_t nm_fh; /* File handle of root dir */
u_char nm_fh[NFSX_V3FHMAX]; /* File handle of root dir */
int nm_fhsize; /* Size of root file handle */
struct socket *nm_so; /* Rpc socket */
int nm_sotype; /* Type of socket */
int nm_soproto; /* and protocol */
@ -65,6 +66,7 @@ struct nfsmount {
int nm_deadthresh; /* Threshold of timeouts-->dead server*/
int nm_rsize; /* Max size of read rpc */
int nm_wsize; /* Max size of write rpc */
int nm_readdirsize; /* Size of a readdir rpc */
int nm_readahead; /* Num. of blocks to readahead */
int nm_leaseterm; /* Term (sec) for NQNFS lease */
CIRCLEQ_HEAD(, nfsnode) nm_timerhead; /* Head of lease timer queue */
@ -73,9 +75,16 @@ struct nfsmount {
int nm_authtype; /* Authenticator type */
int nm_authlen; /* and length */
char *nm_authstr; /* Authenticator string */
char *nm_verfstr; /* and the verifier */
int nm_verflen;
u_char nm_verf[NFSX_V3WRITEVERF]; /* V3 write verifier */
NFSKERBKEY_T nm_key; /* and the session key */
int nm_numuids; /* Number of nfsuid mappings */
TAILQ_HEAD(, nfsuid) nm_uidlruhead; /* Lists of nfsuid mappings */
LIST_HEAD(, nfsuid) nm_uidhashtbl[NFS_MUIDHASHSIZ];
};
#ifdef KERNEL
#if defined(KERNEL) || defined(_KERNEL)
/*
* Convert mount ptr to nfsmount ptr.
*/

View File

@ -34,12 +34,16 @@
* SUCH DAMAGE.
*
* @(#)nfsnode.h 8.4 (Berkeley) 2/13/94
* $Id: nfsnode.h,v 1.8 1994/10/17 17:47:44 phk Exp $
* $Id: nfsnode.h,v 1.9 1995/03/16 18:15:42 bde Exp $
*/
#ifndef _NFS_NFSNODE_H_
#define _NFS_NFSNODE_H_
#ifndef _NFS_NFS_H_
#include <nfs/nfs.h>
#endif
/*
* Silly rename structure that hangs off the nfsnode until the name
* can be removed by nfs_inactive()
@ -51,37 +55,74 @@ struct sillyrename {
char s_name[20];
};
/*
* This structure is used to save the logical directory offset to
* NFS cookie mappings.
* The mappings are stored in a list headed
* by n_cookies, as required.
* There is one mapping for each NFS_DIRBLKSIZ bytes of directory information
* stored in increasing logical offset byte order.
*/
#define NFSNUMCOOKIES 31
struct nfsdmap {
LIST_ENTRY(nfsdmap) ndm_list;
int ndm_eocookie;
nfsuint64 ndm_cookies[NFSNUMCOOKIES];
};
/*
* The nfsnode is the nfs equivalent to ufs's inode. Any similarity
* is purely coincidental.
* There is a unique nfsnode allocated for each active file,
* each current directory, each mounted-on file, text file, and the root.
* An nfsnode is 'named' by its file handle. (nget/nfs_node.c)
* If this structure exceeds 256 bytes (it is currently 256 using 4.4BSD-Lite
* type definitions), file handles of > 32 bytes should probably be split out
* into a separate MALLOC()'d data structure. (Reduce the size of nfsfh_t by
* changing the definition in sys/mount.h of NFS_SMALLFH.)
* NB: Hopefully the current order of the fields is such that everything will
* be well aligned and, therefore, tightly packed.
*/
struct nfsnode {
LIST_ENTRY(nfsnode) n_hash; /* Hash chain */
CIRCLEQ_ENTRY(nfsnode) n_timer; /* Nqnfs timer chain */
nfsv2fh_t n_fh; /* NFS File Handle */
long n_flag; /* Flag for locking.. */
struct vnode *n_vnode; /* vnode associated with this node */
struct vattr n_vattr; /* Vnode attribute cache */
time_t n_attrstamp; /* Time stamp for cached attributes */
struct sillyrename *n_sillyrename; /* Ptr to silly rename struct */
u_quad_t n_size; /* Current size of file */
struct lockf *n_lockf; /* Locking record of file */
int n_error; /* Save write error value */
u_long n_direofoffset; /* Dir. EOF offset cache */
time_t n_mtime; /* Prev modify time. */
time_t n_ctime; /* Prev create time. */
u_quad_t n_brev; /* Modify rev when cached */
u_quad_t n_lrev; /* Modify rev for lease */
time_t n_expiry; /* Lease expiry time */
struct sillyrename n_silly; /* Silly rename struct */
struct timeval n_atim; /* Special file times */
struct timeval n_mtim;
LIST_ENTRY(nfsnode) n_hash; /* Hash chain */
CIRCLEQ_ENTRY(nfsnode) n_timer; /* Nqnfs timer chain */
u_quad_t n_size; /* Current size of file */
u_quad_t n_brev; /* Modify rev when cached */
u_quad_t n_lrev; /* Modify rev for lease */
struct vattr n_vattr; /* Vnode attribute cache */
time_t n_attrstamp; /* Attr. cache timestamp */
time_t n_mtime; /* Prev modify time. */
time_t n_ctime; /* Prev create time. */
time_t n_expiry; /* Lease expiry time */
nfsfh_t *n_fhp; /* NFS File Handle */
struct vnode *n_vnode; /* associated vnode */
struct lockf *n_lockf; /* Locking record of file */
int n_error; /* Save write error value */
union {
struct timespec nf_atim; /* Special file times */
nfsuint64 nd_cookieverf; /* Cookie verifier (dir only) */
} n_un1;
union {
struct timespec nf_mtim;
off_t nd_direof; /* Dir. EOF offset cache */
} n_un2;
union {
struct sillyrename *nf_silly; /* Ptr to silly rename struct */
LIST_HEAD(, nfsdmap) nd_cook; /* cookies */
} n_un3;
short n_fhsize; /* size in bytes, of fh */
short n_flag; /* Flag for locking.. */
nfsfh_t n_fh; /* Small File Handle */
};
#define n_atim n_un1.nf_atim
#define n_mtim n_un2.nf_mtim
#define n_sillyrename n_un3.nf_silly
#define n_cookieverf n_un1.nd_cookieverf
#define n_direofoffset n_un2.nd_direof
#define n_cookies n_un3.nd_cook
/*
* Flags for n_flag
*/
@ -95,6 +136,8 @@ struct nfsnode {
#define NACC 0x0100 /* Special file accessed */
#define NUPD 0x0200 /* Special file updated */
#define NCHG 0x0400 /* Special file times changed */
#define NLOCKED 0x0800 /* node is locked */
#define NWANTED 0x0100 /* someone wants to lock */
/*
* Convert between nfsnode pointers and vnode pointers
@ -107,7 +150,7 @@ struct nfsnode {
*/
TAILQ_HEAD(, buf) nfs_bufq;
#ifdef KERNEL
#if defined(KERNEL) || defined(_KERNEL)
extern int (**fifo_nfsv2nodeop_p)();
extern int (**nfsv2_vnodeop_p)();
extern int (**spec_nfsv2nodeop_p)();
@ -128,12 +171,25 @@ int nfs_getattr __P((struct vop_getattr_args *));
int nfs_setattr __P((struct vop_setattr_args *));
int nfs_read __P((struct vop_read_args *));
int nfs_write __P((struct vop_write_args *));
#ifdef HAS_VOPLEASE
#define nfs_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
#define nqnfs_vop_lease_check lease_check
#else
#ifdef __FreeBSD__
#define nqnfs_lease_check nfs_lease_check
#else
#define nqnfs_lease_check lease_check
#endif
#endif
int nfsspec_read __P((struct vop_read_args *));
int nfsspec_write __P((struct vop_write_args *));
int nfsfifo_read __P((struct vop_read_args *));
int nfsfifo_write __P((struct vop_write_args *));
#define nfs_ioctl ((int (*) __P((struct vop_ioctl_args *)))enoioctl)
#define nfs_select ((int (*) __P((struct vop_select_args *)))seltrue)
#ifdef HAS_VOPREVOKE
#define nfs_revoke vop_revoke
#endif
int nfs_mmap __P((struct vop_mmap_args *));
int nfs_fsync __P((struct vop_fsync_args *));
#define nfs_seek ((int (*) __P((struct vop_seek_args *)))nullop)
@ -157,6 +213,7 @@ int nfs_islocked __P((struct vop_islocked_args *));
int nfs_pathconf __P((struct vop_pathconf_args *));
int nfs_advlock __P((struct vop_advlock_args *));
int nfs_blkatoff __P((struct vop_blkatoff_args *));
int nfs_bwrite __P((struct vop_bwrite_args *));
int nfs_vget __P((struct mount *, ino_t, struct vnode **));
int nfs_valloc __P((struct vop_valloc_args *));
#define nfs_reallocblks \
@ -164,13 +221,20 @@ int nfs_valloc __P((struct vop_valloc_args *));
int nfs_vfree __P((struct vop_vfree_args *));
int nfs_truncate __P((struct vop_truncate_args *));
int nfs_update __P((struct vop_update_args *));
int nfs_bwrite __P((struct vop_bwrite_args *));
/* other stuff */
int nfs_removeit __P((struct sillyrename *));
int nfs_nget __P((struct mount *,nfsv2fh_t *,struct nfsnode **));
int nfs_lookitup __P((struct sillyrename *,nfsv2fh_t *,struct proc *));
int nfs_nget __P((struct mount *,nfsfh_t *,int,struct nfsnode **));
int nfs_lookitup __P((struct vnode *,char *,int,struct ucred *,struct proc *,struct nfsnode **));
int nfs_sillyrename __P((struct vnode *,struct vnode *,struct componentname *));
nfsuint64 *nfs_getcookie __P((struct nfsnode *, off_t, int));
void nfs_invaldir __P((struct vnode *));
#ifdef __FreeBSD__
#define nqnfs_lease_updatetime nfs_lease_updatetime
#else
#define nqnfs_lease_updatetime lease_updatetime
#endif
#endif /* KERNEL */

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs.h 8.1 (Berkeley) 6/10/93
* $Id: nfs.h,v 1.8 1994/11/02 00:11:00 wollman Exp $
* $Id: nfs.h,v 1.9 1995/02/14 06:22:18 phk Exp $
*/
#ifndef _NFS_NFS_H_
@ -45,11 +45,12 @@
*/
#define NFS_MAXIOVEC 34
#define NFS_HZ 25 /* Ticks per second for NFS timeouts */
#define NFS_TIMEO (1*NFS_HZ) /* Default timeout = 1 second */
#define NFS_MINTIMEO (1*NFS_HZ) /* Min timeout to use */
#define NFS_MAXTIMEO (60*NFS_HZ) /* Max timeout to backoff to */
#define NFS_MINIDEMTIMEO (5*NFS_HZ) /* Min timeout for non-idempotent ops*/
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
#define NFS_MINIDEMTIMEO (5 * NFS_HZ) /* Min timeout for non-idempotent ops*/
#define NFS_MAXREXMIT 100 /* Stop counting after this many */
#define NFS_MAXWINDOW 1024 /* Max number of outstanding requests */
#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
@ -62,13 +63,81 @@
#endif
#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
#define NFS_READDIRSIZE 8192 /* Def. readdir size */
#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
#define NFS_MAXREADDIR NFS_MAXDATA /* Max. size of directory read */
#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
#define NFS_DIRBLKSIZ 1024 /* Size of an NFS directory block */
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
#ifndef NFS_GATHERDELAY
#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
#endif
#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
/*
* Oddballs
*/
#define NMOD(a) ((a) % nfs_asyncdaemons)
#define NFS_CMPFH(n, f, s) \
((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s)))
#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3)
#define NFS_SRVMAXDATA(n) \
(((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \
NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA)
/*
* XXX
* sys/buf.h should be editted to change B_APPENDWRITE --> B_NEEDCOMMIT, but
* until then...
* Same goes for sys/malloc.h, which needs M_NFSDIROFF,
* M_NFSRVDESC and M_NFSBIGFH added.
* The VA_EXCLUSIVE flag should be added for va_vaflags and set for an
* exclusive create.
* The B_INVAFTERWRITE flag should be set to whatever is required by the
* buffer cache code to say "Invalidate the block after it is written back".
*/
#ifndef B_NEEDCOMMIT
#define B_NEEDCOMMIT B_APPENDWRITE
#endif
#ifndef M_NFSRVDESC
#define M_NFSRVDESC M_TEMP
#endif
#ifndef M_NFSDIROFF
#define M_NFSDIROFF M_TEMP
#endif
#ifndef M_NFSBIGFH
#define M_NFSBIGFH M_TEMP
#endif
#ifndef VA_EXCLUSIVE
#define VA_EXCLUSIVE 0
#endif
#ifdef __FreeBSD__
#define B_INVAFTERWRITE B_NOCACHE
#else
#define B_INVAFTERWRITE B_INVAL
#endif
/*
* These ifdefs try to handle the differences between the various 4.4BSD-Lite
* based vfs interfaces.
* btw: NetBSD-current does have a VOP_LEASDE(), but I don't know how to
* differentiate between NetBSD-1.0 and NetBSD-current, so..
* I also don't know about BSDi's 2.0 release.
*/
#if !defined(HAS_VOPLEASE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
#define HAS_VOPLEASE 1
#endif
#if !defined(HAS_VOPREVOKE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
#define HAS_VOPREVOKE 1
#endif
/*
* The IO_METASYNC flag should be implemented for local file systems.
* (Until then, it is nothin at all.)
*/
#ifndef IO_METASYNC
#define IO_METASYNC 0
#endif
/*
* Set the attribute timeout based on how recently the file has been modified.
@ -79,6 +148,20 @@
((time.tv_sec - (np)->n_mtime) / 10 > NFS_MAXATTRTIMO ? NFS_MAXATTRTIMO : \
(time.tv_sec - (np)->n_mtime) / 10))
/*
* Expected allocation sizes for major data structures. If the actual size
* of the structure exceeds these sizes, then malloc() will be allocating
* almost twice the memory required. This is used in nfs_init() to warn
* the sysadmin that the size of a structure should be reduced.
* (These sizes are always a power of 2. If the kernel malloc() changes
* to one that does not allocate space in powers of 2 size, then this all
* becomes bunk!)
*/
#define NFS_NODEALLOC 256
#define NFS_MNTALLOC 512
#define NFS_SVCALLOC 256
#define NFS_UIDALLOC 128
/*
* Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
* should ever try and use it.
@ -95,7 +178,12 @@ struct nfsd_srvargs {
u_long nsd_haddr; /* Ip address of client */
struct ucred nsd_cr; /* Cred. uid maps to */
int nsd_authlen; /* Length of auth string (ret) */
char *nsd_authstr; /* Auth string (ret) */
u_char *nsd_authstr; /* Auth string (ret) */
int nsd_verflen; /* and the verfier */
u_char *nsd_verfstr;
struct timeval nsd_timestamp; /* timestamp from verifier */
u_long nsd_ttl; /* credential ttl (sec) */
NFSKERBKEY_T nsd_key; /* Session key */
};
struct nfsd_cargs {
@ -103,7 +191,10 @@ struct nfsd_cargs {
uid_t ncd_authuid; /* Effective uid */
int ncd_authtype; /* Type of authenticator */
int ncd_authlen; /* Length of authenticator string */
char *ncd_authstr; /* Authenticator string */
u_char *ncd_authstr; /* Authenticator string */
int ncd_verflen; /* and the verifier */
u_char *ncd_verfstr;
NFSKERBKEY_T ncd_key; /* Session key */
};
/*
@ -142,6 +233,7 @@ struct nfsstats {
int srvnqnfs_leases;
int srvnqnfs_maxleases;
int srvnqnfs_getleases;
int srvvop_writes;
};
/*
@ -173,7 +265,7 @@ struct nfsstats {
* such as SIGALRM will not expect file I/O system calls to be interrupted
* by them and break.
*/
#ifdef KERNEL
#if defined(KERNEL) || defined(_KERNEL)
struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
@ -224,17 +316,29 @@ TAILQ_HEAD(, nfsreq) nfs_reqq;
#define R_MUSTRESEND 0x40 /* Must resend request */
#define R_GETONEREP 0x80 /* Probe for one reply only */
extern struct nfsstats nfsstats;
/*
* A list of nfssvc_sock structures is maintained with all the sockets
* that require service by the nfsd.
* The nfsuid structs hang off of the nfssvc_sock structs in both lru
* and uid hash lists.
*/
#define NUIDHASHSIZ 32
#ifndef NFS_UIDHASHSIZ
#define NFS_UIDHASHSIZ 29 /* Tune the size of nfssvc_sock with this */
#endif
#define NUIDHASH(sock, uid) \
(&(sock)->ns_uidhashtbl[(uid) & (sock)->ns_uidhash])
(&(sock)->ns_uidhashtbl[(uid) % NFS_UIDHASHSIZ])
#ifndef NFS_WDELAYHASHSIZ
#define NFS_WDELAYHASHSIZ 16 /* and with this */
#endif
#define NWDELAYHASH(sock, f) \
(&(sock)->ns_wdelayhashtbl[(*((u_long *)(f))) % NFS_WDELAYHASHSIZ])
#ifndef NFS_MUIDHASHSIZ
#define NFS_MUIDHASHSIZ 67 /* Tune the size of nfsmount with this */
#endif
#define NMUIDHASH(nmp, uid) \
(&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
#define NFSNOHASH(fhsum) \
(&nfsnodehashtbl[(fhsum) & nfsnodehash])
/*
* Network address hash list element
@ -248,35 +352,41 @@ struct nfsuid {
TAILQ_ENTRY(nfsuid) nu_lru; /* LRU chain */
LIST_ENTRY(nfsuid) nu_hash; /* Hash list */
int nu_flag; /* Flags */
uid_t nu_uid; /* Uid mapped by this entry */
union nethostaddr nu_haddr; /* Host addr. for dgram sockets */
struct ucred nu_cr; /* Cred uid mapped to */
int nu_expire; /* Expiry time (sec) */
struct timeval nu_timestamp; /* Kerb. timestamp */
u_long nu_nickname; /* Nickname on server */
NFSKERBKEY_T nu_key; /* and session key */
};
#define nu_inetaddr nu_haddr.had_inetaddr
#define nu_nam nu_haddr.had_nam
/* Bits for nu_flag */
#define NU_INETADDR 0x1
#define NU_NAM 0x2
#define NU_NETFAM(u) (((u)->nu_flag & NU_INETADDR) ? AF_INET : AF_ISO)
struct nfssvc_sock {
TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
TAILQ_HEAD(, nfsuid) ns_uidlruhead;
LIST_HEAD(, nfsuid) *ns_uidhashtbl;
u_long ns_uidhash;
int ns_flag;
u_long ns_sref;
struct file *ns_fp;
struct socket *ns_so;
int ns_solock;
struct mbuf *ns_nam;
int ns_cc;
struct mbuf *ns_raw;
struct mbuf *ns_rawend;
int ns_reclen;
struct mbuf *ns_rec;
struct mbuf *ns_recend;
struct mbuf *ns_frag;
int ns_flag;
int ns_solock;
int ns_cc;
int ns_reclen;
int ns_numuids;
u_long ns_sref;
LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
LIST_HEAD(, nfsuid) ns_uidhashtbl[NFS_UIDHASHSIZ];
LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
};
/* Bits for "ns_flag" */
@ -285,6 +395,7 @@ struct nfssvc_sock {
#define SLP_NEEDQ 0x04
#define SLP_DISCONN 0x08
#define SLP_GETSTREAM 0x10
#define SLP_LASTFRAG 0x20
#define SLP_ALLFLAGS 0xff
TAILQ_HEAD(, nfssvc_sock) nfssvc_sockhead;
@ -296,73 +407,124 @@ int nfssvc_sockhead_flag;
* One of these structures is allocated for each nfsd.
*/
struct nfsd {
TAILQ_ENTRY(nfsd) nd_chain; /* List of all nfsd's */
int nd_flag; /* NFSD_ flags */
struct nfssvc_sock *nd_slp; /* Current socket */
struct mbuf *nd_nam; /* Client addr for datagram req. */
struct mbuf *nd_mrep; /* Req. mbuf list */
struct mbuf *nd_md;
caddr_t nd_dpos; /* Position in list */
int nd_procnum; /* RPC procedure number */
u_long nd_retxid; /* RPC xid */
int nd_repstat; /* Reply status value */
struct ucred nd_cr; /* Credentials for req. */
int nd_nqlflag; /* Leasing flag */
u_long nd_duration; /* Lease duration */
int nd_authlen; /* Authenticator len */
u_char nd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
struct proc *nd_procp; /* Proc ptr */
TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
int nfsd_flag; /* NFSD_ flags */
struct nfssvc_sock *nfsd_slp; /* Current socket */
int nfsd_authlen; /* Authenticator len */
u_char nfsd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
int nfsd_verflen; /* and the Verifier */
u_char nfsd_verfstr[RPCVERF_MAXSIZ];
struct proc *nfsd_procp; /* Proc ptr */
struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
};
/* Bits for "nd_flag" */
/* Bits for "nfsd_flag" */
#define NFSD_WAITING 0x01
#define NFSD_REQINPROG 0x02
#define NFSD_NEEDAUTH 0x04
#define NFSD_AUTHFAIL 0x08
/*
* This structure is used by the server for describing each request.
* Some fields are used only when write request gathering is performed.
*/
struct nfsrv_descript {
u_quad_t nd_time; /* Write deadline (usec) */
off_t nd_off; /* Start byte offset */
off_t nd_eoff; /* and end byte offset */
LIST_ENTRY(nfsrv_descript) nd_hash; /* Hash list */
LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
LIST_HEAD(,nfsrv_descript) nd_coalesce; /* coalesced writes */
struct mbuf *nd_mrep; /* Request mbuf list */
struct mbuf *nd_md; /* Current dissect mbuf */
struct mbuf *nd_mreq; /* Reply mbuf list */
struct mbuf *nd_nam; /* and socket addr */
struct mbuf *nd_nam2; /* return socket addr */
caddr_t nd_dpos; /* Current dissect pos */
int nd_procnum; /* RPC # */
int nd_stable; /* storage type */
int nd_flag; /* nd_flag */
int nd_len; /* Length of this write */
int nd_repstat; /* Reply status */
u_long nd_retxid; /* Reply xid */
u_long nd_duration; /* Lease duration */
struct timeval nd_starttime; /* Time RPC initiated */
fhandle_t nd_fh; /* File handle */
struct ucred nd_cr; /* Credentials */
};
/* Bits for "nd_flag" */
#define ND_READ LEASE_READ
#define ND_WRITE LEASE_WRITE
#define ND_CHECK 0x04
#define ND_LEASE (ND_READ | ND_WRITE | ND_CHECK)
#define ND_NFSV3 0x08
#define ND_NQNFS 0x10
#define ND_KERBNICK 0x20
#define ND_KERBFULL 0x40
#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
TAILQ_HEAD(, nfsd) nfsd_head;
int nfsd_head_flag;
#define NFSD_CHECKSLP 0x01
/*
* These macros compare nfsrv_descript structures.
*/
#define NFSW_CONTIG(o, n) \
((o)->nd_eoff >= (n)->nd_off && \
!bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH))
#define NFSW_SAMECRED(o, n) \
(((o)->nd_flag & ND_KERBAUTH) == ((n)->nd_flag & ND_KERBAUTH) && \
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
sizeof (struct ucred)))
int nfs_reply __P((struct nfsreq *));
int nfs_getreq __P((struct nfsd *,int));
int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
int nfs_send __P((struct socket *,struct mbuf *,struct mbuf *,struct nfsreq *));
int nfs_rephead __P((int,struct nfsd *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_rephead __P((int,struct nfsrv_descript *,struct nfssvc_sock *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_sndlock __P((int *,struct nfsreq *));
int nfs_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
int nfs_vinvalbuf __P((struct vnode *,int,struct ucred *,struct proc *,int));
int nfs_readrpc __P((struct vnode *,struct uio *,struct ucred *));
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int));
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int *,int *));
int nfs_readdirrpc __P((register struct vnode *,struct uio *,struct ucred *));
int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct proc *));
int nfs_asyncio __P((struct buf *,struct ucred *));
int nfs_doio __P((struct buf *,struct ucred *,struct proc *));
int nfs_readlinkrpc __P((struct vnode *,struct uio *,struct ucred *));
int nfs_sigintr __P((struct nfsmount *,struct nfsreq *r,struct proc *));
int nfs_readdirlookrpc __P((struct vnode *,register struct uio *,struct ucred *));
int nfs_readdirplusrpc __P((struct vnode *,register struct uio *,struct ucred *));
int nfsm_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *));
void nfsm_srvfattr __P((struct nfsrv_descript *,struct vattr *,struct nfs_fattr *));
void nfsm_srvwcc __P((struct nfsrv_descript *,int,struct vattr *,int,struct vattr *,struct mbuf **,char **));
void nfsm_srvpostopattr __P((struct nfsrv_descript *,int,struct vattr *,struct mbuf **,char **));
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *,int));
int nfsrv_access __P((struct vnode *,int,struct ucred *,int,struct proc *));
int netaddr_match __P((int,union nethostaddr *,struct mbuf *));
int nfs_request __P((struct vnode *,struct mbuf *,int,struct proc *,struct ucred *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_loadattrcache __P((struct vnode **,struct mbuf **,caddr_t *,struct vattr *));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct proc *));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int));
void nfsm_adj __P((struct mbuf *,int,int));
int nfsm_mbuftouio __P((struct mbuf **,struct uio *,int,caddr_t *));
void nfsrv_initcache __P((void));
int nfs_rcvlock __P((struct nfsreq *));
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,int *,char **,int *));
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,char **,int *,char *,int *,NFSKERBKEY_T));
int nfs_getnickauth __P((struct nfsmount *,struct ucred *,char **,int *,char *,int));
int nfs_savenickauth __P((struct nfsmount *,struct ucred *,int,NFSKERBKEY_T,struct mbuf **,char **,struct mbuf *));
int nfs_msg __P((struct proc *,char *,char *));
int nfs_adv __P((struct mbuf **,caddr_t *,int,int));
int nfsrv_getstream __P((struct nfssvc_sock *,int));
void nfs_nhinit __P((void));
void nfs_timer __P((void*));
struct nfsnodehashhead * nfs_hash __P((nfsv2fh_t *));
u_long nfs_hash __P((nfsfh_t *,int));
int nfssvc_iod __P((struct proc *));
int nfssvc_nfsd __P((struct nfsd_srvargs *,caddr_t,struct proc *));
int nfssvc_addsock __P((struct file *,struct mbuf *));
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *));
int nfsrv_getcache __P((struct mbuf *,struct nfsd *,struct mbuf **));
void nfsrv_updatecache __P((struct mbuf *,struct nfsd *,int,struct mbuf *));
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *,struct nfsrv_descript **));
int nfsrv_getcache __P((struct nfsrv_descript *,struct nfssvc_sock *,struct mbuf **));
void nfsrv_updatecache __P((struct nfsrv_descript *,int,struct mbuf *));
int mountnfs __P((struct nfs_args *,struct mount *,struct mbuf *,char *,char *,struct vnode **));
int nfs_connect __P((struct nfsmount *,struct nfsreq *));
int nfs_getattrcache __P((struct vnode *,struct vattr *));
@ -370,9 +532,20 @@ int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long));
int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *));
int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *));
void nfsrv_init __P((int));
void nfs_clearcommit __P((struct mount *));
int nfsrv_errmap __P((struct nfsrv_descript *, int));
void nfsrvw_coalesce __P((struct nfsrv_descript *,struct nfsrv_descript *));
void nfsrvw_sort __P((gid_t [],int));
void nfsrv_setcred __P((struct ucred *,struct ucred *));
int nfs_flush __P((struct vnode *,struct ucred *,int,struct proc *,int));
int nfs_writebp __P((struct buf *,int));
int nfsrv_vput __P(( struct vnode * ));
int nfsrv_vrele __P(( struct vnode * ));
int nfsrv_vmio __P(( struct vnode * ));
int nfsrv_writegather __P((struct nfsrv_descript **, struct nfssvc_sock *,
struct proc *, struct mbuf **));
int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
struct proc *p));
#endif /* KERNEL */

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs.h 8.1 (Berkeley) 6/10/93
* $Id: nfs.h,v 1.8 1994/11/02 00:11:00 wollman Exp $
* $Id: nfs.h,v 1.9 1995/02/14 06:22:18 phk Exp $
*/
#ifndef _NFS_NFS_H_
@ -45,11 +45,12 @@
*/
#define NFS_MAXIOVEC 34
#define NFS_HZ 25 /* Ticks per second for NFS timeouts */
#define NFS_TIMEO (1*NFS_HZ) /* Default timeout = 1 second */
#define NFS_MINTIMEO (1*NFS_HZ) /* Min timeout to use */
#define NFS_MAXTIMEO (60*NFS_HZ) /* Max timeout to backoff to */
#define NFS_MINIDEMTIMEO (5*NFS_HZ) /* Min timeout for non-idempotent ops*/
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
#define NFS_MINIDEMTIMEO (5 * NFS_HZ) /* Min timeout for non-idempotent ops*/
#define NFS_MAXREXMIT 100 /* Stop counting after this many */
#define NFS_MAXWINDOW 1024 /* Max number of outstanding requests */
#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
@ -62,13 +63,81 @@
#endif
#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
#define NFS_READDIRSIZE 8192 /* Def. readdir size */
#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
#define NFS_MAXREADDIR NFS_MAXDATA /* Max. size of directory read */
#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
#define NFS_DIRBLKSIZ 1024 /* Size of an NFS directory block */
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
#ifndef NFS_GATHERDELAY
#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
#endif
#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
/*
* Oddballs
*/
#define NMOD(a) ((a) % nfs_asyncdaemons)
#define NFS_CMPFH(n, f, s) \
((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s)))
#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3)
#define NFS_SRVMAXDATA(n) \
(((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \
NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA)
/*
* XXX
* sys/buf.h should be editted to change B_APPENDWRITE --> B_NEEDCOMMIT, but
* until then...
* Same goes for sys/malloc.h, which needs M_NFSDIROFF,
* M_NFSRVDESC and M_NFSBIGFH added.
* The VA_EXCLUSIVE flag should be added for va_vaflags and set for an
* exclusive create.
* The B_INVAFTERWRITE flag should be set to whatever is required by the
* buffer cache code to say "Invalidate the block after it is written back".
*/
#ifndef B_NEEDCOMMIT
#define B_NEEDCOMMIT B_APPENDWRITE
#endif
#ifndef M_NFSRVDESC
#define M_NFSRVDESC M_TEMP
#endif
#ifndef M_NFSDIROFF
#define M_NFSDIROFF M_TEMP
#endif
#ifndef M_NFSBIGFH
#define M_NFSBIGFH M_TEMP
#endif
#ifndef VA_EXCLUSIVE
#define VA_EXCLUSIVE 0
#endif
#ifdef __FreeBSD__
#define B_INVAFTERWRITE B_NOCACHE
#else
#define B_INVAFTERWRITE B_INVAL
#endif
/*
* These ifdefs try to handle the differences between the various 4.4BSD-Lite
* based vfs interfaces.
* btw: NetBSD-current does have a VOP_LEASDE(), but I don't know how to
* differentiate between NetBSD-1.0 and NetBSD-current, so..
* I also don't know about BSDi's 2.0 release.
*/
#if !defined(HAS_VOPLEASE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
#define HAS_VOPLEASE 1
#endif
#if !defined(HAS_VOPREVOKE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
#define HAS_VOPREVOKE 1
#endif
/*
* The IO_METASYNC flag should be implemented for local file systems.
* (Until then, it is nothin at all.)
*/
#ifndef IO_METASYNC
#define IO_METASYNC 0
#endif
/*
* Set the attribute timeout based on how recently the file has been modified.
@ -79,6 +148,20 @@
((time.tv_sec - (np)->n_mtime) / 10 > NFS_MAXATTRTIMO ? NFS_MAXATTRTIMO : \
(time.tv_sec - (np)->n_mtime) / 10))
/*
* Expected allocation sizes for major data structures. If the actual size
* of the structure exceeds these sizes, then malloc() will be allocating
* almost twice the memory required. This is used in nfs_init() to warn
* the sysadmin that the size of a structure should be reduced.
* (These sizes are always a power of 2. If the kernel malloc() changes
* to one that does not allocate space in powers of 2 size, then this all
* becomes bunk!)
*/
#define NFS_NODEALLOC 256
#define NFS_MNTALLOC 512
#define NFS_SVCALLOC 256
#define NFS_UIDALLOC 128
/*
* Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
* should ever try and use it.
@ -95,7 +178,12 @@ struct nfsd_srvargs {
u_long nsd_haddr; /* Ip address of client */
struct ucred nsd_cr; /* Cred. uid maps to */
int nsd_authlen; /* Length of auth string (ret) */
char *nsd_authstr; /* Auth string (ret) */
u_char *nsd_authstr; /* Auth string (ret) */
int nsd_verflen; /* and the verfier */
u_char *nsd_verfstr;
struct timeval nsd_timestamp; /* timestamp from verifier */
u_long nsd_ttl; /* credential ttl (sec) */
NFSKERBKEY_T nsd_key; /* Session key */
};
struct nfsd_cargs {
@ -103,7 +191,10 @@ struct nfsd_cargs {
uid_t ncd_authuid; /* Effective uid */
int ncd_authtype; /* Type of authenticator */
int ncd_authlen; /* Length of authenticator string */
char *ncd_authstr; /* Authenticator string */
u_char *ncd_authstr; /* Authenticator string */
int ncd_verflen; /* and the verifier */
u_char *ncd_verfstr;
NFSKERBKEY_T ncd_key; /* Session key */
};
/*
@ -142,6 +233,7 @@ struct nfsstats {
int srvnqnfs_leases;
int srvnqnfs_maxleases;
int srvnqnfs_getleases;
int srvvop_writes;
};
/*
@ -173,7 +265,7 @@ struct nfsstats {
* such as SIGALRM will not expect file I/O system calls to be interrupted
* by them and break.
*/
#ifdef KERNEL
#if defined(KERNEL) || defined(_KERNEL)
struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
@ -224,17 +316,29 @@ TAILQ_HEAD(, nfsreq) nfs_reqq;
#define R_MUSTRESEND 0x40 /* Must resend request */
#define R_GETONEREP 0x80 /* Probe for one reply only */
extern struct nfsstats nfsstats;
/*
* A list of nfssvc_sock structures is maintained with all the sockets
* that require service by the nfsd.
* The nfsuid structs hang off of the nfssvc_sock structs in both lru
* and uid hash lists.
*/
#define NUIDHASHSIZ 32
#ifndef NFS_UIDHASHSIZ
#define NFS_UIDHASHSIZ 29 /* Tune the size of nfssvc_sock with this */
#endif
#define NUIDHASH(sock, uid) \
(&(sock)->ns_uidhashtbl[(uid) & (sock)->ns_uidhash])
(&(sock)->ns_uidhashtbl[(uid) % NFS_UIDHASHSIZ])
#ifndef NFS_WDELAYHASHSIZ
#define NFS_WDELAYHASHSIZ 16 /* and with this */
#endif
#define NWDELAYHASH(sock, f) \
(&(sock)->ns_wdelayhashtbl[(*((u_long *)(f))) % NFS_WDELAYHASHSIZ])
#ifndef NFS_MUIDHASHSIZ
#define NFS_MUIDHASHSIZ 67 /* Tune the size of nfsmount with this */
#endif
#define NMUIDHASH(nmp, uid) \
(&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
#define NFSNOHASH(fhsum) \
(&nfsnodehashtbl[(fhsum) & nfsnodehash])
/*
* Network address hash list element
@ -248,35 +352,41 @@ struct nfsuid {
TAILQ_ENTRY(nfsuid) nu_lru; /* LRU chain */
LIST_ENTRY(nfsuid) nu_hash; /* Hash list */
int nu_flag; /* Flags */
uid_t nu_uid; /* Uid mapped by this entry */
union nethostaddr nu_haddr; /* Host addr. for dgram sockets */
struct ucred nu_cr; /* Cred uid mapped to */
int nu_expire; /* Expiry time (sec) */
struct timeval nu_timestamp; /* Kerb. timestamp */
u_long nu_nickname; /* Nickname on server */
NFSKERBKEY_T nu_key; /* and session key */
};
#define nu_inetaddr nu_haddr.had_inetaddr
#define nu_nam nu_haddr.had_nam
/* Bits for nu_flag */
#define NU_INETADDR 0x1
#define NU_NAM 0x2
#define NU_NETFAM(u) (((u)->nu_flag & NU_INETADDR) ? AF_INET : AF_ISO)
struct nfssvc_sock {
TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
TAILQ_HEAD(, nfsuid) ns_uidlruhead;
LIST_HEAD(, nfsuid) *ns_uidhashtbl;
u_long ns_uidhash;
int ns_flag;
u_long ns_sref;
struct file *ns_fp;
struct socket *ns_so;
int ns_solock;
struct mbuf *ns_nam;
int ns_cc;
struct mbuf *ns_raw;
struct mbuf *ns_rawend;
int ns_reclen;
struct mbuf *ns_rec;
struct mbuf *ns_recend;
struct mbuf *ns_frag;
int ns_flag;
int ns_solock;
int ns_cc;
int ns_reclen;
int ns_numuids;
u_long ns_sref;
LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
LIST_HEAD(, nfsuid) ns_uidhashtbl[NFS_UIDHASHSIZ];
LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
};
/* Bits for "ns_flag" */
@ -285,6 +395,7 @@ struct nfssvc_sock {
#define SLP_NEEDQ 0x04
#define SLP_DISCONN 0x08
#define SLP_GETSTREAM 0x10
#define SLP_LASTFRAG 0x20
#define SLP_ALLFLAGS 0xff
TAILQ_HEAD(, nfssvc_sock) nfssvc_sockhead;
@ -296,73 +407,124 @@ int nfssvc_sockhead_flag;
* One of these structures is allocated for each nfsd.
*/
struct nfsd {
TAILQ_ENTRY(nfsd) nd_chain; /* List of all nfsd's */
int nd_flag; /* NFSD_ flags */
struct nfssvc_sock *nd_slp; /* Current socket */
struct mbuf *nd_nam; /* Client addr for datagram req. */
struct mbuf *nd_mrep; /* Req. mbuf list */
struct mbuf *nd_md;
caddr_t nd_dpos; /* Position in list */
int nd_procnum; /* RPC procedure number */
u_long nd_retxid; /* RPC xid */
int nd_repstat; /* Reply status value */
struct ucred nd_cr; /* Credentials for req. */
int nd_nqlflag; /* Leasing flag */
u_long nd_duration; /* Lease duration */
int nd_authlen; /* Authenticator len */
u_char nd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
struct proc *nd_procp; /* Proc ptr */
TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
int nfsd_flag; /* NFSD_ flags */
struct nfssvc_sock *nfsd_slp; /* Current socket */
int nfsd_authlen; /* Authenticator len */
u_char nfsd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
int nfsd_verflen; /* and the Verifier */
u_char nfsd_verfstr[RPCVERF_MAXSIZ];
struct proc *nfsd_procp; /* Proc ptr */
struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
};
/* Bits for "nd_flag" */
/* Bits for "nfsd_flag" */
#define NFSD_WAITING 0x01
#define NFSD_REQINPROG 0x02
#define NFSD_NEEDAUTH 0x04
#define NFSD_AUTHFAIL 0x08
/*
* This structure is used by the server for describing each request.
* Some fields are used only when write request gathering is performed.
*/
struct nfsrv_descript {
u_quad_t nd_time; /* Write deadline (usec) */
off_t nd_off; /* Start byte offset */
off_t nd_eoff; /* and end byte offset */
LIST_ENTRY(nfsrv_descript) nd_hash; /* Hash list */
LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
LIST_HEAD(,nfsrv_descript) nd_coalesce; /* coalesced writes */
struct mbuf *nd_mrep; /* Request mbuf list */
struct mbuf *nd_md; /* Current dissect mbuf */
struct mbuf *nd_mreq; /* Reply mbuf list */
struct mbuf *nd_nam; /* and socket addr */
struct mbuf *nd_nam2; /* return socket addr */
caddr_t nd_dpos; /* Current dissect pos */
int nd_procnum; /* RPC # */
int nd_stable; /* storage type */
int nd_flag; /* nd_flag */
int nd_len; /* Length of this write */
int nd_repstat; /* Reply status */
u_long nd_retxid; /* Reply xid */
u_long nd_duration; /* Lease duration */
struct timeval nd_starttime; /* Time RPC initiated */
fhandle_t nd_fh; /* File handle */
struct ucred nd_cr; /* Credentials */
};
/* Bits for "nd_flag" */
#define ND_READ LEASE_READ
#define ND_WRITE LEASE_WRITE
#define ND_CHECK 0x04
#define ND_LEASE (ND_READ | ND_WRITE | ND_CHECK)
#define ND_NFSV3 0x08
#define ND_NQNFS 0x10
#define ND_KERBNICK 0x20
#define ND_KERBFULL 0x40
#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
TAILQ_HEAD(, nfsd) nfsd_head;
int nfsd_head_flag;
#define NFSD_CHECKSLP 0x01
/*
* These macros compare nfsrv_descript structures.
*/
#define NFSW_CONTIG(o, n) \
((o)->nd_eoff >= (n)->nd_off && \
!bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH))
#define NFSW_SAMECRED(o, n) \
(((o)->nd_flag & ND_KERBAUTH) == ((n)->nd_flag & ND_KERBAUTH) && \
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
sizeof (struct ucred)))
int nfs_reply __P((struct nfsreq *));
int nfs_getreq __P((struct nfsd *,int));
int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
int nfs_send __P((struct socket *,struct mbuf *,struct mbuf *,struct nfsreq *));
int nfs_rephead __P((int,struct nfsd *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_rephead __P((int,struct nfsrv_descript *,struct nfssvc_sock *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_sndlock __P((int *,struct nfsreq *));
int nfs_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
int nfs_vinvalbuf __P((struct vnode *,int,struct ucred *,struct proc *,int));
int nfs_readrpc __P((struct vnode *,struct uio *,struct ucred *));
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int));
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int *,int *));
int nfs_readdirrpc __P((register struct vnode *,struct uio *,struct ucred *));
int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct proc *));
int nfs_asyncio __P((struct buf *,struct ucred *));
int nfs_doio __P((struct buf *,struct ucred *,struct proc *));
int nfs_readlinkrpc __P((struct vnode *,struct uio *,struct ucred *));
int nfs_sigintr __P((struct nfsmount *,struct nfsreq *r,struct proc *));
int nfs_readdirlookrpc __P((struct vnode *,register struct uio *,struct ucred *));
int nfs_readdirplusrpc __P((struct vnode *,register struct uio *,struct ucred *));
int nfsm_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *));
void nfsm_srvfattr __P((struct nfsrv_descript *,struct vattr *,struct nfs_fattr *));
void nfsm_srvwcc __P((struct nfsrv_descript *,int,struct vattr *,int,struct vattr *,struct mbuf **,char **));
void nfsm_srvpostopattr __P((struct nfsrv_descript *,int,struct vattr *,struct mbuf **,char **));
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *,int));
int nfsrv_access __P((struct vnode *,int,struct ucred *,int,struct proc *));
int netaddr_match __P((int,union nethostaddr *,struct mbuf *));
int nfs_request __P((struct vnode *,struct mbuf *,int,struct proc *,struct ucred *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_loadattrcache __P((struct vnode **,struct mbuf **,caddr_t *,struct vattr *));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct proc *));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int));
void nfsm_adj __P((struct mbuf *,int,int));
int nfsm_mbuftouio __P((struct mbuf **,struct uio *,int,caddr_t *));
void nfsrv_initcache __P((void));
int nfs_rcvlock __P((struct nfsreq *));
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,int *,char **,int *));
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,char **,int *,char *,int *,NFSKERBKEY_T));
int nfs_getnickauth __P((struct nfsmount *,struct ucred *,char **,int *,char *,int));
int nfs_savenickauth __P((struct nfsmount *,struct ucred *,int,NFSKERBKEY_T,struct mbuf **,char **,struct mbuf *));
int nfs_msg __P((struct proc *,char *,char *));
int nfs_adv __P((struct mbuf **,caddr_t *,int,int));
int nfsrv_getstream __P((struct nfssvc_sock *,int));
void nfs_nhinit __P((void));
void nfs_timer __P((void*));
struct nfsnodehashhead * nfs_hash __P((nfsv2fh_t *));
u_long nfs_hash __P((nfsfh_t *,int));
int nfssvc_iod __P((struct proc *));
int nfssvc_nfsd __P((struct nfsd_srvargs *,caddr_t,struct proc *));
int nfssvc_addsock __P((struct file *,struct mbuf *));
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *));
int nfsrv_getcache __P((struct mbuf *,struct nfsd *,struct mbuf **));
void nfsrv_updatecache __P((struct mbuf *,struct nfsd *,int,struct mbuf *));
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *,struct nfsrv_descript **));
int nfsrv_getcache __P((struct nfsrv_descript *,struct nfssvc_sock *,struct mbuf **));
void nfsrv_updatecache __P((struct nfsrv_descript *,int,struct mbuf *));
int mountnfs __P((struct nfs_args *,struct mount *,struct mbuf *,char *,char *,struct vnode **));
int nfs_connect __P((struct nfsmount *,struct nfsreq *));
int nfs_getattrcache __P((struct vnode *,struct vattr *));
@ -370,9 +532,20 @@ int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long));
int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *));
int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *));
void nfsrv_init __P((int));
void nfs_clearcommit __P((struct mount *));
int nfsrv_errmap __P((struct nfsrv_descript *, int));
void nfsrvw_coalesce __P((struct nfsrv_descript *,struct nfsrv_descript *));
void nfsrvw_sort __P((gid_t [],int));
void nfsrv_setcred __P((struct ucred *,struct ucred *));
int nfs_flush __P((struct vnode *,struct ucred *,int,struct proc *,int));
int nfs_writebp __P((struct buf *,int));
int nfsrv_vput __P(( struct vnode * ));
int nfsrv_vrele __P(( struct vnode * ));
int nfsrv_vmio __P(( struct vnode * ));
int nfsrv_writegather __P((struct nfsrv_descript **, struct nfssvc_sock *,
struct proc *, struct mbuf **));
int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
struct proc *p));
#endif /* KERNEL */

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_srvcache.c 8.1 (Berkeley) 6/10/93
* $Id: nfs_srvcache.c,v 1.4 1994/10/02 17:27:00 phk Exp $
* $Id: nfs_srvcache.c,v 1.5 1994/10/17 17:47:36 phk Exp $
*/
/*
@ -59,11 +59,13 @@
#endif
#include <nfs/nfsm_subs.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
#include <nfs/nfsrvcache.h>
#include <nfs/nqnfs.h>
extern struct nfsstats nfsstats;
extern int nfsv2_procid[NFS_NPROCS];
long numnfsrvcache, desirednfsrvcache = NFSRVCACHESIZ;
#define NFSRCHASH(xid) \
@ -89,15 +91,18 @@ int nonidempotent[NFS_NPROCS] = {
FALSE,
FALSE,
FALSE,
TRUE,
TRUE,
TRUE,
TRUE,
TRUE,
TRUE,
TRUE,
TRUE,
TRUE,
FALSE,
FALSE,
FALSE,
TRUE,
TRUE,
TRUE,
TRUE,
TRUE,
TRUE,
TRUE,
TRUE,
FALSE,
FALSE,
FALSE,
@ -108,7 +113,7 @@ int nonidempotent[NFS_NPROCS] = {
};
/* True iff the rpc reply is an nfs status ONLY! */
static int repliesstatus[NFS_NPROCS] = {
static int nfsv2_repstat[NFS_NPROCS] = {
FALSE,
FALSE,
FALSE,
@ -127,11 +132,6 @@ static int repliesstatus[NFS_NPROCS] = {
TRUE,
FALSE,
FALSE,
FALSE,
FALSE,
FALSE,
FALSE,
TRUE,
};
/*
@ -160,9 +160,9 @@ nfsrv_initcache()
* Update/add new request at end of lru list
*/
int
nfsrv_getcache(nam, nd, repp)
struct mbuf *nam;
register struct nfsd *nd;
nfsrv_getcache(nd, slp, repp)
register struct nfsrv_descript *nd;
struct nfssvc_sock *slp;
struct mbuf **repp;
{
register struct nfsrvcache *rp;
@ -171,13 +171,17 @@ nfsrv_getcache(nam, nd, repp)
caddr_t bpos;
int ret;
if (nd->nd_nqlflag != NQL_NOVAL)
/*
* Don't cache recent requests for reliable transport protocols.
* (Maybe we should for the case of a reconnect, but..)
*/
if (!nd->nd_nam2)
return (RC_DOIT);
loop:
for (rp = NFSRCHASH(nd->nd_retxid)->lh_first; rp != 0;
rp = rp->rc_hash.le_next) {
if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nam)) {
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) {
if ((rp->rc_flag & RC_LOCKED) != 0) {
rp->rc_flag |= RC_WANTED;
(void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
@ -196,7 +200,7 @@ nfsrv_getcache(nam, nd, repp)
ret = RC_DROPIT;
} else if (rp->rc_flag & RC_REPSTATUS) {
nfsstats.srvcache_nonidemdonehits++;
nfs_rephead(0, nd, rp->rc_status,
nfs_rephead(0, nd, slp, rp->rc_status,
0, (u_quad_t *)0, repp, &mb, &bpos);
ret = RC_REPLY;
} else if (rp->rc_flag & RC_REPMBUF) {
@ -243,7 +247,7 @@ nfsrv_getcache(nam, nd, repp)
TAILQ_INSERT_TAIL(&nfsrvlruhead, rp, rc_lru);
rp->rc_state = RC_INPROG;
rp->rc_xid = nd->nd_retxid;
saddr = mtod(nam, struct sockaddr_in *);
saddr = mtod(nd->nd_nam, struct sockaddr_in *);
switch (saddr->sin_family) {
case AF_INET:
rp->rc_flag |= RC_INETADDR;
@ -252,7 +256,7 @@ nfsrv_getcache(nam, nd, repp)
case AF_ISO:
default:
rp->rc_flag |= RC_NAM;
rp->rc_nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
rp->rc_nam = m_copym(nd->nd_nam, 0, M_COPYALL, M_WAIT);
break;
};
rp->rc_proc = nd->nd_procnum;
@ -269,21 +273,20 @@ nfsrv_getcache(nam, nd, repp)
* Update a request cache entry after the rpc has been done
*/
void
nfsrv_updatecache(nam, nd, repvalid, repmbuf)
struct mbuf *nam;
register struct nfsd *nd;
nfsrv_updatecache(nd, repvalid, repmbuf)
register struct nfsrv_descript *nd;
int repvalid;
struct mbuf *repmbuf;
{
register struct nfsrvcache *rp;
if (nd->nd_nqlflag != NQL_NOVAL)
if (!nd->nd_nam2)
return;
loop:
for (rp = NFSRCHASH(nd->nd_retxid)->lh_first; rp != 0;
rp = rp->rc_hash.le_next) {
if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nam)) {
netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) {
if ((rp->rc_flag & RC_LOCKED) != 0) {
rp->rc_flag |= RC_WANTED;
(void) tsleep((caddr_t)rp, PZERO-1, "nfsrc", 0);
@ -296,7 +299,8 @@ nfsrv_updatecache(nam, nd, repvalid, repmbuf)
* the reply for non-idempotent rpc's.
*/
if (repvalid && nonidempotent[nd->nd_procnum]) {
if (repliesstatus[nd->nd_procnum]) {
if ((nd->nd_flag & ND_NFSV3) == 0 &&
nfsv2_repstat[nfsv2_procid[nd->nd_procnum]]) {
rp->rc_status = nd->nd_repstat;
rp->rc_flag |= RC_REPSTATUS;
} else {

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_socket.c 8.3 (Berkeley) 1/12/94
* $Id: nfs_socket.c,v 1.6 1995/03/16 18:15:37 bde Exp $
* $Id: nfs_socket.c,v 1.7 1995/05/30 08:12:40 rgrimes Exp $
*/
/*
@ -59,7 +59,7 @@
#include <netinet/tcp.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
#include <nfs/xdr_subs.h>
#include <nfs/nfsm_subs.h>
@ -94,36 +94,13 @@
* External data, mostly RPC constants in XDR form
*/
extern u_long rpc_reply, rpc_msgdenied, rpc_mismatch, rpc_vers, rpc_auth_unix,
rpc_msgaccepted, rpc_call, rpc_autherr, rpc_rejectedcred,
rpc_msgaccepted, rpc_call, rpc_autherr,
rpc_auth_kerb;
extern u_long nfs_prog, nfs_vers, nqnfs_prog, nqnfs_vers;
extern u_long nfs_prog, nqnfs_prog;
extern time_t nqnfsstarttime;
extern int nonidempotent[NFS_NPROCS];
/*
* Maps errno values to nfs error numbers.
* Use NFSERR_IO as the catch all for ones not specifically defined in
* RFC 1094.
*/
static int nfsrv_errmap[ELAST] = {
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,
NFSERR_NOTEMPTY, NFSERR_IO, NFSERR_IO, NFSERR_DQUOT, NFSERR_STALE,
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO, NFSERR_IO,
NFSERR_IO,
};
extern struct nfsstats nfsstats;
extern int nfsv3_procid[NFS_NPROCS];
extern int nfs_ticks;
/*
* Defines which timer to use for the procnum.
@ -134,7 +111,8 @@ static int nfsrv_errmap[ELAST] = {
* 4 - write
*/
static int proct[NFS_NPROCS] = {
0, 1, 0, 0, 2, 3, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 0, 0, 0,
0, 1, 0, 2, 1, 3, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0,
0, 0, 0,
};
/*
@ -164,10 +142,12 @@ int nfsrv_null(),
nfsrv_getattr(),
nfsrv_setattr(),
nfsrv_lookup(),
nfsrv3_access(),
nfsrv_readlink(),
nfsrv_read(),
nfsrv_write(),
nfsrv_create(),
nfsrv_mknod(),
nfsrv_remove(),
nfsrv_rename(),
nfsrv_link(),
@ -175,37 +155,42 @@ int nfsrv_null(),
nfsrv_mkdir(),
nfsrv_rmdir(),
nfsrv_readdir(),
nfsrv_readdirplus(),
nfsrv_statfs(),
nfsrv_fsinfo(),
nfsrv_pathconf(),
nfsrv_commit(),
nfsrv_noop(),
nqnfsrv_readdirlook(),
nqnfsrv_getlease(),
nqnfsrv_vacated(),
nqnfsrv_access();
nqnfsrv_vacated();
int (*nfsrv_procs[NFS_NPROCS])() = {
int (*nfsrv3_procs[NFS_NPROCS])() = {
nfsrv_null,
nfsrv_getattr,
nfsrv_setattr,
nfsrv_noop,
nfsrv_lookup,
nfsrv3_access,
nfsrv_readlink,
nfsrv_read,
nfsrv_noop,
nfsrv_write,
nfsrv_create,
nfsrv_mkdir,
nfsrv_symlink,
nfsrv_mknod,
nfsrv_remove,
nfsrv_rmdir,
nfsrv_rename,
nfsrv_link,
nfsrv_symlink,
nfsrv_mkdir,
nfsrv_rmdir,
nfsrv_readdir,
nfsrv_readdirplus,
nfsrv_statfs,
nqnfsrv_readdirlook,
nfsrv_fsinfo,
nfsrv_pathconf,
nfsrv_commit,
nqnfsrv_getlease,
nqnfsrv_vacated,
nfsrv_noop,
nqnfsrv_access,
nfsrv_noop
};
/*
@ -874,13 +859,16 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
struct nfsmount *nmp;
struct mbuf *md, *mheadend;
struct nfsnode *np;
char nickv[RPCX_NICKVERF];
time_t reqtime, waituntil;
caddr_t dpos, cp2;
int t1, nqlflag, cachable, s, error = 0, mrest_len, auth_len, auth_type;
int trylater_delay = NQ_TRYLATERDEL, trylater_cnt = 0, failed_auth = 0;
int verf_len, verf_type;
u_long xid;
u_quad_t frev;
char *auth_str;
char *auth_str, *verf_str;
NFSKERBKEY_T key; /* save session key */
nmp = VFSTONFS(vp->v_mount);
MALLOC(rep, struct nfsreq *, sizeof(struct nfsreq), M_NFSREQ, M_WAITOK);
@ -900,19 +888,21 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
* Get the RPC header with authorization.
*/
kerbauth:
auth_str = (char *)0;
verf_str = auth_str = (char *)0;
if (nmp->nm_flag & NFSMNT_KERB) {
if (failed_auth) {
error = nfs_getauth(nmp, rep, cred, &auth_type,
&auth_str, &auth_len);
verf_str = nickv;
verf_len = sizeof (nickv);
auth_type = RPCAUTH_KERB4;
bzero((caddr_t)key, sizeof (key));
if (failed_auth || nfs_getnickauth(nmp, cred, &auth_str,
&auth_len, verf_str, verf_len)) {
error = nfs_getauth(nmp, rep, cred, &auth_str,
&auth_len, verf_str, &verf_len, key);
if (error) {
free((caddr_t)rep, M_NFSREQ);
m_freem(mrest);
return (error);
}
} else {
auth_type = RPCAUTH_UNIX;
auth_len = 5 * NFSX_UNSIGNED;
}
} else {
auth_type = RPCAUTH_UNIX;
@ -922,8 +912,8 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
nmp->nm_numgrps : (cred->cr_ngroups - 1)) << 2) +
5 * NFSX_UNSIGNED;
}
m = nfsm_rpchead(cred, (nmp->nm_flag & NFSMNT_NQNFS), procnum,
auth_type, auth_len, auth_str, mrest, mrest_len, &mheadend, &xid);
m = nfsm_rpchead(cred, nmp->nm_flag, procnum, auth_type, auth_len,
auth_str, verf_len, verf_str, mrest, mrest_len, &mheadend, &xid);
if (auth_str)
free(auth_str, M_TEMP);
@ -1029,12 +1019,12 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
/*
* break down the rpc header and check if ok
*/
nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED);
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
if (*tl++ == rpc_msgdenied) {
if (*tl == rpc_mismatch)
error = EOPNOTSUPP;
else if ((nmp->nm_flag & NFSMNT_KERB) && *tl++ == rpc_autherr) {
if (*tl == rpc_rejectedcred && failed_auth == 0) {
if (!failed_auth) {
failed_auth++;
mheadend->m_next = (struct mbuf *)0;
m_freem(mrep);
@ -1051,22 +1041,25 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
}
/*
* skip over the auth_verf, someday we may want to cache auth_short's
* for nfs_reqhead(), but for now just dump it
* Grab any Kerberos verifier, otherwise just throw it away.
*/
if (*++tl != 0) {
i = nfsm_rndup(fxdr_unsigned(long, *tl));
nfsm_adv(i);
}
verf_type = fxdr_unsigned(int, *tl++);
i = fxdr_unsigned(int, *tl);
if ((nmp->nm_flag & NFSMNT_KERB) && verf_type == RPCAUTH_KERB4) {
error = nfs_savenickauth(nmp, cred, i, key, &md, &dpos, mrep);
if (error)
goto nfsmout;
} else if (i > 0)
nfsm_adv(nfsm_rndup(i));
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
/* 0 == ok */
if (*tl == 0) {
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
if (*tl != 0) {
error = fxdr_unsigned(int, *tl);
m_freem(mrep);
if ((nmp->nm_flag & NFSMNT_NQNFS) &&
error == NQNFS_TRYLATER) {
if ((nmp->nm_flag & NFSMNT_NFSV3) &&
error == NFSERR_TRYLATER) {
m_freem(mrep);
error = 0;
waituntil = time.tv_sec + trylater_delay;
while (time.tv_sec < waituntil)
@ -1084,6 +1077,13 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
*/
if (error == ESTALE)
cache_purge(vp);
if (nmp->nm_flag & NFSMNT_NFSV3) {
*mrp = mrep;
*mdp = md;
*dposp = dpos;
error |= NFSERR_RETERR;
} else
m_freem(mrep);
m_freem(rep->r_mreq);
free((caddr_t)rep, M_NFSREQ);
return (error);
@ -1115,10 +1115,10 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
return (0);
}
m_freem(mrep);
m_freem(rep->r_mreq);
free((caddr_t)rep, M_NFSREQ);
error = EPROTONOSUPPORT;
nfsmout:
m_freem(rep->r_mreq);
free((caddr_t)rep, M_NFSREQ);
return (error);
}
@ -1127,9 +1127,10 @@ nfs_request(vp, mrest, procnum, procp, cred, mrp, mdp, dposp)
* siz arg. is used to decide if adding a cluster is worthwhile
*/
int
nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
nfs_rephead(siz, nd, slp, err, cache, frev, mrq, mbp, bposp)
int siz;
struct nfsd *nd;
struct nfsrv_descript *nd;
struct nfssvc_sock *slp;
int err;
int cache;
u_quad_t *frev;
@ -1154,47 +1155,98 @@ nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
} else
mreq->m_data += max_hdr;
tl = mtod(mreq, u_long *);
mreq->m_len = 6*NFSX_UNSIGNED;
bpos = ((caddr_t)tl)+mreq->m_len;
mreq->m_len = 6 * NFSX_UNSIGNED;
bpos = ((caddr_t)tl) + mreq->m_len;
*tl++ = txdr_unsigned(nd->nd_retxid);
*tl++ = rpc_reply;
if (err == ERPCMISMATCH || err == NQNFS_AUTHERR) {
if (err == ERPCMISMATCH || (err & NFSERR_AUTHERR)) {
*tl++ = rpc_msgdenied;
if (err == NQNFS_AUTHERR) {
if (err & NFSERR_AUTHERR) {
*tl++ = rpc_autherr;
*tl = rpc_rejectedcred;
*tl = txdr_unsigned(err & ~NFSERR_AUTHERR);
mreq->m_len -= NFSX_UNSIGNED;
bpos -= NFSX_UNSIGNED;
} else {
*tl++ = rpc_mismatch;
*tl++ = txdr_unsigned(2);
*tl = txdr_unsigned(2);
*tl++ = txdr_unsigned(RPC_VER2);
*tl = txdr_unsigned(RPC_VER2);
}
} else {
*tl++ = rpc_msgaccepted;
*tl++ = 0;
*tl++ = 0;
/*
* For Kerberos authentication, we must send the nickname
* verifier back, otherwise just RPCAUTH_NULL.
*/
if (nd->nd_flag & ND_KERBFULL) {
register struct nfsuid *nuidp;
struct timeval ktvin, ktvout;
NFSKERBKEYSCHED_T keys; /* stores key schedule */
for (nuidp = NUIDHASH(slp, nd->nd_cr.cr_uid)->lh_first;
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
if (nuidp->nu_cr.cr_uid == nd->nd_cr.cr_uid &&
(!nd->nd_nam2 || netaddr_match(NU_NETFAM(nuidp),
&nuidp->nu_haddr, nd->nd_nam2)))
break;
}
if (nuidp) {
ktvin.tv_sec =
txdr_unsigned(nuidp->nu_timestamp.tv_sec - 1);
ktvin.tv_usec =
txdr_unsigned(nuidp->nu_timestamp.tv_usec);
/*
* Encrypt the timestamp in ecb mode using the
* session key.
*/
#ifdef NFSKERB
XXX
#endif
*tl++ = rpc_auth_kerb;
*tl++ = txdr_unsigned(3 * NFSX_UNSIGNED);
*tl = ktvout.tv_sec;
nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED);
*tl++ = ktvout.tv_usec;
*tl++ = txdr_unsigned(nuidp->nu_cr.cr_uid);
} else {
*tl++ = 0;
*tl++ = 0;
}
} else {
*tl++ = 0;
*tl++ = 0;
}
switch (err) {
case EPROGUNAVAIL:
*tl = txdr_unsigned(RPC_PROGUNAVAIL);
break;
case EPROGMISMATCH:
*tl = txdr_unsigned(RPC_PROGMISMATCH);
nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
*tl++ = txdr_unsigned(2);
*tl = txdr_unsigned(2); /* someday 3 */
nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED);
if (nd->nd_flag & ND_NQNFS) {
*tl++ = txdr_unsigned(3);
*tl = txdr_unsigned(3);
} else {
*tl++ = txdr_unsigned(2);
*tl = txdr_unsigned(3);
}
break;
case EPROCUNAVAIL:
*tl = txdr_unsigned(RPC_PROCUNAVAIL);
break;
case EBADRPC:
*tl = txdr_unsigned(RPC_GARBAGE);
break;
default:
*tl = 0;
if (err != VNOVAL) {
if (err != NFSERR_RETVOID) {
nfsm_build(tl, u_long *, NFSX_UNSIGNED);
if (err)
*tl = txdr_unsigned(nfsrv_errmap[err - 1]);
*tl = txdr_unsigned(nfsrv_errmap(nd, err));
else
*tl = 0;
*tl = 0;
}
break;
};
@ -1203,16 +1255,14 @@ nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
/*
* For nqnfs, piggyback lease as requested.
*/
if (nd->nd_nqlflag != NQL_NOVAL && err == 0) {
if (nd->nd_nqlflag) {
nfsm_build(tl, u_long *, 5*NFSX_UNSIGNED);
*tl++ = txdr_unsigned(nd->nd_nqlflag);
if ((nd->nd_flag & ND_NQNFS) && err == 0) {
if (nd->nd_flag & ND_LEASE) {
nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED);
*tl++ = txdr_unsigned(nd->nd_flag & ND_LEASE);
*tl++ = txdr_unsigned(cache);
*tl++ = txdr_unsigned(nd->nd_duration);
txdr_hyper(frev, tl);
} else {
if (nd->nd_nqlflag != 0)
panic("nqreph");
nfsm_build(tl, u_long *, NFSX_UNSIGNED);
*tl = 0;
}
@ -1220,7 +1270,7 @@ nfs_rephead(siz, nd, err, cache, frev, mrq, mbp, bposp)
*mrq = mreq;
*mbp = mb;
*bposp = bpos;
if (err != 0 && err != VNOVAL)
if (err != 0 && err != NFSERR_RETVOID)
nfsstats.srvrpc_errs++;
return (0);
}
@ -1240,8 +1290,10 @@ nfs_timer(arg)
register struct socket *so;
register struct nfsmount *nmp;
register int timeo;
register struct nfssvc_sock *slp;
static long lasttime = 0;
int s, error;
u_quad_t cur_usec;
s = splnet();
for (rep = nfs_reqq.tqh_first; rep != 0; rep = rep->r_chain.tqe_next) {
@ -1338,8 +1390,19 @@ nfs_timer(arg)
lasttime = time.tv_sec;
nqnfs_serverd();
}
/*
* Scan the write gathering queues for writes that need to be
* completed now.
*/
cur_usec = (u_quad_t)time.tv_sec * 1000000 + (u_quad_t)time.tv_usec;
for (slp = nfssvc_sockhead.tqh_first; slp != 0;
slp = slp->ns_chain.tqe_next) {
if (slp->ns_tq.lh_first && slp->ns_tq.lh_first->nd_time<=cur_usec)
nfsrv_wakenfsd(slp);
}
splx(s);
timeout(nfs_timer, (void *)0, hz / NFS_HZ);
timeout(nfs_timer, (void *)0, nfs_ticks);
}
/*
@ -1673,7 +1736,7 @@ nfsrv_getstream(slp, waitflag)
register struct nfssvc_sock *slp;
int waitflag;
{
register struct mbuf *m;
register struct mbuf *m, **mpp;
register char *cp1, *cp2;
register int len;
struct mbuf *om, *m2, *recm = 0;
@ -1707,7 +1770,12 @@ nfsrv_getstream(slp, waitflag)
}
}
slp->ns_cc -= NFSX_UNSIGNED;
slp->ns_reclen = ntohl(recmark) & ~0x80000000;
recmark = ntohl(recmark);
slp->ns_reclen = recmark & ~0x80000000;
if (recmark & 0x80000000)
slp->ns_flag |= SLP_LASTFRAG;
else
slp->ns_flag &= ~SLP_LASTFRAG;
if (slp->ns_reclen < NFS_MINPACKET || slp->ns_reclen > NFS_MAXPACKET) {
slp->ns_flag &= ~SLP_GETSTREAM;
return (EPERM);
@ -1761,12 +1829,23 @@ nfsrv_getstream(slp, waitflag)
slp->ns_flag &= ~SLP_GETSTREAM;
return (0);
}
nfs_realign(recm, 10 * NFSX_UNSIGNED);
if (slp->ns_recend)
slp->ns_recend->m_nextpkt = recm;
else
slp->ns_rec = recm;
slp->ns_recend = recm;
/*
* Accumulate the fragments into a record.
*/
mpp = &slp->ns_frag;
while (*mpp)
mpp = &((*mpp)->m_next);
*mpp = recm;
if (slp->ns_flag & SLP_LASTFRAG) {
nfs_realign(slp->ns_frag, 10 * NFSX_UNSIGNED);
if (slp->ns_recend)
slp->ns_recend->m_nextpkt = slp->ns_frag;
else
slp->ns_rec = slp->ns_frag;
slp->ns_recend = slp->ns_frag;
slp->ns_frag = (struct mbuf *)0;
}
}
}
@ -1774,13 +1853,16 @@ nfsrv_getstream(slp, waitflag)
* Parse an RPC header.
*/
int
nfsrv_dorec(slp, nd)
nfsrv_dorec(slp, nfsd, ndp)
register struct nfssvc_sock *slp;
register struct nfsd *nd;
struct nfsd *nfsd;
struct nfsrv_descript **ndp;
{
register struct mbuf *m;
register struct mbuf *m, *nam;
register struct nfsrv_descript *nd;
int error;
*ndp = NULL;
if ((slp->ns_flag & SLP_VALID) == 0 ||
(m = slp->ns_rec) == (struct mbuf *)0)
return (ENOBUFS);
@ -1790,19 +1872,24 @@ nfsrv_dorec(slp, nd)
else
slp->ns_recend = (struct mbuf *)0;
if (m->m_type == MT_SONAME) {
nd->nd_nam = m;
nd->nd_md = nd->nd_mrep = m->m_next;
m->m_next = (struct mbuf *)0;
} else {
nd->nd_nam = (struct mbuf *)0;
nd->nd_md = nd->nd_mrep = m;
}
nd->nd_dpos = mtod(nd->nd_md, caddr_t);
error = nfs_getreq(nd, TRUE);
nam = m;
m = m->m_next;
nam->m_next = NULL;
} else
nam = NULL;
MALLOC(nd, struct nfsrv_descript *, sizeof (struct nfsrv_descript),
M_NFSRVDESC, M_WAITOK);
nd->nd_md = nd->nd_mrep = m;
nd->nd_nam2 = nam;
nd->nd_dpos = mtod(m, caddr_t);
error = nfs_getreq(nd, nfsd, TRUE);
if (error) {
m_freem(nd->nd_nam);
m_freem(nam);
free((caddr_t)nd, M_NFSRVDESC);
return (error);
}
*ndp = nd;
nfsd->nfsd_nd = nd;
return (0);
}
@ -1812,8 +1899,9 @@ nfsrv_dorec(slp, nd)
* - fill in the cred struct.
*/
int
nfs_getreq(nd, has_header)
register struct nfsd *nd;
nfs_getreq(nd, nfsd, has_header)
register struct nfsrv_descript *nd;
struct nfsd *nfsd;
int has_header;
{
register int len, i;
@ -1821,57 +1909,67 @@ nfs_getreq(nd, has_header)
register long t1;
struct uio uio;
struct iovec iov;
caddr_t dpos, cp2;
caddr_t dpos, cp2, cp;
u_long nfsvers, auth_type;
int error = 0, nqnfs = 0;
uid_t nickuid;
int error = 0, nqnfs = 0, ticklen;
struct mbuf *mrep, *md;
register struct nfsuid *nuidp;
struct timeval tvin, tvout;
NFSKERBKEYSCHED_T keys; /* stores key schedule */
mrep = nd->nd_mrep;
md = nd->nd_md;
dpos = nd->nd_dpos;
if (has_header) {
nfsm_dissect(tl, u_long *, 10*NFSX_UNSIGNED);
nfsm_dissect(tl, u_long *, 10 * NFSX_UNSIGNED);
nd->nd_retxid = fxdr_unsigned(u_long, *tl++);
if (*tl++ != rpc_call) {
m_freem(mrep);
return (EBADRPC);
}
} else {
nfsm_dissect(tl, u_long *, 8*NFSX_UNSIGNED);
}
} else
nfsm_dissect(tl, u_long *, 8 * NFSX_UNSIGNED);
nd->nd_repstat = 0;
nd->nd_flag = 0;
if (*tl++ != rpc_vers) {
nd->nd_repstat = ERPCMISMATCH;
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
nfsvers = nfs_vers;
if (*tl != nfs_prog) {
if (*tl == nqnfs_prog) {
if (*tl == nqnfs_prog)
nqnfs++;
nfsvers = nqnfs_vers;
} else {
else {
nd->nd_repstat = EPROGUNAVAIL;
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
}
tl++;
if (*tl++ != nfsvers) {
nfsvers = fxdr_unsigned(u_long, *tl++);
if (((nfsvers < NFS_VER2 || nfsvers > NFS_VER3) && !nqnfs) ||
(nfsvers != NQNFS_VER3 && nqnfs)) {
nd->nd_repstat = EPROGMISMATCH;
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
if (nqnfs)
nd->nd_flag = (ND_NFSV3 | ND_NQNFS);
else if (nfsvers == NFS_VER3)
nd->nd_flag = ND_NFSV3;
nd->nd_procnum = fxdr_unsigned(u_long, *tl++);
if (nd->nd_procnum == NFSPROC_NULL)
return (0);
if (nd->nd_procnum >= NFS_NPROCS ||
(!nqnfs && nd->nd_procnum > NFSPROC_STATFS) ||
(*tl != rpc_auth_unix && *tl != rpc_auth_kerb)) {
(!nqnfs && nd->nd_procnum >= NQNFSPROC_GETLEASE) ||
(!nd->nd_flag && nd->nd_procnum > NFSV2PROC_STATFS)) {
nd->nd_repstat = EPROCUNAVAIL;
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
if ((nd->nd_flag & ND_NFSV3) == 0)
nd->nd_procnum = nfsv3_procid[nd->nd_procnum];
auth_type = *tl++;
len = fxdr_unsigned(int, *tl++);
if (len < 0 || len > RPCAUTH_MAXSIZ) {
@ -1879,6 +1977,7 @@ nfs_getreq(nd, has_header)
return (EBADRPC);
}
nd->nd_flag &= ~ND_KERBAUTH;
/*
* Handle auth_unix or auth_kerb.
*/
@ -1889,7 +1988,9 @@ nfs_getreq(nd, has_header)
return (EBADRPC);
}
nfsm_adv(nfsm_rndup(len));
nfsm_dissect(tl, u_long *, 3*NFSX_UNSIGNED);
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
bzero((caddr_t)&nd->nd_cr, sizeof (struct ucred));
nd->nd_cr.cr_ref = 1;
nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);
nd->nd_cr.cr_gid = fxdr_unsigned(gid_t, *tl++);
len = fxdr_unsigned(int, *tl);
@ -1897,45 +1998,124 @@ nfs_getreq(nd, has_header)
m_freem(mrep);
return (EBADRPC);
}
nfsm_dissect(tl, u_long *, (len + 2)*NFSX_UNSIGNED);
nfsm_dissect(tl, u_long *, (len + 2) * NFSX_UNSIGNED);
for (i = 1; i <= len; i++)
if (i < NGROUPS)
nd->nd_cr.cr_groups[i] = fxdr_unsigned(gid_t, *tl++);
else
tl++;
if (i < NGROUPS)
nd->nd_cr.cr_groups[i] = fxdr_unsigned(gid_t, *tl++);
else
tl++;
nd->nd_cr.cr_ngroups = (len >= NGROUPS) ? NGROUPS : (len + 1);
} else if (auth_type == rpc_auth_kerb) {
nd->nd_cr.cr_uid = fxdr_unsigned(uid_t, *tl++);
nd->nd_authlen = fxdr_unsigned(int, *tl);
uio.uio_resid = nfsm_rndup(nd->nd_authlen);
if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
if (nd->nd_cr.cr_ngroups > 1)
nfsrvw_sort(nd->nd_cr.cr_groups, nd->nd_cr.cr_ngroups);
len = fxdr_unsigned(int, *++tl);
if (len < 0 || len > RPCAUTH_MAXSIZ) {
m_freem(mrep);
return (EBADRPC);
}
uio.uio_offset = 0;
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
uio.uio_segflg = UIO_SYSSPACE;
iov.iov_base = (caddr_t)nd->nd_authstr;
iov.iov_len = RPCAUTH_MAXSIZ;
nfsm_mtouio(&uio, uio.uio_resid);
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
nd->nd_flag |= NFSD_NEEDAUTH;
}
if (len > 0)
nfsm_adv(nfsm_rndup(len));
} else if (auth_type == rpc_auth_kerb) {
switch (fxdr_unsigned(int, *tl++)) {
case RPCAKN_FULLNAME:
ticklen = fxdr_unsigned(int, *tl);
*((u_long *)nfsd->nfsd_authstr) = *tl;
uio.uio_resid = nfsm_rndup(ticklen) + NFSX_UNSIGNED;
nfsd->nfsd_authlen = uio.uio_resid + NFSX_UNSIGNED;
if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
m_freem(mrep);
return (EBADRPC);
}
uio.uio_offset = 0;
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
uio.uio_segflg = UIO_SYSSPACE;
iov.iov_base = (caddr_t)&nfsd->nfsd_authstr[4];
iov.iov_len = RPCAUTH_MAXSIZ - 4;
nfsm_mtouio(&uio, uio.uio_resid);
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
if (*tl++ != rpc_auth_kerb ||
fxdr_unsigned(int, *tl) != 4 * NFSX_UNSIGNED) {
printf("Bad kerb verifier\n");
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
nfsm_dissect(cp, caddr_t, 4 * NFSX_UNSIGNED);
tl = (u_long *)cp;
if (fxdr_unsigned(int, *tl) != RPCAKN_FULLNAME) {
printf("Not fullname kerb verifier\n");
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
cp += NFSX_UNSIGNED;
bcopy(cp, nfsd->nfsd_verfstr, 3 * NFSX_UNSIGNED);
nfsd->nfsd_verflen = 3 * NFSX_UNSIGNED;
nd->nd_flag |= ND_KERBFULL;
nfsd->nfsd_flag |= NFSD_NEEDAUTH;
break;
case RPCAKN_NICKNAME:
if (len != 2 * NFSX_UNSIGNED) {
printf("Kerb nickname short\n");
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADCRED);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
nickuid = fxdr_unsigned(uid_t, *tl);
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED);
if (*tl++ != rpc_auth_kerb ||
fxdr_unsigned(int, *tl) != 3 * NFSX_UNSIGNED) {
printf("Kerb nick verifier bad\n");
nd->nd_repstat = (NFSERR_AUTHERR|AUTH_BADVERF);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
tvin.tv_sec = *tl++;
tvin.tv_usec = *tl;
/*
* Do we have any use for the verifier.
* According to the "Remote Procedure Call Protocol Spec." it
* should be AUTH_NULL, but some clients make it AUTH_UNIX?
* For now, just skip over it
*/
len = fxdr_unsigned(int, *++tl);
if (len < 0 || len > RPCAUTH_MAXSIZ) {
m_freem(mrep);
return (EBADRPC);
}
if (len > 0) {
nfsm_adv(nfsm_rndup(len));
for (nuidp = NUIDHASH(nfsd->nfsd_slp,nickuid)->lh_first;
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
if (nuidp->nu_cr.cr_uid == nickuid &&
(!nd->nd_nam2 ||
netaddr_match(NU_NETFAM(nuidp),
&nuidp->nu_haddr, nd->nd_nam2)))
break;
}
if (!nuidp) {
nd->nd_repstat =
(NFSERR_AUTHERR|AUTH_REJECTCRED);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
/*
* Now, decrypt the timestamp using the session key
* and validate it.
*/
#ifdef NFSKERB
XXX
#endif
tvout.tv_sec = fxdr_unsigned(long, tvout.tv_sec);
tvout.tv_usec = fxdr_unsigned(long, tvout.tv_usec);
if (nuidp->nu_expire < time.tv_sec ||
nuidp->nu_timestamp.tv_sec > tvout.tv_sec ||
(nuidp->nu_timestamp.tv_sec == tvout.tv_sec &&
nuidp->nu_timestamp.tv_usec > tvout.tv_usec)) {
nuidp->nu_expire = 0;
nd->nd_repstat =
(NFSERR_AUTHERR|AUTH_REJECTVERF);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
nfsrv_setcred(&nuidp->nu_cr, &nd->nd_cr);
nd->nd_flag |= ND_KERBNICK;
};
} else {
nd->nd_repstat = (NFSERR_AUTHERR | AUTH_REJECTCRED);
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
/*
@ -1943,16 +2123,14 @@ nfs_getreq(nd, has_header)
*/
if (nqnfs && nd->nd_procnum != NQNFSPROC_EVICTED) {
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
nd->nd_nqlflag = fxdr_unsigned(int, *tl);
if (nd->nd_nqlflag) {
nd->nd_flag |= fxdr_unsigned(int, *tl);
if (nd->nd_flag & ND_LEASE) {
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED);
nd->nd_duration = fxdr_unsigned(int, *tl);
} else
nd->nd_duration = NQ_MINLEASE;
} else {
nd->nd_nqlflag = NQL_NOVAL;
} else
nd->nd_duration = NQ_MINLEASE;
}
nd->nd_md = md;
nd->nd_dpos = dpos;
return (0);
@ -1973,13 +2151,13 @@ nfsrv_wakenfsd(slp)
if ((slp->ns_flag & SLP_VALID) == 0)
return;
for (nd = nfsd_head.tqh_first; nd != 0; nd = nd->nd_chain.tqe_next) {
if (nd->nd_flag & NFSD_WAITING) {
nd->nd_flag &= ~NFSD_WAITING;
if (nd->nd_slp)
for (nd = nfsd_head.tqh_first; nd != 0; nd = nd->nfsd_chain.tqe_next) {
if (nd->nfsd_flag & NFSD_WAITING) {
nd->nfsd_flag &= ~NFSD_WAITING;
if (nd->nfsd_slp)
panic("nfsd wakeup");
slp->ns_sref++;
nd->nd_slp = slp;
nd->nfsd_slp = slp;
wakeup((caddr_t)nd);
return;
}

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs_syscalls.c 8.3 (Berkeley) 1/4/94
* $Id: nfs_syscalls.c,v 1.5 1994/10/17 17:47:38 phk Exp $
* $Id: nfs_syscalls.c,v 1.6 1995/05/30 08:12:45 rgrimes Exp $
*/
#include <sys/param.h>
@ -61,9 +61,11 @@
#ifdef ISO
#include <netiso/iso.h>
#endif
#include <nfs/xdr_subs.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
#include <nfs/nfsm_subs.h>
#include <nfs/nfsrvcache.h>
#include <nfs/nfsmount.h>
#include <nfs/nfsnode.h>
@ -73,13 +75,14 @@
void nfsrv_zapsock __P((struct nfssvc_sock *));
/* Global defs. */
extern u_long nfs_prog, nfs_vers;
extern int (*nfsrv_procs[NFS_NPROCS])();
extern int (*nfsrv3_procs[NFS_NPROCS])();
extern struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
extern int nfs_numasync;
extern time_t nqnfsstarttime;
extern int nqsrv_writeslack;
extern int nfsrtton;
extern struct nfsstats nfsstats;
extern int nfsrvw_procrastinate;
struct nfssvc_sock *nfs_udpsock, *nfs_cltpsock;
int nuidhash_max = NFS_MAXUIDHASH;
static int nfs_numnfsd = 0;
@ -225,19 +228,25 @@ nfssvc(p, uap, retval)
if (error)
return (error);
if ((uap->flag & NFSSVC_AUTHIN) && ((nfsd = nsd->nsd_nfsd)) &&
(nfsd->nd_slp->ns_flag & SLP_VALID)) {
slp = nfsd->nd_slp;
(nfsd->nfsd_slp->ns_flag & SLP_VALID)) {
slp = nfsd->nfsd_slp;
/*
* First check to see if another nfsd has already
* added this credential.
*/
for (nuidp = NUIDHASH(slp, nsd->nsd_uid)->lh_first;
for (nuidp = NUIDHASH(slp,nsd->nsd_cr.cr_uid)->lh_first;
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
if (nuidp->nu_uid == nsd->nsd_uid)
if (nuidp->nu_cr.cr_uid == nsd->nsd_cr.cr_uid &&
(!nfsd->nfsd_nd->nd_nam2 ||
netaddr_match(NU_NETFAM(nuidp),
&nuidp->nu_haddr, nfsd->nfsd_nd->nd_nam2)))
break;
}
if (!nuidp) {
if (nuidp) {
nfsrv_setcred(&nuidp->nu_cr,&nfsd->nfsd_nd->nd_cr);
nfsd->nfsd_nd->nd_flag |= ND_KERBFULL;
} else {
/*
* Nope, so we will.
*/
@ -257,22 +266,53 @@ nfssvc(p, uap, retval)
LIST_REMOVE(nuidp, nu_hash);
TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp,
nu_lru);
if (nuidp->nu_flag & NU_NAM)
m_freem(nuidp->nu_nam);
}
nuidp->nu_flag = 0;
nuidp->nu_cr = nsd->nsd_cr;
if (nuidp->nu_cr.cr_ngroups > NGROUPS)
nuidp->nu_cr.cr_ngroups = NGROUPS;
nuidp->nu_cr.cr_ngroups = NGROUPS;
nuidp->nu_cr.cr_ref = 1;
nuidp->nu_uid = nsd->nsd_uid;
nuidp->nu_timestamp = nsd->nsd_timestamp;
nuidp->nu_expire = time.tv_sec + nsd->nsd_ttl;
/*
* and save the session key in nu_key.
*/
bcopy(nsd->nsd_key, nuidp->nu_key,
sizeof (nsd->nsd_key));
if (nfsd->nfsd_nd->nd_nam2) {
struct sockaddr_in *saddr;
saddr = mtod(nfsd->nfsd_nd->nd_nam2,
struct sockaddr_in *);
switch (saddr->sin_family) {
case AF_INET:
nuidp->nu_flag |= NU_INETADDR;
nuidp->nu_inetaddr =
saddr->sin_addr.s_addr;
break;
case AF_ISO:
default:
nuidp->nu_flag |= NU_NAM;
nuidp->nu_nam = m_copym(
nfsd->nfsd_nd->nd_nam2, 0,
M_COPYALL, M_WAIT);
break;
};
}
TAILQ_INSERT_TAIL(&slp->ns_uidlruhead, nuidp,
nu_lru);
LIST_INSERT_HEAD(NUIDHASH(slp, nsd->nsd_uid),
nuidp, nu_hash);
nfsrv_setcred(&nuidp->nu_cr,
&nfsd->nfsd_nd->nd_cr);
nfsd->nfsd_nd->nd_flag |= ND_KERBFULL;
}
}
}
if ((uap->flag & NFSSVC_AUTHINFAIL) && (nfsd = nsd->nsd_nfsd))
nfsd->nd_flag |= NFSD_AUTHFAIL;
nfsd->nfsd_flag |= NFSD_AUTHFAIL;
error = nfssvc_nfsd(nsd, uap->argp, p);
}
if (error == EINTR || error == ERESTART)
@ -353,8 +393,6 @@ nfssvc_addsock(fp, mynam)
slp = (struct nfssvc_sock *)
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
bzero((caddr_t)slp, sizeof (struct nfssvc_sock));
slp->ns_uidhashtbl =
hashinit(NUIDHASHSIZ, M_NFSSVC, &slp->ns_uidhash);
TAILQ_INIT(&slp->ns_uidlruhead);
TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain);
}
@ -381,44 +419,47 @@ nfssvc_nfsd(nsd, argp, p)
caddr_t argp;
struct proc *p;
{
register struct mbuf *m, *nam2;
register struct mbuf *m;
register int siz;
register struct nfssvc_sock *slp;
register struct socket *so;
register int *solockp;
struct nfsd *nd = nsd->nsd_nfsd;
struct mbuf *mreq, *nam;
struct timeval starttime;
struct nfsd *nfsd = nsd->nsd_nfsd;
struct nfsrv_descript *nd = NULL;
struct mbuf *mreq;
struct nfsuid *uidp;
int error = 0, cacherep, s;
int sotype;
int error = 0, cacherep, s, sotype, writes_todo;
u_quad_t cur_usec;
#ifndef nolint
cacherep = RC_DOIT;
writes_todo = 0;
#endif
s = splnet();
if (nd == (struct nfsd *)0) {
nsd->nsd_nfsd = nd = (struct nfsd *)
if (nfsd == (struct nfsd *)0) {
nsd->nsd_nfsd = nfsd = (struct nfsd *)
malloc(sizeof (struct nfsd), M_NFSD, M_WAITOK);
bzero((caddr_t)nd, sizeof (struct nfsd));
nd->nd_procp = p;
nd->nd_cr.cr_ref = 1;
TAILQ_INSERT_TAIL(&nfsd_head, nd, nd_chain);
nd->nd_nqlflag = NQL_NOVAL;
bzero((caddr_t)nfsd, sizeof (struct nfsd));
nfsd->nfsd_procp = p;
TAILQ_INSERT_TAIL(&nfsd_head, nfsd, nfsd_chain);
nfs_numnfsd++;
}
/*
* Loop getting rpc requests until SIGKILL.
*/
for (;;) {
if ((nd->nd_flag & NFSD_REQINPROG) == 0) {
while (nd->nd_slp == (struct nfssvc_sock *)0 &&
if ((nfsd->nfsd_flag & NFSD_REQINPROG) == 0) {
while (nfsd->nfsd_slp == (struct nfssvc_sock *)0 &&
(nfsd_head_flag & NFSD_CHECKSLP) == 0) {
nd->nd_flag |= NFSD_WAITING;
nfsd->nfsd_flag |= NFSD_WAITING;
nfsd_waiting++;
error = tsleep((caddr_t)nd, PSOCK | PCATCH, "nfsd", 0);
error = tsleep((caddr_t)nfsd, PSOCK | PCATCH,
"nfsd", 0);
nfsd_waiting--;
if (error)
goto done;
}
if (nd->nd_slp == (struct nfssvc_sock *)0 &&
if (nfsd->nfsd_slp == (struct nfssvc_sock *)0 &&
(nfsd_head_flag & NFSD_CHECKSLP) != 0) {
for (slp = nfssvc_sockhead.tqh_first; slp != 0;
slp = slp->ns_chain.tqe_next) {
@ -426,14 +467,14 @@ nfssvc_nfsd(nsd, argp, p)
== (SLP_VALID | SLP_DOREC)) {
slp->ns_flag &= ~SLP_DOREC;
slp->ns_sref++;
nd->nd_slp = slp;
nfsd->nfsd_slp = slp;
break;
}
}
if (slp == 0)
nfsd_head_flag &= ~NFSD_CHECKSLP;
}
if ((slp = nd->nd_slp) == (struct nfssvc_sock *)0)
if ((slp = nfsd->nfsd_slp) == (struct nfssvc_sock *)0)
continue;
if (slp->ns_flag & SLP_VALID) {
if (slp->ns_flag & SLP_DISCONN)
@ -446,86 +487,78 @@ nfssvc_nfsd(nsd, argp, p)
M_WAIT);
nfs_sndunlock(&slp->ns_solock);
}
error = nfsrv_dorec(slp, nd);
nd->nd_flag |= NFSD_REQINPROG;
error = nfsrv_dorec(slp, nfsd, &nd);
cur_usec = (u_quad_t)time.tv_sec * 1000000 +
(u_quad_t)time.tv_usec;
if (error && slp->ns_tq.lh_first &&
slp->ns_tq.lh_first->nd_time <= cur_usec) {
error = 0;
cacherep = RC_DOIT;
writes_todo = 1;
} else
writes_todo = 0;
nfsd->nfsd_flag |= NFSD_REQINPROG;
}
} else {
error = 0;
slp = nd->nd_slp;
slp = nfsd->nfsd_slp;
}
if (error || (slp->ns_flag & SLP_VALID) == 0) {
nd->nd_slp = (struct nfssvc_sock *)0;
nd->nd_flag &= ~NFSD_REQINPROG;
if (nd) {
free((caddr_t)nd, M_NFSRVDESC);
nd = NULL;
}
nfsd->nfsd_slp = (struct nfssvc_sock *)0;
nfsd->nfsd_flag &= ~NFSD_REQINPROG;
nfsrv_slpderef(slp);
continue;
}
splx(s);
so = slp->ns_so;
sotype = so->so_type;
starttime = time;
if (so->so_proto->pr_flags & PR_CONNREQUIRED)
solockp = &slp->ns_solock;
else
solockp = (int *)0;
/*
* nam == nam2 for connectionless protocols such as UDP
* nam2 == NULL for connection based protocols to disable
* recent request caching.
*/
nam2 = nd->nd_nam;
if (nam2) {
nam = nam2;
cacherep = RC_CHECKIT;
} else {
nam = slp->ns_nam;
cacherep = RC_DOIT;
}
if (nd) {
nd->nd_starttime = time;
if (nd->nd_nam2)
nd->nd_nam = nd->nd_nam2;
else
nd->nd_nam = slp->ns_nam;
/*
* Check to see if authorization is needed.
*/
if (nd->nd_flag & NFSD_NEEDAUTH) {
static int logauth = 0;
/*
* Check to see if authorization is needed.
*/
if (nfsd->nfsd_flag & NFSD_NEEDAUTH) {
nfsd->nfsd_flag &= ~NFSD_NEEDAUTH;
nsd->nsd_haddr = mtod(nd->nd_nam,
struct sockaddr_in *)->sin_addr.s_addr;
nsd->nsd_authlen = nfsd->nfsd_authlen;
nsd->nsd_verflen = nfsd->nfsd_verflen;
if (!copyout(nfsd->nfsd_authstr,nsd->nsd_authstr,
nfsd->nfsd_authlen) &&
!copyout(nfsd->nfsd_verfstr, nsd->nsd_verfstr,
nfsd->nfsd_verflen) &&
!copyout((caddr_t)nsd, argp, sizeof (*nsd)))
return (ENEEDAUTH);
cacherep = RC_DROPIT;
} else
cacherep = nfsrv_getcache(nd, slp, &mreq);
nd->nd_flag &= ~NFSD_NEEDAUTH;
/*
* Check for a mapping already installed.
*/
for (uidp = NUIDHASH(slp, nd->nd_cr.cr_uid)->lh_first;
uidp != 0; uidp = uidp->nu_hash.le_next) {
if (uidp->nu_uid == nd->nd_cr.cr_uid)
break;
}
if (!uidp) {
nsd->nsd_uid = nd->nd_cr.cr_uid;
if (nam2 && logauth++ == 0)
log(LOG_WARNING, "Kerberized NFS using UDP\n");
nsd->nsd_haddr =
mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
nsd->nsd_authlen = nd->nd_authlen;
if (copyout(nd->nd_authstr, nsd->nsd_authstr,
nd->nd_authlen) == 0 &&
copyout((caddr_t)nsd, argp, sizeof (*nsd)) == 0)
return (ENEEDAUTH);
cacherep = RC_DROPIT;
}
}
if (cacherep == RC_CHECKIT)
cacherep = nfsrv_getcache(nam2, nd, &mreq);
/*
* Check for just starting up for NQNFS and send
* fake "try again later" replies to the NQNFS clients.
*/
if (notstarted && nqnfsstarttime <= time.tv_sec) {
/*
* Check for just starting up for NQNFS and send
* fake "try again later" replies to the NQNFS clients.
*/
if (notstarted && nqnfsstarttime <= time.tv_sec) {
if (modify_flag) {
nqnfsstarttime = time.tv_sec + nqsrv_writeslack;
modify_flag = 0;
} else
notstarted = 0;
}
if (notstarted) {
if (nd->nd_nqlflag == NQL_NOVAL)
}
if (notstarted) {
if ((nd->nd_flag & ND_NQNFS) == 0)
cacherep = RC_DROPIT;
else if (nd->nd_procnum != NFSPROC_WRITE) {
nd->nd_procnum = NFSPROC_NOOP;
@ -533,36 +566,42 @@ nfssvc_nfsd(nsd, argp, p)
cacherep = RC_DOIT;
} else
modify_flag = 1;
} else if (nd->nd_flag & NFSD_AUTHFAIL) {
nd->nd_flag &= ~NFSD_AUTHFAIL;
} else if (nfsd->nfsd_flag & NFSD_AUTHFAIL) {
nfsd->nfsd_flag &= ~NFSD_AUTHFAIL;
nd->nd_procnum = NFSPROC_NOOP;
nd->nd_repstat = NQNFS_AUTHERR;
nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK);
cacherep = RC_DOIT;
}
}
switch (cacherep) {
case RC_DOIT:
error = (*(nfsrv_procs[nd->nd_procnum]))(nd,
nd->nd_mrep, nd->nd_md, nd->nd_dpos, &nd->nd_cr,
nam, &mreq);
if (nd->nd_cr.cr_ref != 1) {
printf("nfssvc cref=%d\n", nd->nd_cr.cr_ref);
panic("nfssvc cref");
}
/*
* Loop to get all the write rpc relies that have been
* gathered together.
*/
do {
switch (cacherep) {
case RC_DOIT:
if (writes_todo || (nd->nd_procnum == NFSPROC_WRITE &&
nfsrvw_procrastinate > 0 && !notstarted))
error = nfsrv_writegather(&nd, slp,
nfsd->nfsd_procp, &mreq);
else
error = (*(nfsrv3_procs[nd->nd_procnum]))(nd,
slp, nfsd->nfsd_procp, &mreq);
if (mreq == NULL)
break;
if (error) {
if (nd->nd_procnum != NQNFSPROC_VACATED)
nfsstats.srv_errs++;
if (nam2) {
nfsrv_updatecache(nam2, nd, FALSE, mreq);
m_freem(nam2);
}
nfsrv_updatecache(nd, FALSE, mreq);
if (nd->nd_nam2)
m_freem(nd->nd_nam2);
break;
}
nfsstats.srvrpccnt[nd->nd_procnum]++;
if (nam2)
nfsrv_updatecache(nam2, nd, TRUE, mreq);
nfsrv_updatecache(nd, TRUE, mreq);
nd->nd_mrep = (struct mbuf *)0;
case RC_REPLY:
case RC_REPLY:
m = mreq;
siz = 0;
while (m) {
@ -587,15 +626,15 @@ nfssvc_nfsd(nsd, argp, p)
if (solockp)
(void) nfs_sndlock(solockp, (struct nfsreq *)0);
if (slp->ns_flag & SLP_VALID)
error = nfs_send(so, nam2, m, (struct nfsreq *)0);
error = nfs_send(so, nd->nd_nam2, m, NULL);
else {
error = EPIPE;
m_freem(m);
}
if (nfsrtton)
nfsd_rt(&starttime, sotype, nd, nam, cacherep);
if (nam2)
MFREE(nam2, m);
nfsd_rt(sotype, nd, cacherep);
if (nd->nd_nam2)
MFREE(nd->nd_nam2, m);
if (nd->nd_mrep)
m_freem(nd->nd_mrep);
if (error == EPIPE)
@ -603,29 +642,50 @@ nfssvc_nfsd(nsd, argp, p)
if (solockp)
nfs_sndunlock(solockp);
if (error == EINTR || error == ERESTART) {
free((caddr_t)nd, M_NFSRVDESC);
nfsrv_slpderef(slp);
s = splnet();
goto done;
}
break;
case RC_DROPIT:
case RC_DROPIT:
if (nfsrtton)
nfsd_rt(&starttime, sotype, nd, nam, cacherep);
nfsd_rt(sotype, nd, cacherep);
m_freem(nd->nd_mrep);
m_freem(nam2);
m_freem(nd->nd_nam2);
break;
};
};
if (nd) {
FREE((caddr_t)nd, M_NFSRVDESC);
nd = NULL;
}
/*
* Check to see if there are outstanding writes that
* need to be serviced.
*/
cur_usec = (u_quad_t)time.tv_sec * 1000000 +
(u_quad_t)time.tv_usec;
s = splsoftclock();
if (slp->ns_tq.lh_first &&
slp->ns_tq.lh_first->nd_time <= cur_usec) {
cacherep = RC_DOIT;
writes_todo = 1;
} else
writes_todo = 0;
splx(s);
} while (writes_todo);
s = splnet();
if (nfsrv_dorec(slp, nd)) {
nd->nd_flag &= ~NFSD_REQINPROG;
nd->nd_slp = (struct nfssvc_sock *)0;
if (nfsrv_dorec(slp, nfsd, &nd)) {
nfsd->nfsd_flag &= ~NFSD_REQINPROG;
nfsd->nfsd_slp = NULL;
nfsrv_slpderef(slp);
}
}
done:
TAILQ_REMOVE(&nfsd_head, nd, nd_chain);
TAILQ_REMOVE(&nfsd_head, nfsd, nfsd_chain);
splx(s);
free((caddr_t)nd, M_NFSD);
free((caddr_t)nfsd, M_NFSD);
nsd->nsd_nfsd = (struct nfsd *)0;
if (--nfs_numnfsd == 0)
nfsrv_init(TRUE); /* Reinitialize everything */
@ -641,9 +701,10 @@ int
nfssvc_iod(p)
struct proc *p;
{
register struct buf *bp;
register struct buf *bp, *nbp;
register int i, myiod;
int error = 0;
struct vnode *vp;
int error = 0, s;
/*
* Assign my position or return error if too many already running
@ -662,24 +723,53 @@ nfssvc_iod(p)
* Just loop around doin our stuff until SIGKILL
*/
for (;;) {
while (nfs_bufq.tqh_first == NULL && error == 0) {
nfs_iodwant[myiod] = p;
error = tsleep((caddr_t)&nfs_iodwant[myiod],
PWAIT | PCATCH, "nfsidl", 0);
}
while ((bp = nfs_bufq.tqh_first) != NULL) {
/* Take one off the front of the list */
TAILQ_REMOVE(&nfs_bufq, bp, b_freelist);
if (bp->b_flags & B_READ)
(void) nfs_doio(bp, bp->b_rcred, (struct proc *)0);
else
(void) nfs_doio(bp, bp->b_wcred, (struct proc *)0);
}
if (error) {
nfs_asyncdaemon[myiod] = 0;
nfs_numasync--;
return (error);
}
while (nfs_bufq.tqh_first == NULL && error == 0) {
nfs_iodwant[myiod] = p;
error = tsleep((caddr_t)&nfs_iodwant[myiod],
PWAIT | PCATCH, "nfsidl", 0);
}
while ((bp = nfs_bufq.tqh_first) != NULL) {
/* Take one off the front of the list */
TAILQ_REMOVE(&nfs_bufq, bp, b_freelist);
if (bp->b_flags & B_READ)
(void) nfs_doio(bp, bp->b_rcred, (struct proc *)0);
else do {
/*
* Look for a delayed write for the same vnode, so I can do
* it now. We must grab it before calling nfs_doio() to
* avoid any risk of the vnode getting vclean()'d while
* we are doing the write rpc.
*/
vp = bp->b_vp;
s = splbio();
for (nbp = vp->v_dirtyblkhd.lh_first; nbp;
nbp = nbp->b_vnbufs.le_next) {
if ((nbp->b_flags &
(B_BUSY|B_DELWRI|B_NEEDCOMMIT|B_NOCACHE))!=B_DELWRI)
continue;
bremfree(nbp);
vfs_busy_pages(nbp, 1);
nbp->b_flags |= (B_BUSY|B_ASYNC);
break;
}
splx(s);
/*
* For the delayed write, do the first part of nfs_bwrite()
* up to, but not including nfs_strategy().
*/
if (nbp) {
nbp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI);
reassignbuf(nbp, nbp->b_vp);
nbp->b_vp->v_numoutput++;
}
(void) nfs_doio(bp, bp->b_wcred, (struct proc *)0);
} while (bp = nbp);
}
if (error) {
nfs_asyncdaemon[myiod] = 0;
nfs_numasync--;
return (error);
}
}
}
@ -695,9 +785,11 @@ nfsrv_zapsock(slp)
register struct nfssvc_sock *slp;
{
register struct nfsuid *nuidp, *nnuidp;
register struct nfsrv_descript *nwp, *nnwp;
struct socket *so;
struct file *fp;
struct mbuf *m;
int s;
slp->ns_flag &= ~SLP_ALLFLAGS;
fp = slp->ns_fp;
@ -716,8 +808,18 @@ nfsrv_zapsock(slp)
nnuidp = nuidp->nu_lru.tqe_next;
LIST_REMOVE(nuidp, nu_hash);
TAILQ_REMOVE(&slp->ns_uidlruhead, nuidp, nu_lru);
if (nuidp->nu_flag & NU_NAM)
m_freem(nuidp->nu_nam);
free((caddr_t)nuidp, M_NFSUID);
}
s = splsoftclock();
for (nwp = slp->ns_tq.lh_first; nwp; nwp = nnwp) {
nnwp = nwp->nd_tq.le_next;
LIST_REMOVE(nwp, nd_tq);
free((caddr_t)nwp, M_NFSRVDESC);
}
LIST_INIT(&slp->ns_tq);
splx(s);
}
}
@ -726,13 +828,15 @@ nfsrv_zapsock(slp)
* on this mount point porpous out of the kernel and do it.
*/
int
nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
nfs_getauth(nmp, rep, cred, auth_str, auth_len, verf_str, verf_len, key)
register struct nfsmount *nmp;
struct nfsreq *rep;
struct ucred *cred;
int *auth_type;
char **auth_str;
int *auth_len;
char *verf_str;
int *verf_len;
NFSKERBKEY_T key; /* return session key */
{
int error = 0;
@ -748,6 +852,9 @@ nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
}
nmp->nm_flag &= ~(NFSMNT_WAITAUTH | NFSMNT_WANTAUTH);
nmp->nm_authstr = *auth_str = (char *)malloc(RPCAUTH_MAXSIZ, M_TEMP, M_WAITOK);
nmp->nm_authlen = RPCAUTH_MAXSIZ;
nmp->nm_verfstr = verf_str;
nmp->nm_verflen = *verf_len;
nmp->nm_authuid = cred->cr_uid;
wakeup((caddr_t)&nmp->nm_authstr);
@ -766,8 +873,9 @@ nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
if (error)
free((caddr_t)*auth_str, M_TEMP);
else {
*auth_type = nmp->nm_authtype;
*auth_len = nmp->nm_authlen;
*verf_len = nmp->nm_verflen;
bcopy((caddr_t)nmp->nm_key, (caddr_t)key, sizeof (key));
}
nmp->nm_flag &= ~NFSMNT_HASAUTH;
nmp->nm_flag |= NFSMNT_WAITAUTH;
@ -778,6 +886,149 @@ nfs_getauth(nmp, rep, cred, auth_type, auth_str, auth_len)
return (error);
}
/*
* Get a nickname authenticator and verifier.
*/
int
nfs_getnickauth(nmp, cred, auth_str, auth_len, verf_str, verf_len)
struct nfsmount *nmp;
struct ucred *cred;
char **auth_str;
int *auth_len;
char *verf_str;
int verf_len;
{
register struct nfsuid *nuidp;
register u_long *nickp, *verfp;
struct timeval ktvin, ktvout;
NFSKERBKEYSCHED_T keys; /* stores key schedule */
#ifdef DIAGNOSTIC
if (verf_len < (4 * NFSX_UNSIGNED))
panic("nfs_getnickauth verf too small");
#endif
for (nuidp = NMUIDHASH(nmp, cred->cr_uid)->lh_first;
nuidp != 0; nuidp = nuidp->nu_hash.le_next) {
if (nuidp->nu_cr.cr_uid == cred->cr_uid)
break;
}
if (!nuidp || nuidp->nu_expire < time.tv_sec)
return (EACCES);
/*
* Move to the end of the lru list (end of lru == most recently used).
*/
TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp, nu_lru);
TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp, nu_lru);
nickp = (u_long *)malloc(2 * NFSX_UNSIGNED, M_TEMP, M_WAITOK);
*nickp++ = txdr_unsigned(RPCAKN_NICKNAME);
*nickp = txdr_unsigned(nuidp->nu_nickname);
*auth_str = (char *)nickp;
*auth_len = 2 * NFSX_UNSIGNED;
/*
* Now we must encrypt the verifier and package it up.
*/
verfp = (u_long *)verf_str;
*verfp++ = txdr_unsigned(RPCAKN_NICKNAME);
if (time.tv_sec > nuidp->nu_timestamp.tv_sec ||
(time.tv_sec == nuidp->nu_timestamp.tv_sec &&
time.tv_usec > nuidp->nu_timestamp.tv_usec))
nuidp->nu_timestamp = time;
else
nuidp->nu_timestamp.tv_usec++;
ktvin.tv_sec = txdr_unsigned(nuidp->nu_timestamp.tv_sec);
ktvin.tv_usec = txdr_unsigned(nuidp->nu_timestamp.tv_usec);
/*
* Now encrypt the timestamp verifier in ecb mode using the session
* key.
*/
#ifdef NFSKERB
XXX
#endif
*verfp++ = ktvout.tv_sec;
*verfp++ = ktvout.tv_usec;
*verfp = 0;
return (0);
}
/*
* Save the current nickname in a hash list entry on the mount point.
*/
int
nfs_savenickauth(nmp, cred, len, key, mdp, dposp, mrep)
register struct nfsmount *nmp;
struct ucred *cred;
int len;
NFSKERBKEY_T key;
struct mbuf **mdp;
char **dposp;
struct mbuf *mrep;
{
register struct nfsuid *nuidp;
register u_long *tl;
register long t1;
struct mbuf *md = *mdp;
struct timeval ktvin, ktvout;
u_long nick;
NFSKERBKEYSCHED_T keys;
char *dpos = *dposp, *cp2;
int deltasec, error = 0;
if (len == (3 * NFSX_UNSIGNED)) {
nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED);
ktvin.tv_sec = *tl++;
ktvin.tv_usec = *tl++;
nick = fxdr_unsigned(u_long, *tl);
/*
* Decrypt the timestamp in ecb mode.
*/
#ifdef NFSKERB
XXX
#endif
ktvout.tv_sec = fxdr_unsigned(long, ktvout.tv_sec);
ktvout.tv_usec = fxdr_unsigned(long, ktvout.tv_usec);
deltasec = time.tv_sec - ktvout.tv_sec;
if (deltasec < 0)
deltasec = -deltasec;
/*
* If ok, add it to the hash list for the mount point.
*/
if (deltasec <= NFS_KERBCLOCKSKEW) {
if (nmp->nm_numuids < nuidhash_max) {
nmp->nm_numuids++;
nuidp = (struct nfsuid *)
malloc(sizeof (struct nfsuid), M_NFSUID,
M_WAITOK);
} else {
nuidp = nmp->nm_uidlruhead.tqh_first;
LIST_REMOVE(nuidp, nu_hash);
TAILQ_REMOVE(&nmp->nm_uidlruhead, nuidp,
nu_lru);
}
nuidp->nu_flag = 0;
nuidp->nu_cr.cr_uid = cred->cr_uid;
nuidp->nu_expire = time.tv_sec + NFS_KERBTTL;
nuidp->nu_timestamp = ktvout;
nuidp->nu_nickname = nick;
bcopy(key, nuidp->nu_key, sizeof (key));
TAILQ_INSERT_TAIL(&nmp->nm_uidlruhead, nuidp,
nu_lru);
LIST_INSERT_HEAD(NMUIDHASH(nmp, cred->cr_uid),
nuidp, nu_hash);
}
} else
nfsm_adv(nfsm_rndup(len));
nfsmout:
*mdp = md;
*dposp = dpos;
return (error);
}
/*
* Derefence a server socket structure. If it has no more references and
* is no longer valid, you can throw it away.
@ -830,16 +1081,12 @@ nfsrv_init(terminating)
nfs_udpsock = (struct nfssvc_sock *)
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
bzero((caddr_t)nfs_udpsock, sizeof (struct nfssvc_sock));
nfs_udpsock->ns_uidhashtbl =
hashinit(NUIDHASHSIZ, M_NFSSVC, &nfs_udpsock->ns_uidhash);
TAILQ_INIT(&nfs_udpsock->ns_uidlruhead);
TAILQ_INSERT_HEAD(&nfssvc_sockhead, nfs_udpsock, ns_chain);
nfs_cltpsock = (struct nfssvc_sock *)
malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK);
bzero((caddr_t)nfs_cltpsock, sizeof (struct nfssvc_sock));
nfs_cltpsock->ns_uidhashtbl =
hashinit(NUIDHASHSIZ, M_NFSSVC, &nfs_cltpsock->ns_uidhash);
TAILQ_INIT(&nfs_cltpsock->ns_uidlruhead);
TAILQ_INSERT_TAIL(&nfssvc_sockhead, nfs_cltpsock, ns_chain);
}
@ -848,11 +1095,9 @@ nfsrv_init(terminating)
* Add entries to the server monitor log.
*/
static void
nfsd_rt(startp, sotype, nd, nam, cacherep)
struct timeval *startp;
nfsd_rt(sotype, nd, cacherep)
int sotype;
register struct nfsd *nd;
struct mbuf *nam;
register struct nfsrv_descript *nd;
int cacherep;
{
register struct drt *rt;
@ -866,15 +1111,17 @@ nfsd_rt(startp, sotype, nd, nam, cacherep)
rt->flag = DRT_CACHEDROP;
if (sotype == SOCK_STREAM)
rt->flag |= DRT_TCP;
if (nd->nd_nqlflag != NQL_NOVAL)
if (nd->nd_flag & ND_NQNFS)
rt->flag |= DRT_NQNFS;
else if (nd->nd_flag & ND_NFSV3)
rt->flag |= DRT_NFSV3;
rt->proc = nd->nd_procnum;
if (mtod(nam, struct sockaddr *)->sa_family == AF_INET)
rt->ipadr = mtod(nam, struct sockaddr_in *)->sin_addr.s_addr;
if (mtod(nd->nd_nam, struct sockaddr *)->sa_family == AF_INET)
rt->ipadr = mtod(nd->nd_nam, struct sockaddr_in *)->sin_addr.s_addr;
else
rt->ipadr = INADDR_ANY;
rt->resptime = ((time.tv_sec - startp->tv_sec) * 1000000) +
(time.tv_usec - startp->tv_usec);
rt->ipadr = INADDR_ANY;
rt->resptime = ((time.tv_sec - nd->nd_starttime.tv_sec) * 1000000) +
(time.tv_usec - nd->nd_starttime.tv_usec);
rt->tstamp = time;
nfsdrt.pos = (nfsdrt.pos + 1) % NFSRTTLOGSIZ;
}

View File

@ -34,12 +34,13 @@
* SUCH DAMAGE.
*
* @(#)nfsm_subs.h 8.1 (Berkeley) 6/16/93
* $Id: nfsm_subs.h,v 1.5 1994/10/17 17:47:42 phk Exp $
* $Id: nfsm_subs.h,v 1.6 1995/05/30 08:12:51 rgrimes Exp $
*/
#ifndef _NFS_NFSM_SUBS_H_
#define _NFS_NFSM_SUBS_H_
/*
* These macros do strange and peculiar things to mbuf chains for
* the assistance of the nfs code. To attempt to use them for any
@ -90,49 +91,153 @@ extern struct mbuf *nfsm_reqh();
mb->m_len += (s); \
bpos += (s); }
#define nfsm_dissect(a,c,s) \
#define nfsm_dissect(a, c, s) \
{ t1 = mtod(md, caddr_t)+md->m_len-dpos; \
if (t1 >= (s)) { \
(a) = (c)(dpos); \
dpos += (s); \
} else if (t1 = nfsm_disct(&md, &dpos, (s), t1, &cp2)) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
} else { \
error = nfsm_disct(&md, &dpos, (s), t1, &cp2); \
if (error) { \
m_freem(mrep); \
goto nfsmout; \
} else { \
(a) = (c)cp2; \
} \
(a) = (c)cp2; \
} }
#define nfsm_fhtom(v) \
nfsm_build(cp,caddr_t,NFSX_FH); \
bcopy((caddr_t)&(VTONFS(v)->n_fh), cp, NFSX_FH)
#define nfsm_fhtom(v, v3) \
{ if (v3) { \
t2 = nfsm_rndup(VTONFS(v)->n_fhsize) + NFSX_UNSIGNED; \
if (t2 <= M_TRAILINGSPACE(mb)) { \
nfsm_build(tl, u_long *, t2); \
*tl++ = txdr_unsigned(VTONFS(v)->n_fhsize); \
*(tl + ((t2>>2) - 2)) = 0; \
bcopy((caddr_t)VTONFS(v)->n_fhp,(caddr_t)tl, \
VTONFS(v)->n_fhsize); \
} else if (t2 = nfsm_strtmbuf(&mb, &bpos, \
(caddr_t)VTONFS(v)->n_fhp, VTONFS(v)->n_fhsize)) { \
error = t2; \
m_freem(mreq); \
goto nfsmout; \
} \
} else { \
nfsm_build(cp, caddr_t, NFSX_V2FH); \
bcopy((caddr_t)VTONFS(v)->n_fhp, cp, NFSX_V2FH); \
} }
#define nfsm_srvfhtom(f) \
nfsm_build(cp,caddr_t,NFSX_FH); \
bcopy((caddr_t)(f), cp, NFSX_FH)
#define nfsm_srvfhtom(f, v3) \
{ if (v3) { \
nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3FH); \
*tl++ = txdr_unsigned(NFSX_V3FH); \
bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
} else { \
nfsm_build(cp, caddr_t, NFSX_V2FH); \
bcopy((caddr_t)(f), cp, NFSX_V2FH); \
} }
#define nfsm_mtofh(d,v) \
{ struct nfsnode *np; nfsv2fh_t *fhp; \
nfsm_dissect(fhp,nfsv2fh_t *,NFSX_FH); \
error = nfs_nget((d)->v_mount, fhp, &np); \
if (error) { \
m_freem(mrep); \
goto nfsmout; \
} \
(v) = NFSTOV(np); \
nfsm_loadattr(v, (struct vattr *)0); \
#define nfsm_srvpostop_fh(f) \
{ nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED + NFSX_V3FH); \
*tl++ = nfs_true; \
*tl++ = txdr_unsigned(NFSX_V3FH); \
bcopy((caddr_t)(f), (caddr_t)tl, NFSX_V3FH); \
}
#define nfsm_loadattr(v,a) \
{ struct vnode *tvp = (v); \
error = nfs_loadattrcache(&tvp, &md, &dpos, (a)); \
if (error) { \
#define nfsm_mtofh(d, v, v3, f) \
{ struct nfsnode *ttnp; nfsfh_t *ttfhp; int ttfhsize; \
if (v3) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
(f) = fxdr_unsigned(int, *tl); \
} else \
(f) = 1; \
if (f) { \
nfsm_getfh(ttfhp, ttfhsize, (v3)); \
if (t1 = nfs_nget((d)->v_mount, ttfhp, ttfhsize, \
&ttnp)) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
} \
(v) = NFSTOV(ttnp); \
} \
if (v3) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (f) \
(f) = fxdr_unsigned(int, *tl); \
else if (fxdr_unsigned(int, *tl)) \
nfsm_adv(NFSX_V3FATTR); \
} \
if (f) \
nfsm_loadattr((v), (struct vattr *)0); \
}
#define nfsm_getfh(f, s, v3) \
{ if (v3) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (((s) = fxdr_unsigned(int, *tl)) <= 0 || \
(s) > NFSX_V3FHMAX) { \
m_freem(mrep); \
error = EBADRPC; \
goto nfsmout; \
} \
} else \
(s) = NFSX_V2FH; \
nfsm_dissect((f), nfsfh_t *, nfsm_rndup(s)); }
#define nfsm_loadattr(v, a) \
{ struct vnode *ttvp = (v); \
if (t1 = nfs_loadattrcache(&ttvp, &md, &dpos, (a))) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
} \
(v) = tvp; }
(v) = ttvp; }
#define nfsm_postop_attr(v, f) \
{ struct vnode *ttvp = (v); \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if ((f) = fxdr_unsigned(int, *tl)) { \
if (t1 = nfs_loadattrcache(&ttvp, &md, &dpos, \
(struct vattr *)0)) { \
error = t1; \
(f) = 0; \
m_freem(mrep); \
goto nfsmout; \
} \
(v) = ttvp; \
} }
/* Used as (f) for nfsm_wcc_data() */
#define NFSV3_WCCRATTR 0
#define NFSV3_WCCCHK 1
#define nfsm_wcc_data(v, f) \
{ int ttattrf, ttretf = 0; \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
nfsm_dissect(tl, u_long *, 6 * NFSX_UNSIGNED); \
if (f) \
ttretf = (VTONFS(v)->n_mtime == \
fxdr_unsigned(u_long, *(tl + 2))); \
} \
nfsm_postop_attr((v), ttattrf); \
if (f) { \
(f) = ttretf; \
} else { \
(f) = ttattrf; \
} }
#define nfsm_v3sattr(s, a, u, g) \
{ (s)->sa_modetrue = nfs_true; \
(s)->sa_mode = vtonfsv3_mode((a)->va_mode); \
(s)->sa_uidtrue = nfs_true; \
(s)->sa_uid = txdr_unsigned(u); \
(s)->sa_gidtrue = nfs_true; \
(s)->sa_gid = txdr_unsigned(g); \
(s)->sa_sizefalse = nfs_false; \
(s)->sa_atimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \
txdr_nfsv3time(&(a)->va_atime, &(s)->sa_atime); \
(s)->sa_mtimetype = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); \
txdr_nfsv3time(&(a)->va_mtime, &(s)->sa_mtime); \
}
#define nfsm_strsiz(s,m) \
{ nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \
@ -149,16 +254,27 @@ extern struct mbuf *nfsm_reqh();
nfsm_reply(0); \
} }
#define nfsm_srvnamesiz(s) \
{ nfsm_dissect(tl,u_long *,NFSX_UNSIGNED); \
if (((s) = fxdr_unsigned(long,*tl)) > NFS_MAXNAMLEN) \
error = NFSERR_NAMETOL; \
if ((s) <= 0) \
error = EBADRPC; \
if (error) \
nfsm_reply(0); \
}
#define nfsm_mtouio(p,s) \
if ((s) > 0 && \
(error = nfsm_mbuftouio(&md,(p),(s),&dpos))) { \
(t1 = nfsm_mbuftouio(&md,(p),(s),&dpos))) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
}
#define nfsm_uiotom(p,s) \
error = nfsm_uiotombuf((p),&mb,(s),&bpos); \
if (error) { \
if (t1 = nfsm_uiotombuf((p),&mb,(s),&bpos)) { \
error = t1; \
m_freem(mreq); \
goto nfsmout; \
}
@ -172,10 +288,13 @@ extern struct mbuf *nfsm_reqh();
#define nfsm_rndup(a) (((a)+3)&(~0x3))
#define nfsm_request(v, t, p, c) \
error = nfs_request((v), mreq, (t), (p), \
(c), &mrep, &md, &dpos); \
if (error) \
goto nfsmout
if (error = nfs_request((v), mreq, (t), (p), \
(c), &mrep, &md, &dpos)) { \
if (error & NFSERR_RETERR) \
error &= ~NFSERR_RETERR; \
else \
goto nfsmout; \
}
#define nfsm_strtom(a,s,m) \
if ((s) > (m)) { \
@ -189,12 +308,10 @@ extern struct mbuf *nfsm_reqh();
*tl++ = txdr_unsigned(s); \
*(tl+((t2>>2)-2)) = 0; \
bcopy((caddr_t)(a), (caddr_t)tl, (s)); \
} else { \
error = nfsm_strtmbuf(&mb, &bpos, (a), (s)); \
if (error) { \
m_freem(mreq); \
goto nfsmout; \
} \
} else if (t2 = nfsm_strtmbuf(&mb, &bpos, (a), (s))) { \
error = t2; \
m_freem(mreq); \
goto nfsmout; \
}
#define nfsm_srvdone \
@ -204,33 +321,53 @@ extern struct mbuf *nfsm_reqh();
#define nfsm_reply(s) \
{ \
nfsd->nd_repstat = error; \
if (error) \
(void) nfs_rephead(0, nfsd, error, cache, &frev, \
if (error && !(nfsd->nd_flag & ND_NFSV3)) \
(void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
mrq, &mb, &bpos); \
else \
(void) nfs_rephead((s), nfsd, error, cache, &frev, \
(void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
mrq, &mb, &bpos); \
m_freem(mrep); \
mreq = *mrq; \
if (error) \
if (error && (!(nfsd->nd_flag & ND_NFSV3) || \
error == EBADRPC)) \
return(0); \
}
#define nfsm_adv(s) \
t1 = mtod(md, caddr_t)+md->m_len-dpos; \
if (t1 >= (s)) { \
dpos += (s); \
} else { \
error = nfs_adv(&md, &dpos, (s), t1); \
if (error) { \
m_freem(mrep); \
goto nfsmout; \
} \
#define nfsm_writereply(s, v3) \
{ \
nfsd->nd_repstat = error; \
if (error && !(v3)) \
(void) nfs_rephead(0, nfsd, slp, error, cache, &frev, \
&mreq, &mb, &bpos); \
else \
(void) nfs_rephead((s), nfsd, slp, error, cache, &frev, \
&mreq, &mb, &bpos); \
}
#define nfsm_adv(s) \
{ t1 = mtod(md, caddr_t)+md->m_len-dpos; \
if (t1 >= (s)) { \
dpos += (s); \
} else if (t1 = nfs_adv(&md, &dpos, (s), t1)) { \
error = t1; \
m_freem(mrep); \
goto nfsmout; \
} }
#define nfsm_srvmtofh(f) \
nfsm_dissect(tl, u_long *, NFSX_FH); \
bcopy((caddr_t)tl, (caddr_t)f, NFSX_FH)
{ if (nfsd->nd_flag & ND_NFSV3) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (fxdr_unsigned(int, *tl) != NFSX_V3FH) { \
error = EBADRPC; \
nfsm_reply(0); \
} \
} \
nfsm_dissect(tl, u_long *, NFSX_V3FH); \
bcopy((caddr_t)tl, (caddr_t)(f), NFSX_V3FH); \
if ((nfsd->nd_flag & ND_NFSV3) == 0) \
nfsm_adv(NFSX_V2FH - NFSX_V3FH); \
}
#define nfsm_clget \
if (bp >= be) { \
@ -246,41 +383,57 @@ extern struct mbuf *nfsm_reqh();
} \
tl = (u_long *)bp
#define nfsm_srvfillattr \
fp->fa_type = vtonfs_type(vap->va_type); \
fp->fa_mode = vtonfs_mode(vap->va_type, vap->va_mode); \
fp->fa_nlink = txdr_unsigned(vap->va_nlink); \
fp->fa_uid = txdr_unsigned(vap->va_uid); \
fp->fa_gid = txdr_unsigned(vap->va_gid); \
if (nfsd->nd_nqlflag == NQL_NOVAL) { \
fp->fa_nfsblocksize = txdr_unsigned(vap->va_blocksize); \
if (vap->va_type == VFIFO) \
fp->fa_nfsrdev = 0xffffffff; \
else \
fp->fa_nfsrdev = txdr_unsigned(vap->va_rdev); \
fp->fa_nfsfsid = txdr_unsigned(vap->va_fsid); \
fp->fa_nfsfileid = txdr_unsigned(vap->va_fileid); \
fp->fa_nfssize = txdr_unsigned(vap->va_size); \
fp->fa_nfsblocks = txdr_unsigned(vap->va_bytes / NFS_FABLKSIZE); \
txdr_nfstime(&vap->va_atime, &fp->fa_nfsatime); \
txdr_nfstime(&vap->va_mtime, &fp->fa_nfsmtime); \
txdr_nfstime(&vap->va_ctime, &fp->fa_nfsctime); \
} else { \
fp->fa_nqblocksize = txdr_unsigned(vap->va_blocksize); \
if (vap->va_type == VFIFO) \
fp->fa_nqrdev = 0xffffffff; \
else \
fp->fa_nqrdev = txdr_unsigned(vap->va_rdev); \
fp->fa_nqfsid = txdr_unsigned(vap->va_fsid); \
fp->fa_nqfileid = txdr_unsigned(vap->va_fileid); \
txdr_hyper(&vap->va_size, &fp->fa_nqsize); \
txdr_hyper(&vap->va_bytes, &fp->fa_nqbytes); \
txdr_nqtime(&vap->va_atime, &fp->fa_nqatime); \
txdr_nqtime(&vap->va_mtime, &fp->fa_nqmtime); \
txdr_nqtime(&vap->va_ctime, &fp->fa_nqctime); \
fp->fa_nqflags = txdr_unsigned(vap->va_flags); \
fp->fa_nqgen = txdr_unsigned(vap->va_gen); \
txdr_hyper(&vap->va_filerev, &fp->fa_nqfilerev); \
}
#define nfsm_srvfillattr(a, f) \
nfsm_srvfattr(nfsd, (a), (f))
#define nfsm_srvwcc_data(br, b, ar, a) \
nfsm_srvwcc(nfsd, (br), (b), (ar), (a), &mb, &bpos)
#define nfsm_srvpostop_attr(r, a) \
nfsm_srvpostopattr(nfsd, (r), (a), &mb, &bpos)
#define nfsm_srvsattr(a) \
{ nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
(a)->va_mode = nfstov_mode(*tl); \
} \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
(a)->va_uid = fxdr_unsigned(uid_t, *tl); \
} \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
(a)->va_gid = fxdr_unsigned(gid_t, *tl); \
} \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
if (*tl == nfs_true) { \
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
fxdr_hyper(tl, &(a)->va_size); \
} \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
switch (fxdr_unsigned(int, *tl)) { \
case NFSV3SATTRTIME_TOCLIENT: \
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
fxdr_nfsv3time(tl, &(a)->va_atime); \
break; \
case NFSV3SATTRTIME_TOSERVER: \
(a)->va_atime.ts_sec = time.tv_sec; \
(a)->va_atime.ts_nsec = time.tv_usec * 1000; \
break; \
}; \
nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); \
switch (fxdr_unsigned(int, *tl)) { \
case NFSV3SATTRTIME_TOCLIENT: \
nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); \
fxdr_nfsv3time(tl, &(a)->va_mtime); \
break; \
case NFSV3SATTRTIME_TOSERVER: \
(a)->va_mtime.ts_sec = time.tv_sec; \
(a)->va_mtime.ts_nsec = time.tv_usec * 1000; \
break; \
}; }
#endif

441
sys/nfsserver/nfsproto.h Normal file
View File

@ -0,0 +1,441 @@
/*
* 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.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* 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.
*
* @(#)nfsproto.h 8.1 (Berkeley) 6/10/93
* $Id: nfsproto.h,v 1.4 1994/08/21 06:50:13 paul Exp $
*/
#ifndef _NFS_NFSPROTO_H_
#define _NFS_NFSPROTO_H_
/*
* nfs definitions as per the Version 2 and 3 specs
*/
/*
* Constants as defined in the Sun NFS Version 2 and 3 specs.
* "NFS: Network File System Protocol Specification" RFC1094
* and in the "NFS: Network File System Version 3 Protocol
* Specification"
*/
#define NFS_PORT 2049
#define NFS_PROG 100003
#define NFS_VER2 2
#define NFS_VER3 3
#define NFS_V2MAXDATA 8192
#define NFS_MAXDGRAMDATA 16384
#define NFS_MAXDATA 32768
#define NFS_MAXPATHLEN 1024
#define NFS_MAXNAMLEN 255
#define NFS_MAXPKTHDR 404
#define NFS_MAXPACKET (NFS_MAXPKTHDR + NFS_MAXDATA)
#define NFS_MINPACKET 20
#define NFS_FABLKSIZE 512 /* Size in bytes of a block wrt fa_blocks */
/* Stat numbers for rpc returns (version 2 and 3) */
#define NFS_OK 0
#define NFSERR_PERM 1
#define NFSERR_NOENT 2
#define NFSERR_IO 5
#define NFSERR_NXIO 6
#define NFSERR_ACCES 13
#define NFSERR_EXIST 17
#define NFSERR_XDEV 18 /* Version 3 only */
#define NFSERR_NODEV 19
#define NFSERR_NOTDIR 20
#define NFSERR_ISDIR 21
#define NFSERR_INVAL 22 /* Version 3 only */
#define NFSERR_FBIG 27
#define NFSERR_NOSPC 28
#define NFSERR_ROFS 30
#define NFSERR_MLINK 31 /* Version 3 only */
#define NFSERR_NAMETOL 63
#define NFSERR_NOTEMPTY 66
#define NFSERR_DQUOT 69
#define NFSERR_STALE 70
#define NFSERR_REMOTE 71 /* Version 3 only */
#define NFSERR_WFLUSH 99 /* Version 2 only */
#define NFSERR_BADHANDLE 10001 /* The rest Version 3 only */
#define NFSERR_NOT_SYNC 10002
#define NFSERR_BAD_COOKIE 10003
#define NFSERR_NOTSUPP 10004
#define NFSERR_TOOSMALL 10005
#define NFSERR_SERVERFAULT 10006
#define NFSERR_BADTYPE 10007
#define NFSERR_JUKEBOX 10008
#define NFSERR_TRYLATER NFSERR_JUKEBOX
#define NFSERR_STALEWRITEVERF 30001 /* Fake return for nfs_commit() */
#define NFSERR_RETVOID 0x20000000 /* Return void, not error */
#define NFSERR_AUTHERR 0x40000000 /* Mark an authentication error */
#define NFSERR_RETERR 0x80000000 /* Mark an error return for V3 */
/* Sizes in bytes of various nfs rpc components */
#define NFSX_UNSIGNED 4
/* specific to NFS Version 2 */
#define NFSX_V2FH 32
#define NFSX_V2FATTR 68
#define NFSX_V2SATTR 32
#define NFSX_V2COOKIE 4
#define NFSX_V2STATFS 20
/* specific to NFS Version 3 */
#define NFSX_V3FH (sizeof (fhandle_t)) /* size this server uses */
#define NFSX_V3FHMAX 64 /* max. allowed by protocol */
#define NFSX_V3FATTR 84
#define NFSX_V3SATTR 60 /* max. all fields filled in */
#define NFSX_V3SRVSATTR (sizeof (struct nfsv3_sattr))
#define NFSX_V3POSTOPATTR (NFSX_V3FATTR + NFSX_UNSIGNED)
#define NFSX_V3WCCDATA (NFSX_V3POSTOPATTR + 8 * NFSX_UNSIGNED)
#define NFSX_V3COOKIEVERF 8
#define NFSX_V3WRITEVERF 8
#define NFSX_V3CREATEVERF 8
#define NFSX_V3STATFS 52
#define NFSX_V3FSINFO 48
#define NFSX_V3PATHCONF 24
/* variants for both versions */
#define NFSX_FH(v3) ((v3) ? (NFSX_V3FHMAX + NFSX_UNSIGNED) : \
NFSX_V2FH)
#define NFSX_SRVFH(v3) ((v3) ? NFSX_V3FH : NFSX_V2FH)
#define NFSX_FATTR(v3) ((v3) ? NFSX_V3FATTR : NFSX_V2FATTR)
#define NFSX_PREOPATTR(v3) ((v3) ? (7 * NFSX_UNSIGNED) : 0)
#define NFSX_POSTOPATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : 0)
#define NFSX_POSTOPORFATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : \
NFSX_V2FATTR)
#define NFSX_WCCDATA(v3) ((v3) ? NFSX_V3WCCDATA : 0)
#define NFSX_WCCORFATTR(v3) ((v3) ? NFSX_V3WCCDATA : NFSX_V2FATTR)
#define NFSX_SATTR(v3) ((v3) ? NFSX_V3SATTR : NFSX_V2SATTR)
#define NFSX_COOKIEVERF(v3) ((v3) ? NFSX_V3COOKIEVERF : 0)
#define NFSX_WRITEVERF(v3) ((v3) ? NFSX_V3WRITEVERF : 0)
#define NFSX_READDIR(v3) ((v3) ? (5 * NFSX_UNSIGNED) : \
(2 * NFSX_UNSIGNED))
#define NFSX_STATFS(v3) ((v3) ? NFSX_V3STATFS : NFSX_V2STATFS)
/* nfs rpc procedure numbers (before version mapping) */
#define NFSPROC_NULL 0
#define NFSPROC_GETATTR 1
#define NFSPROC_SETATTR 2
#define NFSPROC_LOOKUP 3
#define NFSPROC_ACCESS 4
#define NFSPROC_READLINK 5
#define NFSPROC_READ 6
#define NFSPROC_WRITE 7
#define NFSPROC_CREATE 8
#define NFSPROC_MKDIR 9
#define NFSPROC_SYMLINK 10
#define NFSPROC_MKNOD 11
#define NFSPROC_REMOVE 12
#define NFSPROC_RMDIR 13
#define NFSPROC_RENAME 14
#define NFSPROC_LINK 15
#define NFSPROC_READDIR 16
#define NFSPROC_READDIRPLUS 17
#define NFSPROC_FSSTAT 18
#define NFSPROC_FSINFO 19
#define NFSPROC_PATHCONF 20
#define NFSPROC_COMMIT 21
/* And leasing (nqnfs) procedure numbers (must be last) */
#define NQNFSPROC_GETLEASE 22
#define NQNFSPROC_VACATED 23
#define NQNFSPROC_EVICTED 24
#define NFSPROC_NOOP 25
#define NFS_NPROCS 26
/* Actual Version 2 procedure numbers */
#define NFSV2PROC_NULL 0
#define NFSV2PROC_GETATTR 1
#define NFSV2PROC_SETATTR 2
#define NFSV2PROC_NOOP 3
#define NFSV2PROC_ROOT NFSV2PROC_NOOP /* Obsolete */
#define NFSV2PROC_LOOKUP 4
#define NFSV2PROC_READLINK 5
#define NFSV2PROC_READ 6
#define NFSV2PROC_WRITECACHE NFSV2PROC_NOOP /* Obsolete */
#define NFSV2PROC_WRITE 8
#define NFSV2PROC_CREATE 9
#define NFSV2PROC_REMOVE 10
#define NFSV2PROC_RENAME 11
#define NFSV2PROC_LINK 12
#define NFSV2PROC_SYMLINK 13
#define NFSV2PROC_MKDIR 14
#define NFSV2PROC_RMDIR 15
#define NFSV2PROC_READDIR 16
#define NFSV2PROC_STATFS 17
/*
* Constants used by the Version 3 protocol for various RPCs
*/
#define NFSV3SATTRTIME_DONTCHANGE 0
#define NFSV3SATTRTIME_TOSERVER 1
#define NFSV3SATTRTIME_TOCLIENT 2
#define NFSV3ACCESS_READ 0x01
#define NFSV3ACCESS_LOOKUP 0x02
#define NFSV3ACCESS_MODIFY 0x04
#define NFSV3ACCESS_EXTEND 0x08
#define NFSV3ACCESS_DELETE 0x10
#define NFSV3ACCESS_EXECUTE 0x20
#define NFSV3WRITE_UNSTABLE 0
#define NFSV3WRITE_DATASYNC 1
#define NFSV3WRITE_FILESYNC 2
#define NFSV3CREATE_UNCHECKED 0
#define NFSV3CREATE_GUARDED 1
#define NFSV3CREATE_EXCLUSIVE 2
#define NFSV3FSINFO_LINK 0x01
#define NFSV3FSINFO_SYMLINK 0x02
#define NFSV3FSINFO_HOMOGENEOUS 0x08
#define NFSV3FSINFO_CANSETTIME 0x10
/* Conversion macros */
#define vtonfsv2_mode(t,m) \
txdr_unsigned(((t) == VFIFO) ? MAKEIMODE(VCHR, (m)) : \
MAKEIMODE((t), (m)))
#define vtonfsv3_mode(m) txdr_unsigned((m) & 07777)
#define nfstov_mode(a) (fxdr_unsigned(u_short, (a))&07777)
#define vtonfsv2_type(a) txdr_unsigned(nfsv2_type[((long)(a))])
#define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((long)(a))])
#define nfsv2tov_type(a) nv2tov_type[fxdr_unsigned(u_long,(a))&0x7]
#define nfsv3tov_type(a) nv3tov_type[fxdr_unsigned(u_long,(a))&0x7]
/* File types */
typedef enum { NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5,
NFSOCK=6, NFFIFO=7 } nfstype;
/* Structs for common parts of the rpc's */
/*
* File Handle (32 bytes for version 2), variable up to 64 for version 3.
* File Handles of up to NFS_SMALLFH in size are stored directly in the
* nfs node, whereas larger ones are malloc'd. (This never happens when
* NFS_SMALLFH is set to 64.)
* NFS_SMALLFH should be in the range of 32 to 64 and be divisible by 4.
*/
#ifndef NFS_SMALLFH
#define NFS_SMALLFH 64
#endif
union nfsfh {
fhandle_t fh_generic;
u_char fh_bytes[NFS_SMALLFH];
};
typedef union nfsfh nfsfh_t;
struct nfsv2_time {
u_long nfsv2_sec;
u_long nfsv2_usec;
};
typedef struct nfsv2_time nfstime2;
struct nfsv3_time {
u_long nfsv3_sec;
u_long nfsv3_nsec;
};
typedef struct nfsv3_time nfstime3;
/*
* Quads are defined as arrays of 2 longs to ensure dense packing for the
* protocol and to facilitate xdr conversion.
*/
struct nfs_uquad {
u_long nfsuquad[2];
};
typedef struct nfs_uquad nfsuint64;
/*
* Used to convert between two u_longs and a u_quad_t.
*/
union nfs_quadconvert {
u_long lval[2];
u_quad_t qval;
};
typedef union nfs_quadconvert nfsquad_t;
/*
* NFS Version 3 special file number.
*/
struct nfsv3_spec {
u_long specdata1;
u_long specdata2;
};
typedef struct nfsv3_spec nfsv3spec;
/*
* File attributes and setable attributes. These structures cover both
* NFS version 2 and the version 3 protocol. Note that the union is only
* used so that one pointer can refer to both variants. These structures
* go out on the wire and must be densely packed, so no quad data types
* are used. (all fields are longs or u_longs or structures of same)
* NB: You can't do sizeof(struct nfs_fattr), you must use the
* NFSX_FATTR(v3) macro.
*/
struct nfs_fattr {
u_long fa_type;
u_long fa_mode;
u_long fa_nlink;
u_long fa_uid;
u_long fa_gid;
union {
struct {
u_long nfsv2fa_size;
u_long nfsv2fa_blocksize;
u_long nfsv2fa_rdev;
u_long nfsv2fa_blocks;
u_long nfsv2fa_fsid;
u_long nfsv2fa_fileid;
nfstime2 nfsv2fa_atime;
nfstime2 nfsv2fa_mtime;
nfstime2 nfsv2fa_ctime;
} fa_nfsv2;
struct {
nfsuint64 nfsv3fa_size;
nfsuint64 nfsv3fa_used;
nfsv3spec nfsv3fa_rdev;
nfsuint64 nfsv3fa_fsid;
nfsuint64 nfsv3fa_fileid;
nfstime3 nfsv3fa_atime;
nfstime3 nfsv3fa_mtime;
nfstime3 nfsv3fa_ctime;
} fa_nfsv3;
} fa_un;
};
/* and some ugly defines for accessing union components */
#define fa2_size fa_un.fa_nfsv2.nfsv2fa_size
#define fa2_blocksize fa_un.fa_nfsv2.nfsv2fa_blocksize
#define fa2_rdev fa_un.fa_nfsv2.nfsv2fa_rdev
#define fa2_blocks fa_un.fa_nfsv2.nfsv2fa_blocks
#define fa2_fsid fa_un.fa_nfsv2.nfsv2fa_fsid
#define fa2_fileid fa_un.fa_nfsv2.nfsv2fa_fileid
#define fa2_atime fa_un.fa_nfsv2.nfsv2fa_atime
#define fa2_mtime fa_un.fa_nfsv2.nfsv2fa_mtime
#define fa2_ctime fa_un.fa_nfsv2.nfsv2fa_ctime
#define fa3_size fa_un.fa_nfsv3.nfsv3fa_size
#define fa3_used fa_un.fa_nfsv3.nfsv3fa_used
#define fa3_rdev fa_un.fa_nfsv3.nfsv3fa_rdev
#define fa3_fsid fa_un.fa_nfsv3.nfsv3fa_fsid
#define fa3_fileid fa_un.fa_nfsv3.nfsv3fa_fileid
#define fa3_atime fa_un.fa_nfsv3.nfsv3fa_atime
#define fa3_mtime fa_un.fa_nfsv3.nfsv3fa_mtime
#define fa3_ctime fa_un.fa_nfsv3.nfsv3fa_ctime
struct nfsv2_sattr {
u_long sa_mode;
u_long sa_uid;
u_long sa_gid;
u_long sa_size;
nfstime2 sa_atime;
nfstime2 sa_mtime;
};
/*
* NFS Version 3 sattr structure for the new node creation case.
*/
struct nfsv3_sattr {
u_long sa_modetrue;
u_long sa_mode;
u_long sa_uidtrue;
u_long sa_uid;
u_long sa_gidtrue;
u_long sa_gid;
u_long sa_sizefalse;
u_long sa_atimetype;
nfstime3 sa_atime;
u_long sa_mtimetype;
nfstime3 sa_mtime;
};
struct nfs_statfs {
union {
struct {
u_long nfsv2sf_tsize;
u_long nfsv2sf_bsize;
u_long nfsv2sf_blocks;
u_long nfsv2sf_bfree;
u_long nfsv2sf_bavail;
} sf_nfsv2;
struct {
nfsuint64 nfsv3sf_tbytes;
nfsuint64 nfsv3sf_fbytes;
nfsuint64 nfsv3sf_abytes;
nfsuint64 nfsv3sf_tfiles;
nfsuint64 nfsv3sf_ffiles;
nfsuint64 nfsv3sf_afiles;
u_long nfsv3sf_invarsec;
} sf_nfsv3;
} sf_un;
};
#define sf_tsize sf_un.sf_nfsv2.nfsv2sf_tsize
#define sf_bsize sf_un.sf_nfsv2.nfsv2sf_bsize
#define sf_blocks sf_un.sf_nfsv2.nfsv2sf_blocks
#define sf_bfree sf_un.sf_nfsv2.nfsv2sf_bfree
#define sf_bavail sf_un.sf_nfsv2.nfsv2sf_bavail
#define sf_tbytes sf_un.sf_nfsv3.nfsv3sf_tbytes
#define sf_fbytes sf_un.sf_nfsv3.nfsv3sf_fbytes
#define sf_abytes sf_un.sf_nfsv3.nfsv3sf_abytes
#define sf_tfiles sf_un.sf_nfsv3.nfsv3sf_tfiles
#define sf_ffiles sf_un.sf_nfsv3.nfsv3sf_ffiles
#define sf_afiles sf_un.sf_nfsv3.nfsv3sf_afiles
#define sf_invarsec sf_un.sf_nfsv3.nfsv3sf_invarsec
struct nfsv3_fsinfo {
u_long fs_rtmax;
u_long fs_rtpref;
u_long fs_rtmult;
u_long fs_wtmax;
u_long fs_wtpref;
u_long fs_wtmult;
u_long fs_dtpref;
nfsuint64 fs_maxfilesize;
nfstime3 fs_timedelta;
u_long fs_properties;
};
struct nfsv3_pathconf {
u_long pc_linkmax;
u_long pc_namemax;
u_long pc_notrunc;
u_long pc_chownrestricted;
u_long pc_caseinsensitive;
u_long pc_casepreserving;
};
#endif

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfsrvcache.h 8.1 (Berkeley) 6/10/93
* $Id: nfsrvcache.h,v 1.3 1994/08/21 06:50:13 paul Exp $
* $Id: nfsrvcache.h,v 1.4 1994/10/17 17:47:44 phk Exp $
*/
#ifndef _NFS_NFSRVCACHE_H_
@ -44,7 +44,7 @@
* Definitions for the server recent request cache
*/
#define NFSRVCACHESIZ 256
#define NFSRVCACHESIZ 64
struct nfsrvcache {
TAILQ_ENTRY(nfsrvcache) rc_lru; /* LRU chain */

View File

@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)nfs.h 8.1 (Berkeley) 6/10/93
* $Id: nfs.h,v 1.8 1994/11/02 00:11:00 wollman Exp $
* $Id: nfs.h,v 1.9 1995/02/14 06:22:18 phk Exp $
*/
#ifndef _NFS_NFS_H_
@ -45,11 +45,12 @@
*/
#define NFS_MAXIOVEC 34
#define NFS_HZ 25 /* Ticks per second for NFS timeouts */
#define NFS_TIMEO (1*NFS_HZ) /* Default timeout = 1 second */
#define NFS_MINTIMEO (1*NFS_HZ) /* Min timeout to use */
#define NFS_MAXTIMEO (60*NFS_HZ) /* Max timeout to backoff to */
#define NFS_MINIDEMTIMEO (5*NFS_HZ) /* Min timeout for non-idempotent ops*/
#define NFS_TICKINTVL 5 /* Desired time for a tick (msec) */
#define NFS_HZ (hz / nfs_ticks) /* Ticks/sec */
#define NFS_TIMEO (1 * NFS_HZ) /* Default timeout = 1 second */
#define NFS_MINTIMEO (1 * NFS_HZ) /* Min timeout to use */
#define NFS_MAXTIMEO (60 * NFS_HZ) /* Max timeout to backoff to */
#define NFS_MINIDEMTIMEO (5 * NFS_HZ) /* Min timeout for non-idempotent ops*/
#define NFS_MAXREXMIT 100 /* Stop counting after this many */
#define NFS_MAXWINDOW 1024 /* Max number of outstanding requests */
#define NFS_RETRANS 10 /* Num of retrans for soft mounts */
@ -62,13 +63,81 @@
#endif
#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
#define NFS_READDIRSIZE 8192 /* Def. readdir size */
#define NFS_DEFRAHEAD 1 /* Def. read ahead # blocks */
#define NFS_MAXRAHEAD 4 /* Max. read ahead # blocks */
#define NFS_MAXREADDIR NFS_MAXDATA /* Max. size of directory read */
#define NFS_MAXUIDHASH 64 /* Max. # of hashed uid entries/mp */
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
#define NFS_DIRBLKSIZ 1024 /* Size of an NFS directory block */
#define NFS_MAXASYNCDAEMON 20 /* Max. number async_daemons runable */
#define NFS_MAXGATHERDELAY 100 /* Max. write gather delay (msec) */
#ifndef NFS_GATHERDELAY
#define NFS_GATHERDELAY 10 /* Default write gather delay (msec) */
#endif
#define NFS_DIRBLKSIZ 4096 /* Must be a multiple of DIRBLKSIZ */
/*
* Oddballs
*/
#define NMOD(a) ((a) % nfs_asyncdaemons)
#define NFS_CMPFH(n, f, s) \
((n)->n_fhsize == (s) && !bcmp((caddr_t)(n)->n_fhp, (caddr_t)(f), (s)))
#define NFS_ISV3(v) (VFSTONFS((v)->v_mount)->nm_flag & NFSMNT_NFSV3)
#define NFS_SRVMAXDATA(n) \
(((n)->nd_flag & ND_NFSV3) ? (((n)->nd_nam2) ? \
NFS_MAXDGRAMDATA : NFS_MAXDATA) : NFS_V2MAXDATA)
/*
* XXX
* sys/buf.h should be editted to change B_APPENDWRITE --> B_NEEDCOMMIT, but
* until then...
* Same goes for sys/malloc.h, which needs M_NFSDIROFF,
* M_NFSRVDESC and M_NFSBIGFH added.
* The VA_EXCLUSIVE flag should be added for va_vaflags and set for an
* exclusive create.
* The B_INVAFTERWRITE flag should be set to whatever is required by the
* buffer cache code to say "Invalidate the block after it is written back".
*/
#ifndef B_NEEDCOMMIT
#define B_NEEDCOMMIT B_APPENDWRITE
#endif
#ifndef M_NFSRVDESC
#define M_NFSRVDESC M_TEMP
#endif
#ifndef M_NFSDIROFF
#define M_NFSDIROFF M_TEMP
#endif
#ifndef M_NFSBIGFH
#define M_NFSBIGFH M_TEMP
#endif
#ifndef VA_EXCLUSIVE
#define VA_EXCLUSIVE 0
#endif
#ifdef __FreeBSD__
#define B_INVAFTERWRITE B_NOCACHE
#else
#define B_INVAFTERWRITE B_INVAL
#endif
/*
* These ifdefs try to handle the differences between the various 4.4BSD-Lite
* based vfs interfaces.
* btw: NetBSD-current does have a VOP_LEASDE(), but I don't know how to
* differentiate between NetBSD-1.0 and NetBSD-current, so..
* I also don't know about BSDi's 2.0 release.
*/
#if !defined(HAS_VOPLEASE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
#define HAS_VOPLEASE 1
#endif
#if !defined(HAS_VOPREVOKE) && !defined(__FreeBSD__) && !defined(__NetBSD__)
#define HAS_VOPREVOKE 1
#endif
/*
* The IO_METASYNC flag should be implemented for local file systems.
* (Until then, it is nothin at all.)
*/
#ifndef IO_METASYNC
#define IO_METASYNC 0
#endif
/*
* Set the attribute timeout based on how recently the file has been modified.
@ -79,6 +148,20 @@
((time.tv_sec - (np)->n_mtime) / 10 > NFS_MAXATTRTIMO ? NFS_MAXATTRTIMO : \
(time.tv_sec - (np)->n_mtime) / 10))
/*
* Expected allocation sizes for major data structures. If the actual size
* of the structure exceeds these sizes, then malloc() will be allocating
* almost twice the memory required. This is used in nfs_init() to warn
* the sysadmin that the size of a structure should be reduced.
* (These sizes are always a power of 2. If the kernel malloc() changes
* to one that does not allocate space in powers of 2 size, then this all
* becomes bunk!)
*/
#define NFS_NODEALLOC 256
#define NFS_MNTALLOC 512
#define NFS_SVCALLOC 256
#define NFS_UIDALLOC 128
/*
* Structures for the nfssvc(2) syscall. Not that anyone but nfsd and mount_nfs
* should ever try and use it.
@ -95,7 +178,12 @@ struct nfsd_srvargs {
u_long nsd_haddr; /* Ip address of client */
struct ucred nsd_cr; /* Cred. uid maps to */
int nsd_authlen; /* Length of auth string (ret) */
char *nsd_authstr; /* Auth string (ret) */
u_char *nsd_authstr; /* Auth string (ret) */
int nsd_verflen; /* and the verfier */
u_char *nsd_verfstr;
struct timeval nsd_timestamp; /* timestamp from verifier */
u_long nsd_ttl; /* credential ttl (sec) */
NFSKERBKEY_T nsd_key; /* Session key */
};
struct nfsd_cargs {
@ -103,7 +191,10 @@ struct nfsd_cargs {
uid_t ncd_authuid; /* Effective uid */
int ncd_authtype; /* Type of authenticator */
int ncd_authlen; /* Length of authenticator string */
char *ncd_authstr; /* Authenticator string */
u_char *ncd_authstr; /* Authenticator string */
int ncd_verflen; /* and the verifier */
u_char *ncd_verfstr;
NFSKERBKEY_T ncd_key; /* Session key */
};
/*
@ -142,6 +233,7 @@ struct nfsstats {
int srvnqnfs_leases;
int srvnqnfs_maxleases;
int srvnqnfs_getleases;
int srvvop_writes;
};
/*
@ -173,7 +265,7 @@ struct nfsstats {
* such as SIGALRM will not expect file I/O system calls to be interrupted
* by them and break.
*/
#ifdef KERNEL
#if defined(KERNEL) || defined(_KERNEL)
struct uio; struct buf; struct vattr; struct nameidata; /* XXX */
@ -224,17 +316,29 @@ TAILQ_HEAD(, nfsreq) nfs_reqq;
#define R_MUSTRESEND 0x40 /* Must resend request */
#define R_GETONEREP 0x80 /* Probe for one reply only */
extern struct nfsstats nfsstats;
/*
* A list of nfssvc_sock structures is maintained with all the sockets
* that require service by the nfsd.
* The nfsuid structs hang off of the nfssvc_sock structs in both lru
* and uid hash lists.
*/
#define NUIDHASHSIZ 32
#ifndef NFS_UIDHASHSIZ
#define NFS_UIDHASHSIZ 29 /* Tune the size of nfssvc_sock with this */
#endif
#define NUIDHASH(sock, uid) \
(&(sock)->ns_uidhashtbl[(uid) & (sock)->ns_uidhash])
(&(sock)->ns_uidhashtbl[(uid) % NFS_UIDHASHSIZ])
#ifndef NFS_WDELAYHASHSIZ
#define NFS_WDELAYHASHSIZ 16 /* and with this */
#endif
#define NWDELAYHASH(sock, f) \
(&(sock)->ns_wdelayhashtbl[(*((u_long *)(f))) % NFS_WDELAYHASHSIZ])
#ifndef NFS_MUIDHASHSIZ
#define NFS_MUIDHASHSIZ 67 /* Tune the size of nfsmount with this */
#endif
#define NMUIDHASH(nmp, uid) \
(&(nmp)->nm_uidhashtbl[(uid) % NFS_MUIDHASHSIZ])
#define NFSNOHASH(fhsum) \
(&nfsnodehashtbl[(fhsum) & nfsnodehash])
/*
* Network address hash list element
@ -248,35 +352,41 @@ struct nfsuid {
TAILQ_ENTRY(nfsuid) nu_lru; /* LRU chain */
LIST_ENTRY(nfsuid) nu_hash; /* Hash list */
int nu_flag; /* Flags */
uid_t nu_uid; /* Uid mapped by this entry */
union nethostaddr nu_haddr; /* Host addr. for dgram sockets */
struct ucred nu_cr; /* Cred uid mapped to */
int nu_expire; /* Expiry time (sec) */
struct timeval nu_timestamp; /* Kerb. timestamp */
u_long nu_nickname; /* Nickname on server */
NFSKERBKEY_T nu_key; /* and session key */
};
#define nu_inetaddr nu_haddr.had_inetaddr
#define nu_nam nu_haddr.had_nam
/* Bits for nu_flag */
#define NU_INETADDR 0x1
#define NU_NAM 0x2
#define NU_NETFAM(u) (((u)->nu_flag & NU_INETADDR) ? AF_INET : AF_ISO)
struct nfssvc_sock {
TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
TAILQ_HEAD(, nfsuid) ns_uidlruhead;
LIST_HEAD(, nfsuid) *ns_uidhashtbl;
u_long ns_uidhash;
int ns_flag;
u_long ns_sref;
struct file *ns_fp;
struct socket *ns_so;
int ns_solock;
struct mbuf *ns_nam;
int ns_cc;
struct mbuf *ns_raw;
struct mbuf *ns_rawend;
int ns_reclen;
struct mbuf *ns_rec;
struct mbuf *ns_recend;
struct mbuf *ns_frag;
int ns_flag;
int ns_solock;
int ns_cc;
int ns_reclen;
int ns_numuids;
u_long ns_sref;
LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
LIST_HEAD(, nfsuid) ns_uidhashtbl[NFS_UIDHASHSIZ];
LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
};
/* Bits for "ns_flag" */
@ -285,6 +395,7 @@ struct nfssvc_sock {
#define SLP_NEEDQ 0x04
#define SLP_DISCONN 0x08
#define SLP_GETSTREAM 0x10
#define SLP_LASTFRAG 0x20
#define SLP_ALLFLAGS 0xff
TAILQ_HEAD(, nfssvc_sock) nfssvc_sockhead;
@ -296,73 +407,124 @@ int nfssvc_sockhead_flag;
* One of these structures is allocated for each nfsd.
*/
struct nfsd {
TAILQ_ENTRY(nfsd) nd_chain; /* List of all nfsd's */
int nd_flag; /* NFSD_ flags */
struct nfssvc_sock *nd_slp; /* Current socket */
struct mbuf *nd_nam; /* Client addr for datagram req. */
struct mbuf *nd_mrep; /* Req. mbuf list */
struct mbuf *nd_md;
caddr_t nd_dpos; /* Position in list */
int nd_procnum; /* RPC procedure number */
u_long nd_retxid; /* RPC xid */
int nd_repstat; /* Reply status value */
struct ucred nd_cr; /* Credentials for req. */
int nd_nqlflag; /* Leasing flag */
u_long nd_duration; /* Lease duration */
int nd_authlen; /* Authenticator len */
u_char nd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
struct proc *nd_procp; /* Proc ptr */
TAILQ_ENTRY(nfsd) nfsd_chain; /* List of all nfsd's */
int nfsd_flag; /* NFSD_ flags */
struct nfssvc_sock *nfsd_slp; /* Current socket */
int nfsd_authlen; /* Authenticator len */
u_char nfsd_authstr[RPCAUTH_MAXSIZ]; /* Authenticator data */
int nfsd_verflen; /* and the Verifier */
u_char nfsd_verfstr[RPCVERF_MAXSIZ];
struct proc *nfsd_procp; /* Proc ptr */
struct nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
};
/* Bits for "nd_flag" */
/* Bits for "nfsd_flag" */
#define NFSD_WAITING 0x01
#define NFSD_REQINPROG 0x02
#define NFSD_NEEDAUTH 0x04
#define NFSD_AUTHFAIL 0x08
/*
* This structure is used by the server for describing each request.
* Some fields are used only when write request gathering is performed.
*/
struct nfsrv_descript {
u_quad_t nd_time; /* Write deadline (usec) */
off_t nd_off; /* Start byte offset */
off_t nd_eoff; /* and end byte offset */
LIST_ENTRY(nfsrv_descript) nd_hash; /* Hash list */
LIST_ENTRY(nfsrv_descript) nd_tq; /* and timer list */
LIST_HEAD(,nfsrv_descript) nd_coalesce; /* coalesced writes */
struct mbuf *nd_mrep; /* Request mbuf list */
struct mbuf *nd_md; /* Current dissect mbuf */
struct mbuf *nd_mreq; /* Reply mbuf list */
struct mbuf *nd_nam; /* and socket addr */
struct mbuf *nd_nam2; /* return socket addr */
caddr_t nd_dpos; /* Current dissect pos */
int nd_procnum; /* RPC # */
int nd_stable; /* storage type */
int nd_flag; /* nd_flag */
int nd_len; /* Length of this write */
int nd_repstat; /* Reply status */
u_long nd_retxid; /* Reply xid */
u_long nd_duration; /* Lease duration */
struct timeval nd_starttime; /* Time RPC initiated */
fhandle_t nd_fh; /* File handle */
struct ucred nd_cr; /* Credentials */
};
/* Bits for "nd_flag" */
#define ND_READ LEASE_READ
#define ND_WRITE LEASE_WRITE
#define ND_CHECK 0x04
#define ND_LEASE (ND_READ | ND_WRITE | ND_CHECK)
#define ND_NFSV3 0x08
#define ND_NQNFS 0x10
#define ND_KERBNICK 0x20
#define ND_KERBFULL 0x40
#define ND_KERBAUTH (ND_KERBNICK | ND_KERBFULL)
TAILQ_HEAD(, nfsd) nfsd_head;
int nfsd_head_flag;
#define NFSD_CHECKSLP 0x01
/*
* These macros compare nfsrv_descript structures.
*/
#define NFSW_CONTIG(o, n) \
((o)->nd_eoff >= (n)->nd_off && \
!bcmp((caddr_t)&(o)->nd_fh, (caddr_t)&(n)->nd_fh, NFSX_V3FH))
#define NFSW_SAMECRED(o, n) \
(((o)->nd_flag & ND_KERBAUTH) == ((n)->nd_flag & ND_KERBAUTH) && \
!bcmp((caddr_t)&(o)->nd_cr, (caddr_t)&(n)->nd_cr, \
sizeof (struct ucred)))
int nfs_reply __P((struct nfsreq *));
int nfs_getreq __P((struct nfsd *,int));
int nfs_getreq __P((struct nfsrv_descript *,struct nfsd *,int));
int nfs_send __P((struct socket *,struct mbuf *,struct mbuf *,struct nfsreq *));
int nfs_rephead __P((int,struct nfsd *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_rephead __P((int,struct nfsrv_descript *,struct nfssvc_sock *,int,int,u_quad_t *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_sndlock __P((int *,struct nfsreq *));
int nfs_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
int nfs_vinvalbuf __P((struct vnode *,int,struct ucred *,struct proc *,int));
int nfs_readrpc __P((struct vnode *,struct uio *,struct ucred *));
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int));
int nfs_writerpc __P((struct vnode *,struct uio *,struct ucred *,int *,int *));
int nfs_readdirrpc __P((register struct vnode *,struct uio *,struct ucred *));
int nfs_setattrrpc __P((struct vnode *,struct vattr *,struct ucred *,struct proc *));
int nfs_asyncio __P((struct buf *,struct ucred *));
int nfs_doio __P((struct buf *,struct ucred *,struct proc *));
int nfs_readlinkrpc __P((struct vnode *,struct uio *,struct ucred *));
int nfs_sigintr __P((struct nfsmount *,struct nfsreq *r,struct proc *));
int nfs_readdirlookrpc __P((struct vnode *,register struct uio *,struct ucred *));
int nfs_readdirplusrpc __P((struct vnode *,register struct uio *,struct ucred *));
int nfsm_disct __P((struct mbuf **,caddr_t *,int,int,caddr_t *));
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *));
void nfsm_srvfattr __P((struct nfsrv_descript *,struct vattr *,struct nfs_fattr *));
void nfsm_srvwcc __P((struct nfsrv_descript *,int,struct vattr *,int,struct vattr *,struct mbuf **,char **));
void nfsm_srvpostopattr __P((struct nfsrv_descript *,int,struct vattr *,struct mbuf **,char **));
int nfsrv_fhtovp __P((fhandle_t *,int,struct vnode **,struct ucred *,struct nfssvc_sock *,struct mbuf *,int *,int));
int nfsrv_access __P((struct vnode *,int,struct ucred *,int,struct proc *));
int netaddr_match __P((int,union nethostaddr *,struct mbuf *));
int nfs_request __P((struct vnode *,struct mbuf *,int,struct proc *,struct ucred *,struct mbuf **,struct mbuf **,caddr_t *));
int nfs_loadattrcache __P((struct vnode **,struct mbuf **,caddr_t *,struct vattr *));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct proc *));
int nfs_namei __P((struct nameidata *,fhandle_t *,int,struct nfssvc_sock *,struct mbuf *,struct mbuf **,caddr_t *,struct vnode **,struct proc *,int));
void nfsm_adj __P((struct mbuf *,int,int));
int nfsm_mbuftouio __P((struct mbuf **,struct uio *,int,caddr_t *));
void nfsrv_initcache __P((void));
int nfs_rcvlock __P((struct nfsreq *));
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,int *,char **,int *));
int nfs_getauth __P((struct nfsmount *,struct nfsreq *,struct ucred *,char **,int *,char *,int *,NFSKERBKEY_T));
int nfs_getnickauth __P((struct nfsmount *,struct ucred *,char **,int *,char *,int));
int nfs_savenickauth __P((struct nfsmount *,struct ucred *,int,NFSKERBKEY_T,struct mbuf **,char **,struct mbuf *));
int nfs_msg __P((struct proc *,char *,char *));
int nfs_adv __P((struct mbuf **,caddr_t *,int,int));
int nfsrv_getstream __P((struct nfssvc_sock *,int));
void nfs_nhinit __P((void));
void nfs_timer __P((void*));
struct nfsnodehashhead * nfs_hash __P((nfsv2fh_t *));
u_long nfs_hash __P((nfsfh_t *,int));
int nfssvc_iod __P((struct proc *));
int nfssvc_nfsd __P((struct nfsd_srvargs *,caddr_t,struct proc *));
int nfssvc_addsock __P((struct file *,struct mbuf *));
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *));
int nfsrv_getcache __P((struct mbuf *,struct nfsd *,struct mbuf **));
void nfsrv_updatecache __P((struct mbuf *,struct nfsd *,int,struct mbuf *));
int nfsrv_dorec __P((struct nfssvc_sock *,struct nfsd *,struct nfsrv_descript **));
int nfsrv_getcache __P((struct nfsrv_descript *,struct nfssvc_sock *,struct mbuf **));
void nfsrv_updatecache __P((struct nfsrv_descript *,int,struct mbuf *));
int mountnfs __P((struct nfs_args *,struct mount *,struct mbuf *,char *,char *,struct vnode **));
int nfs_connect __P((struct nfsmount *,struct nfsreq *));
int nfs_getattrcache __P((struct vnode *,struct vattr *));
@ -370,9 +532,20 @@ int nfsm_strtmbuf __P((struct mbuf **,char **,char *,long));
int nfs_bioread __P((struct vnode *,struct uio *,int,struct ucred *));
int nfsm_uiotombuf __P((struct uio *,struct mbuf **,int,caddr_t *));
void nfsrv_init __P((int));
void nfs_clearcommit __P((struct mount *));
int nfsrv_errmap __P((struct nfsrv_descript *, int));
void nfsrvw_coalesce __P((struct nfsrv_descript *,struct nfsrv_descript *));
void nfsrvw_sort __P((gid_t [],int));
void nfsrv_setcred __P((struct ucred *,struct ucred *));
int nfs_flush __P((struct vnode *,struct ucred *,int,struct proc *,int));
int nfs_writebp __P((struct buf *,int));
int nfsrv_vput __P(( struct vnode * ));
int nfsrv_vrele __P(( struct vnode * ));
int nfsrv_vmio __P(( struct vnode * ));
int nfsrv_writegather __P((struct nfsrv_descript **, struct nfssvc_sock *,
struct proc *, struct mbuf **));
int nfs_fsinfo __P((struct nfsmount *, struct vnode *, struct ucred *,
struct proc *p));
#endif /* KERNEL */

View File

@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)mount.h 8.13 (Berkeley) 3/27/94
* $Id: mount.h,v 1.18 1995/05/21 21:39:24 davidg Exp $
* $Id: mount.h,v 1.19 1995/05/30 08:14:28 rgrimes Exp $
*/
#ifndef _SYS_MOUNT_H_
@ -402,15 +402,6 @@ struct iso_args {
#endif /* CD9660 */
#ifdef NFS
/*
* File Handle (32 bytes for version 2), variable up to 1024 for version 3
*/
union nfsv2fh {
fhandle_t fh_generic;
u_char fh_bytes[32];
};
typedef union nfsv2fh nfsv2fh_t;
/*
* Arguments to mount NFS
*/
@ -419,10 +410,12 @@ struct nfs_args {
int addrlen; /* length of address */
int sotype; /* Socket type */
int proto; /* and Protocol */
nfsv2fh_t *fh; /* File handle to be mounted */
u_char *fh; /* File handle to be mounted */
int fhsize; /* Size, in bytes, of fh */
int flags; /* flags */
int wsize; /* write size in bytes */
int rsize; /* read size in bytes */
int readdirsize; /* readdir size in bytes */
int timeo; /* initial timeout in .1 secs */
int retrans; /* times to retry send */
int maxgrouplist; /* Max. size of group list */
@ -432,7 +425,6 @@ struct nfs_args {
char *hostname; /* server's name */
};
/*
* NFS mount option flags
*/
@ -445,16 +437,19 @@ struct nfs_args {
#define NFSMNT_INT 0x00000040 /* allow interrupts on hard mount */
#define NFSMNT_NOCONN 0x00000080 /* Don't Connect the socket */
#define NFSMNT_NQNFS 0x00000100 /* Use Nqnfs protocol */
#define NFSMNT_MYWRITE 0x00000200 /* Assume writes were mine */
#define NFSMNT_NFSV3 0x00000200 /* Use NFS Version 3 protocol */
#define NFSMNT_KERB 0x00000400 /* Use Kerberos authentication */
#define NFSMNT_DUMBTIMR 0x00000800 /* Don't estimate rtt dynamically */
#define NFSMNT_RDIRALOOK 0x00001000 /* Do lookup with readdir (nqnfs) */
#define NFSMNT_LEASETERM 0x00002000 /* set lease term (nqnfs) */
#define NFSMNT_READAHEAD 0x00004000 /* set read ahead */
#define NFSMNT_DEADTHRESH 0x00008000 /* set dead server retry thresh */
#define NFSMNT_NQLOOKLEASE 0x00010000 /* Get lease for lookup */
#define NFSMNT_RESVPORT 0x00020000 /* Allocate a reserved port */
#define NFSMNT_INTERNAL 0xffe00000 /* Bits set internally */
#define NFSMNT_LEASETERM 0x00001000 /* set lease term (nqnfs) */
#define NFSMNT_READAHEAD 0x00002000 /* set read ahead */
#define NFSMNT_DEADTHRESH 0x00004000 /* set dead server retry thresh */
#define NFSMNT_RESVPORT 0x00008000 /* Allocate a reserved port */
#define NFSMNT_RDIRPLUS 0x00010000 /* Use Readdirplus for V3 */
#define NFSMNT_READDIRSIZE 0x00020000 /* Set readdir size */
#define NFSMNT_INTERNAL 0xfffc0000 /* Bits set internally */
#define NFSMNT_HASWRITEVERF 0x00040000 /* Has write verifier for V3 */
#define NFSMNT_GOTPATHCONF 0x00080000 /* Got the V3 pathconf info */
#define NFSMNT_GOTFSINFO 0x00100000 /* Got the V3 fsinfo */
#define NFSMNT_MNTD 0x00200000 /* Mnt server for mnt point */
#define NFSMNT_DISMINPROG 0x00400000 /* Dismount in progress */
#define NFSMNT_DISMNT 0x00800000 /* Dismounted */

View File

@ -62,7 +62,7 @@ static char sccsid[] = "@(#)fstat.c 8.1 (Berkeley) 6/6/93";
#undef KERNEL
#define NFS
#include <sys/mount.h>
#include <nfs/nfsv2.h>
#include <nfs/nfsproto.h>
#include <nfs/rpcv2.h>
#include <nfs/nfs.h>
#include <nfs/nfsnode.h>

View File

@ -43,13 +43,14 @@ static char copyright[] =
#ifndef lint
/*static char sccsid[] = "From: @(#)nfsstat.c 8.1 (Berkeley) 6/6/93";*/
static const char rcsid[] =
"$Id$";
"$Id: nfsstat.c,v 1.2 1994/10/23 23:25:43 wollman Exp $";
#endif /* not lint */
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/sysctl.h>
#include <nfs/nfsv2.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
#include <signal.h>
#include <fcntl.h>
@ -73,7 +74,10 @@ kvm_t *kd;
static int deadkernel = 0;
void intpr(void), printhdr(void), sidewaysintpr(u_int), usage(void);
void intpr __P((void));
void printhdr __P((void));
void sidewaysintpr __P((u_int));
void usage __P((void));
main(argc, argv)
int argc;
@ -146,7 +150,8 @@ main(argc, argv)
* for dead ones.
*/
void
readstats(struct nfsstats *stp)
readstats(stp)
struct nfsstats *stp;
{
if(deadkernel) {
if(kvm_read(kd, (u_long)nl[N_NFSSTAT].n_value, stp,
@ -171,7 +176,7 @@ readstats(struct nfsstats *stp)
* Print a description of the nfs stats.
*/
void
intpr(void)
intpr()
{
struct nfsstats nfsstats;
@ -193,7 +198,7 @@ intpr(void)
nfsstats.rpccnt[NFSPROC_REMOVE]);
printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
"Rename", "Link", "Symlink", "Mkdir", "Rmdir",
"Readdir", "Statfs", "RdirLook");
"Readdir", "RdirPlus", "Access");
printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
nfsstats.rpccnt[NFSPROC_RENAME],
nfsstats.rpccnt[NFSPROC_LINK],
@ -201,11 +206,17 @@ intpr(void)
nfsstats.rpccnt[NFSPROC_MKDIR],
nfsstats.rpccnt[NFSPROC_RMDIR],
nfsstats.rpccnt[NFSPROC_READDIR],
nfsstats.rpccnt[NFSPROC_STATFS],
nfsstats.rpccnt[NQNFSPROC_READDIRLOOK]);
printf("%9.9s %9.9s %9.9s\n",
nfsstats.rpccnt[NFSPROC_READDIRPLUS],
nfsstats.rpccnt[NFSPROC_ACCESS]);
printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
"Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit",
"GLease", "Vacate", "Evict");
printf("%9d %9d %9d\n",
printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
nfsstats.rpccnt[NFSPROC_MKNOD],
nfsstats.rpccnt[NFSPROC_FSSTAT],
nfsstats.rpccnt[NFSPROC_FSINFO],
nfsstats.rpccnt[NFSPROC_PATHCONF],
nfsstats.rpccnt[NFSPROC_COMMIT],
nfsstats.rpccnt[NQNFSPROC_GETLEASE],
nfsstats.rpccnt[NQNFSPROC_VACATED],
nfsstats.rpccnt[NQNFSPROC_EVICTED]);
@ -256,7 +267,7 @@ intpr(void)
nfsstats.srvrpccnt[NFSPROC_REMOVE]);
printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
"Rename", "Link", "Symlink", "Mkdir", "Rmdir",
"Readdir", "Statfs", "RdirLook");
"Readdir", "RdirPlus", "Access");
printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
nfsstats.srvrpccnt[NFSPROC_RENAME],
nfsstats.srvrpccnt[NFSPROC_LINK],
@ -264,11 +275,17 @@ intpr(void)
nfsstats.srvrpccnt[NFSPROC_MKDIR],
nfsstats.srvrpccnt[NFSPROC_RMDIR],
nfsstats.srvrpccnt[NFSPROC_READDIR],
nfsstats.srvrpccnt[NFSPROC_STATFS],
nfsstats.srvrpccnt[NQNFSPROC_READDIRLOOK]);
printf("%9.9s %9.9s %9.9s\n",
nfsstats.srvrpccnt[NFSPROC_READDIRPLUS],
nfsstats.srvrpccnt[NFSPROC_ACCESS]);
printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n",
"Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit",
"GLease", "Vacate", "Evict");
printf("%9d %9d %9d\n",
printf("%9d %9d %9d %9d %9d %9d %9d %9d\n",
nfsstats.srvrpccnt[NFSPROC_MKNOD],
nfsstats.srvrpccnt[NFSPROC_FSSTAT],
nfsstats.srvrpccnt[NFSPROC_FSINFO],
nfsstats.srvrpccnt[NFSPROC_PATHCONF],
nfsstats.srvrpccnt[NFSPROC_COMMIT],
nfsstats.srvrpccnt[NQNFSPROC_GETLEASE],
nfsstats.srvrpccnt[NQNFSPROC_VACATED],
nfsstats.srvrpccnt[NQNFSPROC_EVICTED]);
@ -291,6 +308,13 @@ intpr(void)
nfsstats.srvnqnfs_leases,
nfsstats.srvnqnfs_maxleases,
nfsstats.srvnqnfs_getleases);
printf("Server Write Gathering:\n");
printf("%9.9s %9.9s %9.9s\n",
"WriteOps", "WriteRPC", "Opsaved");
printf("%9d %9d %9d\n",
nfsstats.srvvop_writes,
nfsstats.srvrpccnt[NFSPROC_WRITE],
nfsstats.srvrpccnt[NFSPROC_WRITE] - nfsstats.srvvop_writes);
}
u_char signalled; /* set if alarm goes off "early" */
@ -321,23 +345,25 @@ sidewaysintpr(interval)
}
readstats(&nfsstats);
printf("Client: %8d %8d %8d %8d %8d %8d %8d %8d\n",
nfsstats.rpccnt[1]-lastst.rpccnt[1],
nfsstats.rpccnt[4]-lastst.rpccnt[4],
nfsstats.rpccnt[5]-lastst.rpccnt[5],
nfsstats.rpccnt[6]-lastst.rpccnt[6],
nfsstats.rpccnt[8]-lastst.rpccnt[8],
nfsstats.rpccnt[11]-lastst.rpccnt[11],
nfsstats.rpccnt[12]-lastst.rpccnt[12],
nfsstats.rpccnt[16]-lastst.rpccnt[16]);
nfsstats.rpccnt[NFSPROC_GETATTR]-lastst.rpccnt[NFSPROC_GETATTR],
nfsstats.rpccnt[NFSPROC_LOOKUP]-lastst.rpccnt[NFSPROC_LOOKUP],
nfsstats.rpccnt[NFSPROC_READLINK]-lastst.rpccnt[NFSPROC_READLINK],
nfsstats.rpccnt[NFSPROC_READ]-lastst.rpccnt[NFSPROC_READ],
nfsstats.rpccnt[NFSPROC_WRITE]-lastst.rpccnt[NFSPROC_WRITE],
nfsstats.rpccnt[NFSPROC_RENAME]-lastst.rpccnt[NFSPROC_RENAME],
nfsstats.rpccnt[NFSPROC_ACCESS]-lastst.rpccnt[NFSPROC_ACCESS],
(nfsstats.rpccnt[NFSPROC_READDIR]-lastst.rpccnt[NFSPROC_READDIR])
+(nfsstats.rpccnt[NFSPROC_READDIRPLUS]-lastst.rpccnt[NFSPROC_READDIRPLUS]));
printf("Server: %8d %8d %8d %8d %8d %8d %8d %8d\n",
nfsstats.srvrpccnt[1]-lastst.srvrpccnt[1],
nfsstats.srvrpccnt[4]-lastst.srvrpccnt[4],
nfsstats.srvrpccnt[5]-lastst.srvrpccnt[5],
nfsstats.srvrpccnt[6]-lastst.srvrpccnt[6],
nfsstats.srvrpccnt[8]-lastst.srvrpccnt[8],
nfsstats.srvrpccnt[11]-lastst.srvrpccnt[11],
nfsstats.srvrpccnt[12]-lastst.srvrpccnt[12],
nfsstats.srvrpccnt[16]-lastst.srvrpccnt[16]);
nfsstats.srvrpccnt[NFSPROC_GETATTR]-lastst.srvrpccnt[NFSPROC_GETATTR],
nfsstats.srvrpccnt[NFSPROC_LOOKUP]-lastst.srvrpccnt[NFSPROC_LOOKUP],
nfsstats.srvrpccnt[NFSPROC_READLINK]-lastst.srvrpccnt[NFSPROC_READLINK],
nfsstats.srvrpccnt[NFSPROC_READ]-lastst.srvrpccnt[NFSPROC_READ],
nfsstats.srvrpccnt[NFSPROC_WRITE]-lastst.srvrpccnt[NFSPROC_WRITE],
nfsstats.srvrpccnt[NFSPROC_RENAME]-lastst.srvrpccnt[NFSPROC_RENAME],
nfsstats.srvrpccnt[NFSPROC_ACCESS]-lastst.srvrpccnt[NFSPROC_ACCESS],
(nfsstats.srvrpccnt[NFSPROC_READDIR]-lastst.srvrpccnt[NFSPROC_READDIR])
+(nfsstats.srvrpccnt[NFSPROC_READDIRPLUS]-lastst.srvrpccnt[NFSPROC_READDIRPLUS]));
lastst = nfsstats;
fflush(stdout);
oldmask = sigblock(sigmask(SIGALRM));
@ -355,7 +381,7 @@ printhdr()
{
printf(" %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s\n",
"Getattr", "Lookup", "Readlink", "Read", "Write", "Rename",
"Link", "Readdir");
"Access", "Readdir");
fflush(stdout);
}

View File

@ -42,7 +42,7 @@
.Nd show remote nfs mounts on host
.Sh SYNOPSIS
.Nm showmount
.Op Fl ade
.Op Fl ade3
.Op Ar host
.Sh DESCRIPTION
.Nm Showmount
@ -56,7 +56,10 @@ file systems mounted
on the host. See
.%T "NFS: Network File System Protocol Specification" ,
RFC 1094,
Appendix A ,
Appendix A,
and
.%T "NFS: Network File System Version 3 Protocol Specification" ,
Appendix I,
for a detailed description of the protocol.
.Bl -tag -width Ds
.It Fl a
@ -70,6 +73,8 @@ List directory paths of mount points instead of hosts
Show the
.Ar host Ns 's
exports list
.It Fl 3
Use mount protocol Version 3, compatible with NFS Version 3.
.El
.Sh SEE ALSO
.Xr mount 1 ,

View File

@ -90,6 +90,7 @@ int xdr_mntdump(), xdr_exports();
* This command queries the NFS mount daemon for it's mount list and/or
* it's exports list and prints them out.
* See "NFS: Network File System Protocol Specification, RFC1094, Appendix A"
* and the "Network File System Protocol XXX.."
* for detailed information on the protocol.
*/
main(argc, argv)
@ -101,12 +102,12 @@ main(argc, argv)
register struct grouplist *grp;
extern char *optarg;
extern int optind;
register int rpcs = 0;
register int rpcs = 0, mntvers = 1;
char ch;
char *host;
int estat;
while ((ch = getopt(argc, argv, "ade")) != EOF)
while ((ch = getopt(argc, argv, "ade3")) != EOF)
switch((char)ch) {
case 'a':
if (type == 0) {
@ -125,6 +126,9 @@ main(argc, argv)
case 'e':
rpcs |= DOEXPORTS;
break;
case '3':
mntvers = 3;
break;
case '?':
default:
usage();
@ -141,7 +145,7 @@ main(argc, argv)
rpcs = DODUMP;
if (rpcs & DODUMP)
if ((estat = callrpc(host, RPCPROG_MNT, RPCMNT_VER1,
if ((estat = callrpc(host, RPCPROG_MNT, mntvers,
RPCMNT_DUMP, xdr_void, (char *)0,
xdr_mntdump, (char *)&mntdump)) != 0) {
clnt_perrno(estat);
@ -149,7 +153,7 @@ main(argc, argv)
exit(1);
}
if (rpcs & DOEXPORTS)
if ((estat = callrpc(host, RPCPROG_MNT, RPCMNT_VER1,
if ((estat = callrpc(host, RPCPROG_MNT, mntvers,
RPCMNT_EXPORT, xdr_void, (char *)0,
xdr_exports, (char *)&exports)) != 0) {
clnt_perrno(estat);

View File

@ -37,7 +37,7 @@
*
* @(#)afs_ops.c 8.1 (Berkeley) 6/6/93
*
* $Id: afs_ops.c,v 1.1.1.1 1994/05/26 05:22:03 rgrimes Exp $
* $Id: afs_ops.c,v 1.2 1995/05/30 03:45:43 rgrimes Exp $
*
*/
@ -144,6 +144,9 @@ char *opts;
}
NFS_FH_DREF(nfs_args.fh, (NFS_FH_TYPE) fhp);
#ifdef NFSv3
nfs_args.fhsize = FHSIZE;
#endif
/*
* Create sockaddr to point to the local machine. 127.0.0.1

View File

@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: nfs_ops.c,v 1.2 1995/02/13 01:56:22 wpaul Exp $
* $Id: nfs_ops.c,v 1.3 1995/05/30 03:45:52 rgrimes Exp $
*/
#ifndef lint
@ -529,6 +529,9 @@ mntfs *mf;
* set mount args
*/
NFS_FH_DREF(nfs_args.fh, (NFS_FH_TYPE) fhp->fhstatus_u.fhs_fhandle);
#ifdef NFSv3
nfs_args.fhsize = FHSIZE;
#endif
#ifdef ULTRIX_HACK
nfs_args.optstr = mnt.mnt_opts;

View File

@ -37,7 +37,7 @@
*
* @(#)os-bsd44.h 8.1 (Berkeley) 6/6/93
*
* $Id: os-bsd44.h,v 1.1.1.1 1994/05/26 05:22:07 rgrimes Exp $
* $Id: os-bsd44.h,v 1.2 1995/01/20 20:58:54 wollman Exp $
*
* 4.4 BSD definitions for Amd (automounter)
*/
@ -61,6 +61,7 @@
*/
#define NFS_44
#define HAS_TCP_NFS
#define NFSv3
/*
* Does this OS have NDBM support?
@ -170,7 +171,11 @@ struct mntent {
* Type of a file handle
*/
#undef NFS_FH_TYPE
#ifdef NFSv3
#define NFS_FH_TYPE fhandle_t *
#else
#define NFS_FH_TYPE nfsv2fh_t *
#endif
/*
* How to get a mount list

View File

@ -49,7 +49,9 @@ file specifies remote mount points for the
mount protocol per the
.Tn NFS
server specification; see
.%T "Network File System Protocol Specification \\*(tNRFC\\*(sP 1094, Appendix A" .
.%T "Network File System Protocol Specification \\*(tNRFC\\*(sP 1094, Appendix A"
and
.%T "NFS: Network File System Version 3 Specification, Appendix I" .
.Pp
Each line in the file
(other than comment lines that begin with a #)
@ -71,7 +73,8 @@ The second is to specify the pathname of the root of the filesystem
followed by the
.Fl alldirs
flag;
this form allows the host(s) to mount any directory within the filesystem.
this form allows the host(s) to mount at any point within the filesystem,
including regular files if the ``-r'' option is used on mountd.
The pathnames must not have any symbolic links in them and should not have
any "." or ".." components.
Mount points for a filesystem may appear on multiple lines each with
@ -140,8 +143,7 @@ The
.Fl kerb
option specifies that the Kerberos authentication server should be
used to authenticate and map client credentials.
(Note that this is NOT Sun NFS compatible and
is supported for TCP transport only.)
This requires that the kernel be built with the NFSKERB option.
.Pp
The
.Fl ro

View File

@ -30,7 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\" From: @(#)mountd.8 8.1 (Berkeley) 6/9/93
.\" $Id: mountd.8,v 1.2 1994/09/22 22:16:49 wollman Exp $
.\" $Id: mountd.8,v 1.3 1995/02/22 21:42:48 ats Exp $
.\"
.Dd September 22, 1994
.Dt MOUNTD 8
@ -42,7 +42,7 @@
mount requests
.Sh SYNOPSIS
.Nm /sbin/mountd
.Op Fl n
.Op Fl nr
.Op Ar exportsfile
.Sh DESCRIPTION
.Xr Mountd
@ -54,7 +54,9 @@ listens for service requests at the port indicated in the
.Tn NFS
server specification; see
.%T "Network File System Protocol Specification" ,
RFC1094.
RFC1094, Appendix A and
.%T "NFS: Network File System Version 3 Protocol Specification" ,
Appendix I.
.Pp
Options and operands available for
.Nm mountd :
@ -65,6 +67,15 @@ The
option allows non-root mount requests to be served.
This should only be specified if there are clients such as PC's,
that require it.
.It Fl r
The
.Fl r
option allows mount RPCs requests for regular files to be served.
Although this seems to violate the mount protocol specification, some diskless
workstations do mount requests for their swapfiles and expect them to be
regular files. Since a regular file cannot be specified in /etc/exports, the
entire file system that the swapfiles reside in will have to be exported with
the ``-alldirs'' flag.
.It Ar exportsfile
The
.Ar exportsfile

View File

@ -43,7 +43,7 @@ static char copyright[] =
#ifndef lint
/*static char sccsid[] = "From: @(#)mountd.c 8.8 (Berkeley) 2/20/94";*/
static const char rcsid[] =
"$Id: mountd.c,v 1.7.2.1 1995/06/08 04:34:11 davidg Exp $";
"$Id: mountd.c,v 1.8 1995/06/11 19:30:46 rgrimes Exp $";
#endif /*not lint*/
#include <sys/param.h>
@ -62,7 +62,7 @@ static const char rcsid[] =
#include <netiso/iso.h>
#endif
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <nfs/nfsproto.h>
#include <arpa/inet.h>
@ -100,6 +100,8 @@ struct dirlist {
};
/* dp_flag bits */
#define DP_DEFSET 0x1
#define DP_HOSTSET 0x2
#define DP_KERB 0x4
struct exportlist {
struct exportlist *ex_next;
@ -139,22 +141,29 @@ struct grouplist {
#define GT_IGNORE 0x5
struct hostlist {
int ht_flag; /* Uses DP_xx bits */
struct grouplist *ht_grp;
struct hostlist *ht_next;
};
struct fhreturn {
int fhr_flag;
int fhr_vers;
nfsfh_t fhr_fh;
};
/* Global defs */
char *add_expdir __P((struct dirlist **, char *, int));
void add_dlist __P((struct dirlist **, struct dirlist *,
struct grouplist *));
struct grouplist *, int));
void add_mlist __P((char *, char *));
int check_dirpath __P((char *));
int check_options __P((struct dirlist *));
int chk_host __P((struct dirlist *, u_long, int *));
int chk_host __P((struct dirlist *, u_long, int *, int *));
void del_mlist __P((char *, char *));
struct dirlist *dirp_search __P((struct dirlist *, char *));
int do_mount __P((struct exportlist *, struct grouplist *, int,
struct ucred *, char *, int, struct statfs *));
struct ucred *, char *, int, struct statfs *));
int do_opt __P((char **, char **, struct exportlist *, struct grouplist *,
int *, int *, struct ucred *));
struct exportlist *ex_search __P((fsid_t *));
@ -165,6 +174,7 @@ void free_grp __P((struct grouplist *));
void free_host __P((struct hostlist *));
void get_exportlist __P((void));
int get_host __P((char *, struct grouplist *, struct grouplist *));
int get_num __P((char *));
struct hostlist *get_ht __P((void));
int get_line __P((void));
void get_mountlist __P((void));
@ -183,7 +193,7 @@ void send_umntall __P((void));
int umntall_each __P((caddr_t, struct sockaddr_in *));
int xdr_dir __P((XDR *, char *));
int xdr_explist __P((XDR *, caddr_t));
int xdr_fhs __P((XDR *, nfsv2fh_t *));
int xdr_fhs __P((XDR *, caddr_t));
int xdr_mlist __P((XDR *, caddr_t));
/* C library */
@ -205,7 +215,8 @@ struct ucred def_anon = {
1,
{ (gid_t) -2 }
};
int root_only = 1;
int resvport_only = 1;
int dir_only = 1;
int opt_flags;
/* Bits for above */
#define OP_MAPROOT 0x01
@ -238,6 +249,7 @@ main(argc, argv)
{
SVCXPRT *udptransp, *tcptransp;
int c;
#ifdef __FreeBSD__
struct vfsconf *vfc;
vfc = getvfsbyname("nfs");
@ -250,17 +262,21 @@ main(argc, argv)
if(!vfc) {
errx(1, "NFS support is not available in the running kernel");
}
#endif /* __FreeBSD__ */
while ((c = getopt(argc, argv, "dn")) != EOF)
while ((c = getopt(argc, argv, "dnr")) != EOF)
switch (c) {
case 'n':
resvport_only = 0;
break;
case 'r':
dir_only = 0;
break;
case 'd':
debug = debug ? 0 : 1;
break;
case 'n':
root_only = 0;
break;
default:
fprintf(stderr, "Usage: mountd [-n] [export_file]\n");
fprintf(stderr, "Usage: mountd [-r] [-n] [export_file]\n");
exit(1);
};
argc -= optind;
@ -300,11 +316,12 @@ main(argc, argv)
syslog(LOG_ERR, "Can't create socket");
exit(1);
}
pmap_unset(RPCPROG_MNT, RPCMNT_VER1);
if (!svc_register(udptransp, RPCPROG_MNT, RPCMNT_VER1, mntsrv,
IPPROTO_UDP) ||
!svc_register(tcptransp, RPCPROG_MNT, RPCMNT_VER1, mntsrv,
IPPROTO_TCP)) {
pmap_unset(RPCPROG_MNT, 1);
pmap_unset(RPCPROG_MNT, 3);
if (!svc_register(udptransp, RPCPROG_MNT, 1, mntsrv, IPPROTO_UDP) ||
!svc_register(udptransp, RPCPROG_MNT, 3, mntsrv, IPPROTO_UDP) ||
!svc_register(tcptransp, RPCPROG_MNT, 1, mntsrv, IPPROTO_TCP) ||
!svc_register(tcptransp, RPCPROG_MNT, 3, mntsrv, IPPROTO_TCP)) {
syslog(LOG_ERR, "Can't register mount");
exit(1);
}
@ -323,28 +340,21 @@ mntsrv(rqstp, transp)
{
struct exportlist *ep;
struct dirlist *dp;
nfsv2fh_t nfh;
struct fhreturn fhr;
struct authunix_parms *ucr;
struct stat stb;
struct statfs fsb;
struct hostent *hp;
u_long saddr;
u_short sport;
char rpcpath[RPCMNT_PATHLEN+1], dirpath[MAXPATHLEN];
int bad = ENOENT, omask, defset;
uid_t uid = -2;
/* Get authorization */
switch (rqstp->rq_cred.oa_flavor) {
case AUTH_UNIX:
ucr = (struct authunix_parms *)rqstp->rq_clntcred;
uid = ucr->aup_uid;
break;
case AUTH_NULL:
default:
break;
}
int bad = ENOENT, defset, hostset;
sigset_t sighup_mask;
sigemptyset(&sighup_mask);
sigaddset(&sighup_mask, SIGHUP);
saddr = transp->xp_raddr.sin_addr.s_addr;
sport = ntohs(transp->xp_raddr.sin_port);
hp = (struct hostent *)NULL;
switch (rqstp->rq_proc) {
case NULLPROC:
@ -352,7 +362,7 @@ mntsrv(rqstp, transp)
syslog(LOG_ERR, "Can't send reply");
return;
case RPCMNT_MOUNT:
if ((uid != 0 && root_only) || uid == -2) {
if (sport >= IPPORT_RESERVED && resvport_only) {
svcerr_weakauth(transp);
return;
}
@ -363,11 +373,13 @@ mntsrv(rqstp, transp)
/*
* Get the real pathname and make sure it is a directory
* that exists.
* or a regular file if the -r option was specified
* and it exists.
*/
if (realpath(rpcpath, dirpath) == 0 ||
stat(dirpath, &stb) < 0 ||
(stb.st_mode & S_IFMT) != S_IFDIR ||
(!S_ISDIR(stb.st_mode) &&
(dir_only || !S_ISREG(stb.st_mode))) ||
statfs(dirpath, &fsb) < 0) {
chdir("/"); /* Just in case realpath doesn't */
if (debug)
@ -378,26 +390,31 @@ mntsrv(rqstp, transp)
}
/* Check in the exports list */
omask = sigblock(sigmask(SIGHUP));
sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
ep = ex_search(&fsb.f_fsid);
defset = 0;
if (ep && (chk_host(ep->ex_defdir, saddr, &defset) ||
hostset = defset = 0;
if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset) ||
((dp = dirp_search(ep->ex_dirl, dirpath)) &&
chk_host(dp, saddr, &defset)) ||
chk_host(dp, saddr, &defset, &hostset)) ||
(defset && scan_tree(ep->ex_defdir, saddr) == 0 &&
scan_tree(ep->ex_dirl, saddr) == 0))) {
if (hostset & DP_HOSTSET)
fhr.fhr_flag = hostset;
else
fhr.fhr_flag = defset;
fhr.fhr_vers = rqstp->rq_vers;
/* Get the file handle */
bzero((caddr_t)&nfh, sizeof(nfh));
if (getfh(dirpath, (fhandle_t *)&nfh) < 0) {
bzero((caddr_t)&fhr.fhr_fh, sizeof(nfsfh_t));
if (getfh(dirpath, (fhandle_t *)&fhr.fhr_fh) < 0) {
bad = errno;
syslog(LOG_ERR, "Can't get fh for %s", dirpath);
if (!svc_sendreply(transp, xdr_long,
(caddr_t)&bad))
syslog(LOG_ERR, "Can't send reply");
sigsetmask(omask);
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
return;
}
if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&nfh))
if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&fhr))
syslog(LOG_ERR, "Can't send reply");
if (hp == NULL)
hp = gethostbyaddr((caddr_t)&saddr,
@ -414,14 +431,14 @@ mntsrv(rqstp, transp)
if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
syslog(LOG_ERR, "Can't send reply");
}
sigsetmask(omask);
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
return;
case RPCMNT_DUMP:
if (!svc_sendreply(transp, xdr_mlist, (caddr_t)NULL))
syslog(LOG_ERR, "Can't send reply");
return;
case RPCMNT_UMOUNT:
if ((uid != 0 && root_only) || uid == -2) {
if (sport >= IPPORT_RESERVED && resvport_only) {
svcerr_weakauth(transp);
return;
}
@ -437,7 +454,7 @@ mntsrv(rqstp, transp)
del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), dirpath);
return;
case RPCMNT_UMNTALL:
if ((uid != 0 && root_only) || uid == -2) {
if (sport >= IPPORT_RESERVED && resvport_only) {
svcerr_weakauth(transp);
return;
}
@ -470,18 +487,37 @@ xdr_dir(xdrsp, dirp)
}
/*
* Xdr routine to generate fhstatus
* Xdr routine to generate file handle reply
*/
int
xdr_fhs(xdrsp, nfh)
xdr_fhs(xdrsp, cp)
XDR *xdrsp;
nfsv2fh_t *nfh;
caddr_t cp;
{
u_long ok = 0;
register struct fhreturn *fhrp = (struct fhreturn *)cp;
u_long ok = 0, len, auth;
if (!xdr_long(xdrsp, &ok))
return (0);
return (xdr_opaque(xdrsp, (caddr_t)nfh, NFSX_FH));
switch (fhrp->fhr_vers) {
case 1:
return (xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, NFSX_V2FH));
case 3:
len = NFSX_V3FH;
if (!xdr_long(xdrsp, &len))
return (0);
if (!xdr_opaque(xdrsp, (caddr_t)&fhrp->fhr_fh, len))
return (0);
if (fhrp->fhr_flag & DP_KERB)
auth = RPCAUTH_KERB4;
else
auth = RPCAUTH_UNIX;
len = 1;
if (!xdr_long(xdrsp, &len))
return (0);
return (xdr_long(xdrsp, &auth));
};
return (0);
}
int
@ -521,9 +557,12 @@ xdr_explist(xdrsp, cp)
{
struct exportlist *ep;
int false = 0;
int omask, putdef;
int putdef;
sigset_t sighup_mask;
omask = sigblock(sigmask(SIGHUP));
sigemptyset(&sighup_mask);
sigaddset(&sighup_mask, SIGHUP);
sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
ep = exphead;
while (ep) {
putdef = 0;
@ -535,12 +574,12 @@ xdr_explist(xdrsp, cp)
goto errout;
ep = ep->ex_next;
}
sigsetmask(omask);
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
if (!xdr_bool(xdrsp, &false))
return (0);
return (1);
errout:
sigsetmask(omask);
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
return (0);
}
@ -660,6 +699,18 @@ get_exportlist()
struct ufs_args ua;
struct iso_args ia;
struct mfs_args ma;
#ifdef __NetBSD__
struct msdosfs_args da;
} targs;
if (!strcmp(fsp->f_fstypename, MOUNT_MFS) ||
!strcmp(fsp->f_fstypename, MOUNT_UFS) ||
!strcmp(fsp->f_fstypename, MOUNT_MSDOS) ||
!strcmp(fsp->f_fstypename, MOUNT_CD9660)) {
targs.ua.fspec = NULL;
targs.ua.export.ex_flags = MNT_DELEXPORT;
if (mount(fsp->f_fstypename, fsp->f_mntonname,
#else
} targs;
switch (fsp->f_type) {
@ -670,6 +721,7 @@ get_exportlist()
targs.ua.fspec = NULL;
targs.ua.export.ex_flags = MNT_DELEXPORT;
if (mount(fsp->f_type, fsp->f_mntonname,
#endif
fsp->f_flags | MNT_UPDATE,
(caddr_t)&targs) < 0)
syslog(LOG_ERR, "Can't delete exports for %s",
@ -805,6 +857,7 @@ get_exportlist()
if (get_host(hst, grp, tgrp)) {
syslog(LOG_ERR, "Bad netgroup %s", cp);
getexp_err(ep, tgrp);
endnetgrent();
goto nextline;
}
} else if (get_host(cp, grp, tgrp)) {
@ -865,12 +918,12 @@ get_exportlist()
* Success. Update the data structures.
*/
if (has_host) {
hang_dirp(dirhead, tgrp, ep, (opt_flags & OP_ALLDIRS));
hang_dirp(dirhead, tgrp, ep, opt_flags);
grp->gr_next = grphead;
grphead = tgrp;
} else {
hang_dirp(dirhead, (struct grouplist *)NULL, ep,
(opt_flags & OP_ALLDIRS));
opt_flags);
free_grp(grp);
}
dirhead = (struct dirlist *)NULL;
@ -994,24 +1047,28 @@ add_expdir(dpp, cp, len)
* and update the entry for host.
*/
void
hang_dirp(dp, grp, ep, alldirs)
hang_dirp(dp, grp, ep, flags)
struct dirlist *dp;
struct grouplist *grp;
struct exportlist *ep;
int alldirs;
int flags;
{
struct hostlist *hp;
struct dirlist *dp2;
if (alldirs) {
if (flags & OP_ALLDIRS) {
if (ep->ex_defdir)
free((caddr_t)dp);
else
ep->ex_defdir = dp;
if (grp == (struct grouplist *)NULL)
if (grp == (struct grouplist *)NULL) {
ep->ex_defdir->dp_flag |= DP_DEFSET;
else while (grp) {
if (flags & OP_KERB)
ep->ex_defdir->dp_flag |= DP_KERB;
} else while (grp) {
hp = get_ht();
if (flags & OP_KERB)
hp->ht_flag |= DP_KERB;
hp->ht_grp = grp;
hp->ht_next = ep->ex_defdir->dp_hosts;
ep->ex_defdir->dp_hosts = hp;
@ -1024,7 +1081,7 @@ hang_dirp(dp, grp, ep, alldirs)
*/
while (dp) {
dp2 = dp->dp_left;
add_dlist(&ep->ex_dirl, dp, grp);
add_dlist(&ep->ex_dirl, dp, grp, flags);
dp = dp2;
}
}
@ -1035,10 +1092,11 @@ hang_dirp(dp, grp, ep, alldirs)
* for the new directory or adding the new node.
*/
void
add_dlist(dpp, newdp, grp)
add_dlist(dpp, newdp, grp, flags)
struct dirlist **dpp;
struct dirlist *newdp;
struct grouplist *grp;
int flags;
{
struct dirlist *dp;
struct hostlist *hp;
@ -1048,10 +1106,10 @@ add_dlist(dpp, newdp, grp)
if (dp) {
cmp = strcmp(dp->dp_dirp, newdp->dp_dirp);
if (cmp > 0) {
add_dlist(&dp->dp_left, newdp, grp);
add_dlist(&dp->dp_left, newdp, grp, flags);
return;
} else if (cmp < 0) {
add_dlist(&dp->dp_right, newdp, grp);
add_dlist(&dp->dp_right, newdp, grp, flags);
return;
} else
free((caddr_t)newdp);
@ -1067,13 +1125,18 @@ add_dlist(dpp, newdp, grp)
*/
do {
hp = get_ht();
if (flags & OP_KERB)
hp->ht_flag |= DP_KERB;
hp->ht_grp = grp;
hp->ht_next = dp->dp_hosts;
dp->dp_hosts = hp;
grp = grp->gr_next;
} while (grp);
} else
} else {
dp->dp_flag |= DP_DEFSET;
if (flags & OP_KERB)
dp->dp_flag |= DP_KERB;
}
}
/*
@ -1102,10 +1165,11 @@ dirp_search(dp, dirpath)
* Scan for a host match in a directory tree.
*/
int
chk_host(dp, saddr, defsetp)
chk_host(dp, saddr, defsetp, hostsetp)
struct dirlist *dp;
u_long saddr;
int *defsetp;
int *hostsetp;
{
struct hostlist *hp;
struct grouplist *grp;
@ -1113,7 +1177,7 @@ chk_host(dp, saddr, defsetp)
if (dp) {
if (dp->dp_flag & DP_DEFSET)
*defsetp = 1;
*defsetp = dp->dp_flag;
hp = dp->dp_hosts;
while (hp) {
grp = hp->ht_grp;
@ -1122,15 +1186,19 @@ chk_host(dp, saddr, defsetp)
addrp = (u_long **)
grp->gr_ptr.gt_hostent->h_addr_list;
while (*addrp) {
if (**addrp == saddr)
if (**addrp == saddr) {
*hostsetp = (hp->ht_flag | DP_HOSTSET);
return (1);
}
addrp++;
}
break;
case GT_NET:
if ((saddr & grp->gr_ptr.gt_net.nt_mask) ==
grp->gr_ptr.gt_net.nt_net)
grp->gr_ptr.gt_net.nt_net) {
*hostsetp = (hp->ht_flag | DP_HOSTSET);
return (1);
}
break;
};
hp = hp->ht_next;
@ -1147,12 +1215,12 @@ scan_tree(dp, saddr)
struct dirlist *dp;
u_long saddr;
{
int defset;
int defset, hostset;
if (dp) {
if (scan_tree(dp->dp_left, saddr))
return (1);
if (chk_host(dp, saddr, &defset))
if (chk_host(dp, saddr, &defset, &hostset))
return (1);
if (scan_tree(dp->dp_right, saddr))
return (1);
@ -1312,7 +1380,7 @@ get_host(cp, grp, tgrp)
if (isdigit(*cp)) {
saddr = inet_addr(cp);
if (saddr == -1) {
syslog(LOG_ERR, "Inet_addr failed");
syslog(LOG_ERR, "Inet_addr failed for %s", cp);
return (1);
}
if ((hp = gethostbyaddr((caddr_t)&saddr, sizeof (saddr),
@ -1326,7 +1394,7 @@ get_host(cp, grp, tgrp)
aptr[1] = (char *)NULL;
}
} else {
syslog(LOG_ERR, "Gethostbyname failed");
syslog(LOG_ERR, "Gethostbyname failed for %s", cp);
return (1);
}
}
@ -1424,6 +1492,7 @@ get_ht()
if (hp == (struct hostlist *)NULL)
out_of_mem();
hp->ht_next = (struct hostlist *)NULL;
hp->ht_flag = 0;
return (hp);
}
@ -1494,6 +1563,9 @@ do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb)
struct ufs_args ua;
struct iso_args ia;
struct mfs_args ma;
#ifdef __NetBSD__
struct msdosfs_args da;
#endif
} args;
u_long net;
@ -1569,7 +1641,11 @@ do_mount(ep, grp, exflags, anoncrp, dirp, dirplen, fsb)
* Also, needs to know how to export all types of local
* exportable file systems and not just MOUNT_UFS.
*/
#ifdef __NetBSD__
while (mount(fsb->f_fstypename, dirp,
#else
while (mount(fsb->f_type, dirp,
#endif
fsb->f_flags | MNT_UPDATE, (caddr_t)&args) < 0) {
if (cp)
*cp-- = savedc;
@ -2033,15 +2109,30 @@ check_dirpath(dirp)
while (*cp && ret) {
if (*cp == '/') {
*cp = '\0';
if (lstat(dirp, &sb) < 0 ||
(sb.st_mode & S_IFMT) != S_IFDIR)
if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode))
ret = 0;
*cp = '/';
}
cp++;
}
if (lstat(dirp, &sb) < 0 ||
(sb.st_mode & S_IFMT) != S_IFDIR)
if (lstat(dirp, &sb) < 0 || !S_ISDIR(sb.st_mode))
ret = 0;
return (ret);
}
/*
* Just translate an ascii string to an integer.
*/
int
get_num(cp)
register char *cp;
{
register int res = 0;
while (*cp) {
if (*cp < '0' || *cp > '9')
return (-1);
res = res * 10 + (*cp++ - '0');
}
return (res);
}

View File

@ -98,7 +98,8 @@ listens for service requests at the port indicated in the
.Tn NFS
server specification; see
.%T "Network File System Protocol Specification" ,
RFC1094.
RFC1094 and
.%T "NFS: Network File System Version 3 Protocol Specification" .
.Pp
If
.Nm nfsd

View File

@ -63,10 +63,10 @@ static char sccsid[] = "@(#)nfsd.c 8.7 (Berkeley) 2/22/94";
#include <netiso/iso.h>
#endif
#include <nfs/rpcv2.h>
#include <nfs/nfsv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfs.h>
#ifdef KERBEROS
#ifdef NFSKERB
#include <kerberosIV/des.h>
#include <kerberosIV/krb.h>
#endif
@ -94,16 +94,23 @@ struct nfsd_srvargs nsd;
char **Argv = NULL; /* pointer to argument vector */
char *LastArg = NULL; /* end of argv */
#ifdef KERBEROS
#ifdef NFSKERB
char lnam[ANAME_SZ];
KTEXT_ST kt;
AUTH_DAT auth;
AUTH_DAT kauth;
char inst[INST_SZ];
struct nfsrpc_fullblock kin, kout;
struct nfsrpc_fullverf kverf;
NFSKERBKEY_T kivec;
struct timeval ktv;
NFSKERBKEYSCHED_T kerb_keysched;
#endif
void nonfs __P((int));
void reapchild __P((int));
#ifdef __FreeBSD__
void setproctitle __P((char *));
#endif
void usage __P((void));
/*
@ -139,11 +146,13 @@ main(argc, argv, envp)
#ifdef ISO
struct sockaddr_iso isoaddr, isopeer;
#endif
struct timeval ktv;
fd_set ready, sockbits;
int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock;
int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock;
int tp4cnt, tp4flag, tp4sock, tpipcnt, tpipflag, tpipsock, udpflag;
char *cp, **cpp;
#ifdef __FreeBSD__
struct vfsconf *vfc;
vfc = getvfsbyname("nfs");
@ -156,6 +165,7 @@ main(argc, argv, envp)
if(!vfc) {
errx(1, "NFS is not available in the running kernel");
}
#endif
/* Save start and extent of argv for setproctitle. */
Argv = argv;
@ -241,10 +251,12 @@ main(argc, argv, envp)
if (reregister) {
if (udpflag &&
!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT))
(!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
!pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)))
err(1, "can't register with portmap for UDP.");
if (tcpflag &&
!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT))
(!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
!pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)))
err(1, "can't register with portmap for TCP.");
exit(0);
}
@ -261,11 +273,17 @@ main(argc, argv, envp)
continue;
}
setproctitle("nfsd-srv");
setproctitle("server");
nfssvc_flag = NFSSVC_NFSD;
nsd.nsd_nfsd = NULL;
#ifdef KERBEROS
nsd.nsd_authstr = (char *)kt.dat;
#ifdef NFSKERB
if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF ||
sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK)
syslog(LOG_ERR, "Yikes NFSKERB structs not packed!");
nsd.nsd_authstr = (u_char *)&kt;
nsd.nsd_authlen = sizeof (kt);
nsd.nsd_verfstr = (u_char *)&kverf;
nsd.nsd_verflen = sizeof (kverf);
#endif
while (nfssvc(nfssvc_flag, &nsd) < 0) {
if (errno != ENEEDAUTH) {
@ -273,14 +291,27 @@ main(argc, argv, envp)
exit(1);
}
nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL;
#ifdef KERBEROS
kt.length = nsd.nsd_authlen;
kt.mbz = 0;
(void)strcpy(inst, "*");
if (krb_rd_req(&kt, "rcmd",
inst, nsd.nsd_haddr, &auth, "") == RD_AP_OK &&
krb_kntoln(&auth, lnam) == KSUCCESS &&
(pwd = getpwnam(lnam)) != NULL) {
#ifdef NFSKERB
/*
* Get the Kerberos ticket out of the authenticator
* verify it and convert the principal name to a user
* name. The user name is then converted to a set of
* user credentials via the password and group file.
* Finally, decrypt the timestamp and validate it.
* For more info see the IETF Draft "Authentication
* in ONC RPC".
*/
kt.length = ntohl(kt.length);
if (gettimeofday(&ktv, (struct timezone *)0) == 0 &&
kt.length > 0 && kt.length <=
(RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) {
kin.w1 = NFS_KERBW1(kt);
kt.mbz = 0;
(void)strcpy(inst, "*");
if (krb_rd_req(&kt, NFS_KERBSRV,
inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK &&
krb_kntoln(&kauth, lnam) == KSUCCESS &&
(pwd = getpwnam(lnam)) != NULL) {
cr = &nsd.nsd_cr;
cr->cr_uid = pwd->pw_uid;
cr->cr_groups[0] = pwd->pw_gid;
@ -301,9 +332,34 @@ main(argc, argv, envp)
break;
}
endgrent();
nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
/*
* Get the timestamp verifier out of the
* authenticator and verifier strings.
*/
kin.t1 = kverf.t1;
kin.t2 = kverf.t2;
kin.w2 = kverf.w2;
bzero((caddr_t)kivec, sizeof (kivec));
bcopy((caddr_t)kauth.session,
(caddr_t)nsd.nsd_key,sizeof(kauth.session));
/*
* Decrypt the timestamp verifier in CBC mode.
*/
XXX
/*
* Validate the timestamp verifier, to
* check that the session key is ok.
*/
nsd.nsd_timestamp.tv_sec = ntohl(kout.t1);
nsd.nsd_timestamp.tv_usec = ntohl(kout.t2);
nsd.nsd_ttl = ntohl(kout.w1);
if ((nsd.nsd_ttl - 1) == ntohl(kout.w2))
nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN;
}
#endif /* KERBEROS */
#endif /* NFSKERB */
}
exit(0);
}
@ -323,7 +379,8 @@ main(argc, argv, envp)
syslog(LOG_ERR, "can't bind udp addr");
exit(1);
}
if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) {
if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) ||
!pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) {
syslog(LOG_ERR, "can't register with udp portmap");
exit(1);
}
@ -403,7 +460,8 @@ main(argc, argv, envp)
syslog(LOG_ERR, "listen failed");
exit(1);
}
if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) {
if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) ||
!pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) {
syslog(LOG_ERR, "can't register tcp with portmap");
exit(1);
}
@ -492,7 +550,7 @@ main(argc, argv, envp)
if (connect_type_cnt == 0)
exit(0);
setproctitle("nfsd-master");
setproctitle("master");
/*
* Loop forever accepting connections and passing the sockets
@ -566,7 +624,7 @@ main(argc, argv, envp)
void
usage()
{
(void)fprintf(stderr, "nfsd %s\n", USAGE);
(void)fprintf(stderr, "usage: nfsd %s\n", USAGE);
exit(1);
}
@ -582,9 +640,10 @@ reapchild(signo)
int signo;
{
while (wait3(NULL, WNOHANG, NULL));
while (wait3(NULL, WNOHANG, NULL) > 0);
}
#ifdef __FreeBSD__
void
setproctitle(a)
char *a;
@ -593,9 +652,10 @@ setproctitle(a)
char buf[80];
cp = Argv[0];
(void)snprintf(buf, sizeof(buf), "%s", a);
(void)snprintf(buf, sizeof(buf), "nfsd-%s", a);
(void)strncpy(cp, buf, LastArg - cp);
cp += strlen(cp);
while (cp < LastArg)
*cp++ = '\0';
}
#endif /* __FreeBSD__ */

View File

@ -54,6 +54,8 @@ static char sccsid[] = "@(#)pstat.c 8.9 (Berkeley) 2/16/94";
#undef NFS
#undef KERNEL
#include <sys/stat.h>
#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfs/nfsnode.h>
#include <sys/ioctl.h>
#include <sys/ioctl_compat.h> /* XXX NTTYDISC is too well hidden */