home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / fs / nfs / sock.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-07  |  6.3 KB  |  243 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.  * FIXES
  9.  *
  10.  * 2/7/94 James Bottomley and Jon Peatfield DAMTP, Cambridge University
  11.  *
  12.  * An xid mismatch no longer causes the request to be trashed.
  13.  *
  14.  * Peter Eriksson - incorrect XID used to confuse Linux
  15.  * Florian La Roche - use the correct max size, if reading a packet and
  16.  *                    also verify, if the whole packet has been read...
  17.  *                    more checks should be done in proc.c...
  18.  *
  19.  */
  20.  
  21. #ifdef MODULE
  22. #include <linux/module.h>
  23. #endif
  24.  
  25. #include <linux/sched.h>
  26. #include <linux/nfs_fs.h>
  27. #include <linux/errno.h>
  28. #include <linux/socket.h>
  29. #include <linux/fcntl.h>
  30. #include <asm/segment.h>
  31. #include <linux/in.h>
  32. #include <linux/net.h>
  33. #include <linux/mm.h>
  34.  
  35. /* JEJB/JSP 2/7/94
  36.  * this must match the value of NFS_SLACK_SPACE in linux/fs/nfs/proc.c 
  37.  * ***FIXME*** should probably put this in nfs_fs.h */
  38. #define NFS_SLACK_SPACE 1024
  39.  
  40. #define _S(nr) (1<<((nr)-1))
  41.  
  42. /*
  43.  * We violate some modularity principles here by poking around
  44.  * in some socket internals.  Besides having to call socket
  45.  * functions from kernel-space instead of user space, the socket
  46.  * interface does not lend itself well to being cleanly called
  47.  * without a file descriptor.  Since the nfs calls can run on
  48.  * behalf of any process, the superblock maintains a file pointer
  49.  * to the server socket.
  50.  */
  51.  
  52. static int do_nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size)
  53. {
  54.     struct file *file;
  55.     struct inode *inode;
  56.     struct socket *sock;
  57.     unsigned short fs;
  58.     int result;
  59.     int xid;
  60.     int len;
  61.     select_table wait_table;
  62.     struct select_table_entry entry;
  63.     int (*select) (struct inode *, struct file *, int, select_table *);
  64.     int init_timeout, max_timeout;
  65.     int timeout;
  66.     int retrans;
  67.     int major_timeout_seen;
  68.     char *server_name;
  69.     int n;
  70.     int addrlen;
  71.     unsigned long old_mask;
  72.     /* JEJB/JSP 2/7/94
  73.      * This is for a 4 byte recv of the xid only */
  74.     int recv_xid;
  75.  
  76.     xid = start[0];
  77.     len = ((char *) end) - ((char *) start);
  78.     file = server->file;
  79.     inode = file->f_inode;
  80.     select = file->f_op->select;
  81.     sock = &inode->u.socket_i;
  82.     if (!sock) {
  83.         printk("nfs_rpc_call: socki_lookup failed\n");
  84.         return -EBADF;
  85.     }
  86.     init_timeout = server->timeo;
  87.     max_timeout = NFS_MAX_RPC_TIMEOUT*HZ/10;
  88.     retrans = server->retrans;
  89.     major_timeout_seen = 0;
  90.     server_name = server->hostname;
  91.     old_mask = current->blocked;
  92.     current->blocked |= ~(_S(SIGKILL)
  93. #if 0
  94.         | _S(SIGSTOP)
  95. #endif
  96.         | ((server->flags & NFS_MOUNT_INTR)
  97.         ? ((current->sigaction[SIGINT - 1].sa_handler == SIG_DFL
  98.             ? _S(SIGINT) : 0)
  99.         | (current->sigaction[SIGQUIT - 1].sa_handler == SIG_DFL
  100.             ? _S(SIGQUIT) : 0))
  101.         : 0));
  102.     fs = get_fs();
  103.     set_fs(get_ds());
  104.     for (n = 0, timeout = init_timeout; ; n++, timeout <<= 1) {
  105.         result = sock->ops->send(sock, (void *) start, len, 0, 0);
  106.         if (result < 0) {
  107.             printk("nfs_rpc_call: send error = %d\n", result);
  108.             break;
  109.         }
  110.     re_select:
  111.         wait_table.nr = 0;
  112.         wait_table.entry = &entry;
  113.         current->state = TASK_INTERRUPTIBLE;
  114.         if (!select(inode, file, SEL_IN, &wait_table)
  115.             && !select(inode, file, SEL_IN, NULL)) {
  116.             if (timeout > max_timeout) {
  117.               /* JEJB/JSP 2/7/94
  118.                * This is useful to see if the system is
  119.                * hanging */
  120.               printk("NFS max timeout reached on %s\n",
  121.                  server_name);
  122.               timeout = max_timeout;
  123.             }
  124.             current->timeout = jiffies + timeout;
  125.             schedule();
  126.             remove_wait_queue(entry.wait_address, &entry.wait);
  127.             current->state = TASK_RUNNING;
  128.             if (current->signal & ~current->blocked) {
  129.                 current->timeout = 0;
  130.                 result = -ERESTARTSYS;
  131.                 break;
  132.             }
  133.             if (!current->timeout) {
  134.                 if (n < retrans)
  135.                     continue;
  136.                 if (server->flags & NFS_MOUNT_SOFT) {
  137.                     printk("NFS server %s not responding, "
  138.                         "timed out\n", server_name);
  139.                     result = -EIO;
  140.                     break;
  141.                 }
  142.                 n = 0;
  143.                 timeout = init_timeout;
  144.                 init_timeout <<= 1;
  145.                 if (!major_timeout_seen) {
  146.                   printk("NFS server %s not responding, "
  147.                      "still trying\n", server_name);
  148.                 }
  149.                 major_timeout_seen = 1;
  150.                 continue;
  151.             }
  152.             else
  153.                 current->timeout = 0;
  154.         }
  155.         else if (wait_table.nr)
  156.             remove_wait_queue(entry.wait_address, &entry.wait);
  157.         current->state = TASK_RUNNING;
  158.         addrlen = 0;
  159.         /* JEJB/JSP 2/7/94
  160.          * Get the xid from the next packet using a peek, so keep it
  161.          * on the recv queue.  If it is wrong, it will be some reply
  162.          * we don't now need, so discard it */
  163.         result = sock->ops->recvfrom(sock, (void *)&recv_xid,
  164.                          sizeof(recv_xid), 1, MSG_PEEK,
  165.                          NULL, &addrlen);
  166.         if (result < 0) {
  167.             if (result == -EAGAIN) {
  168. #if 0
  169.                 printk("nfs_rpc_call: bad select ready\n");
  170. #endif
  171.                 goto re_select;
  172.             }
  173.             if (result == -ECONNREFUSED) {
  174. #if 0
  175.                 printk("nfs_rpc_call: server playing coy\n");
  176. #endif
  177.                 goto re_select;
  178.             }
  179.             if (result != -ERESTARTSYS) {
  180.                 printk("nfs_rpc_call: recv error = %d\n",
  181.                     -result);
  182.             }
  183.             break;
  184.         }
  185.         if (recv_xid == xid) {
  186.             if (major_timeout_seen)
  187.                 printk("NFS server %s OK\n", server_name);
  188.             break;
  189.         }
  190.         /* JEJB/JSP 2/7/94
  191.          * we have xid mismatch, so discard the packet and start
  192.          * again.  What a hack! but I can't call recvfrom with
  193.          * a null buffer yet. */
  194.         (void)sock->ops->recvfrom(sock, (void *)&recv_xid,
  195.                       sizeof(recv_xid), 1, 0, NULL,
  196.                       &addrlen);
  197. #if 0
  198.         printk("nfs_rpc_call: XID mismatch\n");
  199. #endif
  200.         goto re_select;
  201.     }
  202.     /* JEJB/JSP 2/7/94
  203.      *
  204.      * we have the correct xid, so read into the correct place and
  205.      * return it
  206.      *
  207.      */
  208.     result=sock->ops->recvfrom(sock, (void *)start, 
  209.                   size + 1024, 1, 0, NULL,
  210.             /* Here is NFS_SLACK_SPACE..., hack */
  211.                   &addrlen);
  212.     if (result < 0) {
  213.         printk("NFS: notice message: result=%d\n", result);
  214.     } else if (result < addrlen) {
  215.         printk("NFS: just caught a too small read memory size..., email to NET channel\n");
  216.         printk("NFS: result=%d,addrlen=%d\n", result, addrlen);
  217.         result = -EIO;
  218.     }
  219.     current->blocked = old_mask;
  220.     set_fs(fs);
  221.     return result;
  222. }
  223.  
  224. /*
  225.  * For now we lock out other simultaneous nfs calls for the same filesystem
  226.  * because we are single-threaded and don't want to get mismatched
  227.  * RPC replies.
  228.  */
  229.  
  230. int nfs_rpc_call(struct nfs_server *server, int *start, int *end, int size)
  231. {
  232.     int result;
  233.  
  234.     while (server->lock)
  235.         sleep_on(&server->wait);
  236.     server->lock = 1;
  237.     result = do_nfs_rpc_call(server, start, end, size);
  238.     server->lock = 0;
  239.     wake_up(&server->wait);
  240.     return result;
  241. }
  242.  
  243.