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

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