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

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