bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SoC] NFS status report


From: Manuel Menal
Subject: [SoC] NFS status report
Date: Mon, 03 Jul 2006 22:56:15 +0200
User-agent: Thunderbird 1.5.0.4 (Macintosh/20060530)

Hello,

We are reaching the mid-term evaluation deadline, which is in two days.
Here is my status report for my work on NFS for the Hurd, kindly
sponsored by Thomas Bushnell.

I've just committed the code I have been working on to the Hurd CVS
repository, on the `mmenal-soc2006-nfs-branch' branch. As you can see
from the patch and the ChangeLog entry at the end of this mail, it does
a few things :

  * Create the needed arguments and adapt the code to use either TCP or
      UDP for the mount and portmap protocols (in NFSv2), or for the NFS
      protocol (in NFSv3).
  * Create the needed arguments and make changes to several functions to
      make them work in NFSv3.
  * Add debug statements and various, small, fixes.

The mounting phase works both in NFSv2 and NFSv3, using UDP. You can use
unfs3 on GNU/Linux, for example. Unfortunately, the LOOKUP call results
in a EACCES error with unfs3 and "Bad RPC struct" (EBADRPC) with the
Linux kernel-land NFS server. The debug mode of unfs3 does not show
anything able to explain this. I'm currently working on adding debug
statements to unfs3 (and comparing tcpdump outputs).

As for TCP and UDP, I think the code is mostly there, but it does not
work : I get an EPIPE error using TCP. The packet seems to be
transmitted (according to tcpdump), they seem alright, but no NFS server
shows any request and I get an EPIPE when I send the RPC for the 3rd time.
I've been stuck on that for a week now.   :-(  

As for the milestone : I'd expected to have a basically working NFSv3
read-only client for July 1st : I think the code for it is mostly there,
but it needs debugging.

I'll be working almost full-time on it for for the next 7 weeks on NFS.
I didn't have as much time as expected in the past month due to
additional exams (and me having quite a lot of trouble with them).[0]
I think I'm about a week late now, but I'll have more time than expected
in August.

Here is the ChangeLog entry and the patch :

2006-07-03  Manuel Menal  <address@hidden>

        * README: New file.

        * main.c (OPT_NFS_VERSION, OPT_MNT_TRANSP, OPT_NFS_TRANSP, 
        OPT_DEBUG): New option keys.
        (startup_options): Add --nfs-version, --mount-transport,
        --nfs-transport and --debug-file switches.
        (parse_startup_opt): Parse OPT_NFS_VERSION, OPT_MNT_TRANSP,
        OPT_NFS_TRANSP and OPT_DEBUG option keys. 

        * nfs.h: Renamed main_udp_socket to main_socket.
        * mount.c (mount_root): Likewise.
        * rpc.c (conduct_rpc, rpc_receive_thread): Likewise.
        * main.c (main): Move main socket creation...
        * mount.c (mount_root): ... here.
        * nfs.h (mount_transport, nfs_transport): New variables.
        * mount.c (mount_root): Use UDP or TCP for mount/NFS according to
        OPT_NFS_TRANSP and OPT_MNT_TRANSP.

        * nfs.h (read_lock): New variable.
        * main.c (read_lock): Initialize.
        (main): Lock read_lock at startup.
        * mount.c (mount_root): Lock/unlock when main_socket is
        connected/disconnected.
        * rpc.c (rpc_receive_thread): Lock/unlock before/after read().

        * mount.c (mount_root): Use mount_version instead of MOUNTVERS and
        protocol_version instead of NFS_VERSION.
        (mount_initialize_rpc): Likewise.
        * nfs.c (nfs_initialize_rpc): Likewise.
        * mount.h (MOUNTVERS): Removed macro.
        * nfs-spec.h (NFS_VERSION): Likewise.
        * nfs.h (xdr_encode_fhandle): Implement for NFSv3.
        (xdr_decode_fhandle): Likewise.

        * rpc.c (conduct_rpc): Return an error when the RPC was not entirely
        transmitted.
        (rpc_receive_thread): Skip 0-character read().

        * nfs.h (DEBUG): New macro.
        (debug): New variable.
        * main.c: Add debug statements.
        (main): Ignore SIGPIPE for debugging purposes.
        (main): Move netfs_init() call after the mount phase.
        (initial_transmit_timeout): Change from 1 to 10 seconds.
        * mount.c: Likewise.
        * nfs.c: Likewise.
        * ops.c: Likewise.


diff -x Makefile -x CVS -x TAGS -x ChangeLog -Nurp soc/hurd/nfs/README 
hurdfr/nfs/code/nfs/README
--- soc/hurd/nfs/README Thu Jan  1 01:00:00 1970
+++ hurdfr/nfs/code/nfs/README  Mon Jul  3 19:15:59 2006
@@ -0,0 +1,11 @@
+== Transport layer protocol ==
+
+The NFS protocol itself is supported on UDP only in NFSv2, and both in
+UDP and TCP starting from NFSv3.
+
+Thus,  specifiying the "transport_protocol"  argument will  change the
+transport protocol used for the portmapper and mount protocols.
+
+== Protocol versions ==
+
+NFSv2 works with mountv1 only. NFSv3 works with mountv3 only.
diff -x Makefile -x CVS -x TAGS -x ChangeLog -Nurp soc/hurd/nfs/main.c 
hurdfr/nfs/code/nfs/main.c
--- soc/hurd/nfs/main.c Mon May 13 19:39:37 2002
+++ hurdfr/nfs/code/nfs/main.c  Mon Jul  3 21:33:05 2006
@@ -32,11 +32,23 @@
 #include <error.h>
 #include <version.h>
 
+#include <signal.h>
+
 char *netfs_server_name = "nfs";
 char *netfs_server_version = HURD_VERSION;
 
+int protocol_version = 2;
+int mount_version;
+
+struct protoent *nfs_transport = NULL;
+struct protoent *mount_transport = NULL;
+
+struct mutex read_lock = MUTEX_INITIALIZER;
+
 extern char *localhost ();
 
+FILE *debug = NULL;
+
 /* Default number of times to retry RPCs when mounted soft. */
 #define DEFAULT_SOFT_RETRIES  3
 
@@ -72,7 +84,7 @@ int name_cache_timeout = DEFAULT_NAME_CA
 int name_cache_neg_timeout = DEFAULT_NAME_CACHE_NEG_TIMEOUT;
 
 /* Number of seconds to wait for first retransmission of an RPC. */
-int initial_transmit_timeout = 1;
+int initial_transmit_timeout = 10;
 
 /* Maximum number of seconds to wait between retransmission of RPCs. */
 int max_transmit_timeout = 30;
@@ -93,6 +105,8 @@ int write_size = DEFAULT_WRITE_SIZE;
 #define OPT_HARD       'h'
 #define OPT_RSIZE      'R'
 #define OPT_WSIZE      'W'
+#define OPT_NFS_VERSION 'P'
+#define OPT_DEBUG       'd'
 #define OPT_STAT_TO    -2
 #define OPT_CACHE_TO   -3
 #define OPT_INIT_TR_TO -4
@@ -107,6 +121,8 @@ int write_size = DEFAULT_WRITE_SIZE;
 #define OPT_PMAP_PORT  -13
 #define OPT_NCACHE_TO  -14
 #define OPT_NCACHE_NEG_TO -15
+#define OPT_MNT_TRANSP  -16
+#define OPT_NFS_TRANSP  -17
 
 /* Return a string corresponding to the printed rep of DEFAULT_what */
 #define ___D(what) #what
@@ -196,6 +212,12 @@ static const struct argp_option startup_
   {"nfs-program",           OPT_NFS_PROG,  "ID[.VERS]"},
 
   {"pmap-port",             OPT_PMAP_PORT,  "SVC|PORT"},
+  {"nfs-version",           OPT_NFS_VERSION, "VERSION"},
+  {"mount-transport",       OPT_MNT_TRANSP, "PROTOCOL", 0, 
+   "Transport protocol to use for mount and portmap (tcp ou udp)"},
+  {"nfs-transport",         OPT_NFS_TRANSP, "PROTOCOL", 0,
+   "Transport protocol to use for NFS (tcp or udp) (NFSv3 only)"},
+  {"debug-file", OPT_DEBUG, "FILE"},
 
   {"hold", OPT_HOLD, 0, OPTION_HIDDEN}, /*  */
   { 0 }
@@ -323,6 +345,43 @@ parse_startup_opt (int key, char *arg, s
       nfs_port = atoi (arg);
       break;
 
+    case OPT_NFS_VERSION: 
+      protocol_version = atoi (arg); 
+      break;
+
+    case OPT_MNT_TRANSP:
+      {
+       fprintf (stderr, "mount transport %s requested\n", arg);
+       struct protoent *proto = getprotobyname (arg);
+       if (proto == NULL)
+         argp_error (state, "Invalid PROTOCOL specified");
+
+       mount_transport = malloc (sizeof (struct protoent));
+       mount_transport->p_proto = proto->p_proto;
+       mount_transport->p_name = strdup (proto->p_name);
+
+       fprintf (stderr, "mount transport %s saved\n", mount_transport->p_name);
+       break;
+      }
+
+    case OPT_NFS_TRANSP:
+      {
+       struct protoent *proto = getprotobyname (arg);
+       if (proto == NULL)
+         argp_error (state, "Invalid PROTOCOL specified");
+
+       nfs_transport = malloc (sizeof (struct protoent));
+       nfs_transport->p_proto = proto->p_proto;
+       nfs_transport->p_name = strdup (proto->p_name);
+
+       break;
+      }
+
+    case OPT_DEBUG:
+      debug = fopen (arg, "w");
+      setbuf (debug, NULL);
+      break;
+
     case ARGP_KEY_ARG:
       if (state->arg_num == 0)
        remote_fs = arg;
@@ -358,48 +417,85 @@ main (int argc, char **argv)
   struct argp argp =
     { startup_options, parse_startup_opt, args_doc, doc, argp_children };
   mach_port_t bootstrap;
-  struct sockaddr_in addr;
   int ret;
 
+  DEBUG("[%s] entering the NFS client : parsing command line\n", 
__PRETTY_FUNCTION__);
+
   argp_parse (&argp, argc, argv, 0, 0, 0);
-    
-  task_get_bootstrap_port (mach_task_self (), &bootstrap);
-  netfs_init ();
-  
-  main_udp_socket = socket (PF_INET, SOCK_DGRAM, 0);
-  addr.sin_family = AF_INET;
-  addr.sin_addr.s_addr = INADDR_ANY;
-  addr.sin_port = htons (IPPORT_RESERVED);
-  do
+
+  DEBUG("[%s] argument parsed, initializing socket and nodes\n", 
+       __PRETTY_FUNCTION__);
+
+  /* No  transport protocol  has been  specified  for nfs  : take  the
+     default one. */
+  if (!nfs_transport)
     {
-      addr.sin_port = htons (ntohs (addr.sin_port) - 1);
-      ret = bind (main_udp_socket, (struct sockaddr *)&addr, 
-                 sizeof (struct sockaddr_in));
-      if (ret == -1 && errno == EACCES)
-       {
-         /* We aren't allowed privileged ports; no matter;
-            let the server deny us later if it wants. */
-         ret = 0;
-         break;
-       }
+      DEBUG("[%s] no nfs transport provided, using default : %s\n", 
__PRETTY_FUNCTION__,
+           DEFAULT_TRANSPORT_PROTOCOL);
+      struct protoent *proto = getprotobyname (DEFAULT_TRANSPORT_PROTOCOL);
+
+      nfs_transport = malloc (sizeof (struct protoent));
+      nfs_transport->p_proto = proto->p_proto;
+      nfs_transport->p_name = strdup (proto->p_name);
+    }
+  else
+    {
+      if (protocol_version == 2 
+         && nfs_transport->p_proto != IPPROTO_UDP)
+       error (3, 0, "NFSv2 only supports UDP");
+    }
+
+  /* Same thing for mount/portmap. */
+  if (!mount_transport)
+    {
+      DEBUG("[%s] no mount transport provided, using default : %s\n", 
__PRETTY_FUNCTION__, DEFAULT_TRANSPORT_PROTOCOL);
+      struct protoent *proto = getprotobyname (DEFAULT_TRANSPORT_PROTOCOL);
+
+      mount_transport = malloc (sizeof (struct protoent));
+      mount_transport->p_proto = proto->p_proto;
+      mount_transport->p_name = strdup (proto->p_name);
     }
-  while ((ret == -1) && (errno == EADDRINUSE));
-  if (ret == -1)
-    error (1, errno, "binding main udp socket");
+
+  /* Each protocol version only supports one mount protocol version. */
+  switch (protocol_version)
+    {
+    case 2:
+      mount_version = 1;
+      break;
+    case 3:
+      mount_version = 3;
+      break;
+    default:
+      mount_version = 1;
+    }
+
+  DEBUG("[%s] NFS client running on NFSv%d,  using %s (%p) transport for NFS, 
%s (%p) for mount/portmap\n",
+       __PRETTY_FUNCTION__, protocol_version, nfs_transport->p_name, 
nfs_transport,
+       mount_transport->p_name, mount_transport);
+
+  task_get_bootstrap_port (mach_task_self (), &bootstrap);
 
   err = maptime_map (0, 0, &mapped_time);
+  
   if (err)
     error (2, err, "mapping time");
 
+  hostname = localhost ();
+
+  mutex_lock (&read_lock);
   cthread_detach (cthread_fork ((cthread_fn_t) timeout_service_thread, 0));
   cthread_detach (cthread_fork ((cthread_fn_t) rpc_receive_thread, 0));
-  
-  hostname = localhost ();
+
+  DEBUG("[%s] mounting root node\n", __PRETTY_FUNCTION__);
+
+  signal (SIGPIPE, SIG_IGN);
 
   netfs_root_node = mount_root (remote_fs, host);
 
   if (!netfs_root_node)
     exit (1);
+
+  netfs_init ();
   
   netfs_startup (bootstrap, 0);
   
diff -x Makefile -x CVS -x TAGS -x ChangeLog -Nurp soc/hurd/nfs/mount.c 
hurdfr/nfs/code/nfs/mount.c
--- soc/hurd/nfs/mount.c        Sun Sep 29 17:11:59 2002
+++ hurdfr/nfs/code/nfs/mount.c Mon Jul  3 21:13:10 2006
@@ -35,6 +35,8 @@
 #include "nfs.h"
 #include "mount.h"
 
+int main_socket;
+
 /* Service name for portmapper */
 char *pmap_service_name = "sunrpc";
 
@@ -45,7 +47,7 @@ short pmap_service_number = PMAPPORT;
 int mount_program = MOUNTPROG;
 
 /* RPC version for mount server. */
-int mount_version = MOUNTVERS;
+int mount_version;
 
 /* Fallback port number for mount server. */
 short mount_port = 0;
@@ -56,9 +58,6 @@ int mount_port_override = 0;
 /* RPC program number for NFS server. */
 int nfs_program = NFS_PROGRAM;
 
-/* RPC version number for NFS server. */
-int nfs_version = NFS_VERSION;
-
 /* Fallback port number for NFS server. */
 short nfs_port = NFS_PORT;
 
@@ -69,7 +68,7 @@ int nfs_port_override = 0;
 const char *mounted_hostname;
 uint16_t mounted_nfs_port;     /* host order */
 
-int protocol_version = 2;
+FILE *debug;
 
 /* Set up an RPC for procedure PROCNUM for talking to the portmapper.
    Allocate storage with malloc and point *BUF at it; caller must free
@@ -88,7 +87,7 @@ pmap_initialize_rpc (int procnum, void *
 static int *
 mount_initialize_rpc (int procnum, void **buf)
 {
-  return initialize_rpc (MOUNTPROG, MOUNTVERS, procnum, 0, buf, 0, 0, -1);
+  return initialize_rpc (MOUNTPROG, mount_version, procnum, 0, buf, 0, 0, -1);
 }
 
 /* Using the mount protocol, lookup NAME at host HOST.
@@ -106,18 +105,49 @@ mount_root (char *name, char *host)
   struct node *np;
   short pmapport;
 
+  DEBUG("[%s] mounting share %s from host %s (using protocol version %d)\n", 
__PRETTY_FUNCTION__,
+       name, host, mount_version);
+
+  DEBUG("[%s] creating socket for mount %s\n", __PRETTY_FUNCTION__,
+       name, host);
+
+  error_t create_socket (int proto)
+  {
+    struct sockaddr_in addr;
+    int ret;
+
+    main_socket = socket (PF_INET,
+                         proto == IPPROTO_UDP ? SOCK_DGRAM : SOCK_STREAM, 0);
+    addr.sin_family = AF_INET;
+    addr.sin_addr.s_addr = INADDR_ANY;
+    addr.sin_port = htons (IPPORT_RESERVED);
+    do
+      {
+       addr.sin_port = htons (ntohs (addr.sin_port) - 1);
+       ret = bind (main_socket, (struct sockaddr *)&addr, 
+                   sizeof (struct sockaddr_in));
+       if (ret == -1 && errno == EACCES)
+         {
+           /* We aren't allowed privileged ports; no matter;
+              let the server deny us later if it wants. */
+           ret = 0;
+           break;
+         }
+      }
+    while ((ret == -1) && (errno == EADDRINUSE));
+
+    return ret;
+  }
+  
+  if (create_socket (mount_transport->p_proto))
+      error (1, errno, "binding main socket");
+
   /* Lookup the portmapper port number */
   if (pmap_service_name)
     {
       struct servent *s;
 
-      /* XXX This will always fail! pmap_service_name will always be "sunrpc"
-         What should pmap_service_name really be?  By definition the second
-        argument is either "tcp" or "udp"  Thus, is this backwards
-        (as service_name suggests)?  If so, should it read:
-             s = getservbyname (pmap_service_name, "udp");
-         or is there something I am missing here?  */
-      s = getservbyname ("sunrpc", pmap_service_name);
+      s = getservbyname (pmap_service_name, mount_transport->p_name);
       if (s)
        pmapport = s->s_port;
       else
@@ -126,6 +156,9 @@ mount_root (char *name, char *host)
   else
     pmapport = htons (pmap_service_number);
 
+  DEBUG("[%s] got port %hd for portmapper\n", __PRETTY_FUNCTION__,
+       pmapport);
+
   /* Lookup the host */
   h = gethostbyname (host);
   if (!h)
@@ -142,15 +175,19 @@ mount_root (char *name, char *host)
     addr.sin_port = htons (mount_port);
   else
     {
+      DEBUG("[%s] getting the mount port via the portmapper\n", 
__PRETTY_FUNCTION__);
+
       /* Formulate and send a PMAPPROC_GETPORT request
         to lookup the mount program on the server.  */
-      if (connect (main_udp_socket, (struct sockaddr *)&addr,
+      if (connect (main_socket, (struct sockaddr *)&addr,
                   sizeof (struct sockaddr_in)) == -1)
        {
          error (0, errno, "server mount program");
          return 0;
        }
 
+      mutex_unlock (&read_lock);
+
       p = pmap_initialize_rpc (PMAPPROC_GETPORT, &rpcbuf);
       if (! p)
        {
@@ -158,9 +195,10 @@ mount_root (char *name, char *host)
          return 0;
        }
 
+      DEBUG("[%s] conducting RPC\n", __PRETTY_FUNCTION__);
       *(p++) = htonl (MOUNTPROG);
-      *(p++) = htonl (MOUNTVERS);
-      *(p++) = htonl (IPPROTO_UDP);
+      *(p++) = htonl (mount_version);
+      *(p++) = htonl (mount_transport->p_proto);
       *(p++) = htonl (0);
       err = conduct_rpc (&rpcbuf, &p);
       if (!err)
@@ -173,21 +211,26 @@ mount_root (char *name, char *host)
        addr.sin_port = htons (mount_port);
       else
        {
+         /* FIXME: Check with the other transport protocol (UDP/TCP) ? */
          error (0, err, "portmap of mount");
          goto error_with_rpcbuf;
        }
       free (rpcbuf);
     }
 
+  DEBUG("[%s] connecting to the mount program\n", __PRETTY_FUNCTION__);
+
   /* Now, talking to the mount program, fetch a file handle
      for the root. */
-  if (connect (main_udp_socket, (struct sockaddr *) &addr,
+  if (connect (main_socket, (struct sockaddr *) &addr,
               sizeof (struct sockaddr_in)) == -1)
     {
       error (0, errno, "connect");
       goto error_with_rpcbuf;
     }
 
+  DEBUG("[%s] fetching root handle\n", __PRETTY_FUNCTION__);
+
   p = mount_initialize_rpc (MOUNTPROC_MNT, &rpcbuf);
   if (! p)
     {
@@ -195,6 +238,8 @@ mount_root (char *name, char *host)
       goto error_with_rpcbuf;
     }
 
+  DEBUG("[%s] MOUNTPROC initialized, conducting RPC\n", __PRETTY_FUNCTION__);
+
   p = xdr_encode_string (p, name);
   err = conduct_rpc (&rpcbuf, &p);
   if (err)
@@ -213,18 +258,27 @@ mount_root (char *name, char *host)
       goto error_with_rpcbuf;
     }
 
+  DEBUG("[%s] RPC returned, fetching the handle\n", __PRETTY_FUNCTION__);
+
   /* Create the node for root */
+
   xdr_decode_fhandle (p, &np);
+
+  DEBUG("[%s] retrieved handle, freeing rpcbuf\n", __PRETTY_FUNCTION__);
+
   free (rpcbuf);
   mutex_unlock (&np->lock);
 
+  DEBUG("[%s] retrieving port number for the NFS server\n", 
+       __PRETTY_FUNCTION__);
+
   if (nfs_port_override)
     port = nfs_port;
   else
     {
       /* Send another PMAPPROC_GETPORT request to lookup the nfs server. */
       addr.sin_port = pmapport;
-      if (connect (main_udp_socket, (struct sockaddr *) &addr,
+      if (connect (main_socket, (struct sockaddr *) &addr,
                   sizeof (struct sockaddr_in)) == -1)
        {
          error (0, errno, "connect");
@@ -238,8 +292,8 @@ mount_root (char *name, char *host)
          goto error_with_rpcbuf;
        }
       *(p++) = htonl (NFS_PROGRAM);
-      *(p++) = htonl (NFS_VERSION);
-      *(p++) = htonl (IPPROTO_UDP);
+      *(p++) = htonl (protocol_version);
+      *(p++) = htonl (nfs_transport->p_proto);
       *(p++) = htonl (0);
       err = conduct_rpc (&rpcbuf, &p);
       if (!err)
@@ -257,8 +311,21 @@ mount_root (char *name, char *host)
       free (rpcbuf);
     }
 
+  if (nfs_transport->p_proto != mount_transport->p_proto)
+    {
+      mutex_lock (&read_lock);
+      /* Close the temporary socket. */
+      close (main_socket);
+
+      if (create_socket (nfs_transport->p_proto))
+       error (2, errno, "binding main nfs socket");
+      mutex_unlock (&read_lock);
+    }
+
+  DEBUG("[%s] connecting to NFS server on port %hd\n", 
+       __PRETTY_FUNCTION__, port);
   addr.sin_port = htons (port);
-  if (connect (main_udp_socket, (struct sockaddr *) &addr,
+  if (connect (main_socket, (struct sockaddr *) &addr,
               sizeof (struct sockaddr_in)) == -1)
     {
       error (0, errno, "connect");
diff -x Makefile -x CVS -x TAGS -x ChangeLog -Nurp soc/hurd/nfs/mount.h 
hurdfr/nfs/code/nfs/mount.h
--- soc/hurd/nfs/mount.h        Tue Jan 30 01:38:45 2001
+++ hurdfr/nfs/code/nfs/mount.h Mon Jul  3 19:17:41 2006
@@ -24,7 +24,6 @@
 #define NFS_MOUNT_H
 
 #define MOUNTPROG 100005
-#define MOUNTVERS 1
 
 /* Obnoxious arbitrary limits */
 #define MOUNT_MNTPATHLEN 1024
diff -x Makefile -x CVS -x TAGS -x ChangeLog -Nurp soc/hurd/nfs/nfs-spec.h 
hurdfr/nfs/code/nfs/nfs-spec.h
--- soc/hurd/nfs/nfs-spec.h     Tue Jan 30 01:38:45 2001
+++ hurdfr/nfs/code/nfs/nfs-spec.h      Mon Jul  3 19:46:46 2006
@@ -101,7 +101,6 @@ enum createmode 
 };
 
 #define NFS_PROGRAM ((u_long)100003)
-#define NFS_VERSION ((u_long)2)
 
 #define NFS_PROTOCOL_FUNC(proc,vers) \
        (vers == 2 ? NFS2PROC_ ## proc : NFS3PROC_ ## proc)
diff -x Makefile -x CVS -x TAGS -x ChangeLog -Nurp soc/hurd/nfs/nfs.c 
hurdfr/nfs/code/nfs/nfs.c
--- soc/hurd/nfs/nfs.c  Sun Sep 29 17:11:59 2002
+++ hurdfr/nfs/code/nfs/nfs.c   Mon Jul  3 20:16:04 2006
@@ -71,7 +71,7 @@ nfs_mode_to_hurd_mode (int type, int mod
            hurdmode = S_IFIFO;
            break;
          }
-      else
+      else if (protocol_version == 3)
        switch (type)
          {
          case NF3FIFO:
@@ -143,6 +143,11 @@ xdr_encode_fhandle (int *p, struct fhand
       memcpy (p, fhandle->data, NFS2_FHSIZE);
       return p + INTSIZE (NFS2_FHSIZE);
     }
+  else if (protocol_version == 3)
+    {
+      memcpy (p, fhandle->data, NFS3_FHSIZE);
+      return p + INTSIZE (NFS3_FHSIZE);
+    }
   else
     return xdr_encode_data (p, fhandle->data, fhandle->size);
 }
@@ -153,6 +158,8 @@ xdr_encode_data (int *p, char *data, siz
 {
   int nints = INTSIZE (len);
 
+  DEBUG("[%s] encoding string %s (length: %d)\n",
+       __PRETTY_FUNCTION__, data, len);
   p[nints] = 0;
   *(p++) = htonl (len);
   memcpy (p, data, len);
@@ -384,13 +391,18 @@ xdr_decode_fhandle (int *p, struct node 
 
   if (protocol_version == 2)
     len = NFS2_FHSIZE;
+  else if (protocol_version == 3)
+    len = NFS3_FHSIZE;
   else
     {
       len = ntohl (*p);
       p++;
     }
+
+  DEBUG("[%s] looking up handle of length %d\n", __PRETTY_FUNCTION__, len);
   /* Enter into cache.  */
   lookup_fhandle (p, len, npp);
+  DEBUG("[%s] handle looked up\n", __PRETTY_FUNCTION__);
   return p + len / sizeof (int);
 }
 
@@ -575,7 +587,7 @@ nfs_initialize_rpc (int rpc_proc, struct
   else
     uid = gid = second_gid = -1;
 
-  return initialize_rpc (NFS_PROGRAM, NFS_VERSION, rpc_proc, len, bufp,
+  return initialize_rpc (NFS_PROGRAM, protocol_version, rpc_proc, len, bufp,
                         uid, gid, second_gid);
 }
 
@@ -584,6 +596,9 @@ nfs_initialize_rpc (int rpc_proc, struct
 error_t
 nfs_error_trans (int error)
 {
+  DEBUG("[%s] translating NFS error code %d into Hurd error code\n",
+       __PRETTY_FUNCTION__, error);
+
   switch (error)
     {
     case NFS_OK:
diff -x Makefile -x CVS -x TAGS -x ChangeLog -Nurp soc/hurd/nfs/nfs.h 
hurdfr/nfs/code/nfs/nfs.h
--- soc/hurd/nfs/nfs.h  Sat Dec 29 01:40:09 2001
+++ hurdfr/nfs/code/nfs/nfs.h   Mon Jul  3 19:24:22 2006
@@ -24,6 +24,9 @@
 #include <sys/mman.h>
 #include "nfs-spec.h"
 #include <hurd/netfs.h>
+#include <netdb.h>
+
+#define DEFAULT_TRANSPORT_PROTOCOL "udp"
 
 /* A file handle */
 struct fhandle
@@ -77,7 +80,7 @@ struct netnode
 };
 
 /* Socket file descriptor for talking to RPC servers. */
-int main_udp_socket;
+int main_socket;
 
 /* Our hostname */
 char *hostname;
@@ -153,6 +156,17 @@ extern int nfs_port_override;
 /* Which NFS protocol version we are using */
 extern int protocol_version;
 
+/* Which transport protocol  (TCP or UDP) we are  using for portmapper
+   and mount. */
+extern struct protoent *mount_transport;
+
+/* Which transport protocol  (UDP for NFSv2, TCP or  UDP for NFSv3) we
+   are using for RPC.*/
+extern struct protoent *nfs_transport;
+
+/* Don't read on main_socket when this is locked. */
+extern struct mutex read_lock;
+
 
 /* Count how many four-byte chunks it takes to hold LEN bytes. */
 #define INTSIZE(len) (((len)+3)>>2)
@@ -199,5 +213,8 @@ void enter_lookup_cache (char *, size_t,
 void purge_lookup_cache (struct node *, char *, size_t);
 struct node *check_lookup_cache (struct node *, char *);
 void purge_lookup_cache_node (struct node *);
+
+extern FILE *debug;
+#define DEBUG(format, ...) if (debug) fprintf (debug, format, ## __VA_ARGS__)
 
 #endif /* NFS_NFS_H */
diff -x Makefile -x CVS -x TAGS -x ChangeLog -Nurp soc/hurd/nfs/ops.c 
hurdfr/nfs/code/nfs/ops.c
--- soc/hurd/nfs/ops.c  Sun Sep 29 17:11:59 2002
+++ hurdfr/nfs/code/nfs/ops.c   Mon Jul  3 20:11:02 2006
@@ -26,6 +26,8 @@
 #include <unistd.h>
 #include <maptime.h>
 
+FILE *debug;
+
 /* We have fresh stat information for NP; the file attribute (fattr)
    structure is at P.  Update our entry.  Return the address of the next
    int after the fattr structure.  */
@@ -34,6 +36,9 @@ register_fresh_stat (struct node *np, in
 {
   int *ret;
 
+  DEBUG ("[%s] registering retrieved attr into the node\n",
+        __PRETTY_FUNCTION__);
+
   ret = xdr_decode_fattr (p, &np->nn_stat);
   np->nn->stat_updated = mapped_time->seconds;
 
@@ -143,26 +148,50 @@ netfs_validate_stat (struct node *np, st
   void *rpcbuf;
   error_t err;
 
+  DEBUG("[%s] validating stat for node %s\n", 
+       __PRETTY_FUNCTION__, "42");
+
   if (mapped_time->seconds - np->nn->stat_updated < stat_timeout)
     return 0;
 
   p = nfs_initialize_rpc (NFSPROC_GETATTR (protocol_version),
                          (struct iouser *) -1, 0, &rpcbuf, np, -1);
+
+  DEBUG("[%s] RPC initialized (rpcbuf: %p)\n", __PRETTY_FUNCTION__,
+       rpcbuf);
   if (! p)
     return errno;
 
+  DEBUG("[%s] encoding file handle %s in XDR\n", 
+       __PRETTY_FUNCTION__, np->nn->handle.data);
+
   p = xdr_encode_fhandle (p, &np->nn->handle);
 
+  DEBUG("[%s] fhandle encoded (rpcbuf: %p)\n", 
+       __PRETTY_FUNCTION__, rpcbuf);
+
   err = conduct_rpc (&rpcbuf, &p);
   if (!err)
     {
+      DEBUG("[%s] error sending RPC : %d\n", __PRETTY_FUNCTION__,
+           err);
       err = nfs_error_trans (ntohl (*p));
       p++;
     }
+
+  DEBUG("[%s] RPC sent (rpcbuf: %p)\n", __PRETTY_FUNCTION__,
+       rpcbuf);
+
   if (!err)
     register_fresh_stat (np, p);
 
+  DEBUG ("[%s] freeing rpcbuf (%p)\n", __PRETTY_FUNCTION__,
+        rpcbuf);
+
   free (rpcbuf);
+
+  DEBUG("[%s] returning with error code %d\n", __PRETTY_FUNCTION__, 
+       err);
   return err;
 }
 
@@ -176,6 +205,8 @@ netfs_attempt_chown (struct iouser *cred
   void *rpcbuf;
   error_t err;
 
+  DEBUG("[%s] attempting chown\n", __PRETTY_FUNCTION__);
+
   p = nfs_initialize_rpc (NFSPROC_SETATTR (protocol_version),
                          cred, 0, &rpcbuf, np, gid);
   if (! p)
@@ -392,6 +423,9 @@ netfs_attempt_statfs (struct iouser *cre
   void *rpcbuf;
   error_t err;
 
+  DEBUG("[%s] attempting statfs using node %s\n",
+       __PRETTY_FUNCTION__, "42");
+
   p = nfs_initialize_rpc (NFS2PROC_STATFS, cred, 0, &rpcbuf, np, -1);
   if (! p)
     return errno;
@@ -424,6 +458,10 @@ netfs_attempt_statfs (struct iouser *cre
     }
 
   free (rpcbuf);
+
+  DEBUG("[%s] returning with error code %d\n", 
+       __PRETTY_FUNCTION__, err);
+
   return err;
 }
 
@@ -457,6 +495,9 @@ netfs_attempt_read (struct iouser *cred,
   size_t amt, thisamt;
   int eof;
 
+  DEBUG("[%s] attempting to read %d bytes from node %s, starting from offset 
%d",
+       __PRETTY_FUNCTION__, *len, "42", offset);
+
   for (amt = *len; amt;)
     {
       thisamt = amt;
@@ -516,6 +557,9 @@ netfs_attempt_read (struct iouser *cred,
            }
        }
     }
+
+  DEBUG("[%s] returning normally\n", __PRETTY_FUNCTION__);
+
   return 0;
 }
 
@@ -645,6 +689,9 @@ netfs_attempt_lookup (struct iouser *cre
   char dirhandle[NFS3_FHSIZE];
   size_t dirlen;
 
+  DEBUG("[%s] lookup for %s in directory %s\n",
+       __PRETTY_FUNCTION__, name, "42");
+
   /* Check the cache first. */
   *newnp = check_lookup_cache (np, name);
   if (*newnp)
@@ -673,10 +720,13 @@ netfs_attempt_lookup (struct iouser *cre
 
   mutex_unlock (&np->lock);
 
+  DEBUG("[%s] attempting lookup RPC (name: %s)\n", __PRETTY_FUNCTION__, name);
+
   err = conduct_rpc (&rpcbuf, &p);
   if (!err)
     {
       err = nfs_error_trans (ntohl (*p));
+      DEBUG("[%s] done, got error : %s (from %d : %d)\n", __PRETTY_FUNCTION__, 
strerror (err), ntohl (*p), *p);
       p++;
       if (!err)
        {
@@ -704,6 +754,9 @@ netfs_attempt_lookup (struct iouser *cre
 
   free (rpcbuf);
 
+  DEBUG("[%s] returning with error code %d\n",
+       __PRETTY_FUNCTION__, err);
+
   return err;
 }
 
@@ -1430,6 +1483,9 @@ netfs_attempt_readlink (struct iouser *c
   void *rpcbuf;
   error_t err;
 
+  DEBUG("[%s] reading link %s\n", __PRETTY_FUNCTION__,
+       "42");
+
   if (np->nn->dtrans == SYMLINK)
     {
       strcpy (buf, np->nn->transarg.name);
@@ -1455,6 +1511,10 @@ netfs_attempt_readlink (struct iouser *c
     }
 
   free (rpcbuf);
+
+  DEBUG("[%s] returning with error code %d\n", __PRETTY_FUNCTION__,
+       err);
+
   return err;
 }
 
@@ -1466,10 +1526,16 @@ netfs_check_open_permissions (struct iou
 {
   int modes;
 
+  DEBUG("[%s] checking open permissions for node %s\n", 
+       __PRETTY_FUNCTION__, "42");
+
   if (newnode || (flags & (O_READ|O_WRITE|O_EXEC)) == 0)
     return 0;
 
   netfs_report_access (cred, np, &modes);
+
+  DEBUG("[%s] returning\n", __PRETTY_FUNCTION__);
+
   if ((flags & (O_READ|O_WRITE|O_EXEC)) == (flags & modes))
     return 0;
   else
@@ -1485,6 +1551,9 @@ netfs_report_access (struct iouser *cred
 {
   error_t err;
 
+  DEBUG("[%s] reporting access for node %s\n", __PRETTY_FUNCTION__,
+       "42");
+
   err = netfs_validate_stat (np, cred);
   if (err)
     return err;
@@ -1499,6 +1568,9 @@ netfs_report_access (struct iouser *cred
        *types |= O_WRITE;
       if (fshelp_access (&np->nn_stat, S_IEXEC, cred) == 0)
        *types |= O_EXEC;
+
+      DEBUG("[%s] returning with no problem\n", __PRETTY_FUNCTION__);
+
       return 0;
     }
   else
@@ -1544,6 +1616,10 @@ netfs_report_access (struct iouser *cred
                        | (ret & execute_check ? O_EXEC : 0));
            }
        }
+
+      DEBUG("[%s] returning with error code %d\n", __PRETTY_FUNCTION__,
+           err);
+
       return err;
     }
 }
diff -x Makefile -x CVS -x TAGS -x ChangeLog -Nurp soc/hurd/nfs/rpc.c 
hurdfr/nfs/code/nfs/rpc.c
--- soc/hurd/nfs/rpc.c  Sun Sep 29 17:11:59 2002
+++ hurdfr/nfs/code/nfs/rpc.c   Mon Jul  3 20:33:38 2006
@@ -44,6 +44,8 @@ struct rpc_list
   void *reply;
 };
 
+int main_socket;
+
 /* A list of all pending RPCs.  */
 static struct rpc_list *outstanding_rpcs;
 
@@ -86,6 +88,7 @@ initialize_rpc (int program, int version
   int *p, *lenaddr;
   struct rpc_list *hdr;
 
+  DEBUG("[%s] initializing RPC\n", __PRETTY_FUNCTION__);
   buf = malloc (len + 1024);
   if (! buf)
     {
@@ -99,6 +102,9 @@ initialize_rpc (int program, int version
   
   p = buf + sizeof (struct rpc_list);
 
+  DEBUG("[%s] filling the header : (xid, CALL, rpcver, program, version, 
rpcproc) = (xid, CALL, %d, %d, %d, %d)\n", 
+       __PRETTY_FUNCTION__, RPC_MSG_VERSION, program, version, rpc_proc);
+
   /* RPC header */
   *(p++) = htonl (generate_xid ());
   *(p++) = htonl (CALL);
@@ -106,7 +112,9 @@ initialize_rpc (int program, int version
   *(p++) = htonl (program);
   *(p++) = htonl (version);
   *(p++) = htonl (rpc_proc);
-  
+
+  DEBUG("[%s] filling the auth part of the header\n", __PRETTY_FUNCTION__);
+
   assert ((uid == -1) == (gid == -1));
 
   if (uid == -1)
@@ -135,7 +143,9 @@ initialize_rpc (int program, int version
        }
       *lenaddr = htonl ((p - (lenaddr + 1)) * sizeof (int));
     }
-        
+
+  DEBUG("[%s] filling the VERF field\n", __PRETTY_FUNCTION__);
+
   /* VERF field */
   *(p++) = htonl (AUTH_NONE);
   *(p++) = 0;
@@ -186,6 +196,9 @@ conduct_rpc (void **rpcbuf, int **pp)
   int n;
   int cancel;
   
+  DEBUG("[%s] locking mutex to begin RPC\n", 
+       __PRETTY_FUNCTION__);
+
   mutex_lock (&outstanding_lock);
 
   link_rpc (&outstanding_rpcs, hdr);
@@ -202,27 +215,44 @@ conduct_rpc (void **rpcbuf, int **pp)
          return ETIMEDOUT;
        }
 
+      DEBUG("[%s] issuing the RPC (try %d, previous at %d)\n", 
__PRETTY_FUNCTION__, 
+           ntransmit, lasttrans);
       /* Issue the RPC.  */
       lasttrans = mapped_time->seconds;
       ntransmit++;
       nc = (void *) *pp - *rpcbuf - sizeof (struct rpc_list);
-      cc = write (main_udp_socket, *rpcbuf + sizeof (struct rpc_list), nc);
-      if (cc == -1)
+
+      DEBUG("[%s] writing to socket %d RPC of size %d, from %p\n", 
__PRETTY_FUNCTION__,
+           main_socket, nc, *rpcbuf + sizeof (struct rpc_list));
+
+      cc = write (main_socket, *rpcbuf + sizeof (struct rpc_list), nc);
+
+      DEBUG("[%s] write returned %d\n", __PRETTY_FUNCTION__, cc);
+      if (cc != nc)
        {
          unlink_rpc (hdr);
          mutex_unlock (&outstanding_lock);
          return errno;
        }
-      else 
-       assert (cc == nc);
+      /*      else 
+             assert (cc == nc);*/
       
+      DEBUG("[%s] issued, waiting for reply (timeout: %d seconds)\n", 
__PRETTY_FUNCTION__,
+           timeout);
+
       /* Wait for reply.  */
       cancel = 0;
       while (!hdr->reply
             && (mapped_time->seconds - lasttrans < timeout)
             && !cancel)
-       cancel = hurd_condition_wait (&rpc_wakeup, &outstanding_lock);
+       {
+         DEBUG("[%s] calling hurd_condition_wait\n", __PRETTY_FUNCTION__);
+         cancel = hurd_condition_wait (&rpc_wakeup, &outstanding_lock);
+       }
   
+      DEBUG("[%s] wait ended: %s\n", __PRETTY_FUNCTION__,
+           cancel ? "cancelled" : (hdr->reply ? "received reply" : "timeout 
exceeded"));
+
       if (cancel)
        {
          unlink_rpc (hdr);
@@ -242,6 +272,8 @@ conduct_rpc (void **rpcbuf, int **pp)
     }
   while (!hdr->reply);
 
+  DEBUG("[%s] got reply, unlocking\n", __PRETTY_FUNCTION__);
+
   mutex_unlock (&outstanding_lock);
 
   /* Switch to the reply buffer.  */
@@ -256,22 +288,26 @@ conduct_rpc (void **rpcbuf, int **pp)
      something strange happened in rpc_receive_thread.  */
   assert (*p == xid);
   p++;
-  
+
   switch (ntohl (*p))
     {
     default:
+      DEBUG("[%s] unknown RPC encountered\n", __PRETTY_FUNCTION__);
       err = EBADRPC;
       break;
       
     case REPLY:
+      DEBUG("[%s] reply RPC, seeking status\n", __PRETTY_FUNCTION__);
       p++;
       switch (ntohl (*p))
        {
        default:
+         DEBUG("[%s] unknown status\n", __PRETTY_FUNCTION__);
          err = EBADRPC;
          break;
          
        case MSG_DENIED:
+         DEBUG("[%s] got a permission denied RPC\n", __PRETTY_FUNCTION__);
          p++;
          switch (ntohl (*p))
            {
@@ -307,6 +343,7 @@ conduct_rpc (void **rpcbuf, int **pp)
          break;
          
        case MSG_ACCEPTED:
+         DEBUG("[%s] accepted status for RPC\n", __PRETTY_FUNCTION__);
          p++;
 
          /* Process VERF field.  */
@@ -335,8 +372,10 @@ conduct_rpc (void **rpcbuf, int **pp)
              break;
 
            case SUCCESS:
+             DEBUG("[%s] RPC succeeded\n", __PRETTY_FUNCTION__);
              p++;
              *pp = p;
+             DEBUG("[%s] status : %d\n", __PRETTY_FUNCTION__, ntohl(*p));
              err = 0;
              break;
            }
@@ -352,9 +391,13 @@ conduct_rpc (void **rpcbuf, int **pp)
 void
 timeout_service_thread ()
 {
+  DEBUG("[%s] creating timeout thread\n", __PRETTY_FUNCTION__);
+
   while (1)
     {
       sleep (1);
+      
+      DEBUG("[%s] *DING*\n", __PRETTY_FUNCTION__);
       mutex_lock (&outstanding_lock);
       condition_broadcast (&rpc_wakeup);
       mutex_unlock (&outstanding_lock);
@@ -368,30 +411,44 @@ rpc_receive_thread ()
 {
   void *buf;
 
+  DEBUG("[%s] creating receive thread\n", __PRETTY_FUNCTION__);
+
   /* Allocate a receive buffer.  */
   buf = malloc (1024 + read_size);
   assert (buf);
 
+  DEBUG("[%s] allocated read buffer of size %d (%p)\n", 
+       __PRETTY_FUNCTION__, 1024 + read_size, buf);
+
   while (1)
     {
-      int cc = read (main_udp_socket, buf, 1024 + read_size);
+      mutex_lock (&read_lock);
+      DEBUG("[%s] reading from RPC socket %d\n", __PRETTY_FUNCTION__, 
main_socket);
+      int cc = read (main_socket, buf, 1024 + read_size);
+      mutex_unlock (&read_lock);
       if (cc == -1)
         {
-          error (0, errno, "nfs read");
+         DEBUG("[%s] reading failed : %s\n", __PRETTY_FUNCTION__, strerror 
(errno));
           continue;
         }
-      else
+      else if (cc > 0)
         {
           struct rpc_list *r;
           int xid = *(int *)buf;
 
+         DEBUG("[%s] RPC received (%d bytes) : xid = %d, locking mutex\n", 
__PRETTY_FUNCTION__, 
+               cc, xid);
+
           mutex_lock (&outstanding_lock);
 
+         DEBUG("[%s] mutex locked, finding out the original RPC\n", 
__PRETTY_FUNCTION__);
+
           /* Find the rpc that we just fulfilled.  */
           for (r = outstanding_rpcs; r; r = r->next)
            {
              if (* (int *) &r[1] == xid)
                {
+                 DEBUG("[%s] found the RPC which it replies to\n", 
__PRETTY_FUNCTION__);
                  unlink_rpc (r);
                  r->reply = buf;
                  condition_broadcast (&rpc_wakeup);
@@ -409,8 +466,10 @@ rpc_receive_thread ()
             to get another request, a new buffer is needed.  */
          if (r)
            {
+             DEBUG("[%s] allocating a new buffer\n", __PRETTY_FUNCTION__);
               buf = malloc (1024 + read_size);
               assert (buf);
+             DEBUG("[%s] new buffer: %p\n", __PRETTY_FUNCTION__, buf);
            }
         }
     }



[0]: I'm currently studying political science at the Institut d'Etudes
Politiques de Paris (Sciences Po), second year. Due to the youth and
students struggle in feb-apr we had our mid-term exams at the end of
may, beginning of june and final exams at the end of june.

Cheers,

-- 
Manuel Menal




reply via email to

[Prev in Thread] Current Thread [Next in Thread]