patch-1.3.82 linux/fs/nfs/nfsiod.c
Next file: linux/fs/nfs/nfsroot.c
Previous file: linux/fs/nfs/inode.c
Back to the patch index
Back to the overall index
- Lines: 129
- Date:
Sat Mar 30 23:54:23 1996
- Orig file:
v1.3.81/linux/fs/nfs/nfsiod.c
- Orig date:
Thu Jan 1 02:00:00 1970
diff -u --recursive --new-file v1.3.81/linux/fs/nfs/nfsiod.c linux/fs/nfs/nfsiod.c
@@ -0,0 +1,128 @@
+/*
+ * linux/fs/nfs/nfsiod.c
+ *
+ * Async NFS RPC call support.
+ *
+ * When a process wants to place an asynchronous RPC call, it reserves
+ * an nfsiod slot, fills in all necessary fields including the callback
+ * handler field, and enqueues the request.
+ *
+ * This will wake up nfsiod, which calls nfs_rpc_doio to collect the
+ * reply. It then dispatches the result to the caller via the callback
+ * function, including result value and request pointer. It then re-inserts
+ * itself into the free list.
+ *
+ * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
+ */
+
+#include <linux/sched.h>
+#include <linux/nfs_fs.h>
+#include <linux/errno.h>
+#include <linux/rpcsock.h>
+#include <linux/nfsiod.h>
+
+static struct nfsiod_req * free_list = NULL;
+static int active = 0;
+
+#undef DEBUG_NFSIOD
+#ifdef DEBUG_NFSIOD
+#define dprintk(args...) printk(## args)
+#else
+#define dprintk(args...) /* nothing */
+#endif
+
+
+/*
+ * Reserve an nfsiod slot and initialize the request struct
+ */
+struct nfsiod_req *
+nfsiod_reserve(struct nfs_server *server, nfsiod_done_fn_t callback)
+{
+ struct nfsiod_req *req;
+
+ if (!(req = free_list)) {
+ dprintk("BIO: nfsiod_reserve: no free nfsiods\n");
+ return NULL;
+ }
+ free_list = req->rq_next;
+ memset(&req->rq_rpcreq, 0, sizeof(struct rpc_ioreq));
+
+ if (rpc_reserve(server->rsock, &req->rq_rpcreq, 1) < 0) {
+ dprintk("BIO: nfsiod_reserve failed to reserve RPC slot\n");
+ req->rq_next = free_list;
+ free_list = req;
+ return NULL;
+ }
+
+ req->rq_server = server;
+ req->rq_callback = callback;
+
+ return req;
+}
+
+void
+nfsiod_release(struct nfsiod_req *req)
+{
+ dprintk("BIO: nfsiod_release called\n");
+ rpc_release(req->rq_server->rsock, &req->rq_rpcreq);
+ memset(&req->rq_rpcreq, 0, sizeof(struct rpc_ioreq));
+ req->rq_next = free_list;
+ free_list = req;
+}
+
+/*
+ * Transmit a request and put it on nfsiod's list of pending requests.
+ */
+int
+nfsiod_enqueue(struct nfsiod_req *req)
+{
+ int result;
+
+ dprintk("BIO: enqueuing request %p\n", &req->rq_rpcreq);
+ result = rpc_transmit(req->rq_server->rsock, &req->rq_rpcreq);
+ if (result < 0) {
+ dprintk("BIO: rpc_transmit returned %d\n", result);
+ } else {
+ dprintk("BIO: waking up nfsiod (%p)\n", req->rq_wait);
+ wake_up(&req->rq_wait);
+ schedule();
+ }
+ return result;
+}
+
+/*
+ * This is the main nfsiod loop.
+ */
+int
+nfsiod(void)
+{
+ struct nfsiod_req request, *req = &request;
+ int result;
+
+ dprintk("BIO: nfsiod %d starting\n", current->pid);
+ while (1) {
+ /* Insert request into free list */
+ memset(req, 0, sizeof(*req));
+ req->rq_next = free_list;
+ free_list = req;
+
+ /* Wait until user enqueues request */
+ dprintk("BIO: before: now %d nfsiod's active\n", active);
+ dprintk("BIO: nfsiod %d waiting\n", current->pid);
+ interruptible_sleep_on(&req->rq_wait);
+
+ if (current->signal & ~current->blocked)
+ break;
+ if (!req->rq_rpcreq.rq_slot)
+ continue;
+ dprintk("BIO: nfsiod %d woken up; calling nfs_rpc_doio.\n",
+ current->pid);
+ active++;
+ dprintk("BIO: before: now %d nfsiod's active\n", active);
+ result = nfs_rpc_doio(req->rq_server, &req->rq_rpcreq, 1);
+ req->rq_callback(result, req);
+ active--;
+ }
+
+ return 0;
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this