root/fs/nfs/nfsiod.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nfsiod_reserve
  2. nfsiod_release
  3. nfsiod_enqueue
  4. nfsiod

   1 /*
   2  * linux/fs/nfs/nfsiod.c
   3  *
   4  * Async NFS RPC call support.
   5  *
   6  * When a process wants to place an asynchronous RPC call, it reserves
   7  * an nfsiod slot, fills in all necessary fields including the callback
   8  * handler field, and enqueues the request.
   9  *
  10  * This will wake up nfsiod, which calls nfs_rpc_doio to collect the
  11  * reply. It then dispatches the result to the caller via the callback
  12  * function, including result value and request pointer. It then re-inserts
  13  * itself into the free list.
  14  *
  15  * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
  16  */
  17 
  18 #include <linux/sched.h>
  19 #include <linux/nfs_fs.h>
  20 #include <linux/string.h>
  21 #include <linux/errno.h>
  22 #include <linux/rpcsock.h>
  23 #include <linux/nfsiod.h>
  24 
  25 static struct nfsiod_req *      free_list = NULL;
  26 static int                      active = 0;
  27 
  28 #undef DEBUG_NFSIOD
  29 #ifdef DEBUG_NFSIOD
  30 #define dprintk(args...)        printk(## args)
  31 #else
  32 #define dprintk(args...)        /* nothing */
  33 #endif
  34 
  35 
  36 /*
  37  * Reserve an nfsiod slot and initialize the request struct
  38  */
  39 struct nfsiod_req *
  40 nfsiod_reserve(struct nfs_server *server, nfsiod_done_fn_t callback)
     /* [previous][next][first][last][top][bottom][index][help] */
  41 {
  42         struct nfsiod_req       *req;
  43 
  44         if (!(req = free_list)) {
  45                 dprintk("BIO: nfsiod_reserve: no free nfsiods\n");
  46                 return NULL;
  47         }
  48         free_list = req->rq_next;
  49         memset(&req->rq_rpcreq, 0, sizeof(struct rpc_ioreq));
  50 
  51         if (rpc_reserve(server->rsock, &req->rq_rpcreq, 1) < 0) {
  52                 dprintk("BIO: nfsiod_reserve failed to reserve RPC slot\n");
  53                 req->rq_next = free_list;
  54                 free_list = req;
  55                 return NULL;
  56         }
  57 
  58         req->rq_server = server;
  59         req->rq_callback = callback;
  60 
  61         return req;
  62 }
  63 
  64 void
  65 nfsiod_release(struct nfsiod_req *req)
     /* [previous][next][first][last][top][bottom][index][help] */
  66 {
  67         dprintk("BIO: nfsiod_release called\n");
  68         rpc_release(req->rq_server->rsock, &req->rq_rpcreq);
  69         memset(&req->rq_rpcreq, 0, sizeof(struct rpc_ioreq));
  70         req->rq_next = free_list;
  71         free_list = req;
  72 }
  73 
  74 /*
  75  * Transmit a request and put it on nfsiod's list of pending requests.
  76  */
  77 int
  78 nfsiod_enqueue(struct nfsiod_req *req)
     /* [previous][next][first][last][top][bottom][index][help] */
  79 {
  80         int     result;
  81 
  82         dprintk("BIO: enqueuing request %p\n", &req->rq_rpcreq);
  83         result = rpc_transmit(req->rq_server->rsock, &req->rq_rpcreq);
  84         if (result < 0) {
  85                 dprintk("BIO: rpc_transmit returned %d\n", result);
  86         } else {
  87                 dprintk("BIO: waking up nfsiod (%p)\n", req->rq_wait);
  88                 wake_up(&req->rq_wait);
  89                 schedule();
  90         }
  91         return result;
  92 }
  93 
  94 /*
  95  * This is the main nfsiod loop.
  96  */
  97 int
  98 nfsiod(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  99 {
 100         struct nfsiod_req       request, *req = &request;
 101         int                     result;
 102 
 103         dprintk("BIO: nfsiod %d starting\n", current->pid);
 104         while (1) {
 105                 /* Insert request into free list */
 106                 memset(req, 0, sizeof(*req));
 107                 req->rq_next = free_list;
 108                 free_list = req;
 109 
 110                 /* Wait until user enqueues request */
 111                 dprintk("BIO: before: now %d nfsiod's active\n", active);
 112                 dprintk("BIO: nfsiod %d waiting\n", current->pid);
 113                 interruptible_sleep_on(&req->rq_wait);
 114 
 115                 if (current->signal & ~current->blocked)
 116                         break;
 117                 if (!req->rq_rpcreq.rq_slot)
 118                         continue;
 119                 dprintk("BIO: nfsiod %d woken up; calling nfs_rpc_doio.\n",
 120                                 current->pid);
 121                 active++;
 122                 dprintk("BIO: before: now %d nfsiod's active\n", active);
 123                 result = nfs_rpc_doio(req->rq_server, &req->rq_rpcreq, 1);
 124                 req->rq_callback(result, req);
 125                 active--;
 126         }
 127 
 128         return 0;
 129 }

/* [previous][next][first][last][top][bottom][index][help] */