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 
   9 #include <linux/config.h>
  10 #include <linux/sched.h>
  11 #include <linux/nfs_fs.h>
  12 #include <linux/errno.h>
  13 #include <linux/socket.h>
  14 #include <linux/fcntl.h>
  15 #include <asm/segment.h>
  16 #include <linux/in.h>
  17 #include <linux/net.h>
  18 
  19 
  20 extern struct socket *socki_lookup(struct inode *inode);
  21 
  22 #define _S(nr) (1<<((nr)-1))
  23 
  24 /*
  25  * We violate some modularity principles here by poking around
  26  * in some socket internals.  Besides having to call socket
  27  * functions from kernel-space instead of user space, the socket
  28  * interface does not lend itself well to being cleanly called
  29  * without a file descriptor.  Since the nfs calls can run on
  30  * behalf of any process, the superblock maintains a file pointer
  31  * to the server socket.
  32  */
  33 
  34 static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end)
     /* [previous][next][first][last][top][bottom][index][help] */
  35 {
  36         struct file *file;
  37         struct inode *inode;
  38         struct socket *sock;
  39         unsigned short fs;
  40         int result;
  41         int xid;
  42         int len;
  43         select_table wait_table;
  44         struct select_table_entry entry;
  45         int (*select) (struct inode *, struct file *, int, select_table *);
  46         int init_timeout, max_timeout;
  47         int timeout;
  48         int retrans;
  49         int major_timeout_seen;
  50         char *server_name;
  51         int n;
  52         int addrlen;
  53         unsigned long old_mask;
  54 
  55         xid = start[0];
  56         len = ((char *) end) - ((char *) start);
  57         file = server->file;
  58         inode = file->f_inode;
  59         select = file->f_op->select;
  60         sock = socki_lookup(inode);
  61         if (!sock) {
  62                 printk("nfs_rpc_call: socki_lookup failed\n");
  63                 return -EBADF;
  64         }
  65         init_timeout = server->timeo;
  66         max_timeout = NFS_MAX_RPC_TIMEOUT*HZ/10;
  67         retrans = server->retrans;
  68         major_timeout_seen = 0;
  69         server_name = server->hostname;
  70         old_mask = current->blocked;
  71         current->blocked |= ~(_S(SIGKILL)
  72 #if 0
  73                 | _S(SIGSTOP)
  74 #endif
  75                 | ((server->flags & NFS_MOUNT_INTR)
  76                 ? ((current->sigaction[SIGINT - 1].sa_handler == SIG_DFL
  77                         ? _S(SIGINT) : 0)
  78                 | (current->sigaction[SIGQUIT - 1].sa_handler == SIG_DFL
  79                         ? _S(SIGQUIT) : 0))
  80                 : 0));
  81         fs = get_fs();
  82         set_fs(get_ds());
  83         for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1) {
  84                 result = sock->ops->send(sock, (void *) start, len, 0, 0);
  85                 if (result < 0) {
  86                         printk("nfs_rpc_call: send error = %d\n", result);
  87                         break;
  88                 }
  89         re_select:
  90                 wait_table.nr = 0;
  91                 wait_table.entry = &entry;
  92                 current->state = TASK_INTERRUPTIBLE;
  93                 if (!select(inode, file, SEL_IN, &wait_table)
  94                     && !select(inode, file, SEL_IN, NULL)) {
  95                         if (timeout > max_timeout)
  96                                 timeout = max_timeout;
  97                         current->timeout = jiffies + timeout;
  98                         schedule();
  99                         remove_wait_queue(entry.wait_address, &entry.wait);
 100                         current->state = TASK_RUNNING;
 101                         if (current->signal & ~current->blocked) {
 102                                 current->timeout = 0;
 103                                 result = -ERESTARTSYS;
 104                                 break;
 105                         }
 106                         if (!current->timeout) {
 107                                 if (n < retrans)
 108                                         continue;
 109                                 if (server->flags & NFS_MOUNT_SOFT) {
 110                                         printk("NFS server %s not responding, "
 111                                                 "timed out", server_name);
 112                                         result = -EIO;
 113                                         break;
 114                                 }
 115                                 n = 0;
 116                                 timeout = init_timeout;
 117                                 init_timeout <<= 1;
 118                                 if (!major_timeout_seen) {
 119                                         printk("NFS server %s not responding, "
 120                                                 "still trying\n", server_name);
 121                                 }
 122                                 major_timeout_seen = 1;
 123                                 continue;
 124                         }
 125                         else
 126                                 current->timeout = 0;
 127                 }
 128                 else if (wait_table.nr)
 129                         remove_wait_queue(entry.wait_address, &entry.wait);
 130                 current->state = TASK_RUNNING;
 131                 addrlen = 0;
 132                 result = sock->ops->recvfrom(sock, (void *) start, PAGE_SIZE, 1, 0,
 133                         NULL, &addrlen);
 134                 if (result < 0) {
 135                         if (result == -EAGAIN) {
 136 #if 0
 137                                 printk("nfs_rpc_call: bad select ready\n");
 138 #endif
 139                                 goto re_select;
 140                         }
 141                         if (result == -ECONNREFUSED) {
 142 #if 0
 143                                 printk("nfs_rpc_call: server playing coy\n");
 144 #endif
 145                                 goto re_select;
 146                         }
 147                         if (result != -ERESTARTSYS) {
 148                                 printk("nfs_rpc_call: recv error = %d\n",
 149                                         -result);
 150                         }
 151                         break;
 152                 }
 153                 if (*start == xid) {
 154                         if (major_timeout_seen)
 155                                 printk("NFS server %s OK\n", server_name);
 156                         break;
 157                 }
 158 #if 0
 159                 printk("nfs_rpc_call: XID mismatch\n");
 160 #endif
 161         }
 162         current->blocked = old_mask;
 163         set_fs(fs);
 164         return result;
 165 }
 166 
 167 /*
 168  * For now we lock out other simulaneous nfs calls for the same filesytem
 169  * because we are single-threaded and don't want to get mismatched
 170  * RPC replies.
 171  */
 172 
 173 int nfs_rpc_call(struct nfs_server *server, int *start, int *end)
     /* [previous][next][first][last][top][bottom][index][help] */
 174 {
 175         int result;
 176 
 177         while (server->lock)
 178                 sleep_on(&server->wait);
 179         server->lock = 1;
 180         result = do_nfs_rpc_call(server, start, end);
 181         server->lock = 0;
 182         wake_up(&server->wait);
 183         return result;
 184 }
 185 

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