home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / fs / nfs / sock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-01  |  4.4 KB  |  186 lines

  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)
  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\n", 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)
  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.  
  186.