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         int addrlen;
  50 
  51         xid = start[0];
  52         len = ((char *) end) - ((char *) start);
  53         file = server->file;
  54         inode = file->f_inode;
  55         select = file->f_op->select;
  56         sock = socki_lookup(inode);
  57         init_timeout = server->timeo;
  58         max_timeout = NFS_MAX_RPC_TIMEOUT*HZ/10;
  59         retrans = server->retrans;
  60         major_timeout_seen = 0;
  61         server_name = server->hostname;
  62         if (!sock) {
  63                 printk("nfs_rpc_call: socki_lookup failed\n");
  64                 return -EBADF;
  65         }
  66         __asm__("mov %%fs,%0":"=r" (fs));
  67         __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
  68         for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1) {
  69                 result = sock->ops->send(sock, (void *) start, len, 0, 0);
  70                 if (result < 0) {
  71                         printk("nfs_rpc_call: send error = %d\n", result);
  72                         break;
  73                 }
  74         re_select:
  75                 wait_table.nr = 0;
  76                 wait_table.entry = &entry;
  77                 current->state = TASK_INTERRUPTIBLE;
  78                 if (!select(inode, file, SEL_IN, &wait_table)
  79                     && !select(inode, file, SEL_IN, NULL)) {
  80                         if (timeout > max_timeout)
  81                                 timeout = max_timeout;
  82                         current->timeout = jiffies + timeout;
  83                         schedule();
  84                         remove_wait_queue(entry.wait_address, &entry.wait);
  85                         current->state = TASK_RUNNING;
  86                         if (current->signal & ~current->blocked) {
  87 #if 0
  88                                 /* doesn't work yet */
  89                                 if (!(server->flags & NFS_MOUNT_INTR))
  90                                         goto re_select;
  91 #endif
  92                                 current->timeout = 0;
  93                                 result = -EINTR;
  94                                 break;
  95                         }
  96                         if (!current->timeout) {
  97                                 if (n < retrans)
  98                                         continue;
  99                                 if (server->flags & NFS_MOUNT_SOFT) {
 100                                         printk("NFS server %s not responding, "
 101                                                 "timed out", server_name);
 102                                         result = -EIO;
 103                                         break;
 104                                 }
 105                                 n = 0;
 106                                 timeout = init_timeout;
 107                                 init_timeout <<= 1;
 108                                 if (!major_timeout_seen) {
 109                                         printk("NFS server %s not responding, "
 110                                                 "still trying\n", server_name);
 111                                 }
 112                                 major_timeout_seen = 1;
 113                                 continue;
 114                         }
 115                         else
 116                                 current->timeout = 0;
 117                 }
 118                 else if (wait_table.nr)
 119                         remove_wait_queue(entry.wait_address, &entry.wait);
 120                 current->state = TASK_RUNNING;
 121                 addrlen = 0;
 122                 result = sock->ops->recvfrom(sock, (void *) start, 4096, 1, 0,
 123                         NULL, &addrlen);
 124                 if (result < 0) {
 125                         if (result == -EAGAIN) {
 126                                 printk("nfs_rpc_call: bad select ready\n");
 127                                 goto re_select;
 128                         }
 129                         if (result != -ERESTARTSYS) {
 130                                 printk("nfs_rpc_call: recv error = %d\n",
 131                                         -result);
 132                         }
 133                         break;
 134                 }
 135                 if (*start == xid) {
 136                         if (major_timeout_seen)
 137                                 printk("NFS server %s OK\n", server_name);
 138                         break;
 139                 }
 140 #if 0
 141                 printk("nfs_rpc_call: XID mismatch\n");
 142 #endif
 143         }
 144         __asm__("mov %0,%%fs"::"r" (fs));
 145         return result;
 146 }
 147 
 148 /*
 149  * For now we lock out other simulaneous nfs calls for the same filesytem
 150  * because we are single-threaded and don't want to get mismatched
 151  * RPC replies.
 152  */
 153 
 154 int nfs_rpc_call(struct nfs_server *server, int *start, int *end)
     /* [previous][next][first][last][top][bottom][index][help] */
 155 {
 156         int result;
 157 
 158         while (server->lock)
 159                 sleep_on(&server->wait);
 160         server->lock = 1;
 161         result = do_nfs_rpc_call(server, start, end);
 162         server->lock = 0;
 163         wake_up(&server->wait);
 164         return result;
 165 }
 166 

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