xref: /dflybsd-src/sys/vfs/nfs/nfs_iod.c (revision 52e1cf57a5de67bef07f7942efb1b3c1d31d4cc3)
1*52e1cf57SMatthew Dillon /*
2*52e1cf57SMatthew Dillon  * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
3*52e1cf57SMatthew Dillon  *
4*52e1cf57SMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
5*52e1cf57SMatthew Dillon  * by Matthew Dillon <dillon@backplane.com>
6*52e1cf57SMatthew Dillon  *
7*52e1cf57SMatthew Dillon  * Redistribution and use in source and binary forms, with or without
8*52e1cf57SMatthew Dillon  * modification, are permitted provided that the following conditions
9*52e1cf57SMatthew Dillon  * are met:
10*52e1cf57SMatthew Dillon  *
11*52e1cf57SMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
12*52e1cf57SMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
13*52e1cf57SMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
14*52e1cf57SMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
15*52e1cf57SMatthew Dillon  *    the documentation and/or other materials provided with the
16*52e1cf57SMatthew Dillon  *    distribution.
17*52e1cf57SMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
18*52e1cf57SMatthew Dillon  *    contributors may be used to endorse or promote products derived
19*52e1cf57SMatthew Dillon  *    from this software without specific, prior written permission.
20*52e1cf57SMatthew Dillon  *
21*52e1cf57SMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22*52e1cf57SMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23*52e1cf57SMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24*52e1cf57SMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25*52e1cf57SMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26*52e1cf57SMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27*52e1cf57SMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28*52e1cf57SMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29*52e1cf57SMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30*52e1cf57SMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31*52e1cf57SMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*52e1cf57SMatthew Dillon  * SUCH DAMAGE.
33*52e1cf57SMatthew Dillon  */
34*52e1cf57SMatthew Dillon /*
35*52e1cf57SMatthew Dillon  * NFSIOD operations - now built into the kernel.
36*52e1cf57SMatthew Dillon  */
37*52e1cf57SMatthew Dillon #include <sys/param.h>
38*52e1cf57SMatthew Dillon #include <sys/systm.h>
39*52e1cf57SMatthew Dillon #include <sys/proc.h>
40*52e1cf57SMatthew Dillon #include <sys/malloc.h>
41*52e1cf57SMatthew Dillon #include <sys/mount.h>
42*52e1cf57SMatthew Dillon #include <sys/kernel.h>
43*52e1cf57SMatthew Dillon #include <sys/mbuf.h>
44*52e1cf57SMatthew Dillon #include <sys/vnode.h>
45*52e1cf57SMatthew Dillon #include <sys/fcntl.h>
46*52e1cf57SMatthew Dillon #include <sys/protosw.h>
47*52e1cf57SMatthew Dillon #include <sys/resourcevar.h>
48*52e1cf57SMatthew Dillon #include <sys/socket.h>
49*52e1cf57SMatthew Dillon #include <sys/socketvar.h>
50*52e1cf57SMatthew Dillon #include <sys/socketops.h>
51*52e1cf57SMatthew Dillon #include <sys/syslog.h>
52*52e1cf57SMatthew Dillon #include <sys/thread.h>
53*52e1cf57SMatthew Dillon #include <sys/tprintf.h>
54*52e1cf57SMatthew Dillon #include <sys/sysctl.h>
55*52e1cf57SMatthew Dillon #include <sys/signalvar.h>
56*52e1cf57SMatthew Dillon #include <sys/mutex.h>
57*52e1cf57SMatthew Dillon 
58*52e1cf57SMatthew Dillon #include <sys/signal2.h>
59*52e1cf57SMatthew Dillon #include <sys/mutex2.h>
60*52e1cf57SMatthew Dillon 
61*52e1cf57SMatthew Dillon #include <netinet/in.h>
62*52e1cf57SMatthew Dillon #include <netinet/tcp.h>
63*52e1cf57SMatthew Dillon #include <sys/thread2.h>
64*52e1cf57SMatthew Dillon 
65*52e1cf57SMatthew Dillon #include "rpcv2.h"
66*52e1cf57SMatthew Dillon #include "nfsproto.h"
67*52e1cf57SMatthew Dillon #include "nfs.h"
68*52e1cf57SMatthew Dillon #include "xdr_subs.h"
69*52e1cf57SMatthew Dillon #include "nfsm_subs.h"
70*52e1cf57SMatthew Dillon #include "nfsmount.h"
71*52e1cf57SMatthew Dillon #include "nfsnode.h"
72*52e1cf57SMatthew Dillon #include "nfsrtt.h"
73*52e1cf57SMatthew Dillon 
74*52e1cf57SMatthew Dillon void
75*52e1cf57SMatthew Dillon nfssvc_iod_reader(void *arg)
76*52e1cf57SMatthew Dillon {
77*52e1cf57SMatthew Dillon 	struct nfsmount *nmp = arg;
78*52e1cf57SMatthew Dillon 
79*52e1cf57SMatthew Dillon 	if (nmp->nm_rxstate == NFSSVC_INIT)
80*52e1cf57SMatthew Dillon 		nmp->nm_rxstate = NFSSVC_PENDING;
81*52e1cf57SMatthew Dillon 	for (;;) {
82*52e1cf57SMatthew Dillon 		if (nmp->nm_rxstate == NFSSVC_WAITING) {
83*52e1cf57SMatthew Dillon 			tsleep(&nmp->nm_rxstate, 0, "nfsidl", 0);
84*52e1cf57SMatthew Dillon 			continue;
85*52e1cf57SMatthew Dillon 		}
86*52e1cf57SMatthew Dillon 		if (nmp->nm_rxstate != NFSSVC_PENDING)
87*52e1cf57SMatthew Dillon 			break;
88*52e1cf57SMatthew Dillon 		nmp->nm_rxstate = NFSSVC_WAITING;
89*52e1cf57SMatthew Dillon 
90*52e1cf57SMatthew Dillon #if 0
91*52e1cf57SMatthew Dillon 		error = tsleep((caddr_t)&nfs_iodwant[myiod],
92*52e1cf57SMatthew Dillon 			PCATCH, "nfsidl", 0);
93*52e1cf57SMatthew Dillon #endif
94*52e1cf57SMatthew Dillon 	}
95*52e1cf57SMatthew Dillon 	nmp->nm_rxthread = NULL;
96*52e1cf57SMatthew Dillon 	nmp->nm_rxstate = NFSSVC_DONE;
97*52e1cf57SMatthew Dillon 	wakeup(&nmp->nm_rxthread);
98*52e1cf57SMatthew Dillon }
99*52e1cf57SMatthew Dillon 
100*52e1cf57SMatthew Dillon /*
101*52e1cf57SMatthew Dillon  * The writer sits on the send side of the client's socket and
102*52e1cf57SMatthew Dillon  * does both the initial processing of BIOs and also transmission
103*52e1cf57SMatthew Dillon  * and retransmission of nfsreq's.
104*52e1cf57SMatthew Dillon  */
105*52e1cf57SMatthew Dillon void
106*52e1cf57SMatthew Dillon nfssvc_iod_writer(void *arg)
107*52e1cf57SMatthew Dillon {
108*52e1cf57SMatthew Dillon 	struct nfsmount *nmp = arg;
109*52e1cf57SMatthew Dillon 	struct bio *bio;
110*52e1cf57SMatthew Dillon 	struct vnode *vp;
111*52e1cf57SMatthew Dillon 
112*52e1cf57SMatthew Dillon 	if (nmp->nm_txstate == NFSSVC_INIT)
113*52e1cf57SMatthew Dillon 		nmp->nm_txstate = NFSSVC_PENDING;
114*52e1cf57SMatthew Dillon 	for (;;) {
115*52e1cf57SMatthew Dillon 		if (nmp->nm_txstate == NFSSVC_WAITING) {
116*52e1cf57SMatthew Dillon 			tsleep(&nmp->nm_txstate, 0, "nfsidl", 0);
117*52e1cf57SMatthew Dillon 			continue;
118*52e1cf57SMatthew Dillon 		}
119*52e1cf57SMatthew Dillon 		if (nmp->nm_txstate != NFSSVC_PENDING)
120*52e1cf57SMatthew Dillon 			break;
121*52e1cf57SMatthew Dillon 		nmp->nm_txstate = NFSSVC_WAITING;
122*52e1cf57SMatthew Dillon 
123*52e1cf57SMatthew Dillon 		while (nmp->nm_bioqlen && nmp->nm_reqqlen < 32) {
124*52e1cf57SMatthew Dillon 			bio = TAILQ_FIRST(&nmp->nm_bioq);
125*52e1cf57SMatthew Dillon 			KKASSERT(bio);
126*52e1cf57SMatthew Dillon 			TAILQ_REMOVE(&nmp->nm_bioq, bio, bio_act);
127*52e1cf57SMatthew Dillon 			nmp->nm_bioqlen--;
128*52e1cf57SMatthew Dillon 			vp = bio->bio_driver_info;
129*52e1cf57SMatthew Dillon 			nfs_doio(vp, bio, NULL);
130*52e1cf57SMatthew Dillon 		}
131*52e1cf57SMatthew Dillon 	}
132*52e1cf57SMatthew Dillon 	nmp->nm_txthread = NULL;
133*52e1cf57SMatthew Dillon 	nmp->nm_txstate = NFSSVC_DONE;
134*52e1cf57SMatthew Dillon 	wakeup(&nmp->nm_txthread);
135*52e1cf57SMatthew Dillon }
136*52e1cf57SMatthew Dillon 
137*52e1cf57SMatthew Dillon void
138*52e1cf57SMatthew Dillon nfssvc_iod_stop(struct nfsmount *nmp)
139*52e1cf57SMatthew Dillon {
140*52e1cf57SMatthew Dillon 	nmp->nm_txstate = NFSSVC_STOPPING;
141*52e1cf57SMatthew Dillon 	wakeup(&nmp->nm_txstate);
142*52e1cf57SMatthew Dillon 	while (nmp->nm_txthread)
143*52e1cf57SMatthew Dillon 		tsleep(&nmp->nm_txthread, 0, "nfssttx", 0);
144*52e1cf57SMatthew Dillon 
145*52e1cf57SMatthew Dillon 	nmp->nm_rxstate = NFSSVC_STOPPING;
146*52e1cf57SMatthew Dillon 	wakeup(&nmp->nm_rxstate);
147*52e1cf57SMatthew Dillon 	while (nmp->nm_rxthread)
148*52e1cf57SMatthew Dillon 		tsleep(&nmp->nm_rxthread, 0, "nfsstrx", 0);
149*52e1cf57SMatthew Dillon }
150*52e1cf57SMatthew Dillon 
151*52e1cf57SMatthew Dillon void
152*52e1cf57SMatthew Dillon nfssvc_iod_writer_wakeup(struct nfsmount *nmp)
153*52e1cf57SMatthew Dillon {
154*52e1cf57SMatthew Dillon 	if (nmp->nm_txstate == NFSSVC_WAITING) {
155*52e1cf57SMatthew Dillon 		nmp->nm_txstate = NFSSVC_PENDING;
156*52e1cf57SMatthew Dillon 		wakeup(&nmp->nm_txstate);
157*52e1cf57SMatthew Dillon 	}
158*52e1cf57SMatthew Dillon }
159