root/fs/nfs/sock.c

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

DEFINITIONS

This source file includes following definitions.
  1. do_nfs_rpc_call
  2. nfs_rpc_call

   1 /*
   2  *  linux/fs/nfs/sock.c
   3  *
   4  *  Copyright (C) 1992, 1993  Rick Sladkey
   5  *
   6  *  low-level nfs remote procedure call interface
   7  *
   8  * FIXES
   9  *
  10  * 2/7/94 James Bottomley and Jon Peatfield DAMTP, Cambridge University
  11  *
  12  * An xid mismatch no longer causes the request to be trashed.
  13  *
  14  */
  15 
  16 #include <linux/config.h>
  17 #include <linux/sched.h>
  18 #include <linux/nfs_fs.h>
  19 #include <linux/errno.h>
  20 #include <linux/socket.h>
  21 #include <linux/fcntl.h>
  22 #include <asm/segment.h>
  23 #include <linux/in.h>
  24 #include <linux/net.h>
  25 #include <linux/mm.h>
  26 
  27 /* JEJB/JSP 2/7/94
  28  * this must match the value of NFS_SLACK_SPACE in linux/fs/nfs/proc.c 
  29  * ***FIXME*** should probably put this in nfs_fs.h */
  30 #define NFS_SLACK_SPACE 1024
  31 
  32 
  33 extern struct socket *socki_lookup(struct inode *inode);
  34 
  35 #define _S(nr) (1<<((nr)-1))
  36 
  37 /*
  38  * We violate some modularity principles here by poking around
  39  * in some socket internals.  Besides having to call socket
  40  * functions from kernel-space instead of user space, the socket
  41  * interface does not lend itself well to being cleanly called
  42  * without a file descriptor.  Since the nfs calls can run on
  43  * behalf of any process, the superblock maintains a file pointer
  44  * to the server socket.
  45  */
  46 
  47 static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end)
     /* [previous][next][first][last][top][bottom][index][help] */
  48 {
  49         struct file *file;
  50         struct inode *inode;
  51         struct socket *sock;
  52         unsigned short fs;
  53         int result;
  54         int xid;
  55         int len;
  56         select_table wait_table;
  57         struct select_table_entry entry;
  58         int (*select) (struct inode *, struct file *, int, select_table *);
  59         int init_timeout, max_timeout;
  60         int timeout;
  61         int retrans;
  62         int major_timeout_seen;
  63         char *server_name;
  64         int n;
  65         int addrlen;
  66         unsigned long old_mask;
  67         /* JEJB/JSP 2/7/94
  68          * This is for a 4 byte recv of the xid only */
  69         int recv_xid;
  70 
  71         xid = start[0];
  72         len = ((char *) end) - ((char *) start);
  73         file = server->file;
  74         inode = file->f_inode;
  75         select = file->f_op->select;
  76         sock = socki_lookup(inode);
  77         if (!sock) {
  78                 printk("nfs_rpc_call: socki_lookup failed\n");
  79                 return -EBADF;
  80         }
  81         init_timeout = server->timeo;
  82         max_timeout = NFS_MAX_RPC_TIMEOUT*HZ/10;
  83         retrans = server->retrans;
  84         major_timeout_seen = 0;
  85         server_name = server->hostname;
  86         old_mask = current->blocked;
  87         current->blocked |= ~(_S(SIGKILL)
  88 #if 0
  89                 | _S(SIGSTOP)
  90 #endif
  91                 | ((server->flags & NFS_MOUNT_INTR)
  92                 ? ((current->sigaction[SIGINT - 1].sa_handler == SIG_DFL
  93                         ? _S(SIGINT) : 0)
  94                 | (current->sigaction[SIGQUIT - 1].sa_handler == SIG_DFL
  95                         ? _S(SIGQUIT) : 0))
  96                 : 0));
  97         fs = get_fs();
  98         set_fs(get_ds());
  99         for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1) {
 100                 result = sock->ops->send(sock, (void *) start, len, 0, 0);
 101                 if (result < 0) {
 102                         printk("nfs_rpc_call: send error = %d\n", result);
 103                         break;
 104                 }
 105         re_select:
 106                 wait_table.nr = 0;
 107                 wait_table.entry = &entry;
 108                 current->state = TASK_INTERRUPTIBLE;
 109                 if (!select(inode, file, SEL_IN, &wait_table)
 110                     && !select(inode, file, SEL_IN, NULL)) {
 111                         if (timeout > max_timeout) {
 112                           /* JEJB/JSP 2/7/94
 113                            * This is useful to see if the system is
 114                            * hanging */
 115                           printk("NFS max timeout reached on %s\n",
 116                                  server_name);
 117                           timeout = max_timeout;
 118                         }
 119                         current->timeout = jiffies + timeout;
 120                         schedule();
 121                         remove_wait_queue(entry.wait_address, &entry.wait);
 122                         current->state = TASK_RUNNING;
 123                         if (current->signal & ~current->blocked) {
 124                                 current->timeout = 0;
 125                                 result = -ERESTARTSYS;
 126                                 break;
 127                         }
 128                         if (!current->timeout) {
 129                                 if (n < retrans)
 130                                         continue;
 131                                 if (server->flags & NFS_MOUNT_SOFT) {
 132                                         printk("NFS server %s not responding, "
 133                                                 "timed out\n", server_name);
 134                                         result = -EIO;
 135                                         break;
 136                                 }
 137                                 n = 0;
 138                                 timeout = init_timeout;
 139                                 init_timeout <<= 1;
 140                                 if (!major_timeout_seen) {
 141                                   printk("NFS server %s not responding, "
 142                                          "still trying\n", server_name);
 143                                 }
 144                                 major_timeout_seen = 1;
 145                                 continue;
 146                         }
 147                         else
 148                                 current->timeout = 0;
 149                 }
 150                 else if (wait_table.nr)
 151                         remove_wait_queue(entry.wait_address, &entry.wait);
 152                 current->state = TASK_RUNNING;
 153                 addrlen = 0;
 154                 /* JEJB/JSP 2/7/94
 155                  * Get the xid from the next packet using a peek, so keep it
 156                  * on the recv queue.  If it is wrong, it will be some reply
 157                  * we don't now need, so discard it */
 158                 result = sock->ops->recvfrom(sock, (void *)&recv_xid,
 159                                              sizeof(recv_xid), 1, MSG_PEEK,
 160                                              NULL, &addrlen);
 161                 if (result < 0) {
 162                         if (result == -EAGAIN) {
 163 #if 0
 164                                 printk("nfs_rpc_call: bad select ready\n");
 165 #endif
 166                                 goto re_select;
 167                         }
 168                         if (result == -ECONNREFUSED) {
 169 #if 0
 170                                 printk("nfs_rpc_call: server playing coy\n");
 171 #endif
 172                                 goto re_select;
 173                         }
 174                         if (result != -ERESTARTSYS) {
 175                                 printk("nfs_rpc_call: recv error = %d\n",
 176                                         -result);
 177                         }
 178                         break;
 179                 }
 180                 if (recv_xid == xid) {
 181                         if (major_timeout_seen)
 182                                 printk("NFS server %s OK\n", server_name);
 183                         break;
 184                 }
 185                 /* JEJB/JSP 2/7/94
 186                  * we have xid mismatch, so discard the packet and start
 187                  * again.  What a hack! but I can't call recvfrom with
 188                  * a null buffer yet. */
 189                 (void)sock->ops->recvfrom(sock, (void *)&recv_xid,
 190                                           sizeof(recv_xid), 1, 0, NULL,
 191                                           &addrlen);
 192 #if 0
 193                 printk("nfs_rpc_call: XID mismatch\n");
 194 #endif
 195         }
 196         /* JEJB/JSP 2/7/94
 197          *
 198          * we have the correct xid, so read into the correct place and
 199          * return it
 200          *
 201          * Here we need to know the size given to alloc, server->wsize for
 202          * writes or server->rsize for reads.  In practice these are the
 203          * same. 
 204          *
 205          * If they are not the same then a reply to a write request will be
 206          * a small acknowledgement, so even if wsize < rsize we should never
 207          * cause data to be written past the end of the buffer (unless some
 208          * brain damaged implementation sends out a large write acknowledge).
 209          *
 210          * FIXME:  I should really know how big a packet was alloc'd --
 211          *         should pass it to do_nfs_rpc. */
 212         result=sock->ops->recvfrom(sock, (void *)start, 
 213                                   server->rsize + NFS_SLACK_SPACE, 1, 0, NULL,
 214                                   &addrlen);
 215         current->blocked = old_mask;
 216         set_fs(fs);
 217         return result;
 218 }
 219 
 220 /*
 221  * For now we lock out other simulaneous nfs calls for the same filesytem
 222  * because we are single-threaded and don't want to get mismatched
 223  * RPC replies.
 224  */
 225 
 226 int nfs_rpc_call(struct nfs_server *server, int *start, int *end)
     /* [previous][next][first][last][top][bottom][index][help] */
 227 {
 228         int result;
 229 
 230         while (server->lock)
 231                 sleep_on(&server->wait);
 232         server->lock = 1;
 233         result = do_nfs_rpc_call(server, start, end);
 234         server->lock = 0;
 235         wake_up(&server->wait);
 236         return result;
 237 }
 238 

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