summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordfr <dfr@FreeBSD.org>2009-06-30 19:03:27 +0000
committerdfr <dfr@FreeBSD.org>2009-06-30 19:03:27 +0000
commit5d248bb05f33623d905b8b5a72d90e459d23be96 (patch)
treeb34567acfe860cb1978c433954c8376efa8a9fbb
parent92b2f1511851bf5a137742d90131b79d0ff4c1ff (diff)
downloadFreeBSD-src-5d248bb05f33623d905b8b5a72d90e459d23be96.zip
FreeBSD-src-5d248bb05f33623d905b8b5a72d90e459d23be96.tar.gz
Remove the old kernel RPC implementation and the NFS_LEGACYRPC option.
Approved by: re
-rw-r--r--sys/conf/files4
-rw-r--r--sys/conf/options5
-rw-r--r--sys/i386/i386/genassym.c1
-rw-r--r--sys/modules/nfsclient/Makefile2
-rw-r--r--sys/modules/nfsserver/Makefile4
-rw-r--r--sys/nfs/nfs_common.c1
-rw-r--r--sys/nfs/rpcv2.h108
-rw-r--r--sys/nfsclient/bootp_subr.c10
-rw-r--r--sys/nfsclient/krpc_subr.c10
-rw-r--r--sys/nfsclient/nfs.h61
-rw-r--r--sys/nfsclient/nfs_bio.c1
-rw-r--r--sys/nfsclient/nfs_diskless.c1
-rw-r--r--sys/nfsclient/nfs_krpc.c5
-rw-r--r--sys/nfsclient/nfs_lock.c1
-rw-r--r--sys/nfsclient/nfs_nfsiod.c1
-rw-r--r--sys/nfsclient/nfs_node.c1
-rw-r--r--sys/nfsclient/nfs_socket.c1977
-rw-r--r--sys/nfsclient/nfs_subs.c108
-rw-r--r--sys/nfsclient/nfs_vfsops.c17
-rw-r--r--sys/nfsclient/nfs_vnops.c3
-rw-r--r--sys/nfsclient/nfsm_subs.h4
-rw-r--r--sys/nfsclient/nfsmount.h40
-rw-r--r--sys/nfsserver/nfs.h133
-rw-r--r--sys/nfsserver/nfs_fha.c5
-rw-r--r--sys/nfsserver/nfs_serv.c424
-rw-r--r--sys/nfsserver/nfs_srvcache.c391
-rw-r--r--sys/nfsserver/nfs_srvkrpc.c5
-rw-r--r--sys/nfsserver/nfs_srvsock.c818
-rw-r--r--sys/nfsserver/nfs_srvsubs.c86
-rw-r--r--sys/nfsserver/nfs_syscalls.c723
-rw-r--r--sys/nfsserver/nfsrvcache.h42
31 files changed, 23 insertions, 4969 deletions
diff --git a/sys/conf/files b/sys/conf/files
index 4e7bb5f..c582d56 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -2490,7 +2490,6 @@ nfsclient/krpc_subr.c optional bootp nfsclient
nfsclient/nfs_bio.c optional nfsclient
nfsclient/nfs_diskless.c optional nfsclient nfs_root
nfsclient/nfs_node.c optional nfsclient
-nfsclient/nfs_socket.c optional nfsclient
nfsclient/nfs_krpc.c optional nfsclient
nfsclient/nfs_subs.c optional nfsclient
nfsclient/nfs_nfsiod.c optional nfsclient
@@ -2500,10 +2499,7 @@ nfsclient/nfs_lock.c optional nfsclient
nfsserver/nfs_fha.c optional nfsserver
nfsserver/nfs_serv.c optional nfsserver
nfsserver/nfs_srvkrpc.c optional nfsserver
-nfsserver/nfs_srvsock.c optional nfsserver
-nfsserver/nfs_srvcache.c optional nfsserver
nfsserver/nfs_srvsubs.c optional nfsserver
-nfsserver/nfs_syscalls.c optional nfsserver
nfs/nfs_nfssvc.c optional nfsserver | nfscl | nfsd
nlm/nlm_advlock.c optional nfslockd nfsclient | nfsd nfsclient
nlm/nlm_prot_clnt.c optional nfslockd | nfsd
diff --git a/sys/conf/options b/sys/conf/options
index 1995420..be59f53 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -228,11 +228,6 @@ KGSSAPI_DEBUG opt_kgssapi.h
NFSCLIENT opt_nfs.h
NFSSERVER opt_nfs.h
-# Use this option to compile both NFS client and server using the
-# legacy RPC implementation instead of the newer KRPC system (which
-# supports modern features such as RPCSEC_GSS
-NFS_LEGACYRPC opt_nfs.h
-
# Use these options to compile the experimental nfs client and/or
# server that supports NFSv4 into a kernel.
# NFSCL - client
diff --git a/sys/i386/i386/genassym.c b/sys/i386/i386/genassym.c
index 7c6acf0..46fd67e 100644
--- a/sys/i386/i386/genassym.c
+++ b/sys/i386/i386/genassym.c
@@ -67,7 +67,6 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <netinet/in.h>
#include <nfs/nfsproto.h>
-#include <nfs/rpcv2.h>
#include <nfsclient/nfs.h>
#include <nfsclient/nfsdiskless.h>
#ifdef DEV_APIC
diff --git a/sys/modules/nfsclient/Makefile b/sys/modules/nfsclient/Makefile
index cab161f..c53e3d5 100644
--- a/sys/modules/nfsclient/Makefile
+++ b/sys/modules/nfsclient/Makefile
@@ -4,7 +4,7 @@
KMOD= nfsclient
SRCS= vnode_if.h \
- nfs_bio.c nfs_lock.c nfs_node.c nfs_socket.c nfs_subs.c nfs_nfsiod.c \
+ nfs_bio.c nfs_lock.c nfs_node.c nfs_subs.c nfs_nfsiod.c \
nfs_vfsops.c nfs_vnops.c nfs_common.c nfs_krpc.c \
opt_inet.h opt_nfs.h opt_bootp.h opt_nfsroot.h
SRCS+= opt_inet6.h opt_kdtrace.h opt_kgssapi.h
diff --git a/sys/modules/nfsserver/Makefile b/sys/modules/nfsserver/Makefile
index a85d29c..692179b 100644
--- a/sys/modules/nfsserver/Makefile
+++ b/sys/modules/nfsserver/Makefile
@@ -3,8 +3,8 @@
.PATH: ${.CURDIR}/../../nfsserver ${.CURDIR}/../../nfs
KMOD= nfsserver
SRCS= vnode_if.h \
- nfs_fha.c nfs_serv.c nfs_srvkrpc.c nfs_srvsock.c nfs_srvcache.c \
- nfs_srvsubs.c nfs_syscalls.c nfs_common.c \
+ nfs_fha.c nfs_serv.c nfs_srvkrpc.c nfs_srvsubs.c nfs_common.c \
+ opt_mac.h \
opt_kgssapi.h \
opt_nfs.h
SRCS+= opt_inet6.h
diff --git a/sys/nfs/nfs_common.c b/sys/nfs/nfs_common.c
index faa9302..0869309 100644
--- a/sys/nfs/nfs_common.c
+++ b/sys/nfs/nfs_common.c
@@ -61,7 +61,6 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_object.h>
#include <vm/vm_extern.h>
-#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsserver/nfs.h>
#include <nfs/xdr_subs.h>
diff --git a/sys/nfs/rpcv2.h b/sys/nfs/rpcv2.h
deleted file mode 100644
index 0d7935f..0000000
--- a/sys/nfs/rpcv2.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*-
- * 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.
- * 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.
- *
- * @(#)rpcv2.h 8.2 (Berkeley) 3/30/95
- * $FreeBSD$
- */
-
-
-#ifndef _NFS_RPCV2_H_
-#define _NFS_RPCV2_H_
-
-/*
- * Definitions for Sun RPC Version 2, from
- * "RPC: Remote Procedure Call Protocol Specification" RFC1057
- */
-
-/* Version # */
-#define RPC_VER2 2
-
-/* Authentication */
-#define RPCAUTH_NULL 0
-#define RPCAUTH_UNIX 1
-#define RPCAUTH_SHORT 2
-#define RPCAUTH_KERB4 4
-#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
-
-/* msg type */
-#define RPC_CALL 0
-#define RPC_REPLY 1
-
-/* reply status */
-#define RPC_MSGACCEPTED 0
-#define RPC_MSGDENIED 1
-
-/* accepted status */
-#define RPC_SUCCESS 0
-#define RPC_PROGUNAVAIL 1
-#define RPC_PROGMISMATCH 2
-#define RPC_PROCUNAVAIL 3
-#define RPC_GARBAGE 4 /* I like this one */
-#define RPC_SYSTEMERR 5
-
-/* rejected status */
-#define RPC_MISMATCH 0
-#define RPC_AUTHERR 1
-
-/* Authentication failures */
-#define AUTH_OK 0
-#define AUTH_BADCRED 1
-#define AUTH_REJECTCRED 2
-#define AUTH_BADVERF 3
-#define AUTH_REJECTVERF 4
-#define AUTH_TOOWEAK 5 /* Give em wheaties */
-
-/* Sizes of rpc header parts */
-#define RPC_SIZ 24
-#define RPC_REPLYSIZ 28
-
-/* RPC Prog definitions */
-#define RPCPROG_MNT 100005
-#define RPCMNT_VER1 1
-#define RPCMNT_VER3 3
-#define RPCMNT_MOUNT 1
-#define RPCMNT_DUMP 2
-#define RPCMNT_UMOUNT 3
-#define RPCMNT_UMNTALL 4
-#define RPCMNT_EXPORT 5
-#define RPCMNT_NAMELEN 255
-#define RPCMNT_PATHLEN 1024
-#define RPCPROG_NFS 100003
-
-#endif
diff --git a/sys/nfsclient/bootp_subr.c b/sys/nfsclient/bootp_subr.c
index 10fc8c4..4a4847a 100644
--- a/sys/nfsclient/bootp_subr.c
+++ b/sys/nfsclient/bootp_subr.c
@@ -68,7 +68,6 @@ __FBSDID("$FreeBSD$");
#include <net/if_dl.h>
#include <net/vnet.h>
-#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
#include <nfsclient/nfsdiskless.h>
@@ -1776,6 +1775,13 @@ md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp, int *fhsizep,
int authcount;
int authver;
+#define RPCPROG_MNT 100005
+#define RPCMNT_VER1 1
+#define RPCMNT_VER3 3
+#define RPCMNT_MOUNT 1
+#define AUTH_SYS 1 /* unix style (uid, gids) */
+#define AUTH_UNIX AUTH_SYS
+
/* XXX honor v2/v3 flags in args->flags? */
#ifdef BOOTP_NFSV3
/* First try NFS v3 */
@@ -1836,7 +1842,7 @@ md_mount(struct sockaddr_in *mdsin, char *path, u_char *fhp, int *fhsizep,
while (authcount > 0) {
if (xdr_int_decode(&m, &authver) != 0)
goto bad;
- if (authver == RPCAUTH_UNIX)
+ if (authver == AUTH_UNIX)
authunixok = 1;
authcount--;
}
diff --git a/sys/nfsclient/krpc_subr.c b/sys/nfsclient/krpc_subr.c
index 2023904..996cb05 100644
--- a/sys/nfsclient/krpc_subr.c
+++ b/sys/nfsclient/krpc_subr.c
@@ -57,7 +57,9 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <netinet/in.h>
-#include <nfs/rpcv2.h>
+#include <rpc/types.h>
+#include <rpc/auth.h>
+#include <rpc/rpc_msg.h>
#include <nfsclient/krpc.h>
#include <nfs/xdr_subs.h>
@@ -284,7 +286,7 @@ krpc_call(struct sockaddr_in *sa, u_int prog, u_int vers, u_int func,
call->rp_vers = txdr_unsigned(vers);
call->rp_proc = txdr_unsigned(func);
/* rpc_auth part (auth_unix as root) */
- call->rpc_auth.authtype = txdr_unsigned(RPCAUTH_UNIX);
+ call->rpc_auth.authtype = txdr_unsigned(AUTH_UNIX);
call->rpc_auth.authlen = txdr_unsigned(sizeof(struct auth_unix));
/* rpc_verf part (auth_null) */
call->rpc_verf.authtype = 0;
@@ -359,7 +361,7 @@ krpc_call(struct sockaddr_in *sa, u_int prog, u_int vers, u_int func,
reply = mtod(m, struct krpc_reply *);
/* Is it the right reply? */
- if (reply->rp_direction != txdr_unsigned(RPC_REPLY))
+ if (reply->rp_direction != txdr_unsigned(REPLY))
continue;
if (reply->rp_xid != txdr_unsigned(xid))
@@ -375,7 +377,7 @@ krpc_call(struct sockaddr_in *sa, u_int prog, u_int vers, u_int func,
/* Did the call succeed? */
if (reply->rp_status != 0) {
error = fxdr_unsigned(u_int32_t, reply->rp_status);
- if (error == RPC_PROGMISMATCH) {
+ if (error == PROG_MISMATCH) {
error = EBADRPC;
goto out;
}
diff --git a/sys/nfsclient/nfs.h b/sys/nfsclient/nfs.h
index 845f826..fa7d5ba 100644
--- a/sys/nfsclient/nfs.h
+++ b/sys/nfsclient/nfs.h
@@ -123,9 +123,6 @@ MALLOC_DECLARE(M_NFSDIRECTIO);
extern struct uma_zone *nfsmount_zone;
-#ifdef NFS_LEGACYRPC
-extern struct callout nfs_callout;
-#endif
extern struct nfsstats nfsstats;
extern struct mtx nfs_iod_mtx;
@@ -150,49 +147,6 @@ extern int nfsv3_procid[NFS_NPROCS];
(e) != ERESTART && (e) != EWOULDBLOCK && \
((s) & PR_CONNREQUIRED) == 0)
-#ifdef NFS_LEGACYRPC
-
-/*
- * Nfs outstanding request list element
- */
-struct nfsreq {
- TAILQ_ENTRY(nfsreq) r_chain;
- struct mbuf *r_mreq;
- struct mbuf *r_mrep;
- struct mbuf *r_md;
- caddr_t r_dpos;
- struct nfsmount *r_nmp;
- struct vnode *r_vp;
- u_int32_t r_xid;
- int r_flags; /* flags on request, see below */
- int r_retry; /* max retransmission count */
- int r_rexmit; /* current retrans count */
- int r_timer; /* tick counter on reply */
- u_int32_t r_procnum; /* NFS procedure number */
- int r_rtt; /* RTT for rpc */
- int r_lastmsg; /* last tprintf */
- struct thread *r_td; /* Proc that did I/O system call */
- struct mtx r_mtx; /* Protects nfsreq fields */
-};
-
-/*
- * Queue head for nfsreq's
- */
-extern TAILQ_HEAD(nfs_reqq, nfsreq) nfs_reqq;
-
-/* Flag values for r_flags */
-#define R_TIMING 0x01 /* timing request (in mntp) */
-#define R_SENT 0x02 /* request has been sent */
-#define R_SOFTTERM 0x04 /* soft mnt, too many retries */
-#define R_RESENDERR 0x08 /* Resend failed */
-#define R_SOCKERR 0x10 /* Fatal error on socket */
-#define R_TPRINTFMSG 0x20 /* Did a tprintf msg. */
-#define R_MUSTRESEND 0x40 /* Must resend request */
-#define R_GETONEREP 0x80 /* Probe for one reply only */
-#define R_PIN_REQ 0x100 /* Pin request down (rexmit in prog or other) */
-
-#else
-
/*
* This is only needed to keep things working while we support
* compiling for both RPC implementations.
@@ -200,8 +154,6 @@ extern TAILQ_HEAD(nfs_reqq, nfsreq) nfs_reqq;
struct nfsreq;
struct nfsmount;
-#endif
-
struct buf;
struct socket;
struct uio;
@@ -297,19 +249,6 @@ vfs_init_t nfs_init;
vfs_uninit_t nfs_uninit;
int nfs_mountroot(struct mount *mp);
-#ifdef NFS_LEGACYRPC
-#ifndef NFS4_USE_RPCCLNT
-int nfs_send(struct socket *, struct sockaddr *, struct mbuf *,
- struct nfsreq *);
-int nfs_connect_lock(struct nfsreq *);
-void nfs_connect_unlock(struct nfsreq *);
-void nfs_up(struct nfsreq *, struct nfsmount *, struct thread *,
- const char *, int);
-void nfs_down(struct nfsreq *, struct nfsmount *, struct thread *,
- const char *, int, int);
-#endif /* ! NFS4_USE_RPCCLNT */
-#endif
-
void nfs_purgecache(struct vnode *);
int nfs_vinvalbuf(struct vnode *, int, struct thread *, int);
int nfs_readrpc(struct vnode *, struct uio *, struct ucred *);
diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c
index 22e2a79..95d6e2f 100644
--- a/sys/nfsclient/nfs_bio.c
+++ b/sys/nfsclient/nfs_bio.c
@@ -57,7 +57,6 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_pager.h>
#include <vm/vnode_pager.h>
-#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
#include <nfsclient/nfsmount.h>
diff --git a/sys/nfsclient/nfs_diskless.c b/sys/nfsclient/nfs_diskless.c
index e67b073..ba7a7a1 100644
--- a/sys/nfsclient/nfs_diskless.c
+++ b/sys/nfsclient/nfs_diskless.c
@@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$");
#include <net/vnet.h>
#include <netinet/in.h>
-#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
#include <nfsclient/nfsdiskless.h>
diff --git a/sys/nfsclient/nfs_krpc.c b/sys/nfsclient/nfs_krpc.c
index 4cd6986..44b852d 100644
--- a/sys/nfsclient/nfs_krpc.c
+++ b/sys/nfsclient/nfs_krpc.c
@@ -61,7 +61,6 @@ __FBSDID("$FreeBSD$");
#include <rpc/rpc.h>
-#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
#include <nfs/xdr_subs.h>
@@ -69,8 +68,6 @@ __FBSDID("$FreeBSD$");
#include <nfsclient/nfsmount.h>
#include <nfsclient/nfsnode.h>
-#ifndef NFS_LEGACYRPC
-
#ifdef KDTRACE_HOOKS
#include <sys/dtrace_bsd.h>
@@ -899,5 +896,3 @@ nfs_up(struct nfsmount *nmp, struct thread *td, const char *msg,
} else
mtx_unlock(&nmp->nm_mtx);
}
-
-#endif /* !NFS_LEGACYRPC */
diff --git a/sys/nfsclient/nfs_lock.c b/sys/nfsclient/nfs_lock.c
index ea6649e..6bd126a 100644
--- a/sys/nfsclient/nfs_lock.c
+++ b/sys/nfsclient/nfs_lock.c
@@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
-#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
#include <nfsclient/nfsmount.h>
diff --git a/sys/nfsclient/nfs_nfsiod.c b/sys/nfsclient/nfs_nfsiod.c
index 7dc3f19..3fafa1e 100644
--- a/sys/nfsclient/nfs_nfsiod.c
+++ b/sys/nfsclient/nfs_nfsiod.c
@@ -64,7 +64,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/tcp.h>
#include <nfs/xdr_subs.h>
-#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
#include <nfsclient/nfsm_subs.h>
diff --git a/sys/nfsclient/nfs_node.c b/sys/nfsclient/nfs_node.c
index a7f00ca..f536127 100644
--- a/sys/nfsclient/nfs_node.c
+++ b/sys/nfsclient/nfs_node.c
@@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$");
#include <vm/uma.h>
-#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
#include <nfsclient/nfsnode.h>
diff --git a/sys/nfsclient/nfs_socket.c b/sys/nfsclient/nfs_socket.c
deleted file mode 100644
index 26b365c..0000000
--- a/sys/nfsclient/nfs_socket.c
+++ /dev/null
@@ -1,1977 +0,0 @@
-/*-
- * Copyright (c) 1989, 1991, 1993, 1995
- * 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.
- * 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.
- *
- * @(#)nfs_socket.c 8.5 (Berkeley) 3/30/95
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * Socket operations for use by nfs
- */
-
-#include "opt_inet6.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/proc.h>
-#include <sys/protosw.h>
-#include <sys/signalvar.h>
-#include <sys/syscallsubr.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/sysctl.h>
-#include <sys/syslog.h>
-#include <sys/vnode.h>
-
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-
-#include <nfs/rpcv2.h>
-#include <nfs/nfsproto.h>
-#include <nfsclient/nfs.h>
-#include <nfs/xdr_subs.h>
-#include <nfsclient/nfsm_subs.h>
-#include <nfsclient/nfsmount.h>
-#include <nfsclient/nfsnode.h>
-
-#ifdef NFS_LEGACYRPC
-
-#define TRUE 1
-#define FALSE 0
-
-static int nfs_realign_test;
-static int nfs_realign_count;
-static int nfs_bufpackets = 4;
-static int nfs_reconnects;
-static int nfs3_jukebox_delay = 10;
-static int nfs_skip_wcc_data_onerr = 1;
-static int fake_wchan;
-
-SYSCTL_DECL(_vfs_nfs);
-
-SYSCTL_INT(_vfs_nfs, OID_AUTO, realign_test, CTLFLAG_RW, &nfs_realign_test, 0,
- "Number of realign tests done");
-SYSCTL_INT(_vfs_nfs, OID_AUTO, realign_count, CTLFLAG_RW, &nfs_realign_count, 0,
- "Number of mbuf realignments done");
-SYSCTL_INT(_vfs_nfs, OID_AUTO, bufpackets, CTLFLAG_RW, &nfs_bufpackets, 0,
- "Buffer reservation size 2 < x < 64");
-SYSCTL_INT(_vfs_nfs, OID_AUTO, reconnects, CTLFLAG_RD, &nfs_reconnects, 0,
- "Number of times the nfs client has had to reconnect");
-SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs3_jukebox_delay, CTLFLAG_RW, &nfs3_jukebox_delay, 0,
- "Number of seconds to delay a retry after receiving EJUKEBOX");
-SYSCTL_INT(_vfs_nfs, OID_AUTO, skip_wcc_data_onerr, CTLFLAG_RW, &nfs_skip_wcc_data_onerr, 0,
- "Disable weak cache consistency checking when server returns an error");
-
-/*
- * There is a congestion window for outstanding rpcs maintained per mount
- * point. The cwnd size is adjusted in roughly the way that:
- * Van Jacobson, Congestion avoidance and Control, In "Proceedings of
- * SIGCOMM '88". ACM, August 1988.
- * describes for TCP. The cwnd size is chopped in half on a retransmit timeout
- * and incremented by 1/cwnd when each rpc reply is received and a full cwnd
- * of rpcs is in progress.
- * (The sent count and cwnd are scaled for integer arith.)
- * Variants of "slow start" were tried and were found to be too much of a
- * performance hit (ave. rtt 3 times larger),
- * I suspect due to the large rtt that nfs rpcs have.
- */
-#define NFS_CWNDSCALE 256
-#define NFS_MAXCWND (NFS_CWNDSCALE * 32)
-#define NFS_NBACKOFF 8
-static int nfs_backoff[NFS_NBACKOFF] = { 2, 4, 8, 16, 32, 64, 128, 256, };
-struct callout nfs_callout;
-
-static int nfs_msg(struct thread *, const char *, const char *, int);
-static int nfs_realign(struct mbuf **pm, int hsiz);
-static int nfs_reply(struct nfsreq *);
-static void nfs_softterm(struct nfsreq *rep);
-static int nfs_reconnect(struct nfsreq *rep);
-static int nfs_clnt_tcp_soupcall(struct socket *so, void *arg, int waitflag);
-static int nfs_clnt_udp_soupcall(struct socket *so, void *arg, int waitflag);
-
-extern struct mtx nfs_reqq_mtx;
-
-/*
- * RTT estimator
- */
-
-static enum nfs_rto_timer_t nfs_proct[NFS_NPROCS] = {
- NFS_DEFAULT_TIMER, /* NULL */
- NFS_GETATTR_TIMER, /* GETATTR */
- NFS_DEFAULT_TIMER, /* SETATTR */
- NFS_LOOKUP_TIMER, /* LOOKUP */
- NFS_GETATTR_TIMER, /* ACCESS */
- NFS_READ_TIMER, /* READLINK */
- NFS_READ_TIMER, /* READ */
- NFS_WRITE_TIMER, /* WRITE */
- NFS_DEFAULT_TIMER, /* CREATE */
- NFS_DEFAULT_TIMER, /* MKDIR */
- NFS_DEFAULT_TIMER, /* SYMLINK */
- NFS_DEFAULT_TIMER, /* MKNOD */
- NFS_DEFAULT_TIMER, /* REMOVE */
- NFS_DEFAULT_TIMER, /* RMDIR */
- NFS_DEFAULT_TIMER, /* RENAME */
- NFS_DEFAULT_TIMER, /* LINK */
- NFS_READ_TIMER, /* READDIR */
- NFS_READ_TIMER, /* READDIRPLUS */
- NFS_DEFAULT_TIMER, /* FSSTAT */
- NFS_DEFAULT_TIMER, /* FSINFO */
- NFS_DEFAULT_TIMER, /* PATHCONF */
- NFS_DEFAULT_TIMER, /* COMMIT */
- NFS_DEFAULT_TIMER, /* NOOP */
-};
-
-/*
- * Choose the correct RTT timer for this NFS procedure.
- */
-static inline enum nfs_rto_timer_t
-nfs_rto_timer(u_int32_t procnum)
-{
- return nfs_proct[procnum];
-}
-
-/*
- * Initialize the RTT estimator state for a new mount point.
- */
-static void
-nfs_init_rtt(struct nfsmount *nmp)
-{
- int i;
-
- for (i = 0; i < NFS_MAX_TIMER; i++)
- nmp->nm_srtt[i] = NFS_INITRTT;
- for (i = 0; i < NFS_MAX_TIMER; i++)
- nmp->nm_sdrtt[i] = 0;
-}
-
-/*
- * Update a mount point's RTT estimator state using data from the
- * passed-in request.
- *
- * Use a gain of 0.125 on the mean and a gain of 0.25 on the deviation.
- *
- * NB: Since the timer resolution of NFS_HZ is so course, it can often
- * result in r_rtt == 0. Since r_rtt == N means that the actual RTT is
- * between N + dt and N + 2 - dt ticks, add 1 before calculating the
- * update values.
- */
-static void
-nfs_update_rtt(struct nfsreq *rep)
-{
- int t1 = rep->r_rtt + 1;
- int index = nfs_rto_timer(rep->r_procnum) - 1;
- int *srtt = &rep->r_nmp->nm_srtt[index];
- int *sdrtt = &rep->r_nmp->nm_sdrtt[index];
-
- t1 -= *srtt >> 3;
- *srtt += t1;
- if (t1 < 0)
- t1 = -t1;
- t1 -= *sdrtt >> 2;
- *sdrtt += t1;
-}
-
-/*
- * Estimate RTO for an NFS RPC sent via an unreliable datagram.
- *
- * Use the mean and mean deviation of RTT for the appropriate type
- * of RPC for the frequent RPCs and a default for the others.
- * The justification for doing "other" this way is that these RPCs
- * happen so infrequently that timer est. would probably be stale.
- * Also, since many of these RPCs are non-idempotent, a conservative
- * timeout is desired.
- *
- * getattr, lookup - A+2D
- * read, write - A+4D
- * other - nm_timeo
- */
-static int
-nfs_estimate_rto(struct nfsmount *nmp, u_int32_t procnum)
-{
- enum nfs_rto_timer_t timer = nfs_rto_timer(procnum);
- int index = timer - 1;
- int rto;
-
- switch (timer) {
- case NFS_GETATTR_TIMER:
- case NFS_LOOKUP_TIMER:
- rto = ((nmp->nm_srtt[index] + 3) >> 2) +
- ((nmp->nm_sdrtt[index] + 1) >> 1);
- break;
- case NFS_READ_TIMER:
- case NFS_WRITE_TIMER:
- rto = ((nmp->nm_srtt[index] + 7) >> 3) +
- (nmp->nm_sdrtt[index] + 1);
- break;
- default:
- rto = nmp->nm_timeo;
- return (rto);
- }
-
- if (rto < NFS_MINRTO)
- rto = NFS_MINRTO;
- else if (rto > NFS_MAXRTO)
- rto = NFS_MAXRTO;
-
- return (rto);
-}
-
-
-/*
- * Initialize sockets and congestion for a new NFS connection.
- * We do not free the sockaddr if error.
- */
-int
-nfs_connect(struct nfsmount *nmp, struct nfsreq *rep)
-{
- struct socket *so;
- int error, rcvreserve, sndreserve;
- int pktscale;
- struct sockaddr *saddr;
- struct ucred *origcred;
- struct thread *td = curthread;
-
- /*
- * We need to establish the socket using the credentials of
- * the mountpoint. Some parts of this process (such as
- * sobind() and soconnect()) will use the curent thread's
- * credential instead of the socket credential. To work
- * around this, temporarily change the current thread's
- * credential to that of the mountpoint.
- *
- * XXX: It would be better to explicitly pass the correct
- * credential to sobind() and soconnect().
- */
- origcred = td->td_ucred;
- td->td_ucred = nmp->nm_mountp->mnt_cred;
-
- if (nmp->nm_sotype == SOCK_STREAM) {
- mtx_lock(&nmp->nm_mtx);
- nmp->nm_nfstcpstate.flags |= NFS_TCP_EXPECT_RPCMARKER;
- nmp->nm_nfstcpstate.rpcresid = 0;
- mtx_unlock(&nmp->nm_mtx);
- }
- nmp->nm_so = NULL;
- saddr = nmp->nm_nam;
- error = socreate(saddr->sa_family, &nmp->nm_so, nmp->nm_sotype,
- nmp->nm_soproto, nmp->nm_mountp->mnt_cred, td);
- if (error)
- goto bad;
- so = nmp->nm_so;
- nmp->nm_soflags = so->so_proto->pr_flags;
-
- /*
- * Some servers require that the client port be a reserved port number.
- */
- if (nmp->nm_flag & NFSMNT_RESVPORT) {
- struct sockopt sopt;
- int ip, ip2, len;
- struct sockaddr_in6 ssin;
- struct sockaddr *sa;
-
- bzero(&sopt, sizeof sopt);
- switch(saddr->sa_family) {
- case AF_INET:
- sopt.sopt_level = IPPROTO_IP;
- sopt.sopt_name = IP_PORTRANGE;
- ip = IP_PORTRANGE_LOW;
- ip2 = IP_PORTRANGE_DEFAULT;
- len = sizeof (struct sockaddr_in);
- break;
-#ifdef INET6
- case AF_INET6:
- sopt.sopt_level = IPPROTO_IPV6;
- sopt.sopt_name = IPV6_PORTRANGE;
- ip = IPV6_PORTRANGE_LOW;
- ip2 = IPV6_PORTRANGE_DEFAULT;
- len = sizeof (struct sockaddr_in6);
- break;
-#endif
- default:
- goto noresvport;
- }
- sa = (struct sockaddr *)&ssin;
- bzero(sa, len);
- sa->sa_len = len;
- sa->sa_family = saddr->sa_family;
- sopt.sopt_dir = SOPT_SET;
- sopt.sopt_val = (void *)&ip;
- sopt.sopt_valsize = sizeof(ip);
- error = sosetopt(so, &sopt);
- if (error)
- goto bad;
- error = sobind(so, sa, td);
- if (error)
- goto bad;
- ip = ip2;
- error = sosetopt(so, &sopt);
- if (error)
- goto bad;
- noresvport: ;
- }
-
- /*
- * Protocols that do not require connections may be optionally left
- * unconnected for servers that reply from a port other than NFS_PORT.
- */
- mtx_lock(&nmp->nm_mtx);
- if (nmp->nm_flag & NFSMNT_NOCONN) {
- if (nmp->nm_soflags & PR_CONNREQUIRED) {
- error = ENOTCONN;
- mtx_unlock(&nmp->nm_mtx);
- goto bad;
- } else
- mtx_unlock(&nmp->nm_mtx);
- } else {
- mtx_unlock(&nmp->nm_mtx);
- error = soconnect(so, nmp->nm_nam, td);
- if (error)
- goto bad;
-
- /*
- * Wait for the connection to complete. Cribbed from the
- * connect system call but with the wait timing out so
- * that interruptible mounts don't hang here for a long time.
- */
- SOCK_LOCK(so);
- while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
- (void) msleep(&so->so_timeo, SOCK_MTX(so),
- PSOCK, "nfscon", 2 * hz);
- if ((so->so_state & SS_ISCONNECTING) &&
- so->so_error == 0 && rep &&
- (error = nfs_sigintr(nmp, rep, rep->r_td)) != 0) {
- so->so_state &= ~SS_ISCONNECTING;
- SOCK_UNLOCK(so);
- goto bad;
- }
- }
- if (so->so_error) {
- error = so->so_error;
- so->so_error = 0;
- SOCK_UNLOCK(so);
- goto bad;
- }
- SOCK_UNLOCK(so);
- }
- so->so_rcv.sb_timeo = 12 * hz;
- if (nmp->nm_sotype == SOCK_STREAM)
- so->so_snd.sb_timeo = 1 * hz; /* 1s snd timeout for NFS/TCP */
- else
- so->so_snd.sb_timeo = 5 * hz;
-
- /*
- * Get buffer reservation size from sysctl, but impose reasonable
- * limits.
- */
- pktscale = nfs_bufpackets;
- if (pktscale < 2)
- pktscale = 2;
- if (pktscale > 64)
- pktscale = 64;
- mtx_lock(&nmp->nm_mtx);
- if (nmp->nm_sotype == SOCK_DGRAM) {
- sndreserve = (nmp->nm_wsize + NFS_MAXPKTHDR) * pktscale;
- rcvreserve = (max(nmp->nm_rsize, nmp->nm_readdirsize) +
- NFS_MAXPKTHDR) * pktscale;
- } else if (nmp->nm_sotype == SOCK_SEQPACKET) {
- sndreserve = (nmp->nm_wsize + NFS_MAXPKTHDR) * pktscale;
- rcvreserve = (max(nmp->nm_rsize, nmp->nm_readdirsize) +
- NFS_MAXPKTHDR) * pktscale;
- } else {
- if (nmp->nm_sotype != SOCK_STREAM)
- panic("nfscon sotype");
- if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
- struct sockopt sopt;
- int val;
-
- bzero(&sopt, sizeof sopt);
- sopt.sopt_dir = SOPT_SET;
- sopt.sopt_level = SOL_SOCKET;
- sopt.sopt_name = SO_KEEPALIVE;
- sopt.sopt_val = &val;
- sopt.sopt_valsize = sizeof val;
- val = 1;
- mtx_unlock(&nmp->nm_mtx);
- sosetopt(so, &sopt);
- mtx_lock(&nmp->nm_mtx);
- }
- if (so->so_proto->pr_protocol == IPPROTO_TCP) {
- struct sockopt sopt;
- int val;
-
- bzero(&sopt, sizeof sopt);
- sopt.sopt_dir = SOPT_SET;
- sopt.sopt_level = IPPROTO_TCP;
- sopt.sopt_name = TCP_NODELAY;
- sopt.sopt_val = &val;
- sopt.sopt_valsize = sizeof val;
- val = 1;
- mtx_unlock(&nmp->nm_mtx);
- sosetopt(so, &sopt);
- mtx_lock(&nmp->nm_mtx);
- }
- sndreserve = (nmp->nm_wsize + NFS_MAXPKTHDR +
- sizeof (u_int32_t)) * pktscale;
- rcvreserve = (nmp->nm_rsize + NFS_MAXPKTHDR +
- sizeof (u_int32_t)) * pktscale;
- }
- mtx_unlock(&nmp->nm_mtx);
- error = soreserve(so, sndreserve, rcvreserve);
- if (error)
- goto bad;
- SOCKBUF_LOCK(&so->so_rcv);
- so->so_rcv.sb_flags |= SB_NOINTR;
- if (so->so_type == SOCK_STREAM)
- soupcall_set(so, SO_RCV, nfs_clnt_tcp_soupcall, nmp);
- else
- soupcall_set(so, SO_RCV, nfs_clnt_udp_soupcall, nmp);
- SOCKBUF_UNLOCK(&so->so_rcv);
- SOCKBUF_LOCK(&so->so_snd);
- so->so_snd.sb_flags |= SB_NOINTR;
- SOCKBUF_UNLOCK(&so->so_snd);
-
- /* Restore current thread's credentials. */
- td->td_ucred = origcred;
-
- mtx_lock(&nmp->nm_mtx);
- /* Initialize other non-zero congestion variables */
- nfs_init_rtt(nmp);
- nmp->nm_cwnd = NFS_MAXCWND / 2; /* Initial send window */
- nmp->nm_sent = 0;
- nmp->nm_timeouts = 0;
- mtx_unlock(&nmp->nm_mtx);
- return (0);
-
-bad:
- /* Restore current thread's credentials. */
- td->td_ucred = origcred;
-
- nfs_disconnect(nmp);
- return (error);
-}
-
-static void
-nfs_wakup_reconnectors(struct nfsmount *nmp)
-{
- KASSERT(mtx_owned(&nmp->nm_mtx), ("NFS mnt lock not owned !"));
- if (--nmp->nm_nfstcpstate.sock_send_inprog == 0 &&
- (nmp->nm_nfstcpstate.flags & NFS_TCP_WAIT_WRITE_DRAIN)) {
- nmp->nm_nfstcpstate.flags &= ~NFS_TCP_WAIT_WRITE_DRAIN;
- wakeup((caddr_t)&nmp->nm_nfstcpstate.sock_send_inprog);
- }
-}
-
-/*
- * Reconnect routine:
- * Called when a connection is broken on a reliable protocol.
- * - clean up the old socket
- * - nfs_connect() again
- * - set R_MUSTRESEND for all outstanding requests on mount point
- * If this fails the mount point is DEAD!
- * nb: Must be called with the nfs_sndlock() set on the mount point.
- */
-static int
-nfs_reconnect(struct nfsreq *rep)
-{
- struct nfsreq *rp;
- struct nfsmount *nmp = rep->r_nmp;
- int error;
- int slpflag = 0;
-
- KASSERT(mtx_owned(&nmp->nm_mtx), ("NFS mnt lock not owned !"));
- if (nmp->nm_flag & NFSMNT_INT)
- slpflag = PCATCH;
- /*
- * Wait for any pending writes to this socket to drain (or timeout).
- */
- while (nmp->nm_nfstcpstate.sock_send_inprog > 0) {
- nmp->nm_nfstcpstate.flags |= NFS_TCP_WAIT_WRITE_DRAIN;
- error = msleep((caddr_t)&nmp->nm_nfstcpstate.sock_send_inprog,
- &nmp->nm_mtx, slpflag | (PZERO - 1), "nfscon", 0);
- }
- /*
- * Grab the nfs_connect_lock to serialize connects.
- * After grabbing the nfs_connect_lock, check if a reconnect is necessary or
- * if someone else beat us to the connect !
- */
- error = nfs_connect_lock(rep);
- if (error)
- goto unlock_exit;
- if ((nmp->nm_nfstcpstate.flags & NFS_TCP_FORCE_RECONNECT) == 0)
- goto unlock_exit;
- else
- mtx_unlock(&nmp->nm_mtx);
-
- nfs_reconnects++;
- nfs_disconnect(nmp);
- while ((error = nfs_connect(nmp, rep)) != 0) {
- if (error == ERESTART)
- error = EINTR;
- if (error == EIO || error == EINTR) {
- mtx_lock(&nmp->nm_mtx);
- goto unlock_exit;
- }
- (void) tsleep(&fake_wchan, PSOCK, "nfscon", hz);
- }
-
- /*
- * Clear the FORCE_RECONNECT flag only after the connect
- * succeeds. To prevent races between multiple processes
- * waiting on the mountpoint where the connection is being
- * torn down. The first one to acquire the sndlock will
- * retry the connection. The others block on the sndlock
- * until the connection is established successfully, and
- * then re-transmit the request.
- */
- mtx_lock(&nmp->nm_mtx);
- nmp->nm_nfstcpstate.flags &= ~NFS_TCP_FORCE_RECONNECT;
- nmp->nm_nfstcpstate.rpcresid = 0;
- mtx_unlock(&nmp->nm_mtx);
-
- /*
- * Loop through outstanding request list and fix up all requests
- * on old socket.
- */
- mtx_lock(&nfs_reqq_mtx);
- TAILQ_FOREACH(rp, &nfs_reqq, r_chain) {
- if (rp->r_nmp == nmp) {
- mtx_lock(&rp->r_mtx);
- rp->r_flags |= R_MUSTRESEND;
- mtx_unlock(&rp->r_mtx);
- }
- }
- mtx_unlock(&nfs_reqq_mtx);
- mtx_lock(&nmp->nm_mtx);
-unlock_exit:
- nfs_connect_unlock(rep);
- mtx_unlock(&nmp->nm_mtx);
- return (error);
-}
-
-/*
- * NFS disconnect. Clean up and unlink.
- */
-void
-nfs_disconnect(struct nfsmount *nmp)
-{
- struct socket *so;
-
- mtx_lock(&nmp->nm_mtx);
- if (nmp->nm_so) {
- so = nmp->nm_so;
- nmp->nm_so = NULL;
- mtx_unlock(&nmp->nm_mtx);
- SOCKBUF_LOCK(&so->so_rcv);
- soupcall_clear(so, SO_RCV);
- SOCKBUF_UNLOCK(&so->so_rcv);
- soshutdown(so, SHUT_WR);
- soclose(so);
- } else
- mtx_unlock(&nmp->nm_mtx);
-}
-
-void
-nfs_safedisconnect(struct nfsmount *nmp)
-{
- struct nfsreq dummyreq;
-
- bzero(&dummyreq, sizeof(dummyreq));
- dummyreq.r_nmp = nmp;
- nfs_disconnect(nmp);
-}
-
-/*
- * This is the nfs send routine. For connection based socket types, it
- * must be called with an nfs_sndlock() on the socket.
- * - return EINTR if the RPC is terminated, 0 otherwise
- * - set R_MUSTRESEND if the send fails for any reason
- * - do any cleanup required by recoverable socket errors (?)
- */
-int
-nfs_send(struct socket *so, struct sockaddr *nam, struct mbuf *top,
- struct nfsreq *rep)
-{
- struct sockaddr *sendnam;
- int error, error2, soflags, flags;
-
- KASSERT(rep, ("nfs_send: called with rep == NULL"));
-
- error = nfs_sigintr(rep->r_nmp, rep, rep->r_td);
- if (error) {
- m_freem(top);
- return (error);
- }
- mtx_lock(&rep->r_nmp->nm_mtx);
- mtx_lock(&rep->r_mtx);
- if ((so = rep->r_nmp->nm_so) == NULL) {
- rep->r_flags |= R_MUSTRESEND;
- mtx_unlock(&rep->r_mtx);
- mtx_unlock(&rep->r_nmp->nm_mtx);
- m_freem(top);
- return (EPIPE);
- }
- rep->r_flags &= ~R_MUSTRESEND;
- soflags = rep->r_nmp->nm_soflags;
- mtx_unlock(&rep->r_mtx);
- mtx_unlock(&rep->r_nmp->nm_mtx);
-
- if ((soflags & PR_CONNREQUIRED) || (so->so_state & SS_ISCONNECTED))
- sendnam = NULL;
- else
- sendnam = nam;
- if (so->so_type == SOCK_SEQPACKET)
- flags = MSG_EOR;
- else
- flags = 0;
-
- error = sosend(so, sendnam, 0, top, 0, flags, curthread /*XXX*/);
- if (error == ENOBUFS && so->so_type == SOCK_DGRAM) {
- error = 0;
- mtx_lock(&rep->r_mtx);
- rep->r_flags |= R_MUSTRESEND;
- mtx_unlock(&rep->r_mtx);
- }
-
- if (error) {
- /*
- * Don't report EPIPE errors on nfs sockets.
- * These can be due to idle tcp mounts which will be closed by
- * netapp, solaris, etc. if left idle too long.
- */
- if (error != EPIPE) {
- log(LOG_INFO, "nfs send error %d for server %s\n",
- error,
- rep->r_nmp->nm_mountp->mnt_stat.f_mntfromname);
- }
- /*
- * Deal with errors for the client side.
- */
- error2 = NFS_SIGREP(rep);
- if (error2)
- error = error2;
- else {
- mtx_lock(&rep->r_mtx);
- rep->r_flags |= R_MUSTRESEND;
- mtx_unlock(&rep->r_mtx);
- }
-
- /*
- * Handle any recoverable (soft) socket errors here. (?)
- * Make EWOULDBLOCK a recoverable error, we'll rexmit from nfs_timer().
- */
- if (error != EINTR && error != ERESTART && error != EIO && error != EPIPE)
- error = 0;
- }
- return (error);
-}
-
-int
-nfs_reply(struct nfsreq *rep)
-{
- register struct socket *so;
- register struct mbuf *m;
- int error = 0, sotype, slpflag;
- struct nfsmount *nmp = rep->r_nmp;
-
- sotype = nmp->nm_sotype;
- /*
- * For reliable protocols, lock against other senders/receivers
- * in case a reconnect is necessary.
- */
- if (sotype != SOCK_DGRAM) {
-tryagain:
- mtx_lock(&nmp->nm_mtx);
- mtx_lock(&rep->r_mtx);
- if (rep->r_mrep) {
- mtx_unlock(&rep->r_mtx);
- mtx_unlock(&nmp->nm_mtx);
- return (0);
- }
- if (rep->r_flags & R_SOFTTERM) {
- mtx_unlock(&rep->r_mtx);
- mtx_unlock(&nmp->nm_mtx);
- return (EINTR);
- }
- so = nmp->nm_so;
- if (!so ||
- (nmp->nm_nfstcpstate.flags & NFS_TCP_FORCE_RECONNECT)) {
- mtx_unlock(&rep->r_mtx);
- nmp->nm_nfstcpstate.flags |= NFS_TCP_FORCE_RECONNECT;
- error = nfs_reconnect(rep);
- if (error)
- return (error);
- goto tryagain;
- }
- while (rep->r_flags & R_MUSTRESEND) {
- mtx_unlock(&rep->r_mtx);
- nmp->nm_nfstcpstate.sock_send_inprog++;
- mtx_unlock(&nmp->nm_mtx);
- m = m_copym(rep->r_mreq, 0, M_COPYALL, M_WAIT);
- nfsstats.rpcretries++;
- error = nfs_send(so, nmp->nm_nam, m, rep);
- if (error) {
- mtx_lock(&nmp->nm_mtx);
- nfs_wakup_reconnectors(nmp);
- if (!(error == EINTR || error == ERESTART)) {
- nmp->nm_nfstcpstate.flags |= NFS_TCP_FORCE_RECONNECT;
- error = nfs_reconnect(rep);
- } else
- mtx_unlock(&nmp->nm_mtx);
- if (error)
- return (error);
- goto tryagain;
- } else {
- mtx_lock(&nmp->nm_mtx);
- nfs_wakup_reconnectors(nmp);
- mtx_lock(&rep->r_mtx);
- }
- }
- mtx_unlock(&rep->r_mtx);
- mtx_unlock(&nmp->nm_mtx);
- }
- slpflag = 0;
- mtx_lock(&nmp->nm_mtx);
- if (nmp->nm_flag & NFSMNT_INT)
- slpflag = PCATCH;
- mtx_unlock(&nmp->nm_mtx);
- mtx_lock(&rep->r_mtx);
- while ((rep->r_mrep == NULL) && (error == 0) &&
- ((rep->r_flags & R_SOFTTERM) == 0) &&
- ((sotype == SOCK_DGRAM) || ((rep->r_flags & R_MUSTRESEND) == 0)))
- error = msleep((caddr_t)rep, &rep->r_mtx,
- slpflag | (PZERO - 1), "nfsreq", 0);
- if (error == EINTR || error == ERESTART) {
- /* NFS operations aren't restartable. Map ERESTART to EINTR */
- mtx_unlock(&rep->r_mtx);
- return (EINTR);
- }
- if (rep->r_flags & R_SOFTTERM) {
- /* Request was terminated because we exceeded the retries (soft mount) */
- mtx_unlock(&rep->r_mtx);
- return (ETIMEDOUT);
- }
- mtx_unlock(&rep->r_mtx);
- if (sotype == SOCK_STREAM) {
- mtx_lock(&nmp->nm_mtx);
- mtx_lock(&rep->r_mtx);
- if (((nmp->nm_nfstcpstate.flags & NFS_TCP_FORCE_RECONNECT) ||
- (rep->r_flags & R_MUSTRESEND))) {
- mtx_unlock(&rep->r_mtx);
- mtx_unlock(&nmp->nm_mtx);
- goto tryagain;
- } else {
- mtx_unlock(&rep->r_mtx);
- mtx_unlock(&nmp->nm_mtx);
- }
- }
- return (error);
-}
-
-/*
- * XXX TO DO
- * Make nfs_realign() non-blocking. Also make nfsm_dissect() nonblocking.
- */
-static void
-nfs_clnt_match_xid(struct socket *so,
- struct nfsmount *nmp,
- struct mbuf *mrep)
-{
- struct mbuf *md;
- caddr_t dpos;
- u_int32_t rxid, *tl;
- struct nfsreq *rep;
- int error;
-
- /*
- * Search for any mbufs that are not a multiple of 4 bytes long
- * or with m_data not longword aligned.
- * These could cause pointer alignment problems, so copy them to
- * well aligned mbufs.
- */
- if (nfs_realign(&mrep, 5 * NFSX_UNSIGNED) == ENOMEM) {
- m_freem(mrep);
- nfsstats.rpcinvalid++;
- return;
- }
-
- /*
- * Get the xid and check that it is an rpc reply
- */
- md = mrep;
- dpos = mtod(md, caddr_t);
- tl = nfsm_dissect_nonblock(u_int32_t *, 2*NFSX_UNSIGNED);
- rxid = *tl++;
- if (*tl != rpc_reply) {
- m_freem(mrep);
-nfsmout:
- nfsstats.rpcinvalid++;
- return;
- }
-
- mtx_lock(&nfs_reqq_mtx);
- /*
- * Loop through the request list to match up the reply
- * Iff no match, just drop the datagram
- */
- TAILQ_FOREACH(rep, &nfs_reqq, r_chain) {
- mtx_lock(&nmp->nm_mtx);
- mtx_lock(&rep->r_mtx);
- if (rep->r_mrep == NULL && rxid == rep->r_xid) {
- /* Found it.. */
- rep->r_mrep = mrep;
- rep->r_md = md;
- rep->r_dpos = dpos;
- /*
- * Update congestion window.
- * Do the additive increase of
- * one rpc/rtt.
- */
- if (nmp->nm_cwnd <= nmp->nm_sent) {
- nmp->nm_cwnd +=
- (NFS_CWNDSCALE * NFS_CWNDSCALE +
- (nmp->nm_cwnd >> 1)) / nmp->nm_cwnd;
- if (nmp->nm_cwnd > NFS_MAXCWND)
- nmp->nm_cwnd = NFS_MAXCWND;
- }
- if (rep->r_flags & R_SENT) {
- rep->r_flags &= ~R_SENT;
- nmp->nm_sent -= NFS_CWNDSCALE;
- }
- if (rep->r_flags & R_TIMING)
- nfs_update_rtt(rep);
- nmp->nm_timeouts = 0;
- wakeup((caddr_t)rep);
- mtx_unlock(&rep->r_mtx);
- mtx_unlock(&nmp->nm_mtx);
- break;
- }
- mtx_unlock(&rep->r_mtx);
- mtx_unlock(&nmp->nm_mtx);
- }
- /*
- * If not matched to a request, drop it.
- * If it's mine, wake up requestor.
- */
- if (rep == 0) {
- nfsstats.rpcunexpected++;
- m_freem(mrep);
- }
- mtx_unlock(&nfs_reqq_mtx);
-}
-
-static void
-nfs_mark_for_reconnect(struct nfsmount *nmp)
-{
- struct nfsreq *rp;
-
- mtx_lock(&nmp->nm_mtx);
- nmp->nm_nfstcpstate.flags |= NFS_TCP_FORCE_RECONNECT;
- mtx_unlock(&nmp->nm_mtx);
- /*
- * Wakeup all processes that are waiting for replies
- * on this mount point. One of them does the reconnect.
- */
- mtx_lock(&nfs_reqq_mtx);
- TAILQ_FOREACH(rp, &nfs_reqq, r_chain) {
- if (rp->r_nmp == nmp) {
- mtx_lock(&rp->r_mtx);
- rp->r_flags |= R_MUSTRESEND;
- wakeup((caddr_t)rp);
- mtx_unlock(&rp->r_mtx);
- }
- }
- mtx_unlock(&nfs_reqq_mtx);
-}
-
-static int
-nfstcp_readable(struct socket *so, int bytes)
-{
- int retval;
-
- SOCKBUF_LOCK_ASSERT(&so->so_rcv);
- retval = (so->so_rcv.sb_cc >= (bytes) ||
- (so->so_rcv.sb_state & SBS_CANTRCVMORE) ||
- so->so_error);
- return (retval);
-}
-
-#define nfstcp_marker_readable(so) nfstcp_readable(so, sizeof(u_int32_t))
-
-static int
-nfs_copy_len(struct mbuf *mp, char *buf, int len)
-{
- while (len > 0 && mp != NULL) {
- int copylen = min(len, mp->m_len);
-
- bcopy(mp->m_data, buf, copylen);
- buf += copylen;
- len -= copylen;
- mp = mp->m_next;
- }
- return (len);
-}
-
-static int
-nfs_clnt_tcp_soupcall(struct socket *so, void *arg, int waitflag)
-{
- struct nfsmount *nmp = (struct nfsmount *)arg;
- struct mbuf *mp = NULL;
- struct uio auio;
- int error;
- u_int32_t len;
- int rcvflg;
-
- /*
- * Don't pick any more data from the socket if we've marked the
- * mountpoint for reconnect.
- */
- mtx_lock(&nmp->nm_mtx);
- if (nmp->nm_nfstcpstate.flags & NFS_TCP_FORCE_RECONNECT) {
- mtx_unlock(&nmp->nm_mtx);
- return (SU_OK);
- } else
- mtx_unlock(&nmp->nm_mtx);
- auio.uio_td = curthread;
- auio.uio_segflg = UIO_SYSSPACE;
- auio.uio_rw = UIO_READ;
- for ( ; ; ) {
- mtx_lock(&nmp->nm_mtx);
- if (nmp->nm_nfstcpstate.flags & NFS_TCP_EXPECT_RPCMARKER) {
- int resid;
-
- mtx_unlock(&nmp->nm_mtx);
- if (!nfstcp_marker_readable(so)) {
- /* Marker is not readable */
- return (SU_OK);
- }
- SOCKBUF_UNLOCK(&so->so_rcv);
- auio.uio_resid = sizeof(u_int32_t);
- auio.uio_iov = NULL;
- auio.uio_iovcnt = 0;
- mp = NULL;
- rcvflg = (MSG_DONTWAIT | MSG_SOCALLBCK);
- error = soreceive(so, (struct sockaddr **)0, &auio,
- &mp, (struct mbuf **)0, &rcvflg);
- SOCKBUF_LOCK(&so->so_rcv);
- /*
- * We've already tested that the socket is readable. 2 cases
- * here, we either read 0 bytes (client closed connection),
- * or got some other error. In both cases, we tear down the
- * connection.
- */
- if (error || auio.uio_resid > 0) {
- if (error && error != ECONNRESET) {
- log(LOG_ERR,
- "nfs/tcp clnt: Error %d reading socket, tearing down TCP connection\n",
- error);
- }
- goto mark_reconnect;
- }
- if (mp == NULL)
- panic("nfs_clnt_tcp_soupcall: Got empty mbuf chain from sorecv\n");
- /*
- * Sigh. We can't do the obvious thing here (which would
- * be to have soreceive copy the length from mbufs for us).
- * Calling uiomove() from the context of a socket callback
- * (even for kernel-kernel copies) leads to LORs (since
- * we hold network locks at this point).
- */
- if ((resid = nfs_copy_len(mp, (char *)&len,
- sizeof(u_int32_t)))) {
- log(LOG_ERR, "%s (%d) from nfs server %s\n",
- "Bad RPC HDR length",
- (int)(sizeof(u_int32_t) - resid),
- nmp->nm_mountp->mnt_stat.f_mntfromname);
- goto mark_reconnect;
- }
- len = ntohl(len) & ~0x80000000;
- m_freem(mp);
- /*
- * This is SERIOUS! We are out of sync with the sender
- * and forcing a disconnect/reconnect is all I can do.
- */
- if (len > NFS_MAXPACKET || len == 0) {
- log(LOG_ERR, "%s (%d) from nfs server %s\n",
- "impossible packet length",
- len,
- nmp->nm_mountp->mnt_stat.f_mntfromname);
- goto mark_reconnect;
- }
- mtx_lock(&nmp->nm_mtx);
- nmp->nm_nfstcpstate.rpcresid = len;
- nmp->nm_nfstcpstate.flags &= ~(NFS_TCP_EXPECT_RPCMARKER);
- mtx_unlock(&nmp->nm_mtx);
- } else
- mtx_unlock(&nmp->nm_mtx);
-
- /*
- * Processed RPC marker or no RPC marker to process.
- * Pull in and process data.
- */
- mtx_lock(&nmp->nm_mtx);
- if (nmp->nm_nfstcpstate.rpcresid > 0) {
- mtx_unlock(&nmp->nm_mtx);
- if (!nfstcp_readable(so, nmp->nm_nfstcpstate.rpcresid)) {
- /* All data not readable */
- return (SU_OK);
- }
- SOCKBUF_UNLOCK(&so->so_rcv);
- auio.uio_resid = nmp->nm_nfstcpstate.rpcresid;
- auio.uio_iov = NULL;
- auio.uio_iovcnt = 0;
- mp = NULL;
- rcvflg = (MSG_DONTWAIT | MSG_SOCALLBCK);
- error = soreceive(so, (struct sockaddr **)0, &auio,
- &mp, (struct mbuf **)0, &rcvflg);
- SOCKBUF_LOCK(&so->so_rcv);
- if (error || auio.uio_resid > 0) {
- if (error && error != ECONNRESET) {
- log(LOG_ERR,
- "nfs/tcp clnt: Error %d reading socket, tearing down TCP connection\n",
- error);
- }
- goto mark_reconnect;
- }
- if (mp == NULL)
- panic("nfs_clnt_tcp_soupcall: Got empty mbuf chain from sorecv\n");
- mtx_lock(&nmp->nm_mtx);
- nmp->nm_nfstcpstate.rpcresid = 0;
- nmp->nm_nfstcpstate.flags |= NFS_TCP_EXPECT_RPCMARKER;
- mtx_unlock(&nmp->nm_mtx);
- /* We got the entire RPC reply. Match XIDs and wake up requestor */
- nfs_clnt_match_xid(so, nmp, mp);
- } else
- mtx_unlock(&nmp->nm_mtx);
- }
-
-mark_reconnect:
- nfs_mark_for_reconnect(nmp);
- return (SU_OK);
-}
-
-static int
-nfs_clnt_udp_soupcall(struct socket *so, void *arg, int waitflag)
-{
- struct nfsmount *nmp = (struct nfsmount *)arg;
- struct uio auio;
- struct mbuf *mp = NULL;
- struct mbuf *control = NULL;
- int error, rcvflag;
-
- SOCKBUF_UNLOCK(&so->so_rcv);
- auio.uio_resid = 1000000;
- auio.uio_td = curthread;
- rcvflag = MSG_DONTWAIT;
- auio.uio_resid = 1000000000;
- do {
- mp = control = NULL;
- error = soreceive(so, NULL, &auio, &mp, &control, &rcvflag);
- if (control)
- m_freem(control);
- if (mp)
- nfs_clnt_match_xid(so, nmp, mp);
- } while (mp && !error);
- SOCKBUF_LOCK(&so->so_rcv);
- return (SU_OK);
-}
-
-/*
- * nfs_request - goes something like this
- * - fill in request struct
- * - links it into list
- * - calls nfs_send() for first transmit
- * - calls nfs_receive() to get reply
- * - break down rpc header and return with nfs reply pointed to
- * by mrep or error
- * nb: always frees up mreq mbuf list
- */
-int
-nfs_request(struct vnode *vp, struct mbuf *mrest, int procnum,
- struct thread *td, struct ucred *cred, struct mbuf **mrp,
- struct mbuf **mdp, caddr_t *dposp)
-{
- struct mbuf *mrep, *m2;
- struct nfsreq *rep;
- u_int32_t *tl;
- int i;
- struct nfsmount *nmp;
- struct mbuf *m, *md, *mheadend;
- time_t waituntil;
- caddr_t dpos;
- int error = 0, mrest_len, auth_len, auth_type;
- struct timeval now;
- u_int32_t *xidp;
-
- /* Reject requests while attempting a forced unmount. */
- if (vp->v_mount->mnt_kern_flag & MNTK_UNMOUNTF) {
- m_freem(mrest);
- return (ESTALE);
- }
- nmp = VFSTONFS(vp->v_mount);
- rep = malloc(sizeof(struct nfsreq), M_NFSREQ, M_WAITOK);
- bzero(rep, sizeof(struct nfsreq));
- rep->r_nmp = nmp;
- rep->r_vp = vp;
- rep->r_td = td;
- rep->r_procnum = procnum;
- mtx_init(&rep->r_mtx, "NFSrep lock", NULL, MTX_DEF);
-
- getmicrouptime(&now);
- rep->r_lastmsg = now.tv_sec -
- ((nmp->nm_tprintf_delay) - (nmp->nm_tprintf_initial_delay));
- mrest_len = m_length(mrest, NULL);
-
- /*
- * Get the RPC header with authorization.
- */
- auth_type = RPCAUTH_UNIX;
- if (cred->cr_ngroups < 1)
- panic("nfsreq nogrps");
- auth_len = ((((cred->cr_ngroups - 1) > nmp->nm_numgrps) ?
- nmp->nm_numgrps : (cred->cr_ngroups - 1)) << 2) +
- 5 * NFSX_UNSIGNED;
- m = nfsm_rpchead(cred, nmp->nm_flag, procnum, auth_type, auth_len,
- mrest, mrest_len, &mheadend, &xidp);
-
- /*
- * For stream protocols, insert a Sun RPC Record Mark.
- */
- if (nmp->nm_sotype == SOCK_STREAM) {
- M_PREPEND(m, NFSX_UNSIGNED, M_WAIT);
- *mtod(m, u_int32_t *) = htonl(0x80000000 |
- (m->m_pkthdr.len - NFSX_UNSIGNED));
- }
- rep->r_mreq = m;
- rep->r_xid = *xidp;
-tryagain:
- if (nmp->nm_flag & NFSMNT_SOFT)
- rep->r_retry = nmp->nm_retry;
- else
- rep->r_retry = NFS_MAXREXMIT + 1; /* past clip limit */
- rep->r_rtt = rep->r_rexmit = 0;
- if (nfs_rto_timer(procnum) != NFS_DEFAULT_TIMER)
- rep->r_flags = R_TIMING;
- else
- rep->r_flags = 0;
- rep->r_mrep = NULL;
-
- /*
- * Do the client side RPC.
- */
- nfsstats.rpcrequests++;
- /*
- * Chain request into list of outstanding requests. Be sure
- * to put it LAST so timer finds oldest requests first.
- */
- mtx_lock(&nfs_reqq_mtx);
- if (TAILQ_EMPTY(&nfs_reqq))
- callout_reset(&nfs_callout, nfs_ticks, nfs_timer, NULL);
- TAILQ_INSERT_TAIL(&nfs_reqq, rep, r_chain);
- mtx_unlock(&nfs_reqq_mtx);
-
- /*
- * If backing off another request or avoiding congestion, don't
- * send this one now but let timer do it. If not timing a request,
- * do it now.
- */
- mtx_lock(&nmp->nm_mtx);
- if (nmp->nm_so &&
- (((nmp->nm_sotype == SOCK_STREAM) && !(nmp->nm_nfstcpstate.flags & NFS_TCP_FORCE_RECONNECT)) ||
- (nmp->nm_flag & NFSMNT_DUMBTIMR) || nmp->nm_sent < nmp->nm_cwnd)) {
- if (nmp->nm_sotype == SOCK_STREAM)
- nmp->nm_nfstcpstate.sock_send_inprog++;
- mtx_unlock(&nmp->nm_mtx);
- m2 = m_copym(m, 0, M_COPYALL, M_WAIT);
- error = nfs_send(nmp->nm_so, nmp->nm_nam, m2, rep);
- mtx_lock(&nmp->nm_mtx);
- mtx_lock(&rep->r_mtx);
- /*
- * nfs_timer() could've re-transmitted the request if we ended up
- * blocking on nfs_send() too long, so check for R_SENT here.
- */
- if (!error && (rep->r_flags & (R_SENT | R_MUSTRESEND)) == 0) {
- nmp->nm_sent += NFS_CWNDSCALE;
- rep->r_flags |= R_SENT;
- }
- mtx_unlock(&rep->r_mtx);
- if (nmp->nm_sotype == SOCK_STREAM)
- nfs_wakup_reconnectors(rep->r_nmp);
- mtx_unlock(&nmp->nm_mtx);
- } else {
- mtx_unlock(&nmp->nm_mtx);
- rep->r_rtt = -1;
- }
-
- /*
- * Wait for the reply from our send or the timer's.
- */
- if (!error || error == EPIPE)
- error = nfs_reply(rep);
-
- /*
- * nfs_timer() may be in the process of re-transmitting this request.
- * nfs_timer() drops the nfs_reqq_mtx before the pru_send() (to avoid LORs).
- * Wait till nfs_timer() completes the re-transmission. When the reply
- * comes back, it will be discarded (since the req struct for it no longer
- * exists).
- */
-wait_for_pinned_req:
- mtx_lock(&rep->r_mtx);
- while (rep->r_flags & R_PIN_REQ) {
- msleep((caddr_t)&rep->r_flags, &rep->r_mtx,
- (PZERO - 1), "nfsrxmt", 0);
- }
- mtx_unlock(&rep->r_mtx);
-
- mtx_lock(&nfs_reqq_mtx);
- /* Have to check for R_PIN_REQ after grabbing wlock again */
- mtx_lock(&rep->r_mtx);
- if (rep->r_flags & R_PIN_REQ) {
- mtx_unlock(&rep->r_mtx);
- mtx_unlock(&nfs_reqq_mtx);
- goto wait_for_pinned_req;
- } else
- mtx_unlock(&rep->r_mtx);
- /* RPC done (timer not active, request not pinned), unlink the request */
- TAILQ_REMOVE(&nfs_reqq, rep, r_chain);
- if (TAILQ_EMPTY(&nfs_reqq))
- callout_stop(&nfs_callout);
- mtx_unlock(&nfs_reqq_mtx);
-
- /*
- * Decrement the outstanding request count.
- */
- mtx_lock(&rep->r_mtx);
- if (rep->r_flags & R_SENT) {
- rep->r_flags &= ~R_SENT; /* paranoia */
- mtx_unlock(&rep->r_mtx);
- mtx_lock(&nmp->nm_mtx);
- nmp->nm_sent -= NFS_CWNDSCALE;
- mtx_unlock(&nmp->nm_mtx);
- } else
- mtx_unlock(&rep->r_mtx);
-
- /*
- * If there was a successful reply and a tprintf msg.
- * tprintf a response.
- */
- if (!error) {
- nfs_up(rep, nmp, rep->r_td, "is alive again", NFSSTA_TIMEO);
- }
- mrep = rep->r_mrep;
- md = rep->r_md;
- dpos = rep->r_dpos;
- if (error) {
- /*
- * If we got interrupted by a signal in nfs_reply(), there's
- * a very small window where the reply could've come in before
- * this process got scheduled in. To handle that case, we need
- * to free the reply if it was delivered.
- */
- if (rep->r_mrep != NULL)
- m_freem(rep->r_mrep);
- m_freem(rep->r_mreq);
- mtx_destroy(&rep->r_mtx);
- free((caddr_t)rep, M_NFSREQ);
- return (error);
- }
-
- if (rep->r_mrep == NULL)
- panic("nfs_request: rep->r_mrep shouldn't be NULL if no error\n");
-
- /*
- * break down the rpc header and check if ok
- */
- tl = nfsm_dissect(u_int32_t *, 3 * NFSX_UNSIGNED);
- if (*tl++ == rpc_msgdenied) {
- if (*tl == rpc_mismatch)
- error = EOPNOTSUPP;
- else
- error = EACCES;
- m_freem(mrep);
- m_freem(rep->r_mreq);
- mtx_destroy(&rep->r_mtx);
- free((caddr_t)rep, M_NFSREQ);
- return (error);
- }
-
- /*
- * Just throw away any verifyer (ie: kerberos etc).
- */
- i = fxdr_unsigned(int, *tl++); /* verf type */
- i = fxdr_unsigned(int32_t, *tl); /* len */
- if (i > 0)
- nfsm_adv(nfsm_rndup(i));
- tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
- /* 0 == ok */
- if (*tl == 0) {
- tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
- if (*tl != 0) {
- error = fxdr_unsigned(int, *tl);
- if ((nmp->nm_flag & NFSMNT_NFSV3) &&
- error == NFSERR_TRYLATER) {
- m_freem(mrep);
- error = 0;
- waituntil = time_second + nfs3_jukebox_delay;
- while (time_second < waituntil) {
- (void) tsleep(&fake_wchan, PSOCK, "nqnfstry", hz);
- }
- rep->r_xid = *xidp = txdr_unsigned(nfs_xid_gen());
- goto tryagain;
- }
-
- /*
- * If the File Handle was stale, invalidate the
- * lookup cache, just in case.
- */
- if (error == ESTALE)
- nfs_purgecache(vp);
- /*
- * Skip wcc data on NFS errors for now. NetApp filers return corrupt
- * postop attrs in the wcc data for NFS err EROFS. Not sure if they
- * could return corrupt postop attrs for others errors.
- */
- if ((nmp->nm_flag & NFSMNT_NFSV3) && !nfs_skip_wcc_data_onerr) {
- *mrp = mrep;
- *mdp = md;
- *dposp = dpos;
- error |= NFSERR_RETERR;
- } else
- m_freem(mrep);
- m_freem(rep->r_mreq);
- mtx_destroy(&rep->r_mtx);
- free((caddr_t)rep, M_NFSREQ);
- return (error);
- }
-
- *mrp = mrep;
- *mdp = md;
- *dposp = dpos;
- m_freem(rep->r_mreq);
- mtx_destroy(&rep->r_mtx);
- free((caddr_t)rep, M_NFSREQ);
- return (0);
- }
- m_freem(mrep);
- error = EPROTONOSUPPORT;
-nfsmout:
- m_freem(rep->r_mreq);
- mtx_destroy(&rep->r_mtx);
- free((caddr_t)rep, M_NFSREQ);
- return (error);
-}
-
-/*
- * Nfs timer routine
- * Scan the nfsreq list and retranmit any requests that have timed out
- * To avoid retransmission attempts on STREAM sockets (in the future) make
- * sure to set the r_retry field to 0 (implies nm_retry == 0).
- *
- * The nfs reqq lock cannot be held while we do the pru_send() because of a
- * lock ordering violation. The NFS client socket callback acquires
- * inp_lock->nfsreq mutex and pru_send acquires inp_lock. So we drop the
- * reqq mutex (and reacquire it after the pru_send()). The req structure
- * (for the rexmit) is prevented from being removed by the R_PIN_REQ flag.
- */
-void
-nfs_timer(void *arg)
-{
- struct nfsreq *rep;
- struct mbuf *m;
- struct socket *so;
- struct nfsmount *nmp;
- int timeo;
- int error;
- struct timeval now;
-
- getmicrouptime(&now);
- mtx_lock(&nfs_reqq_mtx);
- TAILQ_FOREACH(rep, &nfs_reqq, r_chain) {
- nmp = rep->r_nmp;
- mtx_lock(&rep->r_mtx);
- if (rep->r_mrep || (rep->r_flags & R_SOFTTERM)) {
- mtx_unlock(&rep->r_mtx);
- continue;
- } else {
- /*
- * Terminate request if force-unmount in progress.
- * Note that NFS could have vfs_busy'ed the mount,
- * causing the unmount to wait and making this bit
- * of logic necessary.
- */
- if (rep->r_nmp->nm_mountp->mnt_kern_flag & MNTK_UNMOUNTF) {
- nfs_softterm(rep);
- mtx_unlock(&rep->r_mtx);
- continue;
- }
- mtx_unlock(&rep->r_mtx);
- }
- if (nfs_sigintr(nmp, rep, rep->r_td))
- continue;
- mtx_lock(&nmp->nm_mtx);
- mtx_lock(&rep->r_mtx);
- if (nmp->nm_tprintf_initial_delay != 0 &&
- (rep->r_rexmit > 2 || (rep->r_flags & R_RESENDERR)) &&
- rep->r_lastmsg + nmp->nm_tprintf_delay < now.tv_sec) {
- rep->r_lastmsg = now.tv_sec;
- /*
- * Pin down the request and drop locks for the acquisition
- * of Giant from tprintf() in nfs_down().
- */
- rep->r_flags |= R_PIN_REQ;
- mtx_unlock(&rep->r_mtx);
- mtx_unlock(&nmp->nm_mtx);
- mtx_unlock(&nfs_reqq_mtx);
- nfs_down(rep, nmp, rep->r_td, "not responding",
- 0, NFSSTA_TIMEO);
- mtx_lock(&nfs_reqq_mtx);
- mtx_lock(&nmp->nm_mtx);
- mtx_lock(&rep->r_mtx);
- rep->r_flags &= ~R_PIN_REQ;
- wakeup((caddr_t)&rep->r_flags);
- }
- if (rep->r_rtt >= 0) {
- rep->r_rtt++;
- if (nmp->nm_flag & NFSMNT_DUMBTIMR)
- timeo = nmp->nm_timeo;
- else
- timeo = nfs_estimate_rto(nmp, rep->r_procnum);
- if (nmp->nm_timeouts > 0)
- timeo *= nfs_backoff[nmp->nm_timeouts - 1];
- if (rep->r_rtt <= timeo) {
- mtx_unlock(&rep->r_mtx);
- mtx_unlock(&nmp->nm_mtx);
- continue;
- }
- if (nmp->nm_timeouts < NFS_NBACKOFF)
- nmp->nm_timeouts++;
- }
- if (rep->r_rexmit >= rep->r_retry) { /* too many */
- nfsstats.rpctimeouts++;
- nfs_softterm(rep);
- mtx_unlock(&rep->r_mtx);
- mtx_unlock(&nmp->nm_mtx);
- continue;
- }
- if (nmp->nm_sotype != SOCK_DGRAM) {
- if (++rep->r_rexmit > NFS_MAXREXMIT)
- rep->r_rexmit = NFS_MAXREXMIT;
- /*
- * For NFS/TCP, setting R_MUSTRESEND and waking up
- * the requester will cause the request to be
- * retransmitted (in nfs_reply()), re-connecting
- * if necessary.
- */
- rep->r_flags |= R_MUSTRESEND;
- wakeup((caddr_t)rep);
- rep->r_rtt = 0;
- mtx_unlock(&rep->r_mtx);
- mtx_unlock(&nmp->nm_mtx);
- continue;
- }
- if ((so = nmp->nm_so) == NULL) {
- mtx_unlock(&rep->r_mtx);
- mtx_unlock(&nmp->nm_mtx);
- continue;
- }
- /*
- * If there is enough space and the window allows..
- * Resend it
- * Set r_rtt to -1 in case we fail to send it now.
- */
- rep->r_rtt = -1;
- if (sbspace(&so->so_snd) >= rep->r_mreq->m_pkthdr.len &&
- ((nmp->nm_flag & NFSMNT_DUMBTIMR) || (rep->r_flags & R_SENT) ||
- nmp->nm_sent < nmp->nm_cwnd)) {
- mtx_unlock(&rep->r_mtx);
- mtx_unlock(&nmp->nm_mtx);
- if ((m = m_copym(rep->r_mreq, 0, M_COPYALL, M_DONTWAIT))) {
- /*
- * Mark the request to indicate that a XMIT is in
- * progress to prevent the req structure being
- * removed in nfs_request().
- */
- mtx_lock(&rep->r_mtx);
- rep->r_flags |= R_PIN_REQ;
- mtx_unlock(&rep->r_mtx);
- mtx_unlock(&nfs_reqq_mtx);
- if ((nmp->nm_flag & NFSMNT_NOCONN) == 0)
- error = (*so->so_proto->pr_usrreqs->pru_send)
- (so, 0, m, NULL, NULL, curthread);
- else
- error = (*so->so_proto->pr_usrreqs->pru_send)
- (so, 0, m, nmp->nm_nam, NULL,
- curthread);
- mtx_lock(&nfs_reqq_mtx);
- mtx_lock(&nmp->nm_mtx);
- mtx_lock(&rep->r_mtx);
- rep->r_flags &= ~R_PIN_REQ;
- wakeup((caddr_t)&rep->r_flags);
- if (error) {
- if (NFSIGNORE_SOERROR(nmp->nm_soflags, error))
- so->so_error = 0;
- rep->r_flags |= R_RESENDERR;
- } else {
- /*
- * Iff first send, start timing
- * else turn timing off, backoff timer
- * and divide congestion window by 2.
- */
- rep->r_flags &= ~R_RESENDERR;
- if (rep->r_flags & R_SENT) {
- rep->r_flags &= ~R_TIMING;
- if (++rep->r_rexmit > NFS_MAXREXMIT)
- rep->r_rexmit = NFS_MAXREXMIT;
- nmp->nm_cwnd >>= 1;
- if (nmp->nm_cwnd < NFS_CWNDSCALE)
- nmp->nm_cwnd = NFS_CWNDSCALE;
- nfsstats.rpcretries++;
- } else {
- rep->r_flags |= R_SENT;
- nmp->nm_sent += NFS_CWNDSCALE;
- }
- rep->r_rtt = 0;
- }
- mtx_unlock(&rep->r_mtx);
- mtx_unlock(&nmp->nm_mtx);
- }
- } else {
- mtx_unlock(&rep->r_mtx);
- mtx_unlock(&nmp->nm_mtx);
- }
- }
- mtx_unlock(&nfs_reqq_mtx);
- callout_reset(&nfs_callout, nfs_ticks, nfs_timer, NULL);
-}
-
-/*
- * Mark all of an nfs mount's outstanding requests with R_SOFTTERM and
- * wait for all requests to complete. This is used by forced unmounts
- * to terminate any outstanding RPCs.
- */
-int
-nfs_nmcancelreqs(nmp)
- struct nfsmount *nmp;
-{
- struct nfsreq *req;
- int i;
-
- mtx_lock(&nfs_reqq_mtx);
- TAILQ_FOREACH(req, &nfs_reqq, r_chain) {
- mtx_lock(&req->r_mtx);
- if (nmp != req->r_nmp || req->r_mrep != NULL ||
- (req->r_flags & R_SOFTTERM)) {
- mtx_unlock(&req->r_mtx);
- continue;
- }
- nfs_softterm(req);
- mtx_unlock(&req->r_mtx);
- }
- mtx_unlock(&nfs_reqq_mtx);
-
- for (i = 0; i < 30; i++) {
- mtx_lock(&nfs_reqq_mtx);
- TAILQ_FOREACH(req, &nfs_reqq, r_chain) {
- if (nmp == req->r_nmp)
- break;
- }
- mtx_unlock(&nfs_reqq_mtx);
- if (req == NULL)
- return (0);
- tsleep(&fake_wchan, PSOCK, "nfscancel", hz);
- }
- return (EBUSY);
-}
-
-/*
- * Flag a request as being about to terminate (due to NFSMNT_INT/NFSMNT_SOFT).
- * The nm_send count is decremented now to avoid deadlocks when the process in
- * soreceive() hasn't yet managed to send its own request.
- */
-
-static void
-nfs_softterm(struct nfsreq *rep)
-{
- KASSERT(mtx_owned(&rep->r_mtx), ("NFS req lock not owned !"));
- rep->r_flags |= R_SOFTTERM;
- if (rep->r_flags & R_SENT) {
- rep->r_nmp->nm_sent -= NFS_CWNDSCALE;
- rep->r_flags &= ~R_SENT;
- }
- /*
- * Request terminated, wakeup the blocked process, so that we
- * can return EINTR back.
- */
- wakeup((caddr_t)rep);
-}
-
-/*
- * Any signal that can interrupt an NFS operation in an intr mount
- * should be added to this set. SIGSTOP and SIGKILL cannot be masked.
- */
-int nfs_sig_set[] = {
- SIGINT,
- SIGTERM,
- SIGHUP,
- SIGKILL,
- SIGSTOP,
- SIGQUIT
-};
-
-/*
- * Check to see if one of the signals in our subset is pending on
- * the process (in an intr mount).
- */
-static int
-nfs_sig_pending(sigset_t set)
-{
- int i;
-
- for (i = 0 ; i < sizeof(nfs_sig_set)/sizeof(int) ; i++)
- if (SIGISMEMBER(set, nfs_sig_set[i]))
- return (1);
- return (0);
-}
-
-/*
- * The set/restore sigmask functions are used to (temporarily) overwrite
- * the process p_sigmask during an RPC call (for example). These are also
- * used in other places in the NFS client that might tsleep().
- */
-void
-nfs_set_sigmask(struct thread *td, sigset_t *oldset)
-{
- sigset_t newset;
- int i;
- struct proc *p;
-
- SIGFILLSET(newset);
- if (td == NULL)
- td = curthread; /* XXX */
- p = td->td_proc;
- /* Remove the NFS set of signals from newset */
- PROC_LOCK(p);
- mtx_lock(&p->p_sigacts->ps_mtx);
- for (i = 0 ; i < sizeof(nfs_sig_set)/sizeof(int) ; i++) {
- /*
- * But make sure we leave the ones already masked
- * by the process, ie. remove the signal from the
- * temporary signalmask only if it wasn't already
- * in p_sigmask.
- */
- if (!SIGISMEMBER(td->td_sigmask, nfs_sig_set[i]) &&
- !SIGISMEMBER(p->p_sigacts->ps_sigignore, nfs_sig_set[i]))
- SIGDELSET(newset, nfs_sig_set[i]);
- }
- mtx_unlock(&p->p_sigacts->ps_mtx);
- PROC_UNLOCK(p);
- kern_sigprocmask(td, SIG_SETMASK, &newset, oldset, 0);
-}
-
-void
-nfs_restore_sigmask(struct thread *td, sigset_t *set)
-{
- if (td == NULL)
- td = curthread; /* XXX */
- kern_sigprocmask(td, SIG_SETMASK, set, NULL, 0);
-}
-
-/*
- * NFS wrapper to msleep(), that shoves a new p_sigmask and restores the
- * old one after msleep() returns.
- */
-int
-nfs_msleep(struct thread *td, void *ident, struct mtx *mtx, int priority, char *wmesg, int timo)
-{
- sigset_t oldset;
- int error;
- struct proc *p;
-
- if ((priority & PCATCH) == 0)
- return msleep(ident, mtx, priority, wmesg, timo);
- if (td == NULL)
- td = curthread; /* XXX */
- nfs_set_sigmask(td, &oldset);
- error = msleep(ident, mtx, priority, wmesg, timo);
- nfs_restore_sigmask(td, &oldset);
- p = td->td_proc;
- return (error);
-}
-
-/*
- * Test for a termination condition pending on the process.
- * This is used for NFSMNT_INT mounts.
- */
-int
-nfs_sigintr(struct nfsmount *nmp, struct nfsreq *rep, struct thread *td)
-{
- struct proc *p;
- sigset_t tmpset;
-
- if (rep) {
- mtx_lock(&rep->r_mtx);
- if (rep->r_flags & R_SOFTTERM) {
- mtx_unlock(&rep->r_mtx);
- return (EIO);
- } else
- mtx_unlock(&rep->r_mtx);
- }
- /* Terminate all requests while attempting a forced unmount. */
- if (nmp->nm_mountp->mnt_kern_flag & MNTK_UNMOUNTF)
- return (EIO);
- if (!(nmp->nm_flag & NFSMNT_INT))
- return (0);
- if (td == NULL)
- return (0);
- p = td->td_proc;
- PROC_LOCK(p);
- tmpset = p->p_siglist;
- SIGSETOR(tmpset, td->td_siglist);
- SIGSETNAND(tmpset, td->td_sigmask);
- mtx_lock(&p->p_sigacts->ps_mtx);
- SIGSETNAND(tmpset, p->p_sigacts->ps_sigignore);
- mtx_unlock(&p->p_sigacts->ps_mtx);
- if ((SIGNOTEMPTY(p->p_siglist) || SIGNOTEMPTY(td->td_siglist))
- && nfs_sig_pending(tmpset)) {
- PROC_UNLOCK(p);
- return (EINTR);
- }
- PROC_UNLOCK(p);
- return (0);
-}
-
-/*
- * Lock a socket against others.
- * Necessary for STREAM sockets to ensure you get an entire rpc request/reply
- * and also to avoid race conditions between the processes with nfs requests
- * in progress when a reconnect is necessary.
- */
-int
-nfs_connect_lock(struct nfsreq *rep)
-{
- int *statep = &rep->r_nmp->nm_state;
- struct thread *td;
- int error, slpflag = 0, slptimeo = 0;
-
- td = rep->r_td;
- if (rep->r_nmp->nm_flag & NFSMNT_INT)
- slpflag = PCATCH;
- while (*statep & NFSSTA_SNDLOCK) {
- error = nfs_sigintr(rep->r_nmp, rep, td);
- if (error) {
- return (error);
- }
- *statep |= NFSSTA_WANTSND;
- (void) msleep(statep, &rep->r_nmp->nm_mtx,
- slpflag | (PZERO - 1), "nfsndlck", slptimeo);
- if (slpflag == PCATCH) {
- slpflag = 0;
- slptimeo = 2 * hz;
- }
- }
- *statep |= NFSSTA_SNDLOCK;
- return (0);
-}
-
-/*
- * Unlock the stream socket for others.
- */
-void
-nfs_connect_unlock(struct nfsreq *rep)
-{
- int *statep = &rep->r_nmp->nm_state;
-
- if ((*statep & NFSSTA_SNDLOCK) == 0)
- panic("nfs sndunlock");
- *statep &= ~NFSSTA_SNDLOCK;
- if (*statep & NFSSTA_WANTSND) {
- *statep &= ~NFSSTA_WANTSND;
- wakeup(statep);
- }
-}
-
-/*
- * nfs_realign:
- *
- * Check for badly aligned mbuf data and realign by copying the unaligned
- * portion of the data into a new mbuf chain and freeing the portions
- * of the old chain that were replaced.
- *
- * We cannot simply realign the data within the existing mbuf chain
- * because the underlying buffers may contain other rpc commands and
- * we cannot afford to overwrite them.
- *
- * We would prefer to avoid this situation entirely. The situation does
- * not occur with NFS/UDP and is supposed to only occassionally occur
- * with TCP. Use vfs.nfs.realign_count and realign_test to check this.
- *
- */
-static int
-nfs_realign(struct mbuf **pm, int hsiz)
-{
- struct mbuf *m;
- struct mbuf *n = NULL;
- int off = 0;
-
- ++nfs_realign_test;
- while ((m = *pm) != NULL) {
- if ((m->m_len & 0x3) || (mtod(m, intptr_t) & 0x3)) {
- MGET(n, M_DONTWAIT, MT_DATA);
- if (n == NULL)
- return (ENOMEM);
- if (m->m_len >= MINCLSIZE) {
- MCLGET(n, M_DONTWAIT);
- if (n->m_ext.ext_buf == NULL) {
- m_freem(n);
- return (ENOMEM);
- }
- }
- n->m_len = 0;
- break;
- }
- pm = &m->m_next;
- }
- /*
- * If n is non-NULL, loop on m copying data, then replace the
- * portion of the chain that had to be realigned.
- */
- if (n != NULL) {
- ++nfs_realign_count;
- while (m) {
- m_copyback(n, off, m->m_len, mtod(m, caddr_t));
- off += m->m_len;
- m = m->m_next;
- }
- m_freem(*pm);
- *pm = n;
- }
- return (0);
-}
-
-
-static int
-nfs_msg(struct thread *td, const char *server, const char *msg, int error)
-{
- struct proc *p;
-
- p = td ? td->td_proc : NULL;
- if (error) {
- tprintf(p, LOG_INFO, "nfs server %s: %s, error %d\n", server,
- msg, error);
- } else {
- tprintf(p, LOG_INFO, "nfs server %s: %s\n", server, msg);
- }
- return (0);
-}
-
-void
-nfs_down(rep, nmp, td, msg, error, flags)
- struct nfsreq *rep;
- struct nfsmount *nmp;
- struct thread *td;
- const char *msg;
- int error, flags;
-{
- if (nmp == NULL)
- return;
- mtx_lock(&nmp->nm_mtx);
- if ((flags & NFSSTA_TIMEO) && !(nmp->nm_state & NFSSTA_TIMEO)) {
- nmp->nm_state |= NFSSTA_TIMEO;
- mtx_unlock(&nmp->nm_mtx);
- vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid,
- VQ_NOTRESP, 0);
- } else
- mtx_unlock(&nmp->nm_mtx);
-#ifdef NFSSTA_LOCKTIMEO
- mtx_lock(&nmp->nm_mtx);
- if ((flags & NFSSTA_LOCKTIMEO) && !(nmp->nm_state & NFSSTA_LOCKTIMEO)) {
- nmp->nm_state |= NFSSTA_LOCKTIMEO;
- mtx_unlock(&nmp->nm_mtx);
- vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid,
- VQ_NOTRESPLOCK, 0);
- } else
- mtx_unlock(&nmp->nm_mtx);
-#endif
- if (rep != NULL) {
- mtx_lock(&rep->r_mtx);
- rep->r_flags |= R_TPRINTFMSG;
- mtx_unlock(&rep->r_mtx);
- }
- nfs_msg(td, nmp->nm_mountp->mnt_stat.f_mntfromname, msg, error);
-}
-
-void
-nfs_up(rep, nmp, td, msg, flags)
- struct nfsreq *rep;
- struct nfsmount *nmp;
- struct thread *td;
- const char *msg;
- int flags;
-{
- if (nmp == NULL || rep == NULL)
- return;
- mtx_lock(&rep->r_mtx);
- if ((rep->r_flags & R_TPRINTFMSG) != 0) {
- mtx_unlock(&rep->r_mtx);
- nfs_msg(td, nmp->nm_mountp->mnt_stat.f_mntfromname, msg, 0);
- } else
- mtx_unlock(&rep->r_mtx);
-
- mtx_lock(&nmp->nm_mtx);
- if ((flags & NFSSTA_TIMEO) && (nmp->nm_state & NFSSTA_TIMEO)) {
- nmp->nm_state &= ~NFSSTA_TIMEO;
- mtx_unlock(&nmp->nm_mtx);
- vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid,
- VQ_NOTRESP, 1);
- } else
- mtx_unlock(&nmp->nm_mtx);
-
-#ifdef NFSSTA_LOCKTIMEO
- mtx_lock(&nmp->nm_mtx);
- if ((flags & NFSSTA_LOCKTIMEO) && (nmp->nm_state & NFSSTA_LOCKTIMEO)) {
- nmp->nm_state &= ~NFSSTA_LOCKTIMEO;
- mtx_unlock(&nmp->nm_mtx);
- vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid,
- VQ_NOTRESPLOCK, 1);
- } else
- mtx_unlock(&nmp->nm_mtx);
-#endif
-}
-
-#endif /* NFS_LEGACYRPC */
diff --git a/sys/nfsclient/nfs_subs.c b/sys/nfsclient/nfs_subs.c
index 71d4fb1..6f4ef7b 100644
--- a/sys/nfsclient/nfs_subs.c
+++ b/sys/nfsclient/nfs_subs.c
@@ -65,7 +65,6 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_extern.h>
#include <vm/uma.h>
-#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
#include <nfsclient/nfsnode.h>
@@ -105,8 +104,6 @@ uint32_t nfsclient_attrcache_load_done_id;
* This is kinda hokey, but may save a little time doing byte swaps
*/
u_int32_t nfs_xdrneg1;
-u_int32_t rpc_call, rpc_vers, rpc_reply, rpc_msgdenied, rpc_autherr,
- rpc_mismatch, rpc_auth_unix, rpc_msgaccepted;
u_int32_t nfs_true, nfs_false;
/* And other global data */
@@ -118,10 +115,6 @@ static enum vtype nv2tov_type[8]= {
int nfs_ticks;
int nfs_pbuf_freecnt = -1; /* start out unlimited */
-#ifdef NFS_LEGACYRPC
-struct nfs_reqq nfs_reqq;
-struct mtx nfs_reqq_mtx;
-#endif
struct nfs_bufq nfs_bufq;
static struct mtx nfs_xid_mtx;
@@ -194,87 +187,6 @@ nfsm_reqhead(struct vnode *vp, u_long procid, int hsiz)
}
/*
- * Build the RPC header and fill in the authorization info.
- * The authorization string argument is only used when the credentials
- * come from outside of the kernel.
- * Returns the head of the mbuf list.
- */
-struct mbuf *
-nfsm_rpchead(struct ucred *cr, int nmflag, int procid, int auth_type,
- int auth_len, struct mbuf *mrest, int mrest_len, struct mbuf **mbp,
- u_int32_t **xidpp)
-{
- struct mbuf *mb;
- u_int32_t *tl;
- caddr_t bpos;
- int i;
- struct mbuf *mreq;
- int grpsiz, authsiz;
-
- authsiz = nfsm_rndup(auth_len);
- MGETHDR(mb, M_WAIT, MT_DATA);
- if ((authsiz + 10 * NFSX_UNSIGNED) >= MINCLSIZE) {
- MCLGET(mb, M_WAIT);
- } else if ((authsiz + 10 * NFSX_UNSIGNED) < MHLEN) {
- MH_ALIGN(mb, authsiz + 10 * NFSX_UNSIGNED);
- } else {
- MH_ALIGN(mb, 8 * NFSX_UNSIGNED);
- }
- mb->m_len = 0;
- mreq = mb;
- bpos = mtod(mb, caddr_t);
-
- /*
- * First the RPC header.
- */
- tl = nfsm_build(u_int32_t *, 8 * NFSX_UNSIGNED);
-
- *xidpp = tl;
- *tl++ = txdr_unsigned(nfs_xid_gen());
- *tl++ = rpc_call;
- *tl++ = rpc_vers;
- *tl++ = txdr_unsigned(NFS_PROG);
- if (nmflag & NFSMNT_NFSV3) {
- *tl++ = txdr_unsigned(NFS_VER3);
- *tl++ = txdr_unsigned(procid);
- } else {
- *tl++ = txdr_unsigned(NFS_VER2);
- *tl++ = txdr_unsigned(nfsv2_procid[procid]);
- }
-
- /*
- * And then the authorization cred.
- */
- *tl++ = txdr_unsigned(auth_type);
- *tl = txdr_unsigned(authsiz);
- switch (auth_type) {
- case RPCAUTH_UNIX:
- tl = nfsm_build(u_int32_t *, auth_len);
- *tl++ = 0; /* stamp ?? */
- *tl++ = 0; /* NULL hostname */
- *tl++ = txdr_unsigned(cr->cr_uid);
- *tl++ = txdr_unsigned(cr->cr_groups[0]);
- grpsiz = (auth_len >> 2) - 5;
- *tl++ = txdr_unsigned(grpsiz);
- for (i = 1; i <= grpsiz; i++)
- *tl++ = txdr_unsigned(cr->cr_groups[i]);
- break;
- }
-
- /*
- * And the verifier...
- */
- tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(RPCAUTH_NULL);
- *tl = 0;
- mb->m_next = mrest;
- mreq->m_pkthdr.len = authsiz + 10 * NFSX_UNSIGNED + mrest_len;
- mreq->m_pkthdr.rcvif = NULL;
- *mbp = mb;
- return (mreq);
-}
-
-/*
* copies a uio scatter/gather list to an mbuf chain.
* NOTE: can ony handle iovcnt == 1
*/
@@ -427,14 +339,6 @@ nfs_init(struct vfsconf *vfsp)
nfsmount_zone = uma_zcreate("NFSMOUNT", sizeof(struct nfsmount),
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
- rpc_vers = txdr_unsigned(RPC_VER2);
- rpc_call = txdr_unsigned(RPC_CALL);
- rpc_reply = txdr_unsigned(RPC_REPLY);
- rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);
- rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
- rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
- rpc_autherr = txdr_unsigned(RPC_AUTHERR);
- rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
nfs_true = txdr_unsigned(TRUE);
nfs_false = txdr_unsigned(FALSE);
nfs_xdrneg1 = txdr_unsigned(-1);
@@ -451,11 +355,6 @@ nfs_init(struct vfsconf *vfsp)
/*
* Initialize reply list and start timer
*/
-#ifdef NFS_LEGACYRPC
- TAILQ_INIT(&nfs_reqq);
- mtx_init(&nfs_reqq_mtx, "NFS reqq lock", NULL, MTX_DEF);
- callout_init(&nfs_callout, CALLOUT_MPSAFE);
-#endif
mtx_init(&nfs_iod_mtx, "NFS iod lock", NULL, MTX_DEF);
mtx_init(&nfs_xid_mtx, "NFS xid lock", NULL, MTX_DEF);
@@ -469,13 +368,6 @@ nfs_uninit(struct vfsconf *vfsp)
{
int i;
-#ifdef NFS_LEGACYRPC
- callout_stop(&nfs_callout);
-
- KASSERT(TAILQ_EMPTY(&nfs_reqq),
- ("nfs_uninit: request queue not empty"));
-#endif
-
/*
* Tell all nfsiod processes to exit. Clear nfs_iodmax, and wakeup
* any sleeping nfsiods so they check nfs_iodmax and exit.
diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c
index 6a28eab..599aea0 100644
--- a/sys/nfsclient/nfs_vfsops.c
+++ b/sys/nfsclient/nfs_vfsops.c
@@ -68,7 +68,6 @@ __FBSDID("$FreeBSD$");
#include <rpc/rpc.h>
-#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
#include <nfsclient/nfsnode.h>
@@ -142,9 +141,7 @@ VFS_SET(nfs_vfsops, nfs, VFCF_NETWORK);
/* So that loader and kldload(2) can find us, wherever we are.. */
MODULE_VERSION(nfs, 1);
-#ifndef NFS_LEGACYRPC
MODULE_DEPEND(nfs, krpc, 1, 1, 1);
-#endif
#ifdef KGSSAPI
MODULE_DEPEND(nfs, kgssapi, 1, 1, 1);
#endif
@@ -551,7 +548,6 @@ nfs_mountdiskless(char *path,
return (0);
}
-#ifndef NFS_LEGACYRPC
static int
nfs_sec_name_to_num(char *sec)
{
@@ -569,7 +565,6 @@ nfs_sec_name_to_num(char *sec)
*/
return (AUTH_SYS);
}
-#endif
static void
nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
@@ -579,10 +574,8 @@ nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
int adjsock;
int maxio;
char *p;
-#ifndef NFS_LEGACYRPC
char *secname;
char *principal;
-#endif
s = splnet();
@@ -734,13 +727,7 @@ nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
nmp->nm_sotype = argp->sotype;
nmp->nm_soproto = argp->proto;
- if (
-#ifdef NFS_LEGACYRPC
- nmp->nm_so
-#else
- nmp->nm_client
-#endif
- && adjsock) {
+ if (nmp->nm_client && adjsock) {
nfs_safedisconnect(nmp);
if (nmp->nm_sotype == SOCK_DGRAM)
while (nfs_connect(nmp, NULL)) {
@@ -757,7 +744,6 @@ nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
*p = '\0';
}
-#ifndef NFS_LEGACYRPC
if (vfs_getopt(mp->mnt_optnew, "sec",
(void **) &secname, NULL) == 0) {
nmp->nm_secflavor = nfs_sec_name_to_num(secname);
@@ -773,7 +759,6 @@ nfs_decode_args(struct mount *mp, struct nfsmount *nmp, struct nfs_args *argp,
snprintf(nmp->nm_principal, sizeof(nmp->nm_principal),
"nfs@%s", nmp->nm_hostname);
}
-#endif
}
static const char *nfs_opts[] = { "from", "nfs_args",
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c
index bc6936d..e557321 100644
--- a/sys/nfsclient/nfs_vnops.c
+++ b/sys/nfsclient/nfs_vnops.c
@@ -70,7 +70,6 @@ __FBSDID("$FreeBSD$");
#include <fs/fifofs/fifo.h>
-#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
#include <nfsclient/nfsnode.h>
@@ -3193,7 +3192,7 @@ loop:
&np->n_mtx, slpflag | (PRIBIO + 1),
"nfsfsync", 0);
if (error) {
- if (nfs_sigintr(nmp, (struct nfsreq *)0, td)) {
+ if (nfs_sigintr(nmp, NULL, td)) {
mtx_unlock(&np->n_mtx);
error = EINTR;
goto done;
diff --git a/sys/nfsclient/nfsm_subs.h b/sys/nfsclient/nfsm_subs.h
index 51d2611..583aec1 100644
--- a/sys/nfsclient/nfsm_subs.h
+++ b/sys/nfsclient/nfsm_subs.h
@@ -54,10 +54,6 @@ struct vnode;
*/
u_int32_t nfs_xid_gen(void);
struct mbuf *nfsm_reqhead(struct vnode *vp, u_long procid, int hsiz);
-struct mbuf *nfsm_rpchead(struct ucred *cr, int nmflag, int procid,
- int auth_type, int auth_len,
- struct mbuf *mrest, int mrest_len,
- struct mbuf **mbp, u_int32_t **xidpp);
#define M_HASCL(m) ((m)->m_flags & M_EXT)
#define NFSMINOFF(m) \
diff --git a/sys/nfsclient/nfsmount.h b/sys/nfsclient/nfsmount.h
index 85f8501..99d12d9 100644
--- a/sys/nfsclient/nfsmount.h
+++ b/sys/nfsclient/nfsmount.h
@@ -36,36 +36,11 @@
#ifndef _NFSCLIENT_NFSMOUNT_H_
#define _NFSCLIENT_NFSMOUNT_H_
-#ifndef NFS_LEGACYRPC
-
-#undef RPC_SUCCESS
-#undef RPC_PROGUNAVAIL
-#undef RPC_PROCUNAVAIL
-#undef AUTH_OK
-#undef AUTH_BADCRED
-#undef AUTH_BADVERF
-#undef AUTH_TOOWEAK
-
#include <rpc/types.h>
#include <rpc/auth.h>
#include <rpc/clnt.h>
#include <rpc/rpcsec_gss.h>
-#endif
-
-#ifdef NFS_LEGACYRPC
-
-struct nfs_tcp_mountstate {
- int rpcresid;
-#define NFS_TCP_EXPECT_RPCMARKER 0x0001 /* Expect to see a RPC/TCP marker next */
-#define NFS_TCP_FORCE_RECONNECT 0x0002 /* Force a TCP reconnect */
-#define NFS_TCP_WAIT_WRITE_DRAIN 0x0004 /* Waiting for socket writers to finish */
- int flags;
- int sock_send_inprog;
-};
-
-#endif
-
/*
* Mount structure.
* One allocated on every NFS mount.
@@ -79,22 +54,12 @@ struct nfsmount {
int nm_numgrps; /* Max. size of groupslist */
u_char nm_fh[NFSX_V4FH]; /* File handle of root dir */
int nm_fhsize; /* Size of root file handle */
-#ifdef NFS_LEGACYRPC
- struct socket *nm_so; /* Rpc socket */
-#endif
int nm_sotype; /* Type of socket */
int nm_soproto; /* and protocol */
int nm_soflags; /* pr_flags for socket protocol */
struct sockaddr *nm_nam; /* Addr of server */
int nm_timeo; /* Init timer for NFSMNT_DUMBTIMR */
int nm_retry; /* Max retries */
-#ifdef NFS_LEGACYRPC
- int nm_srtt[NFS_MAX_TIMER], /* RTT Timers for rpcs */
- nm_sdrtt[NFS_MAX_TIMER];
- int nm_sent; /* Request send count */
- int nm_cwnd; /* Request send window */
- int nm_timeouts; /* Request timeouts */
-#endif
int nm_deadthresh; /* Threshold of timeouts-->dead server*/
int nm_rsize; /* Max size of read rpc */
int nm_wsize; /* Max size of write rpc */
@@ -114,17 +79,12 @@ struct nfsmount {
struct nfs_rpcops *nm_rpcops;
int nm_tprintf_initial_delay; /* initial delay */
int nm_tprintf_delay; /* interval for messages */
-#ifdef NFS_LEGACYRPC
- struct nfs_tcp_mountstate nm_nfstcpstate;
-#endif
char nm_hostname[MNAMELEN]; /* server's name */
-#ifndef NFS_LEGACYRPC
int nm_secflavor; /* auth flavor to use for rpc */
struct __rpc_client *nm_client;
struct rpc_timers nm_timers[NFS_MAX_TIMER]; /* RTT Timers for rpcs */
char nm_principal[MNAMELEN]; /* GSS-API principal of server */
gss_OID nm_mech_oid; /* OID of selected GSS-API mechanism */
-#endif
/* NFSv4 */
uint64_t nm_clientid;
diff --git a/sys/nfsserver/nfs.h b/sys/nfsserver/nfs.h
index 25fe8ae..b907a06 100644
--- a/sys/nfsserver/nfs.h
+++ b/sys/nfsserver/nfs.h
@@ -176,102 +176,6 @@ extern int32_t (*nfsrv3_procs[NFS_NPROCS])(struct nfsrv_descript *nd,
#define NWDELAYHASH(sock, f) \
(&(sock)->ns_wdelayhashtbl[(*((u_int32_t *)(f))) % NFS_WDELAYHASHSIZ])
-#ifdef NFS_LEGACYRPC
-/*
- * Network address hash list element
- */
-union nethostaddr {
- u_int32_t had_inetaddr;
- struct sockaddr *had_nam;
-};
-
-struct nfsrv_rec {
- STAILQ_ENTRY(nfsrv_rec) nr_link;
- struct sockaddr *nr_address;
- struct mbuf *nr_packet;
-};
-
-struct nfssvc_sock {
- TAILQ_ENTRY(nfssvc_sock) ns_chain; /* List of all nfssvc_sock's */
- struct file *ns_fp;
- struct socket *ns_so;
- struct sockaddr *ns_nam;
- struct mbuf *ns_raw;
- struct mbuf *ns_rawend;
- STAILQ_HEAD(, nfsrv_rec) ns_rec;
- struct mbuf *ns_frag;
- int ns_flag;
- int ns_solock;
- int ns_cc;
- int ns_reclen;
- u_int32_t ns_sref;
- LIST_HEAD(, nfsrv_descript) ns_tq; /* Write gather lists */
- LIST_HEAD(nfsrvw_delayhash, nfsrv_descript) ns_wdelayhashtbl[NFS_WDELAYHASHSIZ];
-};
-
-/* Bits for "ns_flag" */
-#define SLP_VALID 0x01 /* Socket valid for use (XXX) */
-#define SLP_DOREC 0x02 /* Socket ready for processing */
-#define SLP_NEEDQ 0x04 /* Socket has request queued */
-#define SLP_DISCONN 0x08 /* Error received from stream socket */
-#define SLP_GETSTREAM 0x10 /* nfsrv_getstream in prog on sock */
-#define SLP_LASTFRAG 0x20 /* Socket received end-of-record */
-#define SLP_ALLFLAGS 0xff
-
-extern TAILQ_HEAD(nfssvc_sockhead, nfssvc_sock) nfssvc_sockhead;
-extern int nfssvc_sockhead_flag;
-#define SLP_INIT 0x01
-#define SLP_WANTINIT 0x02
-
-/*
- * One of these structures is allocated for each nfsd.
- */
-struct nfsd {
- 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 nfsrv_descript *nfsd_nd; /* Associated nfsrv_descript */
-};
-
-/* Bits for "nfsd_flag" */
-#define NFSD_WAITING 0x01
-#define NFSD_REQINPROG 0x02
-
-/*
- * 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 sockaddr *nd_nam; /* and socket addr */
- struct sockaddr *nd_nam2; /* return socket addr */
- caddr_t nd_dpos; /* Current dissect pos */
- u_int32_t 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_int32_t nd_retxid; /* Reply xid */
- struct timeval nd_starttime; /* Time RPC initiated */
- fhandle_t nd_fh; /* File handle */
- struct ucred *nd_cr; /* Credentials */
- int nd_credflavor; /* Security flavor */
-};
-
-#else
-
/*
* This structure is used by the server for describing each request.
*/
@@ -291,26 +195,9 @@ struct nfsrv_descript {
int nd_credflavor; /* Security flavor */
};
-#endif
-
/* Bits for "nd_flag" */
#define ND_NFSV3 0x08
-#ifdef NFS_LEGACYRPC
-
-extern TAILQ_HEAD(nfsd_head, nfsd) nfsd_head;
-extern 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))
-
-#endif
-
/*
* Defines for WebNFS
*/
@@ -353,26 +240,6 @@ extern int nfs_debug;
#endif
-#ifdef NFS_LEGACYRPC
-int netaddr_match(int, union nethostaddr *, struct sockaddr *);
-int nfs_getreq(struct nfsrv_descript *, struct nfsd *, int);
-int nfsrv_send(struct socket *, struct sockaddr *, struct mbuf *);
-int nfsrv_dorec(struct nfssvc_sock *, struct nfsd *,
- struct nfsrv_descript **);
-int nfs_slplock(struct nfssvc_sock *, int);
-void nfs_slpunlock(struct nfssvc_sock *);
-void nfsrv_initcache(void);
-void nfsrv_destroycache(void);
-void nfsrv_timer(void *);
-int nfsrv_getcache(struct nfsrv_descript *, struct mbuf **);
-void nfsrv_updatecache(struct nfsrv_descript *, int, struct mbuf *);
-void nfsrv_cleancache(void);
-int nfsrv_rcv(struct socket *so, void *arg, int waitflag);
-void nfsrv_slpderef(struct nfssvc_sock *slp);
-void nfsrv_wakenfsd(struct nfssvc_sock *slp);
-int nfsrv_writegather(struct nfsrv_descript **, struct nfssvc_sock *,
- struct mbuf **);
-#endif
struct mbuf *nfs_rephead(int, struct nfsrv_descript *, int, struct mbuf **,
caddr_t *);
void nfsm_srvfattr(struct nfsrv_descript *, struct vattr *,
diff --git a/sys/nfsserver/nfs_fha.c b/sys/nfsserver/nfs_fha.c
index 27dc9b3..901a0ce 100644
--- a/sys/nfsserver/nfs_fha.c
+++ b/sys/nfsserver/nfs_fha.c
@@ -39,14 +39,11 @@ __FBSDID("$FreeBSD$");
#include <rpc/rpc.h>
#include <nfs/xdr_subs.h>
-#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsserver/nfs.h>
#include <nfsserver/nfsm_subs.h>
#include <nfsserver/nfs_fha.h>
-#ifndef NFS_LEGACYRPC
-
static MALLOC_DEFINE(M_NFS_FHA, "NFS FHA", "NFS FHA");
/* Sysctl defaults. */
@@ -598,5 +595,3 @@ fhe_stats_sysctl(SYSCTL_HANDLER_ARGS)
sbuf_delete(&sb);
return (error);
}
-
-#endif /* !NFS_LEGACYRPC */
diff --git a/sys/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c
index b6a61a8..00be15e 100644
--- a/sys/nfsserver/nfs_serv.c
+++ b/sys/nfsserver/nfs_serv.c
@@ -93,7 +93,6 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_object.h>
#include <nfs/nfsproto.h>
-#include <nfs/rpcv2.h>
#include <nfsserver/nfs.h>
#include <nfs/xdr_subs.h>
#include <nfsserver/nfsm_subs.h>
@@ -142,10 +141,6 @@ SYSCTL_STRUCT(_vfs_nfsrv, NFS_NFSRVSTATS, nfsrvstats, CTLFLAG_RW,
static int nfsrv_access(struct vnode *, accmode_t, struct ucred *,
int, int);
-#ifdef NFS_LEGACYRPC
-static void nfsrvw_coalesce(struct nfsrv_descript *,
- struct nfsrv_descript *);
-#endif
/*
* Clear nameidata fields that are tested in nsfmout cleanup code prior
@@ -1229,425 +1224,6 @@ nfsmout:
return(error);
}
-#ifdef NFS_LEGACYRPC
-
-/*
- * XXX dfr - write gathering isn't supported by the new RPC code since
- * its really only useful for NFSv2. If there is a real need, we could
- * attempt to fit it into the filehandle affinity system, e.g. by
- * looking to see if there are queued write requests that overlap this
- * one.
- */
-
-/*
- * For the purposes of write gathering, we must decide if the credential
- * associated with two pending requests have equivilent privileges. Since
- * NFS only uses a subset of the BSD ucred -- the effective uid and group
- * IDs -- we have a compare routine that checks only the relevant fields.
- */
-static int
-nfsrv_samecred(struct ucred *cr1, struct ucred *cr2)
-{
- int i;
-
- if (cr1->cr_uid != cr2->cr_uid)
- return (0);
- if (cr1->cr_ngroups != cr2->cr_ngroups)
- return (0);
- for (i = 0; i < cr1->cr_ngroups; i++) {
- if (cr1->cr_groups[i] != cr2->cr_groups[i])
- return (0);
- }
- return (1);
-}
-
-/*
- * NFS write service with write gathering support. Called when
- * nfsrvw_procrastinate > 0.
- * See: Chet Juszczak, "Improving the Write Performance of an NFS Server",
- * in Proc. of the Winter 1994 Usenix Conference, pg. 247-259, San Franscisco,
- * Jan. 1994.
- */
-int
-nfsrv_writegather(struct nfsrv_descript **ndp, struct nfssvc_sock *slp,
- struct mbuf **mrq)
-{
- struct iovec *ivp;
- struct mbuf *mp;
- struct nfsrv_descript *wp, *nfsd, *owp, *swp;
- struct nfs_fattr *fp;
- int i;
- struct iovec *iov;
- struct nfsrvw_delayhash *wpp;
- struct ucred *cred;
- struct vattr va, forat;
- u_int32_t *tl;
- caddr_t bpos, dpos;
- int error = 0, rdonly, len, forat_ret = 1;
- int ioflags, aftat_ret = 1, s, adjust, v3, zeroing;
- struct mbuf *mb, *mreq, *mrep, *md;
- struct vnode *vp = NULL;
- struct uio io, *uiop = &io;
- u_quad_t cur_usec;
- struct mount *mntp = NULL;
- int mvfslocked;
- int vfslocked;
-
- nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
-#ifndef nolint
- i = 0;
- len = 0;
-#endif
- vfslocked = 0;
- *mrq = NULL;
- if (*ndp) {
- nfsd = *ndp;
- *ndp = NULL;
- mrep = nfsd->nd_mrep;
- md = nfsd->nd_md;
- dpos = nfsd->nd_dpos;
- cred = nfsd->nd_cr;
- v3 = (nfsd->nd_flag & ND_NFSV3);
- LIST_INIT(&nfsd->nd_coalesce);
- nfsd->nd_mreq = NULL;
- nfsd->nd_stable = NFSV3WRITE_FILESYNC;
- cur_usec = nfs_curusec();
- nfsd->nd_time = cur_usec +
- (v3 ? nfsrvw_procrastinate_v3 : nfsrvw_procrastinate);
-
- /*
- * Now, get the write header..
- */
- nfsm_srvmtofh(&nfsd->nd_fh);
- if (v3) {
- tl = nfsm_dissect_nonblock(u_int32_t *, 5 * NFSX_UNSIGNED);
- nfsd->nd_off = fxdr_hyper(tl);
- tl += 3;
- nfsd->nd_stable = fxdr_unsigned(int, *tl++);
- } else {
- tl = nfsm_dissect_nonblock(u_int32_t *, 4 * NFSX_UNSIGNED);
- nfsd->nd_off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
- tl += 2;
- if (nfs_async)
- nfsd->nd_stable = NFSV3WRITE_UNSTABLE;
- }
- len = fxdr_unsigned(int32_t, *tl);
- nfsd->nd_len = len;
- nfsd->nd_eoff = nfsd->nd_off + len;
-
- /*
- * Trim the header out of the mbuf list and trim off any trailing
- * junk so that the mbuf list has only the write data.
- */
- zeroing = 1;
- i = 0;
- mp = mrep;
- while (mp) {
- if (mp == md) {
- zeroing = 0;
- adjust = dpos - mtod(mp, caddr_t);
- mp->m_len -= adjust;
- if (mp->m_len > 0 && adjust > 0)
- mp->m_data += adjust;
- }
- if (zeroing)
- mp->m_len = 0;
- else {
- i += mp->m_len;
- if (i > len) {
- mp->m_len -= (i - len);
- zeroing = 1;
- }
- }
- mp = mp->m_next;
- }
- if (len > NFS_MAXDATA || len < 0 || i < len) {
-nfsmout:
- m_freem(mrep);
- error = EIO;
- nfsm_writereply(2 * NFSX_UNSIGNED);
- if (v3)
- nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
- nfsd->nd_mreq = mreq;
- nfsd->nd_mrep = NULL;
- nfsd->nd_time = 0;
- }
-
- /*
- * Add this entry to the hash and time queues.
- */
- s = splsoftclock();
- owp = NULL;
- wp = LIST_FIRST(&slp->ns_tq);
- while (wp && wp->nd_time < nfsd->nd_time) {
- owp = wp;
- wp = LIST_NEXT(wp, nd_tq);
- }
- NFS_DPF(WG, ("Q%03x", nfsd->nd_retxid & 0xfff));
- if (owp) {
- LIST_INSERT_AFTER(owp, nfsd, nd_tq);
- } else {
- LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
- }
- if (nfsd->nd_mrep) {
- wpp = NWDELAYHASH(slp, nfsd->nd_fh.fh_fid.fid_data);
- owp = NULL;
- wp = LIST_FIRST(wpp);
- while (wp &&
- bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh, NFSX_V3FH)){
- owp = wp;
- wp = LIST_NEXT(wp, nd_hash);
- }
- while (wp && wp->nd_off < nfsd->nd_off &&
- !bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh, NFSX_V3FH)) {
- owp = wp;
- wp = LIST_NEXT(wp, nd_hash);
- }
- if (owp) {
- LIST_INSERT_AFTER(owp, nfsd, nd_hash);
-
- /*
- * Search the hash list for overlapping entries and
- * coalesce.
- */
- for(; nfsd && NFSW_CONTIG(owp, nfsd); nfsd = wp) {
- wp = LIST_NEXT(nfsd, nd_hash);
- if (nfsrv_samecred(owp->nd_cr, nfsd->nd_cr))
- nfsrvw_coalesce(owp, nfsd);
- }
- } else {
- LIST_INSERT_HEAD(wpp, nfsd, nd_hash);
- }
- }
- splx(s);
- }
-
- /*
- * Now, do VOP_WRITE()s for any one(s) that need to be done now
- * and generate the associated reply mbuf list(s).
- */
-loop1:
- cur_usec = nfs_curusec();
- s = splsoftclock();
- for (nfsd = LIST_FIRST(&slp->ns_tq); nfsd; nfsd = owp) {
- owp = LIST_NEXT(nfsd, nd_tq);
- if (nfsd->nd_time > cur_usec)
- break;
- if (nfsd->nd_mreq)
- continue;
- NFS_DPF(WG, ("P%03x", nfsd->nd_retxid & 0xfff));
- LIST_REMOVE(nfsd, nd_tq);
- LIST_REMOVE(nfsd, nd_hash);
- splx(s);
- mrep = nfsd->nd_mrep;
- nfsd->nd_mrep = NULL;
- cred = nfsd->nd_cr;
- v3 = (nfsd->nd_flag & ND_NFSV3);
- forat_ret = aftat_ret = 1;
- error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, &vfslocked, nfsd,
- slp, nfsd->nd_nam, &rdonly, TRUE);
- if (!error) {
- if (v3)
- forat_ret = VOP_GETATTR(vp, &forat, cred);
- if (vp->v_type != VREG) {
- if (v3)
- error = EINVAL;
- else
- error = (vp->v_type == VDIR) ? EISDIR : EACCES;
- }
- } else {
- vp = NULL;
- }
- if (!error)
- error = nfsrv_access(vp, VWRITE, cred, rdonly, 1);
- if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE)
- ioflags = IO_NODELOCKED;
- else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC)
- ioflags = (IO_SYNC | IO_NODELOCKED);
- else
- ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
- uiop->uio_rw = UIO_WRITE;
- uiop->uio_segflg = UIO_SYSSPACE;
- uiop->uio_td = NULL;
- uiop->uio_offset = nfsd->nd_off;
- uiop->uio_resid = nfsd->nd_eoff - nfsd->nd_off;
- if (uiop->uio_resid > 0) {
- mp = mrep;
- i = 0;
- while (mp) {
- if (mp->m_len > 0)
- i++;
- mp = mp->m_next;
- }
- uiop->uio_iovcnt = i;
- iov = malloc(i * sizeof (struct iovec),
- M_TEMP, M_WAITOK);
- uiop->uio_iov = ivp = iov;
- mp = mrep;
- while (mp) {
- if (mp->m_len > 0) {
- ivp->iov_base = mtod(mp, caddr_t);
- ivp->iov_len = mp->m_len;
- ivp++;
- }
- mp = mp->m_next;
- }
- mvfslocked = 0;
- if (!error) {
- if (vn_start_write(vp, &mntp, V_NOWAIT) != 0) {
- VOP_UNLOCK(vp, 0);
- error = vn_start_write(NULL, &mntp, V_WAIT);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- }
- mvfslocked = VFS_LOCK_GIANT(mntp);
- }
- if (!error) {
- error = VOP_WRITE(vp, uiop, ioflags, cred);
- /* Unlocked write. */
- nfsrvstats.srvvop_writes++;
- vn_finished_write(mntp);
- }
- VFS_UNLOCK_GIANT(mvfslocked);
- free((caddr_t)iov, M_TEMP);
- }
- m_freem(mrep);
- if (vp) {
- aftat_ret = VOP_GETATTR(vp, &va, cred);
- vput(vp);
- vp = NULL;
- }
- VFS_UNLOCK_GIANT(vfslocked);
- /*
- * Loop around generating replies for all write rpcs that have
- * now been completed.
- */
- swp = nfsd;
- do {
- NFS_DPF(WG, ("R%03x", nfsd->nd_retxid & 0xfff));
- if (error) {
- nfsm_writereply(NFSX_WCCDATA(v3));
- if (v3) {
- nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
- }
- } else {
- nfsm_writereply(NFSX_PREOPATTR(v3) +
- NFSX_POSTOPORFATTR(v3) + 2 * NFSX_UNSIGNED +
- NFSX_WRITEVERF(v3));
- if (v3) {
- nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
- tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
- *tl++ = txdr_unsigned(nfsd->nd_len);
- *tl++ = txdr_unsigned(swp->nd_stable);
- /*
- * Actually, there is no need to txdr these fields,
- * but it may make the values more human readable,
- * for debugging purposes.
- */
- if (nfsver.tv_sec == 0)
- nfsver = boottime;
- *tl++ = txdr_unsigned(nfsver.tv_sec);
- *tl = txdr_unsigned(nfsver.tv_usec);
- } else {
- fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
- nfsm_srvfillattr(&va, fp);
- }
- }
- nfsd->nd_mreq = mreq;
- if (nfsd->nd_mrep)
- panic("nfsrv_write: nd_mrep not free");
-
- /*
- * Done. Put it at the head of the timer queue so that
- * the final phase can return the reply.
- */
- s = splsoftclock();
- if (nfsd != swp) {
- nfsd->nd_time = 0;
- LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
- }
- nfsd = LIST_FIRST(&swp->nd_coalesce);
- if (nfsd) {
- LIST_REMOVE(nfsd, nd_tq);
- }
- splx(s);
- } while (nfsd);
- s = splsoftclock();
- swp->nd_time = 0;
- LIST_INSERT_HEAD(&slp->ns_tq, swp, nd_tq);
- splx(s);
- goto loop1;
- }
- splx(s);
-
- /*
- * Search for a reply to return.
- */
- s = splsoftclock();
- LIST_FOREACH(nfsd, &slp->ns_tq, nd_tq)
- if (nfsd->nd_mreq) {
- NFS_DPF(WG, ("X%03x", nfsd->nd_retxid & 0xfff));
- LIST_REMOVE(nfsd, nd_tq);
- *mrq = nfsd->nd_mreq;
- *ndp = nfsd;
- break;
- }
- splx(s);
- return (0);
-}
-
-/*
- * Coalesce the write request nfsd into owp. To do this we must:
- * - remove nfsd from the queues
- * - merge nfsd->nd_mrep into owp->nd_mrep
- * - update the nd_eoff and nd_stable for owp
- * - put nfsd on owp's nd_coalesce list
- * NB: Must be called at splsoftclock().
- */
-static void
-nfsrvw_coalesce(struct nfsrv_descript *owp, struct nfsrv_descript *nfsd)
-{
- int overlap;
- struct mbuf *mp;
- struct nfsrv_descript *p;
-
- NFS_DPF(WG, ("C%03x-%03x",
- nfsd->nd_retxid & 0xfff, owp->nd_retxid & 0xfff));
- LIST_REMOVE(nfsd, nd_hash);
- LIST_REMOVE(nfsd, nd_tq);
- if (owp->nd_eoff < nfsd->nd_eoff) {
- overlap = owp->nd_eoff - nfsd->nd_off;
- if (overlap < 0)
- panic("nfsrv_coalesce: bad off");
- if (overlap > 0)
- m_adj(nfsd->nd_mrep, overlap);
- mp = owp->nd_mrep;
- while (mp->m_next)
- mp = mp->m_next;
- mp->m_next = nfsd->nd_mrep;
- owp->nd_eoff = nfsd->nd_eoff;
- } else
- m_freem(nfsd->nd_mrep);
- nfsd->nd_mrep = NULL;
- if (nfsd->nd_stable == NFSV3WRITE_FILESYNC)
- owp->nd_stable = NFSV3WRITE_FILESYNC;
- else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC &&
- owp->nd_stable == NFSV3WRITE_UNSTABLE)
- owp->nd_stable = NFSV3WRITE_DATASYNC;
- LIST_INSERT_HEAD(&owp->nd_coalesce, nfsd, nd_tq);
-
- /*
- * If nfsd had anything else coalesced into it, transfer them
- * to owp, otherwise their replies will never get sent.
- */
- for (p = LIST_FIRST(&nfsd->nd_coalesce); p;
- p = LIST_FIRST(&nfsd->nd_coalesce)) {
- LIST_REMOVE(p, nd_tq);
- LIST_INSERT_HEAD(&owp->nd_coalesce, p, nd_tq);
- }
-}
-
-#endif
-
/*
* nfs create service
* now does a truncate to 0 length via. setattr if it already exists
diff --git a/sys/nfsserver/nfs_srvcache.c b/sys/nfsserver/nfs_srvcache.c
deleted file mode 100644
index 5121690..0000000
--- a/sys/nfsserver/nfs_srvcache.c
+++ /dev/null
@@ -1,391 +0,0 @@
-/*-
- * 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.
- * 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.
- *
- * @(#)nfs_srvcache.c 8.3 (Berkeley) 3/30/95
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * Reference: Chet Juszczak, "Improving the Performance and Correctness
- * of an NFS Server", in Proc. Winter 1989 USENIX Conference,
- * pages 53-63. San Diego, February 1989.
- */
-#include <sys/param.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/systm.h>
-#include <sys/lock.h>
-#include <sys/mbuf.h>
-#include <sys/mutex.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h> /* for sodupsockaddr */
-#include <sys/eventhandler.h>
-
-#include <netinet/in.h>
-#include <nfs/rpcv2.h>
-#include <nfs/nfsproto.h>
-#include <nfsserver/nfs.h>
-#include <nfsserver/nfsrvcache.h>
-
-#ifdef NFS_LEGACYRPC
-
-static long numnfsrvcache;
-static long desirednfsrvcache;
-
-#define NFSRCHASH(xid) \
- (&nfsrvhashtbl[((xid) + ((xid) >> 24)) & nfsrvhash])
-static LIST_HEAD(nfsrvhash, nfsrvcache) *nfsrvhashtbl;
-static TAILQ_HEAD(nfsrvlru, nfsrvcache) nfsrvlruhead;
-static u_long nfsrvhash;
-static eventhandler_tag nfsrv_nmbclusters_tag;
-
-#define TRUE 1
-#define FALSE 0
-
-#define NETFAMILY(rp) \
- (((rp)->rc_flag & RC_NAM) ? (rp)->rc_nam->sa_family : AF_INET)
-
-/*
- * Static array that defines which nfs rpc's are nonidempotent
- */
-static const int nonidempotent[NFS_NPROCS] = {
- FALSE,
- FALSE,
- TRUE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- TRUE,
- TRUE,
- TRUE,
- TRUE,
- TRUE,
- TRUE,
- TRUE,
- TRUE,
- TRUE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
-};
-
-/* True iff the rpc reply is an nfs status ONLY! */
-static const int nfsv2_repstat[NFS_NPROCS] = {
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- FALSE,
- TRUE,
- TRUE,
- TRUE,
- TRUE,
- FALSE,
- TRUE,
- FALSE,
- FALSE,
-};
-
-/*
- * Size the NFS server's duplicate request cache at 1/2 the nmbclsters, floating
- * within a (64, 2048) range. This is to prevent all mbuf clusters being tied up
- * in the NFS dupreq cache for small values of nmbclusters.
- */
-static void
-nfsrvcache_size_change(void *tag)
-{
- desirednfsrvcache = nmbclusters /2;
- if (desirednfsrvcache > NFSRVCACHE_MAX_SIZE)
- desirednfsrvcache = NFSRVCACHE_MAX_SIZE;
- if (desirednfsrvcache < NFSRVCACHE_MIN_SIZE)
- desirednfsrvcache = NFSRVCACHE_MIN_SIZE;
-}
-
-/*
- * Initialize the server request cache list
- */
-void
-nfsrv_initcache(void)
-{
- nfsrvcache_size_change(NULL);
- nfsrvhashtbl = hashinit(desirednfsrvcache, M_NFSD, &nfsrvhash);
- TAILQ_INIT(&nfsrvlruhead);
- nfsrv_nmbclusters_tag = EVENTHANDLER_REGISTER(nmbclusters_change,
- nfsrvcache_size_change, NULL, EVENTHANDLER_PRI_FIRST);
-}
-
-/*
- * Teardown the server request cache list
- */
-void
-nfsrv_destroycache(void)
-{
- KASSERT(TAILQ_EMPTY(&nfsrvlruhead), ("%s: pending requests", __func__));
- EVENTHANDLER_DEREGISTER(nmbclusters_change, nfsrv_nmbclusters_tag);
- hashdestroy(nfsrvhashtbl, M_NFSD, nfsrvhash);
-}
-
-/*
- * Look for the request in the cache
- * If found then
- * return action and optionally reply
- * else
- * insert it in the cache
- *
- * The rules are as follows:
- * - if in progress, return DROP request
- * - if completed within DELAY of the current time, return DROP it
- * - if completed a longer time ago return REPLY if the reply was cached or
- * return DOIT
- * Update/add new request at end of lru list
- */
-int
-nfsrv_getcache(struct nfsrv_descript *nd, struct mbuf **repp)
-{
- struct nfsrvcache *rp;
- struct mbuf *mb;
- struct sockaddr_in *saddr;
- caddr_t bpos;
- int ret;
-
- NFSD_LOCK_ASSERT();
-
- /*
- * 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:
- LIST_FOREACH(rp, NFSRCHASH(nd->nd_retxid), rc_hash) {
- if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
- netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) {
- NFS_DPF(RC, ("H%03x", rp->rc_xid & 0xfff));
- if ((rp->rc_flag & RC_LOCKED) != 0) {
- rp->rc_flag |= RC_WANTED;
- (void) msleep(rp, &nfsd_mtx, PZERO-1,
- "nfsrc", 0);
- goto loop;
- }
- rp->rc_flag |= RC_LOCKED;
- /* If not at end of LRU chain, move it there */
- if (TAILQ_NEXT(rp, rc_lru)) {
- TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru);
- TAILQ_INSERT_TAIL(&nfsrvlruhead, rp, rc_lru);
- }
- if (rp->rc_state == RC_UNUSED)
- panic("nfsrv cache");
- if (rp->rc_state == RC_INPROG) {
- nfsrvstats.srvcache_inproghits++;
- ret = RC_DROPIT;
- } else if (rp->rc_flag & RC_REPSTATUS) {
- nfsrvstats.srvcache_nonidemdonehits++;
- NFSD_UNLOCK();
- *repp = nfs_rephead(0, nd, rp->rc_status,
- &mb, &bpos);
- ret = RC_REPLY;
- NFSD_LOCK();
- } else if (rp->rc_flag & RC_REPMBUF) {
- nfsrvstats.srvcache_nonidemdonehits++;
- NFSD_UNLOCK();
- *repp = m_copym(rp->rc_reply, 0, M_COPYALL,
- M_WAIT);
- NFSD_LOCK();
- ret = RC_REPLY;
- } else {
- nfsrvstats.srvcache_idemdonehits++;
- rp->rc_state = RC_INPROG;
- ret = RC_DOIT;
- }
- rp->rc_flag &= ~RC_LOCKED;
- if (rp->rc_flag & RC_WANTED) {
- rp->rc_flag &= ~RC_WANTED;
- wakeup(rp);
- }
- return (ret);
- }
- }
- nfsrvstats.srvcache_misses++;
- NFS_DPF(RC, ("M%03x", nd->nd_retxid & 0xfff));
- if (numnfsrvcache < desirednfsrvcache) {
- NFSD_UNLOCK();
- rp = (struct nfsrvcache *)malloc((u_long)sizeof *rp,
- M_NFSD, M_WAITOK | M_ZERO);
- NFSD_LOCK();
- numnfsrvcache++;
- rp->rc_flag = RC_LOCKED;
- } else {
- rp = TAILQ_FIRST(&nfsrvlruhead);
- while ((rp->rc_flag & RC_LOCKED) != 0) {
- rp->rc_flag |= RC_WANTED;
- (void) msleep(rp, &nfsd_mtx, PZERO-1, "nfsrc", 0);
- rp = TAILQ_FIRST(&nfsrvlruhead);
- }
- rp->rc_flag |= RC_LOCKED;
- LIST_REMOVE(rp, rc_hash);
- TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru);
- if (rp->rc_flag & RC_REPMBUF)
- m_freem(rp->rc_reply);
- if (rp->rc_flag & RC_NAM)
- free(rp->rc_nam, M_SONAME);
- rp->rc_flag &= (RC_LOCKED | RC_WANTED);
- }
- TAILQ_INSERT_TAIL(&nfsrvlruhead, rp, rc_lru);
- rp->rc_state = RC_INPROG;
- rp->rc_xid = nd->nd_retxid;
- saddr = (struct sockaddr_in *)nd->nd_nam;
- switch (saddr->sin_family) {
- case AF_INET:
- rp->rc_flag |= RC_INETADDR;
- rp->rc_inetaddr = saddr->sin_addr.s_addr;
- break;
-/* case AF_INET6: */
-/* case AF_ISO: */
- default:
- /*
- * XXXRW: Seems like we should only set RC_NAM if we
- * actually manage to set rc_nam to something non-NULL.
- */
- rp->rc_flag |= RC_NAM;
- rp->rc_nam = sodupsockaddr(nd->nd_nam, M_NOWAIT);
- break;
- };
- rp->rc_proc = nd->nd_procnum;
- LIST_INSERT_HEAD(NFSRCHASH(nd->nd_retxid), rp, rc_hash);
- rp->rc_flag &= ~RC_LOCKED;
- if (rp->rc_flag & RC_WANTED) {
- rp->rc_flag &= ~RC_WANTED;
- wakeup(rp);
- }
- return (RC_DOIT);
-}
-
-/*
- * Update a request cache entry after the rpc has been done
- */
-void
-nfsrv_updatecache(struct nfsrv_descript *nd, int repvalid, struct mbuf *repmbuf)
-{
- struct nfsrvcache *rp;
-
- NFSD_LOCK_ASSERT();
-
- if (!nd->nd_nam2)
- return;
-loop:
- LIST_FOREACH(rp, NFSRCHASH(nd->nd_retxid), rc_hash) {
- if (nd->nd_retxid == rp->rc_xid && nd->nd_procnum == rp->rc_proc &&
- netaddr_match(NETFAMILY(rp), &rp->rc_haddr, nd->nd_nam)) {
- NFS_DPF(RC, ("U%03x", rp->rc_xid & 0xfff));
- if ((rp->rc_flag & RC_LOCKED) != 0) {
- rp->rc_flag |= RC_WANTED;
- (void) msleep(rp, &nfsd_mtx, PZERO-1,
- "nfsrc", 0);
- goto loop;
- }
- rp->rc_flag |= RC_LOCKED;
- if (rp->rc_state == RC_DONE) {
- /*
- * This can occur if the cache is too small.
- * Retransmits of the same request aren't
- * dropped so we may see the operation
- * complete more then once.
- */
- if (rp->rc_flag & RC_REPMBUF) {
- m_freem(rp->rc_reply);
- rp->rc_flag &= ~RC_REPMBUF;
- }
- }
- rp->rc_state = RC_DONE;
- /*
- * If we have a valid reply update status and save
- * the reply for non-idempotent rpc's.
- */
- if (repvalid && nonidempotent[nd->nd_procnum]) {
- if ((nd->nd_flag & ND_NFSV3) == 0 &&
- nfsv2_repstat[
- nfsrvv2_procid[nd->nd_procnum]]) {
- rp->rc_status = nd->nd_repstat;
- rp->rc_flag |= RC_REPSTATUS;
- } else {
- NFSD_UNLOCK();
- rp->rc_reply = m_copym(repmbuf,
- 0, M_COPYALL, M_WAIT);
- NFSD_LOCK();
- rp->rc_flag |= RC_REPMBUF;
- }
- }
- rp->rc_flag &= ~RC_LOCKED;
- if (rp->rc_flag & RC_WANTED) {
- rp->rc_flag &= ~RC_WANTED;
- wakeup(rp);
- }
- return;
- }
- }
- NFS_DPF(RC, ("L%03x", nd->nd_retxid & 0xfff));
-}
-
-/*
- * Clean out the cache. Called when the last nfsd terminates.
- */
-void
-nfsrv_cleancache(void)
-{
- struct nfsrvcache *rp, *nextrp;
-
- NFSD_LOCK_ASSERT();
-
- TAILQ_FOREACH_SAFE(rp, &nfsrvlruhead, rc_lru, nextrp) {
- LIST_REMOVE(rp, rc_hash);
- TAILQ_REMOVE(&nfsrvlruhead, rp, rc_lru);
- if (rp->rc_flag & RC_REPMBUF)
- m_freem(rp->rc_reply);
- if (rp->rc_flag & RC_NAM)
- free(rp->rc_nam, M_SONAME);
- free(rp, M_NFSD);
- }
- numnfsrvcache = 0;
-}
-
-#endif /* NFS_LEGACYRPC */
diff --git a/sys/nfsserver/nfs_srvkrpc.c b/sys/nfsserver/nfs_srvkrpc.c
index 99edac5..54b1c4a 100644
--- a/sys/nfsserver/nfs_srvkrpc.c
+++ b/sys/nfsserver/nfs_srvkrpc.c
@@ -75,7 +75,6 @@ __FBSDID("$FreeBSD$");
#include <rpc/replay.h>
#include <nfs/xdr_subs.h>
-#include <nfs/rpcv2.h>
#include <nfs/nfsproto.h>
#include <nfsserver/nfs.h>
#include <nfsserver/nfsm_subs.h>
@@ -84,8 +83,6 @@ __FBSDID("$FreeBSD$");
#include <security/mac/mac_framework.h>
-#ifndef NFS_LEGACYRPC
-
static MALLOC_DEFINE(M_NFSSVC, "nfss_srvsock", "Nfs server structure");
MALLOC_DEFINE(M_NFSRVDESC, "nfss_srvdesc", "NFS server socket descriptor");
@@ -607,5 +604,3 @@ nfsrv_init(int terminating)
NFSD_LOCK();
}
-
-#endif /* !NFS_LEGACYRPC */
diff --git a/sys/nfsserver/nfs_srvsock.c b/sys/nfsserver/nfs_srvsock.c
deleted file mode 100644
index b5c3fa2..0000000
--- a/sys/nfsserver/nfs_srvsock.c
+++ /dev/null
@@ -1,818 +0,0 @@
-/*-
- * Copyright (c) 1989, 1991, 1993, 1995
- * 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.
- * 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.
- *
- * @(#)nfs_socket.c 8.5 (Berkeley) 3/30/95
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * Socket operations for use by nfs
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/jail.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/mount.h>
-#include <sys/mutex.h>
-#include <sys/proc.h>
-#include <sys/protosw.h>
-#include <sys/refcount.h>
-#include <sys/signalvar.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/sysctl.h>
-#include <sys/syslog.h>
-#include <sys/vnode.h>
-
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-
-#include <nfs/rpcv2.h>
-#include <nfs/nfsproto.h>
-#include <nfsserver/nfs.h>
-#include <nfs/xdr_subs.h>
-#include <nfsserver/nfsm_subs.h>
-
-#include <security/mac/mac_framework.h>
-
-#ifdef NFS_LEGACYRPC
-
-#define TRUE 1
-#define FALSE 0
-
-static int nfs_realign_test;
-static int nfs_realign_count;
-
-SYSCTL_DECL(_vfs_nfsrv);
-
-SYSCTL_INT(_vfs_nfsrv, OID_AUTO, realign_test, CTLFLAG_RW, &nfs_realign_test, 0, "");
-SYSCTL_INT(_vfs_nfsrv, OID_AUTO, realign_count, CTLFLAG_RW, &nfs_realign_count, 0, "");
-
-
-/*
- * There is a congestion window for outstanding rpcs maintained per mount
- * point. The cwnd size is adjusted in roughly the way that:
- * Van Jacobson, Congestion avoidance and Control, In "Proceedings of
- * SIGCOMM '88". ACM, August 1988.
- * describes for TCP. The cwnd size is chopped in half on a retransmit timeout
- * and incremented by 1/cwnd when each rpc reply is received and a full cwnd
- * of rpcs is in progress.
- * (The sent count and cwnd are scaled for integer arith.)
- * Variants of "slow start" were tried and were found to be too much of a
- * performance hit (ave. rtt 3 times larger),
- * I suspect due to the large rtt that nfs rpcs have.
- */
-#define NFS_CWNDSCALE 256
-#define NFS_MAXCWND (NFS_CWNDSCALE * 32)
-struct callout nfsrv_callout;
-
-static void nfs_realign(struct mbuf **pm, int hsiz); /* XXX SHARED */
-static int nfsrv_getstream(struct nfssvc_sock *, int);
-
-int32_t (*nfsrv3_procs[NFS_NPROCS])(struct nfsrv_descript *nd,
- struct nfssvc_sock *slp,
- struct mbuf **mreqp) = {
- nfsrv_null,
- nfsrv_getattr,
- nfsrv_setattr,
- nfsrv_lookup,
- nfsrv3_access,
- nfsrv_readlink,
- nfsrv_read,
- nfsrv_write,
- nfsrv_create,
- nfsrv_mkdir,
- nfsrv_symlink,
- nfsrv_mknod,
- nfsrv_remove,
- nfsrv_rmdir,
- nfsrv_rename,
- nfsrv_link,
- nfsrv_readdir,
- nfsrv_readdirplus,
- nfsrv_statfs,
- nfsrv_fsinfo,
- nfsrv_pathconf,
- nfsrv_commit,
- nfsrv_noop
-};
-
-
-/*
- * Generate the rpc reply header
- * siz arg. is used to decide if adding a cluster is worthwhile
- */
-struct mbuf *
-nfs_rephead(int siz, struct nfsrv_descript *nd, int err,
- struct mbuf **mbp, caddr_t *bposp)
-{
- u_int32_t *tl;
- struct mbuf *mreq;
- caddr_t bpos;
- struct mbuf *mb;
-
- nd->nd_repstat = err;
- if (err && (nd->nd_flag & ND_NFSV3) == 0) /* XXX recheck */
- siz = 0;
- MGETHDR(mreq, M_WAIT, MT_DATA);
- mb = mreq;
- /*
- * If this is a big reply, use a cluster else
- * try and leave leading space for the lower level headers.
- */
- mreq->m_len = 6 * NFSX_UNSIGNED;
- siz += RPC_REPLYSIZ;
- if ((max_hdr + siz) >= MINCLSIZE) {
- MCLGET(mreq, M_WAIT);
- } else
- mreq->m_data += min(max_hdr, M_TRAILINGSPACE(mreq));
- tl = mtod(mreq, u_int32_t *);
- bpos = ((caddr_t)tl) + mreq->m_len;
- *tl++ = txdr_unsigned(nd->nd_retxid);
- *tl++ = nfsrv_rpc_reply;
- if (err == ERPCMISMATCH || (err & NFSERR_AUTHERR)) {
- *tl++ = nfsrv_rpc_msgdenied;
- if (err & NFSERR_AUTHERR) {
- *tl++ = nfsrv_rpc_autherr;
- *tl = txdr_unsigned(err & ~NFSERR_AUTHERR);
- mreq->m_len -= NFSX_UNSIGNED;
- bpos -= NFSX_UNSIGNED;
- } else {
- *tl++ = nfsrv_rpc_mismatch;
- *tl++ = txdr_unsigned(RPC_VER2);
- *tl = txdr_unsigned(RPC_VER2);
- }
- } else {
- *tl++ = nfsrv_rpc_msgaccepted;
- /*
- * Send a RPCAUTH_NULL verifier - no Kerberos.
- */
- *tl++ = 0;
- *tl++ = 0;
- switch (err) {
- case EPROGUNAVAIL:
- *tl = txdr_unsigned(RPC_PROGUNAVAIL);
- break;
- case EPROGMISMATCH:
- *tl = txdr_unsigned(RPC_PROGMISMATCH);
- tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
- *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 != NFSERR_RETVOID) {
- tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
- if (err)
- *tl = txdr_unsigned(nfsrv_errmap(nd, err));
- else
- *tl = 0;
- }
- break;
- }
- }
- *mbp = mb;
- *bposp = bpos;
- if (err != 0 && err != NFSERR_RETVOID)
- nfsrvstats.srvrpc_errs++;
- return mreq;
-}
-
-
-/*
- * nfs_realign:
- *
- * Check for badly aligned mbuf data and realign by copying the unaligned
- * portion of the data into a new mbuf chain and freeing the portions
- * of the old chain that were replaced.
- *
- * We cannot simply realign the data within the existing mbuf chain
- * because the underlying buffers may contain other rpc commands and
- * we cannot afford to overwrite them.
- *
- * We would prefer to avoid this situation entirely. The situation does
- * not occur with NFS/UDP and is supposed to only occassionally occur
- * with TCP. Use vfs.nfs.realign_count and realign_test to check this.
- */
-static void
-nfs_realign(struct mbuf **pm, int hsiz) /* XXX COMMON */
-{
- struct mbuf *m;
- struct mbuf *n = NULL;
- int off = 0;
-
- ++nfs_realign_test;
- while ((m = *pm) != NULL) {
- if ((m->m_len & 0x3) || (mtod(m, intptr_t) & 0x3)) {
- MGET(n, M_WAIT, MT_DATA);
- if (m->m_len >= MINCLSIZE) {
- MCLGET(n, M_WAIT);
- }
- n->m_len = 0;
- break;
- }
- pm = &m->m_next;
- }
-
- /*
- * If n is non-NULL, loop on m copying data, then replace the
- * portion of the chain that had to be realigned.
- */
- if (n != NULL) {
- ++nfs_realign_count;
- while (m) {
- m_copyback(n, off, m->m_len, mtod(m, caddr_t));
- off += m->m_len;
- m = m->m_next;
- }
- m_freem(*pm);
- *pm = n;
- }
-}
-
-
-/*
- * Parse an RPC request
- * - verify it
- * - fill in the cred struct.
- */
-int
-nfs_getreq(struct nfsrv_descript *nd, struct nfsd *nfsd, int has_header)
-{
- int len, i;
- u_int32_t *tl;
- caddr_t dpos;
- u_int32_t nfsvers, auth_type;
- int error = 0;
- struct mbuf *mrep, *md;
-
- NFSD_LOCK_ASSERT();
-
- mrep = nd->nd_mrep;
- md = nd->nd_md;
- dpos = nd->nd_dpos;
- if (has_header) {
- tl = nfsm_dissect_nonblock(u_int32_t *, 10 * NFSX_UNSIGNED);
- nd->nd_retxid = fxdr_unsigned(u_int32_t, *tl++);
- if (*tl++ != nfsrv_rpc_call) {
- m_freem(mrep);
- return (EBADRPC);
- }
- } else
- tl = nfsm_dissect_nonblock(u_int32_t *, 8 * NFSX_UNSIGNED);
- nd->nd_repstat = 0;
- nd->nd_flag = 0;
- if (*tl++ != nfsrv_rpc_vers) {
- nd->nd_repstat = ERPCMISMATCH;
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- if (*tl != nfsrv_nfs_prog) {
- nd->nd_repstat = EPROGUNAVAIL;
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- tl++;
- nfsvers = fxdr_unsigned(u_int32_t, *tl++);
- if (nfsvers < NFS_VER2 || nfsvers > NFS_VER3) {
- nd->nd_repstat = EPROGMISMATCH;
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- nd->nd_procnum = fxdr_unsigned(u_int32_t, *tl++);
- if (nd->nd_procnum == NFSPROC_NULL)
- return (0);
- if (nfsvers == NFS_VER3) {
- nd->nd_flag = ND_NFSV3;
- if (nd->nd_procnum >= NFS_NPROCS) {
- nd->nd_repstat = EPROCUNAVAIL;
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- } else {
- if (nd->nd_procnum > NFSV2PROC_STATFS) {
- nd->nd_repstat = EPROCUNAVAIL;
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
- /* Map the v2 procedure numbers into v3 ones */
- nd->nd_procnum = nfsrv_nfsv3_procid[nd->nd_procnum];
- }
- auth_type = *tl++;
- len = fxdr_unsigned(int, *tl++);
- if (len < 0 || len > RPCAUTH_MAXSIZ) {
- m_freem(mrep);
- return (EBADRPC);
- }
-
- /*
- * Handle auth_unix;
- */
- if (auth_type == nfsrv_rpc_auth_unix) {
- len = fxdr_unsigned(int, *++tl);
- if (len < 0 || len > NFS_MAXNAMLEN) {
- m_freem(mrep);
- return (EBADRPC);
- }
- nfsm_adv(nfsm_rndup(len));
- tl = nfsm_dissect_nonblock(u_int32_t *, 3 * NFSX_UNSIGNED);
- nd->nd_cr->cr_uid = nd->nd_cr->cr_ruid =
- nd->nd_cr->cr_svuid = fxdr_unsigned(uid_t, *tl++);
- nd->nd_cr->cr_groups[0] = nd->nd_cr->cr_rgid =
- nd->nd_cr->cr_svgid = fxdr_unsigned(gid_t, *tl++);
-#ifdef MAC
- mac_cred_associate_nfsd(nd->nd_cr);
-#endif
- len = fxdr_unsigned(int, *tl);
- if (len < 0 || len > RPCAUTH_UNIXGIDS) {
- m_freem(mrep);
- return (EBADRPC);
- }
- tl = nfsm_dissect_nonblock(u_int32_t *, (len + 2) * NFSX_UNSIGNED);
- for (i = 1; i <= len; i++)
- if (i < XU_NGROUPS)
- nd->nd_cr->cr_groups[i] = fxdr_unsigned(gid_t, *tl++);
- else
- tl++;
- nd->nd_cr->cr_ngroups = MIN(XU_NGROUPS, len + 1);
- 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);
- }
- if (len > 0)
- nfsm_adv(nfsm_rndup(len));
- nd->nd_credflavor = RPCAUTH_UNIX;
- } else {
- nd->nd_repstat = (NFSERR_AUTHERR | AUTH_REJECTCRED);
- nd->nd_procnum = NFSPROC_NOOP;
- return (0);
- }
-
- nd->nd_md = md;
- nd->nd_dpos = dpos;
- return (0);
-nfsmout:
- return (error);
-}
-
-/*
- * Socket upcall routine for the nfsd sockets.
- * The caddr_t arg is a pointer to the "struct nfssvc_sock".
- * Essentially do as much as possible non-blocking, else punt and it will
- * be called with M_WAIT from an nfsd.
- */
-int
-nfsrv_rcv(struct socket *so, void *arg, int waitflag)
-{
- struct nfssvc_sock *slp = (struct nfssvc_sock *)arg;
- struct mbuf *m;
- struct mbuf *mp;
- struct sockaddr *nam;
- struct uio auio;
- int flags, error;
-
- NFSD_UNLOCK_ASSERT();
-
- /* XXXRW: Unlocked read. */
- if ((slp->ns_flag & SLP_VALID) == 0)
- return (SU_OK);
-
- /*
- * We can't do this in the context of a socket callback
- * because we're called with locks held.
- * XXX: SMP
- */
- if (waitflag == M_DONTWAIT) {
- NFSD_LOCK();
- slp->ns_flag |= SLP_NEEDQ;
- goto dorecs;
- }
-
-
- NFSD_LOCK();
- auio.uio_td = NULL;
- if (so->so_type == SOCK_STREAM) {
- /*
- * If there are already records on the queue, defer soreceive()
- * to an nfsd so that there is feedback to the TCP layer that
- * the nfs servers are heavily loaded.
- */
- if (STAILQ_FIRST(&slp->ns_rec) != NULL &&
- waitflag == M_DONTWAIT) {
- slp->ns_flag |= SLP_NEEDQ;
- goto dorecs;
- }
-
- /*
- * Do soreceive().
- */
- auio.uio_resid = 1000000000;
- flags = MSG_DONTWAIT;
- NFSD_UNLOCK();
- error = soreceive(so, &nam, &auio, &mp, NULL, &flags);
- NFSD_LOCK();
- if (error || mp == NULL) {
- if (error == EWOULDBLOCK)
- slp->ns_flag |= SLP_NEEDQ;
- else
- slp->ns_flag |= SLP_DISCONN;
- goto dorecs;
- }
- m = mp;
- if (slp->ns_rawend) {
- slp->ns_rawend->m_next = m;
- slp->ns_cc += 1000000000 - auio.uio_resid;
- } else {
- slp->ns_raw = m;
- slp->ns_cc = 1000000000 - auio.uio_resid;
- }
- while (m->m_next)
- m = m->m_next;
- slp->ns_rawend = m;
-
- /*
- * Now try and parse record(s) out of the raw stream data.
- */
- error = nfsrv_getstream(slp, waitflag);
- if (error) {
- if (error == EPERM)
- slp->ns_flag |= SLP_DISCONN;
- else
- slp->ns_flag |= SLP_NEEDQ;
- }
- } else {
- do {
- auio.uio_resid = 1000000000;
- flags = MSG_DONTWAIT;
- NFSD_UNLOCK();
- error = soreceive(so, &nam, &auio, &mp, NULL, &flags);
- if (mp) {
- struct nfsrv_rec *rec;
- rec = malloc(sizeof(struct nfsrv_rec),
- M_NFSRVDESC,
- waitflag == M_DONTWAIT ? M_NOWAIT : M_WAITOK);
- if (!rec) {
- if (nam)
- free(nam, M_SONAME);
- m_freem(mp);
- NFSD_LOCK();
- continue;
- }
- nfs_realign(&mp, 10 * NFSX_UNSIGNED);
- NFSD_LOCK();
- rec->nr_address = nam;
- rec->nr_packet = mp;
- STAILQ_INSERT_TAIL(&slp->ns_rec, rec, nr_link);
- } else
- NFSD_LOCK();
- if (error) {
- if ((so->so_proto->pr_flags & PR_CONNREQUIRED)
- && error != EWOULDBLOCK) {
- slp->ns_flag |= SLP_DISCONN;
- goto dorecs;
- }
- }
- } while (mp);
- }
-
- /*
- * Now try and process the request records, non-blocking.
- */
-dorecs:
- if (waitflag == M_DONTWAIT &&
- (STAILQ_FIRST(&slp->ns_rec) != NULL ||
- (slp->ns_flag & (SLP_NEEDQ | SLP_DISCONN))))
- nfsrv_wakenfsd(slp);
- NFSD_UNLOCK();
- return (SU_OK);
-}
-
-/*
- * Try and extract an RPC request from the mbuf data list received on a
- * stream socket. The "waitflag" argument indicates whether or not it
- * can sleep.
- */
-static int
-nfsrv_getstream(struct nfssvc_sock *slp, int waitflag)
-{
- struct mbuf *m, **mpp;
- char *cp1, *cp2;
- int len;
- struct mbuf *om, *m2, *recm;
- u_int32_t recmark;
-
- NFSD_LOCK_ASSERT();
-
- if (slp->ns_flag & SLP_GETSTREAM)
- panic("nfs getstream");
- slp->ns_flag |= SLP_GETSTREAM;
- for (;;) {
- if (slp->ns_reclen == 0) {
- if (slp->ns_cc < NFSX_UNSIGNED) {
- slp->ns_flag &= ~SLP_GETSTREAM;
- return (0);
- }
- m = slp->ns_raw;
- if (m->m_len >= NFSX_UNSIGNED) {
- bcopy(mtod(m, caddr_t), (caddr_t)&recmark, NFSX_UNSIGNED);
- m->m_data += NFSX_UNSIGNED;
- m->m_len -= NFSX_UNSIGNED;
- } else {
- cp1 = (caddr_t)&recmark;
- cp2 = mtod(m, caddr_t);
- while (cp1 < ((caddr_t)&recmark) + NFSX_UNSIGNED) {
- while (m->m_len == 0) {
- m = m->m_next;
- cp2 = mtod(m, caddr_t);
- }
- *cp1++ = *cp2++;
- m->m_data++;
- m->m_len--;
- }
- }
- slp->ns_cc -= NFSX_UNSIGNED;
- 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_MAXPACKET || slp->ns_reclen <= 0) {
- slp->ns_flag &= ~SLP_GETSTREAM;
- return (EPERM);
- }
- }
-
- /*
- * Now get the record part.
- *
- * Note that slp->ns_reclen may be 0. Linux sometimes
- * generates 0-length RPCs.
- */
- recm = NULL;
- if (slp->ns_cc == slp->ns_reclen) {
- recm = slp->ns_raw;
- slp->ns_raw = slp->ns_rawend = NULL;
- slp->ns_cc = slp->ns_reclen = 0;
- } else if (slp->ns_cc > slp->ns_reclen) {
- len = 0;
- m = slp->ns_raw;
- om = NULL;
-
- while (len < slp->ns_reclen) {
- if ((len + m->m_len) > slp->ns_reclen) {
- NFSD_UNLOCK();
- m2 = m_copym(m, 0, slp->ns_reclen - len,
- waitflag);
- NFSD_LOCK();
- if (m2) {
- if (om) {
- om->m_next = m2;
- recm = slp->ns_raw;
- } else
- recm = m2;
- m->m_data += slp->ns_reclen - len;
- m->m_len -= slp->ns_reclen - len;
- len = slp->ns_reclen;
- } else {
- slp->ns_flag &= ~SLP_GETSTREAM;
- return (EWOULDBLOCK);
- }
- } else if ((len + m->m_len) == slp->ns_reclen) {
- om = m;
- len += m->m_len;
- m = m->m_next;
- recm = slp->ns_raw;
- om->m_next = NULL;
- } else {
- om = m;
- len += m->m_len;
- m = m->m_next;
- }
- }
- slp->ns_raw = m;
- slp->ns_cc -= len;
- slp->ns_reclen = 0;
- } else {
- slp->ns_flag &= ~SLP_GETSTREAM;
- return (0);
- }
-
- /*
- * Accumulate the fragments into a record.
- */
- mpp = &slp->ns_frag;
- while (*mpp)
- mpp = &((*mpp)->m_next);
- *mpp = recm;
- if (slp->ns_flag & SLP_LASTFRAG) {
- struct nfsrv_rec *rec;
- NFSD_UNLOCK();
- rec = malloc(sizeof(struct nfsrv_rec), M_NFSRVDESC,
- waitflag == M_DONTWAIT ? M_NOWAIT : M_WAITOK);
- if (rec) {
- nfs_realign(&slp->ns_frag, 10 * NFSX_UNSIGNED);
- rec->nr_address = NULL;
- rec->nr_packet = slp->ns_frag;
- NFSD_LOCK();
- STAILQ_INSERT_TAIL(&slp->ns_rec, rec, nr_link);
- } else {
- NFSD_LOCK();
- }
- if (!rec) {
- m_freem(slp->ns_frag);
- }
- slp->ns_frag = NULL;
- }
- }
-}
-
-/*
- * Parse an RPC header.
- */
-int
-nfsrv_dorec(struct nfssvc_sock *slp, struct nfsd *nfsd,
- struct nfsrv_descript **ndp)
-{
- struct nfsrv_rec *rec;
- struct mbuf *m;
- struct sockaddr *nam;
- struct nfsrv_descript *nd;
- int error;
-
- NFSD_LOCK_ASSERT();
-
- *ndp = NULL;
- if ((slp->ns_flag & SLP_VALID) == 0 ||
- STAILQ_FIRST(&slp->ns_rec) == NULL)
- return (ENOBUFS);
- rec = STAILQ_FIRST(&slp->ns_rec);
- KASSERT(rec->nr_packet != NULL, ("nfsrv_dorec: missing mbuf"));
- STAILQ_REMOVE_HEAD(&slp->ns_rec, nr_link);
- nam = rec->nr_address;
- m = rec->nr_packet;
- free(rec, M_NFSRVDESC);
- NFSD_UNLOCK();
- nd = malloc(sizeof (struct nfsrv_descript),
- M_NFSRVDESC, M_WAITOK);
- nd->nd_cr = crget();
- prison_hold(&prison0);
- nd->nd_cr->cr_prison = &prison0;
- NFSD_LOCK();
- 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) {
- if (nam) {
- free(nam, M_SONAME);
- }
- if (nd->nd_cr != NULL)
- crfree(nd->nd_cr);
- free((caddr_t)nd, M_NFSRVDESC);
- return (error);
- }
- *ndp = nd;
- nfsd->nfsd_nd = nd;
- return (0);
-}
-
-/*
- * Search for a sleeping nfsd and wake it up.
- * SIDE EFFECT: If none found, set NFSD_CHECKSLP flag, so that one of the
- * running nfsds will go look for the work in the nfssvc_sock list.
- */
-void
-nfsrv_wakenfsd(struct nfssvc_sock *slp)
-{
- struct nfsd *nd;
-
- NFSD_LOCK_ASSERT();
-
- if ((slp->ns_flag & SLP_VALID) == 0)
- return;
- TAILQ_FOREACH(nd, &nfsd_head, nfsd_chain) {
- if (nd->nfsd_flag & NFSD_WAITING) {
- nd->nfsd_flag &= ~NFSD_WAITING;
- if (nd->nfsd_slp)
- panic("nfsd wakeup");
- slp->ns_sref++;
- nd->nfsd_slp = slp;
- wakeup(nd);
- return;
- }
- }
- slp->ns_flag |= SLP_DOREC;
- nfsd_head_flag |= NFSD_CHECKSLP;
-}
-
-/*
- * This is the nfs send routine.
- * For the server side:
- * - return EINTR or ERESTART if interrupted by a signal
- * - return EPIPE if a connection is lost for connection based sockets (TCP...)
- * - do any cleanup required by recoverable socket errors (?)
- */
-int
-nfsrv_send(struct socket *so, struct sockaddr *nam, struct mbuf *top)
-{
- struct sockaddr *sendnam;
- int error, soflags, flags;
-
- NFSD_UNLOCK_ASSERT();
-
- soflags = so->so_proto->pr_flags;
- if ((soflags & PR_CONNREQUIRED) || (so->so_state & SS_ISCONNECTED))
- sendnam = NULL;
- else
- sendnam = nam;
- if (so->so_type == SOCK_SEQPACKET)
- flags = MSG_EOR;
- else
- flags = 0;
-
- error = sosend(so, sendnam, 0, top, 0, flags, curthread/*XXX*/);
- if (error == ENOBUFS && so->so_type == SOCK_DGRAM)
- error = 0;
-
- if (error) {
- log(LOG_INFO, "nfsd send error %d\n", error);
-
- /*
- * Handle any recoverable (soft) socket errors here. (?)
- */
- if (error != EINTR && error != ERESTART &&
- error != EWOULDBLOCK && error != EPIPE)
- error = 0;
- }
- return (error);
-}
-
-/*
- * NFS server timer routine.
- */
-void
-nfsrv_timer(void *arg)
-{
- struct nfssvc_sock *slp;
- u_quad_t cur_usec;
-
- NFSD_LOCK();
- /*
- * Scan the write gathering queues for writes that need to be
- * completed now.
- */
- cur_usec = nfs_curusec();
- TAILQ_FOREACH(slp, &nfssvc_sockhead, ns_chain) {
- if (LIST_FIRST(&slp->ns_tq) &&
- LIST_FIRST(&slp->ns_tq)->nd_time <= cur_usec)
- nfsrv_wakenfsd(slp);
- }
- NFSD_UNLOCK();
- callout_reset(&nfsrv_callout, nfsrv_ticks, nfsrv_timer, NULL);
-}
-
-#endif /* NFS_LEGACYRPC */
diff --git a/sys/nfsserver/nfs_srvsubs.c b/sys/nfsserver/nfs_srvsubs.c
index 87fda28..ee0614b 100644
--- a/sys/nfsserver/nfs_srvsubs.c
+++ b/sys/nfsserver/nfs_srvsubs.c
@@ -67,7 +67,8 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_extern.h>
#include <vm/uma.h>
-#include <nfs/rpcv2.h>
+#include <rpc/rpc.h>
+
#include <nfs/nfsproto.h>
#include <nfsserver/nfs.h>
#include <nfs/xdr_subs.h>
@@ -80,10 +81,7 @@ __FBSDID("$FreeBSD$");
* This is kinda hokey, but may save a little time doing byte swaps
*/
u_int32_t nfsrv_nfs_xdrneg1;
-u_int32_t nfsrv_rpc_call, nfsrv_rpc_vers, nfsrv_rpc_reply,
- nfsrv_rpc_msgdenied, nfsrv_rpc_autherr,
- nfsrv_rpc_mismatch, nfsrv_rpc_auth_unix, nfsrv_rpc_msgaccepted;
-u_int32_t nfsrv_nfs_prog, nfsrv_nfs_true, nfsrv_nfs_false;
+u_int32_t nfsrv_nfs_true, nfsrv_nfs_false;
/* And other global data */
static const nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR,
@@ -93,13 +91,6 @@ static const nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR,
int nfsrv_ticks;
-#ifdef NFS_LEGACYRPC
-struct nfssvc_sockhead nfssvc_sockhead;
-int nfssvc_sockhead_flag;
-struct nfsd_head nfsd_head;
-int nfsd_head_flag;
-#endif
-
struct mtx nfsd_mtx;
/*
@@ -528,15 +519,6 @@ nfsrv_modevent(module_t mod, int type, void *data)
switch (type) {
case MOD_LOAD:
mtx_init(&nfsd_mtx, "nfsd_mtx", NULL, MTX_DEF);
- nfsrv_rpc_vers = txdr_unsigned(RPC_VER2);
- nfsrv_rpc_call = txdr_unsigned(RPC_CALL);
- nfsrv_rpc_reply = txdr_unsigned(RPC_REPLY);
- nfsrv_rpc_msgdenied = txdr_unsigned(RPC_MSGDENIED);
- nfsrv_rpc_msgaccepted = txdr_unsigned(RPC_MSGACCEPTED);
- nfsrv_rpc_mismatch = txdr_unsigned(RPC_MISMATCH);
- nfsrv_rpc_autherr = txdr_unsigned(RPC_AUTHERR);
- nfsrv_rpc_auth_unix = txdr_unsigned(RPCAUTH_UNIX);
- nfsrv_nfs_prog = txdr_unsigned(NFS_PROG);
nfsrv_nfs_true = txdr_unsigned(TRUE);
nfsrv_nfs_false = txdr_unsigned(FALSE);
nfsrv_nfs_xdrneg1 = txdr_unsigned(-1);
@@ -544,18 +526,9 @@ nfsrv_modevent(module_t mod, int type, void *data)
if (nfsrv_ticks < 1)
nfsrv_ticks = 1;
-#ifdef NFS_LEGACYRPC
- nfsrv_initcache(); /* Init the server request cache */
NFSD_LOCK();
nfsrv_init(0); /* Init server data structures */
- callout_init(&nfsrv_callout, CALLOUT_MPSAFE);
NFSD_UNLOCK();
- nfsrv_timer(0);
-#else
- NFSD_LOCK();
- nfsrv_init(0); /* Init server data structures */
- NFSD_UNLOCK();
-#endif
nfsd_call_nfsserver = nfssvc_nfsserver;
break;
@@ -568,9 +541,6 @@ nfsrv_modevent(module_t mod, int type, void *data)
nfsd_call_nfsserver = NULL;
callout_drain(&nfsrv_callout);
-#ifdef NFS_LEGACYRPC
- nfsrv_destroycache(); /* Free the server request cache */
-#endif
mtx_destroy(&nfsd_mtx);
break;
default:
@@ -589,9 +559,7 @@ DECLARE_MODULE(nfsserver, nfsserver_mod, SI_SUB_VFS, SI_ORDER_ANY);
/* So that loader and kldload(2) can find us, wherever we are.. */
MODULE_VERSION(nfsserver, 1);
MODULE_DEPEND(nfsserver, nfssvc, 1, 1, 1);
-#ifndef NFS_LEGACYRPC
MODULE_DEPEND(nfsserver, krpc, 1, 1, 1);
-#endif
/*
* Set up nameidata for a lookup() call and do it.
@@ -1128,7 +1096,7 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp, int *vfslockedp,
* old mountd that doesn't pass in a secflavor list.
*/
numsecflavors = 1;
- authsys = RPCAUTH_UNIX;
+ authsys = AUTH_SYS;
secflavors = &authsys;
}
credflavor = nfsd->nd_credflavor;
@@ -1221,52 +1189,6 @@ nfs_ispublicfh(fhandle_t *fhp)
return (TRUE);
}
-#ifdef NFS_LEGACYRPC
-
-/*
- * This function compares two net addresses by family and returns TRUE
- * if they are the same host.
- * If there is any doubt, return FALSE.
- * The AF_INET family is handled as a special case so that address mbufs
- * don't need to be saved to store "struct in_addr", which is only 4 bytes.
- */
-int
-netaddr_match(int family, union nethostaddr *haddr, struct sockaddr *nam)
-{
- struct sockaddr_in *inetaddr;
-
- NFSD_LOCK_DONTCARE();
-
- switch (family) {
- case AF_INET:
- inetaddr = (struct sockaddr_in *)nam;
- if (inetaddr->sin_family == AF_INET &&
- inetaddr->sin_addr.s_addr == haddr->had_inetaddr)
- return (1);
- break;
-#ifdef INET6
- case AF_INET6:
- {
- register struct sockaddr_in6 *inet6addr1, *inet6addr2;
-
- inet6addr1 = (struct sockaddr_in6 *)nam;
- inet6addr2 = (struct sockaddr_in6 *)haddr->had_nam;
- /* XXX - should test sin6_scope_id ? */
- if (inet6addr1->sin6_family == AF_INET6 &&
- IN6_ARE_ADDR_EQUAL(&inet6addr1->sin6_addr,
- &inet6addr2->sin6_addr))
- return (1);
- break;
- }
-#endif
- default:
- break;
- };
- return (0);
-}
-
-#endif
-
/*
* Map errnos to NFS error numbers. For Version 3 also filter out error
* numbers not specified for the associated procedure.
diff --git a/sys/nfsserver/nfs_syscalls.c b/sys/nfsserver/nfs_syscalls.c
deleted file mode 100644
index 29c9643..0000000
--- a/sys/nfsserver/nfs_syscalls.c
+++ /dev/null
@@ -1,723 +0,0 @@
-/*-
- * 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.
- * 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.
- *
- * @(#)nfs_syscalls.c 8.5 (Berkeley) 3/30/95
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "opt_inet6.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/sysproto.h>
-#include <sys/kernel.h>
-#include <sys/sysctl.h>
-#include <sys/file.h>
-#include <sys/filedesc.h>
-#include <sys/vnode.h>
-#include <sys/malloc.h>
-#include <sys/mount.h>
-#include <sys/priv.h>
-#include <sys/proc.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/domain.h>
-#include <sys/protosw.h>
-#include <sys/namei.h>
-#include <sys/fcntl.h>
-#include <sys/lockf.h>
-
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#ifdef INET6
-#include <net/if.h>
-#include <netinet6/in6_var.h>
-#endif
-#include <nfs/xdr_subs.h>
-#include <nfs/rpcv2.h>
-#include <nfs/nfsproto.h>
-#include <nfsserver/nfs.h>
-#include <nfsserver/nfsm_subs.h>
-#include <nfsserver/nfsrvcache.h>
-
-#include <security/audit/audit.h>
-
-#ifdef NFS_LEGACYRPC
-
-static MALLOC_DEFINE(M_NFSSVC, "nfss_srvsock", "Nfs server structure");
-
-MALLOC_DEFINE(M_NFSRVDESC, "nfss_srvdesc", "NFS server socket descriptor");
-MALLOC_DEFINE(M_NFSD, "nfss_daemon", "Nfs server daemon structure");
-
-#define TRUE 1
-#define FALSE 0
-
-SYSCTL_DECL(_vfs_nfsrv);
-
-int nfsd_waiting = 0;
-int nfsrv_numnfsd = 0;
-static int notstarted = 1;
-
-static int nfs_privport = 0;
-SYSCTL_INT(_vfs_nfsrv, NFS_NFSPRIVPORT, nfs_privport, CTLFLAG_RW,
- &nfs_privport, 0,
- "Only allow clients using a privileged port");
-SYSCTL_INT(_vfs_nfsrv, OID_AUTO, gatherdelay, CTLFLAG_RW,
- &nfsrvw_procrastinate, 0,
- "Delay value for write gathering");
-SYSCTL_INT(_vfs_nfsrv, OID_AUTO, gatherdelay_v3, CTLFLAG_RW,
- &nfsrvw_procrastinate_v3, 0,
- "Delay in seconds for NFSv3 write gathering");
-
-static int nfssvc_addsock(struct file *, struct sockaddr *);
-static void nfsrv_zapsock(struct nfssvc_sock *slp);
-static int nfssvc_nfsd(void);
-
-extern u_long sb_max_adj;
-
-/*
- * NFS server system calls
- */
-
-/*
- * This is now called from nfssvc() in nfs/nfs_nfssvc.c.
- */
-/*
- * Nfs server psuedo system call for the nfsd's
- * Based on the flag value it either:
- * - adds a socket to the selection list
- * - remains in the kernel as an nfsd
- * - remains in the kernel as an nfsiod
- * For INET6 we suppose that nfsd provides only IN6P_IPV6_V6ONLY sockets
- * and that mountd provides
- * - sockaddr with no IPv4-mapped addresses
- * - mask for both INET and INET6 families if there is IPv4-mapped overlap
- */
-int
-nfssvc_nfsserver(struct thread *td, struct nfssvc_args *uap)
-{
- struct file *fp;
- struct sockaddr *nam;
- struct nfsd_addsock_args nfsdarg;
- int error;
-
- NFSD_LOCK();
- while (nfssvc_sockhead_flag & SLP_INIT) {
- nfssvc_sockhead_flag |= SLP_WANTINIT;
- (void) msleep(&nfssvc_sockhead, &nfsd_mtx, PSOCK,
- "nfsd init", 0);
- }
- NFSD_UNLOCK();
- if (uap->flag & NFSSVC_ADDSOCK) {
- error = copyin(uap->argp, (caddr_t)&nfsdarg, sizeof(nfsdarg));
- if (error)
- return (error);
- if ((error = fget(td, nfsdarg.sock, &fp)) != 0)
- return (error);
- if (fp->f_type != DTYPE_SOCKET) {
- fdrop(fp, td);
- return (error); /* XXXRW: Should be EINVAL? */
- }
- /*
- * Get the client address for connected sockets.
- */
- if (nfsdarg.name == NULL || nfsdarg.namelen == 0)
- nam = NULL;
- else {
- error = getsockaddr(&nam, nfsdarg.name,
- nfsdarg.namelen);
- if (error) {
- fdrop(fp, td);
- return (error);
- }
- }
- error = nfssvc_addsock(fp, nam);
- fdrop(fp, td);
- } else if (uap->flag & NFSSVC_OLDNFSD) {
- error = nfssvc_nfsd();
- } else {
- error = ENXIO;
- }
- return (error);
-}
-
-/*
- * Adds a socket to the list for servicing by nfsds.
- */
-static int
-nfssvc_addsock(struct file *fp, struct sockaddr *mynam)
-{
- int siz;
- struct nfssvc_sock *slp;
- struct socket *so;
- int error;
-
- so = fp->f_data;
-#if 0
- /*
- * XXXRW: If this code is ever enabled, there's a race when running
- * MPSAFE.
- */
- tslp = NULL;
- /*
- * Add it to the list, as required.
- */
- if (so->so_proto->pr_protocol == IPPROTO_UDP) {
- tslp = nfs_udpsock;
- if (tslp->ns_flag & SLP_VALID) {
- if (mynam != NULL)
- free(mynam, M_SONAME);
- return (EPERM);
- }
- }
-#endif
- siz = sb_max_adj;
- error = soreserve(so, siz, siz);
- if (error) {
- if (mynam != NULL)
- free(mynam, M_SONAME);
- return (error);
- }
-
- /*
- * Set protocol specific options { for now TCP only } and
- * reserve some space. For datagram sockets, this can get called
- * repeatedly for the same socket, but that isn't harmful.
- */
- if (so->so_type == SOCK_STREAM) {
- struct sockopt sopt;
- int val;
-
- bzero(&sopt, sizeof sopt);
- sopt.sopt_dir = SOPT_SET;
- sopt.sopt_level = SOL_SOCKET;
- sopt.sopt_name = SO_KEEPALIVE;
- sopt.sopt_val = &val;
- sopt.sopt_valsize = sizeof val;
- val = 1;
- sosetopt(so, &sopt);
- }
- if (so->so_proto->pr_protocol == IPPROTO_TCP) {
- struct sockopt sopt;
- int val;
-
- bzero(&sopt, sizeof sopt);
- sopt.sopt_dir = SOPT_SET;
- sopt.sopt_level = IPPROTO_TCP;
- sopt.sopt_name = TCP_NODELAY;
- sopt.sopt_val = &val;
- sopt.sopt_valsize = sizeof val;
- val = 1;
- sosetopt(so, &sopt);
- }
- SOCKBUF_LOCK(&so->so_rcv);
- so->so_rcv.sb_flags &= ~SB_NOINTR;
- so->so_rcv.sb_timeo = 0;
- SOCKBUF_UNLOCK(&so->so_rcv);
- SOCKBUF_LOCK(&so->so_snd);
- so->so_snd.sb_flags &= ~SB_NOINTR;
- so->so_snd.sb_timeo = 0;
- SOCKBUF_UNLOCK(&so->so_snd);
-
- slp = (struct nfssvc_sock *)
- malloc(sizeof (struct nfssvc_sock), M_NFSSVC,
- M_WAITOK | M_ZERO);
- STAILQ_INIT(&slp->ns_rec);
- NFSD_LOCK();
- TAILQ_INSERT_TAIL(&nfssvc_sockhead, slp, ns_chain);
-
- slp->ns_so = so;
- slp->ns_nam = mynam;
- fhold(fp);
- slp->ns_fp = fp;
- NFSD_UNLOCK();
- SOCKBUF_LOCK(&so->so_rcv);
- soupcall_set(so, SO_RCV, nfsrv_rcv, slp);
- SOCKBUF_UNLOCK(&so->so_rcv);
- NFSD_LOCK();
- slp->ns_flag = (SLP_VALID | SLP_NEEDQ);
- nfsrv_wakenfsd(slp);
- NFSD_UNLOCK();
- return (0);
-}
-
-/*
- * Called by nfssvc() for nfsds. Just loops around servicing rpc requests
- * until it is killed by a signal.
- */
-static int
-nfssvc_nfsd()
-{
- int siz;
- struct nfssvc_sock *slp;
- struct nfsd *nfsd;
- struct nfsrv_descript *nd = NULL;
- struct mbuf *m, *mreq;
- int error = 0, cacherep, s, sotype, writes_todo;
- int procrastinate;
- u_quad_t cur_usec;
-
-#ifndef nolint
- cacherep = RC_DOIT;
- writes_todo = 0;
-#endif
- nfsd = (struct nfsd *)
- malloc(sizeof (struct nfsd), M_NFSD, M_WAITOK | M_ZERO);
- s = splnet();
- NFSD_LOCK();
-
- TAILQ_INSERT_TAIL(&nfsd_head, nfsd, nfsd_chain);
- nfsrv_numnfsd++;
-
- /*
- * Loop getting rpc requests until SIGKILL.
- */
- for (;;) {
- if ((nfsd->nfsd_flag & NFSD_REQINPROG) == 0) {
- while (nfsd->nfsd_slp == NULL &&
- (nfsd_head_flag & NFSD_CHECKSLP) == 0) {
- nfsd->nfsd_flag |= NFSD_WAITING;
- nfsd_waiting++;
- error = msleep(nfsd, &nfsd_mtx,
- PSOCK | PCATCH, "-", 0);
- nfsd_waiting--;
- if (error)
- goto done;
- }
- if (nfsd->nfsd_slp == NULL &&
- (nfsd_head_flag & NFSD_CHECKSLP) != 0) {
- TAILQ_FOREACH(slp, &nfssvc_sockhead, ns_chain) {
- if ((slp->ns_flag & (SLP_VALID | SLP_DOREC))
- == (SLP_VALID | SLP_DOREC)) {
- slp->ns_flag &= ~SLP_DOREC;
- slp->ns_sref++;
- nfsd->nfsd_slp = slp;
- break;
- }
- }
- if (slp == NULL)
- nfsd_head_flag &= ~NFSD_CHECKSLP;
- }
- if ((slp = nfsd->nfsd_slp) == NULL)
- continue;
- if (slp->ns_flag & SLP_VALID) {
- if (slp->ns_flag & SLP_DISCONN)
- nfsrv_zapsock(slp);
- else if (slp->ns_flag & SLP_NEEDQ) {
- slp->ns_flag &= ~SLP_NEEDQ;
- (void) nfs_slplock(slp, 1);
- NFSD_UNLOCK();
- nfsrv_rcv(slp->ns_so, (caddr_t)slp,
- M_WAIT);
- NFSD_LOCK();
- nfs_slpunlock(slp);
- }
- error = nfsrv_dorec(slp, nfsd, &nd);
- cur_usec = nfs_curusec();
- if (error && LIST_FIRST(&slp->ns_tq) &&
- LIST_FIRST(&slp->ns_tq)->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 = nfsd->nfsd_slp;
- }
- if (error || (slp->ns_flag & SLP_VALID) == 0) {
- if (nd) {
- if (nd->nd_cr != NULL)
- crfree(nd->nd_cr);
- free((caddr_t)nd, M_NFSRVDESC);
- nd = NULL;
- }
- nfsd->nfsd_slp = NULL;
- nfsd->nfsd_flag &= ~NFSD_REQINPROG;
- nfsrv_slpderef(slp);
- continue;
- }
- splx(s);
- sotype = slp->ns_so->so_type;
- if (nd) {
- getmicrotime(&nd->nd_starttime);
- if (nd->nd_nam2)
- nd->nd_nam = nd->nd_nam2;
- else
- nd->nd_nam = slp->ns_nam;
-
- /*
- * Check to see if authorization is needed.
- */
- cacherep = nfsrv_getcache(nd, &mreq);
-
- if (nfs_privport) {
- /* Check if source port is privileged */
- u_short port;
- struct sockaddr *nam = nd->nd_nam;
- struct sockaddr_in *sin;
-
- sin = (struct sockaddr_in *)nam;
- /*
- * INET/INET6 - same code:
- * sin_port and sin6_port are at same offset
- */
- port = ntohs(sin->sin_port);
- if (port >= IPPORT_RESERVED &&
- nd->nd_procnum != NFSPROC_NULL) {
-#ifdef INET6
- char b6[INET6_ADDRSTRLEN];
-#if defined(KLD_MODULE)
- /* Do not use ip6_sprintf: the nfs module should work without INET6. */
-#define ip6_sprintf(buf, a) \
- (sprintf((buf), "%x:%x:%x:%x:%x:%x:%x:%x", \
- (a)->s6_addr16[0], (a)->s6_addr16[1], \
- (a)->s6_addr16[2], (a)->s6_addr16[3], \
- (a)->s6_addr16[4], (a)->s6_addr16[5], \
- (a)->s6_addr16[6], (a)->s6_addr16[7]), \
- (buf))
-#endif
-#endif
- nd->nd_procnum = NFSPROC_NOOP;
- nd->nd_repstat = (NFSERR_AUTHERR | AUTH_TOOWEAK);
- cacherep = RC_DOIT;
- printf("NFS request from unprivileged port (%s:%d)\n",
-#ifdef INET6
- sin->sin_family == AF_INET6 ?
- ip6_sprintf(b6, &satosin6(sin)->sin6_addr) :
-#if defined(KLD_MODULE)
-#undef ip6_sprintf
-#endif
-#endif
- inet_ntoa(sin->sin_addr), port);
- }
- }
-
- }
-
- /*
- * Loop to get all the write rpc relies that have been
- * gathered together.
- */
- do {
- switch (cacherep) {
- case RC_DOIT:
- if (nd && (nd->nd_flag & ND_NFSV3))
- procrastinate = nfsrvw_procrastinate_v3;
- else
- procrastinate = nfsrvw_procrastinate;
- NFSD_UNLOCK();
- if (writes_todo || (!(nd->nd_flag & ND_NFSV3) &&
- nd->nd_procnum == NFSPROC_WRITE &&
- procrastinate > 0 && !notstarted))
- error = nfsrv_writegather(&nd, slp, &mreq);
- else
- error = (*(nfsrv3_procs[nd->nd_procnum]))(nd,
- slp, &mreq);
- NFSD_LOCK();
- if (mreq == NULL)
- break;
- if (error != 0 && error != NFSERR_RETVOID) {
- nfsrvstats.srv_errs++;
- nfsrv_updatecache(nd, FALSE, mreq);
- if (nd->nd_nam2)
- free(nd->nd_nam2, M_SONAME);
- break;
- }
- nfsrvstats.srvrpccnt[nd->nd_procnum]++;
- nfsrv_updatecache(nd, TRUE, mreq);
- nd->nd_mrep = NULL;
- /* FALLTHROUGH */
- case RC_REPLY:
- NFSD_UNLOCK();
- siz = m_length(mreq, NULL);
- if (siz <= 0 || siz > NFS_MAXPACKET) {
- printf("mbuf siz=%d\n",siz);
- panic("Bad nfs svc reply");
- }
- m = mreq;
- m->m_pkthdr.len = siz;
- m->m_pkthdr.rcvif = NULL;
- /*
- * For stream protocols, prepend a Sun RPC
- * Record Mark.
- */
- if (sotype == SOCK_STREAM) {
- M_PREPEND(m, NFSX_UNSIGNED, M_WAIT);
- *mtod(m, u_int32_t *) = htonl(0x80000000 | siz);
- }
- NFSD_LOCK();
- if (slp->ns_so->so_proto->pr_flags & PR_CONNREQUIRED)
- (void) nfs_slplock(slp, 1);
- if (slp->ns_flag & SLP_VALID) {
- NFSD_UNLOCK();
- error = nfsrv_send(slp->ns_so, nd->nd_nam2, m);
- NFSD_LOCK();
- } else {
- error = EPIPE;
- m_freem(m);
- }
- if (nd->nd_nam2)
- free(nd->nd_nam2, M_SONAME);
- if (nd->nd_mrep)
- m_freem(nd->nd_mrep);
- if (error == EPIPE)
- nfsrv_zapsock(slp);
- if (slp->ns_so->so_proto->pr_flags & PR_CONNREQUIRED)
- nfs_slpunlock(slp);
- if (error == EINTR || error == ERESTART) {
- if (nd->nd_cr != NULL)
- crfree(nd->nd_cr);
- free((caddr_t)nd, M_NFSRVDESC);
- nfsrv_slpderef(slp);
- s = splnet();
- goto done;
- }
- break;
- case RC_DROPIT:
- m_freem(nd->nd_mrep);
- if (nd->nd_nam2)
- free(nd->nd_nam2, M_SONAME);
- break;
- };
- if (nd) {
- if (nd->nd_cr != NULL)
- crfree(nd->nd_cr);
- free((caddr_t)nd, M_NFSRVDESC);
- nd = NULL;
- }
-
- /*
- * Check to see if there are outstanding writes that
- * need to be serviced.
- */
- cur_usec = nfs_curusec();
- s = splsoftclock();
- if (LIST_FIRST(&slp->ns_tq) &&
- LIST_FIRST(&slp->ns_tq)->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, nfsd, &nd)) {
- nfsd->nfsd_flag &= ~NFSD_REQINPROG;
- nfsd->nfsd_slp = NULL;
- nfsrv_slpderef(slp);
- }
- mtx_assert(&Giant, MA_NOTOWNED);
- }
-done:
- mtx_assert(&Giant, MA_NOTOWNED);
- TAILQ_REMOVE(&nfsd_head, nfsd, nfsd_chain);
- splx(s);
- free((caddr_t)nfsd, M_NFSD);
- if (--nfsrv_numnfsd == 0)
- nfsrv_init(TRUE); /* Reinitialize everything */
- NFSD_UNLOCK();
- return (error);
-}
-
-/*
- * Shut down a socket associated with an nfssvc_sock structure.
- * Should be called with the send lock set, if required.
- * The trick here is to increment the sref at the start, so that the nfsds
- * will stop using it and clear ns_flag at the end so that it will not be
- * reassigned during cleanup.
- */
-static void
-nfsrv_zapsock(struct nfssvc_sock *slp)
-{
- struct nfsrv_descript *nwp, *nnwp;
- struct socket *so;
- struct file *fp;
- struct nfsrv_rec *rec;
- int s;
-
- NFSD_LOCK_ASSERT();
-
- /*
- * XXXRW: By clearing all flags, other threads/etc should ignore
- * this slp and we can safely release nfsd_mtx so we can clean
- * up the slp safely.
- */
- slp->ns_flag &= ~SLP_ALLFLAGS;
- fp = slp->ns_fp;
- if (fp) {
- NFSD_UNLOCK();
- slp->ns_fp = NULL;
- so = slp->ns_so;
- SOCKBUF_LOCK(&so->so_rcv);
- soupcall_clear(so, SO_RCV);
- SOCKBUF_UNLOCK(&so->so_rcv);
- soshutdown(so, SHUT_RDWR);
- closef(fp, NULL);
- NFSD_LOCK();
- if (slp->ns_nam)
- free(slp->ns_nam, M_SONAME);
- m_freem(slp->ns_raw);
- while ((rec = STAILQ_FIRST(&slp->ns_rec)) != NULL) {
- STAILQ_REMOVE_HEAD(&slp->ns_rec, nr_link);
- if (rec->nr_address)
- free(rec->nr_address, M_SONAME);
- m_freem(rec->nr_packet);
- free(rec, M_NFSRVDESC);
- }
- s = splsoftclock();
- for (nwp = LIST_FIRST(&slp->ns_tq); nwp; nwp = nnwp) {
- nnwp = LIST_NEXT(nwp, nd_tq);
- LIST_REMOVE(nwp, nd_tq);
- if (nwp->nd_cr != NULL)
- crfree(nwp->nd_cr);
- free((caddr_t)nwp, M_NFSRVDESC);
- }
- LIST_INIT(&slp->ns_tq);
- splx(s);
- }
-}
-
-/*
- * Derefence a server socket structure. If it has no more references and
- * is no longer valid, you can throw it away.
- */
-void
-nfsrv_slpderef(struct nfssvc_sock *slp)
-{
-
- NFSD_LOCK_ASSERT();
-
- if (--(slp->ns_sref) == 0 && (slp->ns_flag & SLP_VALID) == 0) {
- TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain);
- free((caddr_t)slp, M_NFSSVC);
- }
-}
-
-/*
- * Lock a socket against others.
- *
- * XXXRW: Wait argument is always 1 in the caller. Replace with a real
- * sleep lock?
- */
-int
-nfs_slplock(struct nfssvc_sock *slp, int wait)
-{
- int *statep = &slp->ns_solock;
-
- NFSD_LOCK_ASSERT();
-
- if (!wait && (*statep & NFSRV_SNDLOCK))
- return(0); /* already locked, fail */
- while (*statep & NFSRV_SNDLOCK) {
- *statep |= NFSRV_WANTSND;
- (void) msleep(statep, &nfsd_mtx, PZERO - 1, "nfsslplck", 0);
- }
- *statep |= NFSRV_SNDLOCK;
- return (1);
-}
-
-/*
- * Unlock the stream socket for others.
- */
-void
-nfs_slpunlock(struct nfssvc_sock *slp)
-{
- int *statep = &slp->ns_solock;
-
- NFSD_LOCK_ASSERT();
-
- if ((*statep & NFSRV_SNDLOCK) == 0)
- panic("nfs slpunlock");
- *statep &= ~NFSRV_SNDLOCK;
- if (*statep & NFSRV_WANTSND) {
- *statep &= ~NFSRV_WANTSND;
- wakeup(statep);
- }
-}
-
-/*
- * Initialize the data structures for the server.
- * Handshake with any new nfsds starting up to avoid any chance of
- * corruption.
- */
-void
-nfsrv_init(int terminating)
-{
- struct nfssvc_sock *slp, *nslp;
-
- NFSD_LOCK_ASSERT();
-
- if (nfssvc_sockhead_flag & SLP_INIT)
- panic("nfsd init");
- nfssvc_sockhead_flag |= SLP_INIT;
- if (terminating) {
- TAILQ_FOREACH_SAFE(slp, &nfssvc_sockhead, ns_chain, nslp) {
- if (slp->ns_flag & SLP_VALID)
- nfsrv_zapsock(slp);
- TAILQ_REMOVE(&nfssvc_sockhead, slp, ns_chain);
- free((caddr_t)slp, M_NFSSVC);
- }
- nfsrv_cleancache(); /* And clear out server cache */
- } else
- nfs_pub.np_valid = 0;
-
- TAILQ_INIT(&nfssvc_sockhead);
- nfssvc_sockhead_flag &= ~SLP_INIT;
- if (nfssvc_sockhead_flag & SLP_WANTINIT) {
- nfssvc_sockhead_flag &= ~SLP_WANTINIT;
- wakeup(&nfssvc_sockhead);
- }
-
- TAILQ_INIT(&nfsd_head);
- nfsd_head_flag &= ~NFSD_CHECKSLP;
-
-#if 0
- nfs_udpsock = (struct nfssvc_sock *)
- malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK | M_ZERO);
- STAILQ_INIT(&nfs_udpsock->ns_rec);
- TAILQ_INSERT_HEAD(&nfssvc_sockhead, nfs_udpsock, ns_chain);
-
- nfs_cltpsock = (struct nfssvc_sock *)
- malloc(sizeof (struct nfssvc_sock), M_NFSSVC, M_WAITOK | M_ZERO);
- STAILQ_INIT(&nfs_cltpsock->ns_rec);
- TAILQ_INSERT_TAIL(&nfssvc_sockhead, nfs_cltpsock, ns_chain);
-#endif
-}
-
-#endif /* NFS_LEGACYRPC */
diff --git a/sys/nfsserver/nfsrvcache.h b/sys/nfsserver/nfsrvcache.h
index 9c527e9..d4e31b1 100644
--- a/sys/nfsserver/nfsrvcache.h
+++ b/sys/nfsserver/nfsrvcache.h
@@ -44,46 +44,4 @@
#define NFSRVCACHE_MAX_SIZE 2048
#define NFSRVCACHE_MIN_SIZE 64
-#ifdef NFS_LEGACYRPC
-
-struct nfsrvcache {
- TAILQ_ENTRY(nfsrvcache) rc_lru; /* LRU chain */
- LIST_ENTRY(nfsrvcache) rc_hash; /* Hash chain */
- u_int32_t rc_xid; /* rpc id number */
- union {
- struct mbuf *ru_repmb; /* Reply mbuf list OR */
- int ru_repstat; /* Reply status */
- } rc_un;
- union nethostaddr rc_haddr; /* Host address */
- u_int32_t rc_proc; /* rpc proc number */
- u_char rc_state; /* Current state of request */
- u_char rc_flag; /* Flag bits */
-};
-
-#define rc_reply rc_un.ru_repmb
-#define rc_status rc_un.ru_repstat
-#define rc_inetaddr rc_haddr.had_inetaddr
-#define rc_nam rc_haddr.had_nam
-
-/* Cache entry states */
-#define RC_UNUSED 0
-#define RC_INPROG 1
-#define RC_DONE 2
-
-/* Return values */
-#define RC_DROPIT 0
-#define RC_REPLY 1
-#define RC_DOIT 2
-
-/* Flag bits */
-#define RC_LOCKED 0x01
-#define RC_WANTED 0x02
-#define RC_REPSTATUS 0x04
-#define RC_REPMBUF 0x08
-/* free 0x10 */
-#define RC_INETADDR 0x20
-#define RC_NAM 0x40
-
-#endif
-
#endif
OpenPOWER on IntegriCloud