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

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