summaryrefslogtreecommitdiffstats
path: root/sys/nfs4client/nfs4_socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/nfs4client/nfs4_socket.c')
-rw-r--r--sys/nfs4client/nfs4_socket.c340
1 files changed, 340 insertions, 0 deletions
diff --git a/sys/nfs4client/nfs4_socket.c b/sys/nfs4client/nfs4_socket.c
new file mode 100644
index 0000000..f997d52
--- /dev/null
+++ b/sys/nfs4client/nfs4_socket.c
@@ -0,0 +1,340 @@
+/* $FreeBSD$ */
+/* $Id: nfs_socket.c,v 1.12 2003/11/05 14:59:01 rees Exp $ */
+
+/*
+ * copyright (c) 2003
+ * the regents of the university of michigan
+ * all rights reserved
+ *
+ * permission is granted to use, copy, create derivative works and redistribute
+ * this software and such derivative works for any purpose, so long as the name
+ * of the university of michigan is not used in any advertising or publicity
+ * pertaining to the use or distribution of this software without specific,
+ * written prior authorization. if the above copyright notice or any other
+ * identification of the university of michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must also be included.
+ *
+ * this software is provided as is, without representation from the university
+ * of michigan as to its fitness for any purpose, and without warranty by the
+ * university of michigan of any kind, either express or implied, including
+ * without limitation the implied warranties of merchantability and fitness for
+ * a particular purpose. the regents of the university of michigan shall not be
+ * liable for any damages, including special, indirect, incidental, or
+ * consequential damages, with respect to any claim arising out of or in
+ * connection with the use of the software, even if it has been or is hereafter
+ * advised of the possibility of such damages.
+ */
+
+/*
+ * 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)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/socket.h>
+#include <sys/socketvar.h>
+#include <sys/syslog.h>
+#include <sys/vnode.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <rpc/rpcclnt.h>
+
+#include <nfs/rpcv2.h>
+#include <nfs/nfsproto.h>
+#include <nfsclient/nfs.h>
+#include <nfs4client/nfs4.h>
+#include <nfs/xdr_subs.h>
+#include <nfsclient/nfsm_subs.h>
+#include <nfsclient/nfsmount.h>
+
+#ifdef NFS4_USE_RPCCLNT
+#include <rpc/rpcclnt.h>
+#include <rpc/rpcm_subs.h>
+#endif
+
+#ifdef NFS4_USE_RPCCLNT
+static struct rpc_program nfs_program = {
+ NFS_PROG, NFS_VER4, "NFSv4"
+};
+#endif
+
+
+int
+nfs4_connect(struct nfsmount *nmp)
+{
+ struct rpcclnt * rpc = &nmp->nm_rpcclnt;
+ struct rpc_auth * auth;
+ int flag = 0;
+ int error;
+
+ /* XXX hack! */
+#ifdef __OpenBSD__
+ struct proc * td = curproc;
+#else
+ struct thread * td = curthread;
+#endif
+
+ MALLOC(auth, struct rpc_auth *, sizeof(struct rpc_auth), M_TEMP, M_WAITOK);
+ auth->auth_type = RPCAUTH_UNIX;
+
+ /* translate nfs flags -> rpcclnt flags */
+ if (nmp->nm_flag & NFSMNT_SOFT)
+ flag |= RPCCLNT_SOFT;
+
+ if (nmp->nm_flag & NFSMNT_INT)
+ flag |= RPCCLNT_INT;
+
+ if (nmp->nm_flag & NFSMNT_NOCONN)
+ flag |= RPCCLNT_NOCONN;
+
+ if (nmp->nm_flag & NFSMNT_DUMBTIMR)
+ flag |= RPCCLNT_DUMBTIMR;
+
+ /* rpc->rc_servername = nmp->nm_mountp->mnt_stat.f_mntfromname; */
+
+ error = rpcclnt_setup(rpc, &nfs_program, nmp->nm_nam, nmp->nm_sotype,
+ nmp->nm_soproto, auth,
+ /* XXX: check nmp->nm_flag to make sure these are set */
+ (nmp->nm_rsize > nmp->nm_readdirsize) ? nmp->nm_rsize : nmp->nm_readdirsize,
+ nmp->nm_wsize, flag);
+
+ /* set deadthresh, timeo, retry */
+ rpc->rc_deadthresh = nmp->nm_deadthresh;
+ rpc->rc_timeo = nmp->nm_timeo;
+ rpc->rc_retry = nmp->nm_retry;
+
+
+ if (error)
+ return error;
+
+ return rpcclnt_connect(rpc, td);
+}
+
+/*
+ * NFS disconnect. Clean up and unlink.
+ */
+void
+nfs4_disconnect(struct nfsmount *nmp)
+{
+ rpcclnt_disconnect(&nmp->nm_rpcclnt);
+}
+
+void
+nfs4_safedisconnect(struct nfsmount *nmp)
+{
+ rpcclnt_safedisconnect(&nmp->nm_rpcclnt);
+}
+
+/*
+ * 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
+ */
+/* XXX overloaded before */
+#define NQ_TRYLATERDEL 15 /* Initial try later delay (sec) */
+
+int
+nfs4_request(struct vnode *vp, struct mbuf *mrest, int procnum,
+ struct thread *td, struct ucred *cred, struct mbuf **mrp,
+ struct mbuf **mdp, caddr_t *dposp)
+{
+ int error;
+ u_int32_t *tl;
+ struct nfsmount * nmp = VFSTONFS(vp->v_mount);
+ struct rpcclnt * clnt = &nmp->nm_rpcclnt;
+ struct mbuf *md, *mrep;
+ caddr_t dpos;
+ struct rpc_reply reply;
+
+ if ((error = rpcclnt_request(clnt, mrest, procnum, td, cred,
+ &reply)) != 0) {
+ goto out;
+ }
+
+ /* XXX: don't free mrest if an error occured, to allow caller to retry*/
+ m_freem(mrest);
+ mrep = reply.mrep;
+ md = reply.result_md;
+ dpos = reply.result_dpos;
+
+ tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
+ if (*tl != 0) {
+ error = fxdr_unsigned(int, *tl);
+
+ #if 0
+ if ((nmp->nm_flag & NFSMNT_NFSV3) &&
+ error == NFSERR_TRYLATER) {
+ m_freem(mrep);
+ error = 0;
+ waituntil = time_second + trylater_delay;
+ while (time_second < waituntil)
+ (void) tsleep(&lbolt, PSOCK, "nqnfstry", 0);
+ trylater_delay *= nfs_backoff[trylater_cnt];
+ if (trylater_cnt < NFS_NBACKOFF - 1)
+ trylater_cnt++;
+ goto tryagain;
+ }
+ #endif
+
+ /*
+ ** If the File Handle was stale, invalidate the
+ ** lookup cache, just in case.
+ **/
+ if (error == ESTALE)
+ cache_purge(vp);
+ goto out;
+ }
+
+ *mrp = mrep;
+ *mdp = md;
+ *dposp = dpos;
+ return (0);
+nfsmout:
+out:
+ m_freem(reply.mrep);
+ *mrp = NULL;
+ *mdp = NULL;
+ return (error);
+}
+
+
+int
+nfs4_request_mnt(struct nfsmount *nmp, struct mbuf *mrest, int procnum,
+ struct thread *td, struct ucred *cred, struct mbuf **mrp,
+ struct mbuf **mdp, caddr_t *dposp)
+{
+ int error;
+ u_int32_t *tl;
+ struct rpcclnt * clnt = &nmp->nm_rpcclnt;
+ struct mbuf *md, *mrep;
+ caddr_t dpos;
+ struct rpc_reply reply;
+
+ if ((error = rpcclnt_request(clnt, mrest, procnum, td, cred,
+ &reply)) != 0) {
+ goto out;
+ }
+
+ /* XXX: don't free mrest if an error occured, to allow caller to retry*/
+ m_freem(mrest);
+ mrep = reply.mrep;
+ md = reply.result_md;
+ dpos = reply.result_dpos;
+
+ tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
+ if (*tl != 0) {
+ error = fxdr_unsigned(int, *tl);
+#if 0
+ if ((nmp->nm_flag & NFSMNT_NFSV3) &&
+ error == NFSERR_TRYLATER) {
+ m_freem(mrep);
+ error = 0;
+ waituntil = time_second + trylater_delay;
+ while (time_second < waituntil)
+ (void) tsleep(&lbolt, PSOCK, "nqnfstry", 0);
+ trylater_delay *= nfs_backoff[trylater_cnt];
+ if (trylater_cnt < NFS_NBACKOFF - 1)
+ trylater_cnt++;
+ goto tryagain;
+ }
+#endif
+ goto out;
+ }
+
+ *mrp = mrep;
+ *mdp = md;
+ *dposp = dpos;
+ return (0);
+nfsmout:
+out:
+ m_freem(reply.mrep);
+ *mrp = NULL;
+ *mdp = NULL;
+ return (error);
+}
+
+
+/*
+ * 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
+nfs4_nmcancelreqs(nmp)
+ struct nfsmount *nmp;
+{
+ return rpcclnt_cancelreqs(&nmp->nm_rpcclnt);
+}
+
+/*
+ * Test for a termination condition pending on the process.
+ * This is used for NFSMNT_INT mounts.
+ */
+int
+nfs4_sigintr(struct nfsmount *nmp, struct nfsreq *rep, struct thread *td)
+{
+ if (rep != NULL) {
+ printf("nfs_sigintr: attempting to use nfsreq != NULL\n");
+ return EINTR;
+ }
+ return rpcclnt_sigintr(&nmp->nm_rpcclnt, NULL, td);
+}
OpenPOWER on IntegriCloud