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 #ifdef MODULE
  22 #include <linux/module.h>
  23 #endif
  24 
  25 #include <linux/sched.h>
  26 #include <linux/nfs_fs.h>
  27 #include <linux/errno.h>
  28 #include <linux/socket.h>
  29 #include <linux/fcntl.h>
  30 #include <asm/segment.h>
  31 #include <linux/in.h>
  32 #include <linux/net.h>
  33 #include <linux/mm.h>
  34 
  35 /* JEJB/JSP 2/7/94
  36  * this must match the value of NFS_SLACK_SPACE in linux/fs/nfs/proc.c 
  37  * ***FIXME*** should probably put this in nfs_fs.h */
  38 #define NFS_SLACK_SPACE 1024
  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 = &inode->u.socket_i;
  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           /* JSP 1995-07-01  Use sendto() not send() to cope with multi-homed hosts
 106              as we have set the socket to have INADDR_ANY as it's desination */
 107                 result = sock->ops->sendto(sock, (void *) start, len, 0, 0,
 108                                            &(server->toaddr), sizeof((server->toaddr))) ;
 109                 if (result < 0) {
 110                         printk("nfs_rpc_call: send error = %d\n", result);
 111                         break;
 112                 }
 113         re_select:
 114                 wait_table.nr = 0;
 115                 wait_table.entry = &entry;
 116                 current->state = TASK_INTERRUPTIBLE;
 117                 if (!select(inode, file, SEL_IN, &wait_table)
 118                     && !select(inode, file, SEL_IN, NULL)) {
 119                         if (timeout > max_timeout) {
 120                           /* JEJB/JSP 2/7/94
 121                            * This is useful to see if the system is
 122                            * hanging */
 123                           printk("NFS max timeout reached on %s\n",
 124                                  server_name);
 125                           timeout = max_timeout;
 126                         }
 127                         current->timeout = jiffies + timeout;
 128                         schedule();
 129                         remove_wait_queue(entry.wait_address, &entry.wait);
 130                         current->state = TASK_RUNNING;
 131                         if (current->signal & ~current->blocked) {
 132                                 current->timeout = 0;
 133                                 result = -ERESTARTSYS;
 134                                 break;
 135                         }
 136                         if (!current->timeout) {
 137                                 if (n < retrans)
 138                                         continue;
 139                                 if (server->flags & NFS_MOUNT_SOFT) {
 140                                         printk("NFS server %s not responding, "
 141                                                 "timed out\n", server_name);
 142                                         result = -EIO;
 143                                         break;
 144                                 }
 145                                 n = 0;
 146                                 timeout = init_timeout;
 147                                 init_timeout <<= 1;
 148                                 if (!major_timeout_seen) {
 149                                   printk("NFS server %s not responding, "
 150                                          "still trying\n", server_name);
 151                                 }
 152                                 major_timeout_seen = 1;
 153                                 continue;
 154                         }
 155                         else
 156                                 current->timeout = 0;
 157                 }
 158                 else if (wait_table.nr)
 159                         remove_wait_queue(entry.wait_address, &entry.wait);
 160                 current->state = TASK_RUNNING;
 161                 addrlen = 0;
 162                 /* JEJB/JSP 2/7/94
 163                  * Get the xid from the next packet using a peek, so keep it
 164                  * on the recv queue.  If it is wrong, it will be some reply
 165                  * we don't now need, so discard it */
 166                 result = sock->ops->recvfrom(sock, (void *)&recv_xid,
 167                                              sizeof(recv_xid), 1, MSG_PEEK,
 168                                              NULL, &addrlen);
 169                 if (result < 0) {
 170                         if (result == -EAGAIN) {
 171 #if 0
 172                                 printk("nfs_rpc_call: bad select ready\n");
 173 #endif
 174                                 goto re_select;
 175                         }
 176                         if (result == -ECONNREFUSED) {
 177 #if 0
 178                                 printk("nfs_rpc_call: server playing coy\n");
 179 #endif
 180                                 goto re_select;
 181                         }
 182                         if (result != -ERESTARTSYS) {
 183                                 printk("nfs_rpc_call: recv error = %d\n",
 184                                         -result);
 185                         }
 186                         break;
 187                 }
 188                 if (recv_xid == xid) {
 189                         if (major_timeout_seen)
 190                                 printk("NFS server %s OK\n", server_name);
 191                         break;
 192                 }
 193                 /* JEJB/JSP 2/7/94
 194                  * we have xid mismatch, so discard the packet and start
 195                  * again.  What a hack! but I can't call recvfrom with
 196                  * a null buffer yet. */
 197                 (void)sock->ops->recvfrom(sock, (void *)&recv_xid,
 198                                           sizeof(recv_xid), 1, 0, NULL,
 199                                           &addrlen);
 200 #if 0
 201                 printk("nfs_rpc_call: XID mismatch\n");
 202 #endif
 203                 goto re_select;
 204         }
 205         /* JEJB/JSP 2/7/94
 206          *
 207          * we have the correct xid, so read into the correct place and
 208          * return it
 209          *
 210          */
 211         result=sock->ops->recvfrom(sock, (void *)start, 
 212                                   size + 1024, 1, 0, NULL,
 213                         /* Here is NFS_SLACK_SPACE..., hack */
 214                                   &addrlen);
 215         if (result < 0) {
 216                 printk("NFS: notice message: result=%d\n", result);
 217         } else if (result < addrlen) {
 218                 printk("NFS: just caught a too small read memory size..., email to NET channel\n");
 219                 printk("NFS: result=%d,addrlen=%d\n", result, addrlen);
 220                 result = -EIO;
 221         }
 222         current->blocked = old_mask;
 223         set_fs(fs);
 224         return result;
 225 }
 226 
 227 /*
 228  * For now we lock out other simultaneous nfs calls for the same filesystem
 229  * because we are single-threaded and don't want to get mismatched
 230  * RPC replies.
 231  */
 232 
 233 int nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size)
     /* [previous][next][first][last][top][bottom][index][help] */
 234 {
 235         int result;
 236 
 237         while (server->lock)
 238                 sleep_on(&server->wait);
 239         server->lock = 1;
 240         result = do_nfs_rpc_call(server, start, end, size);
 241         server->lock = 0;
 242         wake_up(&server->wait);
 243         return result;
 244 }
 245 

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