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

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