network - Tokenize NFS, fix MP races
[dragonfly.git] / sys / vfs / nfs / nfs_iod.c
index b1547b4..1df710d 100644 (file)
 #include <sys/mutex.h>
 
 #include <sys/signal2.h>
+#include <sys/thread2.h>
 #include <sys/mutex2.h>
+#include <sys/mplock2.h>
 
 #include <netinet/in.h>
 #include <netinet/tcp.h>
-#include <sys/thread2.h>
 
 #include "rpcv2.h"
 #include "nfsproto.h"
@@ -71,6 +72,9 @@
 #include "nfsnode.h"
 #include "nfsrtt.h"
 
+/*
+ * nfs service connection reader thread
+ */
 void
 nfssvc_iod_reader(void *arg)
 {
@@ -79,9 +83,10 @@ nfssvc_iod_reader(void *arg)
        struct nfsreq *req;
        int error;
 
+       lwkt_gettoken(&nmp->nm_token);
+
        if (nmp->nm_rxstate == NFSSVC_INIT)
                nmp->nm_rxstate = NFSSVC_PENDING;
-       crit_enter();
        for (;;) {
                if (nmp->nm_rxstate == NFSSVC_WAITING) {
                        if (TAILQ_FIRST(&nmp->nm_reqq) == NULL &&
@@ -125,7 +130,6 @@ nfssvc_iod_reader(void *arg)
                                continue;
                        }
                        TAILQ_REMOVE(&nmp->nm_reqrxq, req, r_chain);
-                       crit_exit();
                        info = req->r_info;
                        KKASSERT(info);
                        info->error = nfs_request(info,
@@ -139,16 +143,18 @@ nfssvc_iod_reader(void *arg)
                                atomic_subtract_int(&nmp->nm_bioqlen, 1);
                                info->done(info);
                        }
-                       crit_enter();
                }
        }
-       crit_exit();
        nmp->nm_rxthread = NULL;
        nmp->nm_rxstate = NFSSVC_DONE;
+
+       lwkt_reltoken(&nmp->nm_token);
        wakeup(&nmp->nm_rxthread);
 }
 
 /*
+ * nfs service connection writer thread
+ *
  * The writer sits on the send side of the client's socket and
  * does both the initial processing of BIOs and also transmission
  * and retransmission of nfsreq's.
@@ -165,9 +171,11 @@ nfssvc_iod_writer(void *arg)
        struct vnode *vp;
        nfsm_info_t info;
 
+       lwkt_gettoken(&nmp->nm_token);
+
        if (nmp->nm_txstate == NFSSVC_INIT)
                nmp->nm_txstate = NFSSVC_PENDING;
-       crit_enter();
+
        for (;;) {
                if (nmp->nm_txstate == NFSSVC_WAITING) {
                        tsleep(&nmp->nm_txstate, 0, "nfsidl", 0);
@@ -186,9 +194,7 @@ nfssvc_iod_writer(void *arg)
                                break;
                        TAILQ_REMOVE(&nmp->nm_bioq, bio, bio_act);
                        vp = bio->bio_driver_info;
-                       crit_exit();
                        nfs_startio(vp, bio, NULL);
-                       crit_enter();
                }
 
                /*
@@ -201,11 +207,9 @@ nfssvc_iod_writer(void *arg)
                        TAILQ_REMOVE(&nmp->nm_reqtxq, req, r_chain);
                        info = req->r_info;
                        KKASSERT(info);
-                       crit_exit();
                        info->error = nfs_request(info,
                                                  NFSM_STATE_AUTH,
                                                  NFSM_STATE_WAITREPLY);
-                       crit_enter();
                        if (info->error == EINPROGRESS) {
                                ;
                        } else {
@@ -214,19 +218,17 @@ nfssvc_iod_writer(void *arg)
                        }
                }
        }
-       crit_exit();
        nmp->nm_txthread = NULL;
        nmp->nm_txstate = NFSSVC_DONE;
+       lwkt_reltoken(&nmp->nm_token);
        wakeup(&nmp->nm_txthread);
 }
 
 void
 nfssvc_iod_stop1(struct nfsmount *nmp)
 {
-       crit_enter();
        nmp->nm_txstate = NFSSVC_STOPPING;
        nmp->nm_rxstate = NFSSVC_STOPPING;
-       crit_exit();
 }
 
 void