summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nfs/ChangeLog30
-rw-r--r--nfs/cache.c63
-rw-r--r--nfs/mount.c3
-rw-r--r--nfs/nfs.c250
-rw-r--r--nfs/nfs.h17
-rw-r--r--nfs/ops.c15
-rw-r--r--nfs/rpcsvc/nfs_prot.h8
7 files changed, 295 insertions, 91 deletions
diff --git a/nfs/ChangeLog b/nfs/ChangeLog
index fcb44299..dfe11aa4 100644
--- a/nfs/ChangeLog
+++ b/nfs/ChangeLog
@@ -1,5 +1,35 @@
+Thu Aug 15 15:24:29 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+
+ * ops.c (verify_nonexistent): Don't need to lock DIR; it's already
+ locked.
+ (netfs_attempt_link): Lock DIR *before* calling verify_nonexistent.
+
+ * nfs.c (xdr_encode_fhandle) [protocol_version == 2]: Copy
+ fhandle->data, not fhandle itself.
+
Wed Aug 14 12:33:37 1996 Thomas Bushnell, n/BSG <thomas@gnu.ai.mit.edu>
+ * nfs.c (xdr_encode_fhandle): Second arg now a `struct fhandle *'.
+ Encode v3 fhandle if appropriate.
+ * cache.c: Include <netinet/in.h>.
+ (hash): New arg `length'.
+ (lookup_fhandle): Changed to be more like xdr_decode_* functions.
+ All callers changed. Do the right thing for v3.
+ (recache_handle): Likewise.
+ * nfs.h (struct fhandle): New type.
+ (struct netnode): Member `handle' is now a `struct fhandle'.
+ (xdr_encode_fhandle): Second arg now a `struct fhandle *'.
+ (lookup_fhandle, recache_handle): Changed to be more like
+ xdr_decode_* functions.
+
+ * rpcsvc/nfs_prot.h (enum sattr_time_how): New type.
+ * nfs.c (xdr_encode_64bit): New function.
+ (xdr_encode_sattr_mode, xdr_encode_sattr_ids,
+ xdr_encode_sattr_size, xdr_encode_sattr_times,
+ xdr_encode_create_state, xdr_encode_sattr_stat): Encode v3 sattr
+ if appropriate.
+ (xdr_decode_fattr): Decode v3 fattr if appropriate.
+
* rpcsvc/nfs_prot.h (NFS_FHSIZE): Deleted macro.
(NFS2_FHSIZE, NFS3_FHSIZE, NFS3_COOKIEVERFSIZE, NFS3_CREATEVERFSIZE,
NFS3_WRITEVERFSIZE): New macros.
diff --git a/nfs/cache.c b/nfs/cache.c
index b6577440..7f5135f1 100644
--- a/nfs/cache.c
+++ b/nfs/cache.c
@@ -21,49 +21,62 @@
#include "nfs.h"
#include <string.h>
+#include <netinet/in.h>
/* Hash table containing all the nodes currently active. */
#define CACHESIZE 512
static struct node *nodehash [CACHESIZE];
-/* Compute and return a hash key for NFS file handle FHANDLE. */
+/* Compute and return a hash key for NFS file handle DATA of LEN bytes. */
static inline int
-hash (void *fhandle)
+hash (int *data, size_t len)
{
unsigned int h = 0;
+ char *cp = (char *)data;
int i;
- for (i = 0; i < NFS2_FHSIZE; i++)
- h += ((char *)fhandle)[i];
+ for (i = 0; i < len; i++)
+ h += cp[i];
return h % CACHESIZE;
}
-/* Lookup the specified file handle FHANDLE in the hash table. If it
+/* Lookup the file handle in RPC result at P in the hash table. If it
is not present, initialize a new node structure and insert it into
the hash table. Whichever course, a new reference is generated and
- the node is returned. */
-struct node *
-lookup_fhandle (void *fhandle)
+ the node is returned in *NPP. Return the address in the RPC result
+ after the file handle. */
+int *
+lookup_fhandle (int *p, struct node **npp)
{
struct node *np;
struct netnode *nn;
- int h = hash (fhandle);
+ size_t len;
+ int h;
+
+ if (protocol_version == 2)
+ len = NFS2_FHSIZE;
+ else
+ len = ntohl (*p++);
+ h = hash (p, len);
spin_lock (&netfs_node_refcnt_lock);
for (np = nodehash[h]; np; np = np->nn->hnext)
{
- if (bcmp (np->nn->handle, fhandle, NFS2_FHSIZE) != 0)
+ if (np->nn->handle.size != len
+ || bcmp (np->nn->handle.data, p, len) != 0)
continue;
np->references++;
spin_unlock (&netfs_node_refcnt_lock);
mutex_lock (&np->lock);
- return np;
+ *npp = np;
+ return p + len / sizeof (int);
}
nn = malloc (sizeof (struct netnode));
- bcopy (fhandle, nn->handle, NFS2_FHSIZE);
+ nn->handle.size = len;
+ bcopy (p, nn->handle.data, len);
nn->stat_updated = 0;
nn->dtrans = NOT_POSSIBLE;
nn->dead_dir = 0;
@@ -79,7 +92,8 @@ lookup_fhandle (void *fhandle)
spin_unlock (&netfs_node_refcnt_lock);
- return np;
+ *npp = np;
+ return p + len / sizeof (int);
}
/* Called by libnetfs when node NP has no more references. (See
@@ -123,27 +137,36 @@ netfs_node_norefs (struct node *np)
}
}
-/* Change the file handle used for node NP to be HANDLE. Make sure the
- hash table stays up to date. */
-void
-recache_handle (struct node *np, void *handle)
+/* Change the file handle used for node NP to be the handle at P.
+ Make sure the hash table stays up to date. Return the address
+ after the hnadle. */
+int *
+recache_handle (int *p, struct node *np)
{
int h;
+ size_t len;
+
+ if (protocol_version == 2)
+ len = NFS2_FHSIZE;
+ else
+ len = ntohl (*p++);
spin_lock (&netfs_node_refcnt_lock);
*np->nn->hprevp = np->nn->hnext;
if (np->nn->hnext)
np->nn->hnext->nn->hprevp = np->nn->hprevp;
+
+ np->nn->handle.size = len;
+ bcopy (p, np->nn->handle.data, len);
- bcopy (handle, np->nn->handle, NFS2_FHSIZE);
-
- h = hash (handle);
+ h = hash (p, len);
np->nn->hnext = nodehash[h];
if (np->nn->hnext)
np->nn->hnext->nn->hprevp = &np->nn->hnext;
np->nn->hprevp = &nodehash[h];
spin_unlock (&netfs_node_refcnt_lock);
+ return p + len / sizeof (int);
}
diff --git a/nfs/mount.c b/nfs/mount.c
index 233a0298..a7ceaf50 100644
--- a/nfs/mount.c
+++ b/nfs/mount.c
@@ -176,8 +176,7 @@ mount_root (char *name, char *host)
}
/* Create the node for root */
- np = lookup_fhandle (p);
- p += NFS2_FHSIZE / sizeof (int);
+ lookup_fhandle (p, &np);
free (rpcbuf);
mutex_unlock (&np->lock);
diff --git a/nfs/nfs.c b/nfs/nfs.c
index f053ea41..490f494b 100644
--- a/nfs/nfs.c
+++ b/nfs/nfs.c
@@ -104,10 +104,15 @@ hurd_mode_to_nfs_mode (mode_t mode)
/* Encode an NFS file handle. */
int *
-xdr_encode_fhandle (int *p, void *fhandle)
+xdr_encode_fhandle (int *p, struct fhandle *fhandle)
{
- bcopy (fhandle, p, NFS2_FHSIZE);
- return p + INTSIZE (NFS2_FHSIZE);
+ if (protocol_version == 2)
+ {
+ bcopy (fhandle->data, p, NFS2_FHSIZE);
+ return p + INTSIZE (NFS2_FHSIZE);
+ }
+ else
+ return xdr_encode_data (p, fhandle->data, fhandle->size);
}
/* Encode uninterpreted bytes. */
@@ -122,6 +127,15 @@ xdr_encode_data (int *p, char *data, size_t len)
return p + nints;
}
+/* Encode a 64 bit integer */
+int *
+xdr_encode_64bit (int *p, long long n)
+{
+ *p++ = htonl (n & 0xffffffff00000000LL >> 32);
+ *p++ = htonl (n & 0xffffffff);
+ return p;
+}
+
/* Encode a C string. */
int *
xdr_encode_string (int *p, char *string)
@@ -133,14 +147,27 @@ xdr_encode_string (int *p, char *string)
int *
xdr_encode_sattr_mode (int *p, mode_t mode)
{
- *p++ = htonl (hurd_mode_to_nfs_mode (mode));
- *p++ = -1; /* uid */
- *p++ = -1; /* gid */
- *p++ = -1; /* size */
- *p++ = -1; /* atime secs */
- *p++ = -1; /* atime usecs */
- *p++ = -1; /* mtime secs */
- *p++ = -1; /* mtime usecs */
+ if (protocol_version == 2)
+ {
+ *p++ = htonl (hurd_mode_to_nfs_mode (mode));
+ *p++ = -1; /* uid */
+ *p++ = -1; /* gid */
+ *p++ = -1; /* size */
+ *p++ = -1; /* atime secs */
+ *p++ = -1; /* atime usecs */
+ *p++ = -1; /* mtime secs */
+ *p++ = -1; /* mtime usecs */
+ }
+ else
+ {
+ *p++ = htonl (1); /* set mode */
+ *p++ = htonl (hurd_mode_to_nfs_mode (mode));
+ *p++ = 0; /* no uid */
+ *p++ = 0; /* no gid */
+ *p++ = 0; /* no size */
+ *p++ = DONT_CHANGE; /* no atime */
+ *p++ = DONT_CHANGE; /* no mtime */
+ }
return p;
}
@@ -148,14 +175,28 @@ xdr_encode_sattr_mode (int *p, mode_t mode)
int *
xdr_encode_sattr_ids (int *p, u_int uid, u_int gid)
{
- *p++ = -1; /* mode */
- *p++ = htonl (uid);
- *p++ = htonl (gid);
- *p++ = -1; /* size */
- *p++ = -1; /* atime secs */
- *p++ = -1; /* atime usecs */
- *p++ = -1; /* mtime secs */
- *p++ = -1; /* mtime usecs */
+ if (protocol_version == 2)
+ {
+ *p++ = -1; /* mode */
+ *p++ = htonl (uid);
+ *p++ = htonl (gid);
+ *p++ = -1; /* size */
+ *p++ = -1; /* atime secs */
+ *p++ = -1; /* atime usecs */
+ *p++ = -1; /* mtime secs */
+ *p++ = -1; /* mtime usecs */
+ }
+ else
+ {
+ *p++ = 0; /* no mode */
+ *p++ = htonl (1); /* set uid */
+ *p++ = htonl (uid);
+ *p++ = htonl (1); /* set gid */
+ *p++ = htonl (gid);
+ *p++ = 0; /* no size */
+ *p++ = DONT_CHANGE; /* no atime */
+ *p++ = DONT_CHANGE; /* no mtime */
+ }
return p;
}
@@ -163,14 +204,27 @@ xdr_encode_sattr_ids (int *p, u_int uid, u_int gid)
int *
xdr_encode_sattr_size (int *p, off_t size)
{
- *p++ = -1; /* mode */
- *p++ = -1; /* uid */
- *p++ = -1; /* gid */
- *p++ = htonl (size);
- *p++ = -1; /* atime secs */
- *p++ = -1; /* atime usecs */
- *p++ = -1; /* mtime secs */
- *p++ = -1; /* mtime secs */
+ if (protocol_version == 2)
+ {
+ *p++ = -1; /* mode */
+ *p++ = -1; /* uid */
+ *p++ = -1; /* gid */
+ *p++ = htonl (size);
+ *p++ = -1; /* atime secs */
+ *p++ = -1; /* atime usecs */
+ *p++ = -1; /* mtime secs */
+ *p++ = -1; /* mtime secs */
+ }
+ else
+ {
+ *p++ = 0; /* no mode */
+ *p++ = 0; /* no uid */
+ *p++ = 0; /* no gid */
+ *p++ = htonl (1); /* size */
+ p = xdr_encode_64bit (p, size);
+ *p++ = DONT_CHANGE; /* no atime */
+ *p++ = DONT_CHANGE; /* no mtime */
+ }
return p;
}
@@ -178,14 +232,30 @@ xdr_encode_sattr_size (int *p, off_t size)
int *
xdr_encode_sattr_times (int *p, struct timespec *atime, struct timespec *mtime)
{
- *p++ = -1; /* mode */
- *p++ = -1; /* uid */
- *p++ = -1; /* gid */
- *p++ = -1; /* size */
- *p++ = htonl (atime->tv_sec);
- *p++ = htonl (atime->tv_nsec * 1000);
- *p++ = htonl (mtime->tv_sec);
- *p++ = htonl (mtime->tv_nsec * 1000);
+ if (protocol_version == 2)
+ {
+ *p++ = -1; /* mode */
+ *p++ = -1; /* uid */
+ *p++ = -1; /* gid */
+ *p++ = -1; /* size */
+ *p++ = htonl (atime->tv_sec);
+ *p++ = htonl (atime->tv_nsec * 1000);
+ *p++ = htonl (mtime->tv_sec);
+ *p++ = htonl (mtime->tv_nsec * 1000);
+ }
+ else
+ {
+ *p++ = 0; /* no mode */
+ *p++ = 0; /* no uid */
+ *p++ = 0; /* no gid */
+ *p++ = 0; /* no size */
+ *p++ = htonl (SET_TO_CLIENT_TIME); /* atime */
+ *p++ = htonl (atime->tv_sec);
+ *p++ = htonl (atime->tv_nsec);
+ *p++ = htonl (SET_TO_CLIENT_TIME); /* mtime */
+ *p++ = htonl (mtime->tv_sec);
+ *p++ = htonl (mtime->tv_nsec);
+ }
return p;
}
@@ -194,14 +264,28 @@ int *
xdr_encode_create_state (int *p,
mode_t mode)
{
- *p++ = htonl (hurd_mode_to_nfs_mode (mode));
- *p++ = -1; /* uid */
- *p++ = -1; /* gid */
- *p++ = 0; /* size */
- *p++ = -1; /* atime sec */
- *p++ = -1; /* atime usec */
- *p++ = -1; /* mtime sec */
- *p++ = -1; /* mtime usec */
+ if (protocol_version == 2)
+ {
+ *p++ = htonl (hurd_mode_to_nfs_mode (mode));
+ *p++ = -1; /* uid */
+ *p++ = -1; /* gid */
+ *p++ = 0; /* size */
+ *p++ = -1; /* atime sec */
+ *p++ = -1; /* atime usec */
+ *p++ = -1; /* mtime sec */
+ *p++ = -1; /* mtime usec */
+ }
+ else
+ {
+ *p++ = htonl (1); /* mode */
+ *p++ = htonl (hurd_mode_to_nfs_mode (mode));
+ *p++ = 0; /* no uid */
+ *p++ = 0; /* no gid */
+ *p++ = htonl (1); /* set size */
+ p = xdr_encode_64bit (p, 0);
+ *p++ = htonl (SET_TO_SERVER_TIME); /* atime */
+ *p++ = htonl (SET_TO_SERVER_TIME); /* mtime */
+ }
return p;
}
@@ -210,18 +294,49 @@ int *
xdr_encode_sattr_stat (int *p,
struct stat *st)
{
- *p++ = htonl (st->st_mode);
- *p++ = htonl (st->st_uid);
- *p++ = htonl (st->st_gid);
- *p++ = htonl (st->st_size);
- *p++ = htonl (st->st_atime);
- *p++ = htonl (st->st_atime_usec);
- *p++ = htonl (st->st_mtime);
- *p++ = htonl (st->st_mtime_usec);
+ if (protocol_version == 2)
+ {
+ *p++ = htonl (hurd_mode_to_nfs_mode (st->st_mode));
+ *p++ = htonl (st->st_uid);
+ *p++ = htonl (st->st_gid);
+ *p++ = htonl (st->st_size);
+ *p++ = htonl (st->st_atime);
+ *p++ = htonl (st->st_atime_usec);
+ *p++ = htonl (st->st_mtime);
+ *p++ = htonl (st->st_mtime_usec);
+ }
+ else
+ {
+ *p++ = htonl (1); /* set mode */
+ *p++ = htonl (hurd_mode_to_nfs_mode (st->st_mode));
+ *p++ = htonl (1); /* set uid */
+ *p++ = htonl (st->st_uid);
+ *p++ = htonl (1); /* set gid */
+ *p++ = htonl (st->st_gid);
+ *p++ = htonl (1); /* set size */
+ p = xdr_encode_64bit (p, st->st_size);
+ *p++ = htonl (SET_TO_CLIENT_TIME); /* set atime */
+ *p++ = htonl (st->st_atime);
+ *p++ = htonl (st->st_atime_usec * 1000);
+ *p++ = htonl (SET_TO_CLIENT_TIME); /* set mtime */
+ *p++ = htonl (st->st_mtime);
+ *p++ = htonl (st->st_mtime_usec * 1000);
+ }
return p;
}
+/* Decode *P into a long long; return the address of the following data. */
+int *
+xdr_decode_64bit (int *p, long long *n)
+{
+ long long high, low;
+ high = ntohl (*p++);
+ low = ntohl (*p++);
+ *n = ((high & 0xffffffff) << 32) | (low & 0xffffffff);
+ return p;
+}
+
/* Decode *P into a stat structure; return the address of the
following data. */
int *
@@ -235,10 +350,28 @@ xdr_decode_fattr (int *p, struct stat *st)
st->st_nlink = ntohl (*p++);
st->st_uid = ntohl (*p++);
st->st_gid = ntohl (*p++);
- st->st_size = ntohl (*p++);
- st->st_blksize = ntohl (*p++);
- st->st_rdev = ntohl (*p++);
- st->st_blocks = ntohl (*p++);
+ if (protocol_version == 2)
+ {
+ st->st_size = ntohl (*p++);
+ st->st_blksize = ntohl (*p++);
+ st->st_rdev = ntohl (*p++);
+ st->st_blocks = ntohl (*p++);
+ }
+ else
+ {
+ long long size;
+ int major, minor;
+ p = xdr_decode_64bit (p, &size);
+ st->st_size = size;
+ p = xdr_decode_64bit (p, &size);
+ st->st_blocks = size / 512;
+ st->st_blksize = read_size < write_size ? read_size : write_size;
+ major = ntohl (*p++);
+ minor = ntohl (*p++);
+/* XXX - Temporary */
+#define makedev(maj,min) ((((maj)&0xFF)<<8)+((min)&0xFF))
+ st->st_rdev = makedev (major, minor);
+ }
st->st_fsid = ntohl (*p++);
st->st_ino = ntohl (*p++);
st->st_atime = ntohl (*p++);
@@ -248,6 +381,13 @@ xdr_decode_fattr (int *p, struct stat *st)
st->st_ctime = ntohl (*p++);
st->st_ctime_usec = ntohl (*p++);
+ if (protocol_version == 3)
+ {
+ st->st_atime_usec /= 1000;
+ st->st_mtime_usec /= 1000;
+ st->st_ctime_usec /= 1000;
+ }
+
return p;
}
diff --git a/nfs/nfs.h b/nfs/nfs.h
index 1996dfce..29fc8ccc 100644
--- a/nfs/nfs.h
+++ b/nfs/nfs.h
@@ -24,11 +24,20 @@ typedef int bool_t; /* Ick. */
#include <rpcsvc/nfs_prot.h>
#include <hurd/netfs.h>
+/* A file handle */
+struct fhandle
+{
+ size_t size;
+
+ /* Leave enough room for the biggest possible fhandle. */
+ char data[NFS3_FHSIZE];
+};
+
/* One of these exists for private data needed by the client for each
node. */
struct netnode
{
- char handle[NFS2_FHSIZE];
+ struct fhandle handle;
time_t stat_updated;
struct node *hnext, **hprevp;
@@ -155,7 +164,7 @@ int cred_has_uid (struct netcred *, uid_t);
int cred_has_gid (struct netcred *, gid_t);
/* nfs.c */
-int *xdr_encode_fhandle (int *, void *);
+int *xdr_encode_fhandle (int *, struct fhandle *);
int *xdr_encode_data (int *, char *, size_t);
int *xdr_encode_string (int *, char *);
int *xdr_encode_sattr_mode (int *, mode_t);
@@ -183,5 +192,5 @@ void timeout_service_thread (void);
void rpc_receive_thread (void);
/* cache.c */
-struct node *lookup_fhandle (void *);
-void recache_handle (struct node *, void *);
+int *lookup_fhandle (int *, struct node **);
+int *recache_handle (int *, struct node *);
diff --git a/nfs/ops.c b/nfs/ops.c
index 2efeb6fd..50218fa5 100644
--- a/nfs/ops.c
+++ b/nfs/ops.c
@@ -429,7 +429,6 @@ verify_nonexistent (struct netcred *cred, struct node *dir,
p = xdr_encode_fhandle (p, &dir->nn->handle);
p = xdr_encode_string (p, name);
- mutex_lock (&dir->lock);
err = conduct_rpc (&rpcbuf, &p);
if (!err)
err = nfs_error_trans (ntohl (*p++));
@@ -463,8 +462,7 @@ netfs_attempt_lookup (struct netcred *cred, struct node *np,
if (!err)
{
- *newnp = lookup_fhandle (p);
- p += NFS2_FHSIZE / sizeof (int);
+ p = lookup_fhandle (p, newnp);
register_fresh_stat (*newnp, p);
}
else
@@ -617,8 +615,7 @@ netfs_attempt_link (struct netcred *cred, struct node *dir,
else
{
mutex_lock (&np->lock);
- recache_handle (np, p);
- p += NFS2_FHSIZE / sizeof (int);
+ p = recache_handle (p, np);
register_fresh_stat (np, p);
mutex_unlock (&np->lock);
}
@@ -632,11 +629,11 @@ netfs_attempt_link (struct netcred *cred, struct node *dir,
case FIFO:
case SOCK:
+ mutex_lock (&dir->lock);
err = verify_nonexistent (cred, dir, name);
if (err)
return err;
- mutex_lock (&dir->lock);
p = nfs_initialize_rpc (NFSPROC_CREATE (protocol_version),
cred, 0, &rpcbuf, dir, -1);
p = xdr_encode_fhandle (p, &dir->nn->handle);
@@ -662,8 +659,7 @@ netfs_attempt_link (struct netcred *cred, struct node *dir,
mutex_unlock (&dir->lock);
mutex_lock (&np->lock);
- recache_handle (np, p);
- p += NFS2_FHSIZE / sizeof (int);
+ p = recache_handle (p, np);
register_fresh_stat (np, p);
mutex_unlock (&np->lock);
@@ -765,8 +761,7 @@ netfs_attempt_create_file (struct netcred *cred, struct node *np,
if (!err)
{
- *newnp = lookup_fhandle (p);
- p += NFS2_FHSIZE / sizeof (int);
+ p = lookup_fhandle (p, newnp);
register_fresh_stat (*newnp, p);
}
else
diff --git a/nfs/rpcsvc/nfs_prot.h b/nfs/rpcsvc/nfs_prot.h
index a51f7c9f..476c72ef 100644
--- a/nfs/rpcsvc/nfs_prot.h
+++ b/nfs/rpcsvc/nfs_prot.h
@@ -66,6 +66,14 @@ enum ftype {
NF2FIFO = 8, /* v2 only */
};
+/* Ways to set the time in setattr structures */
+enum sattr_time_how
+{
+ DONT_CHANGE = 0,
+ SET_TO_SERVER_TIME = 1,
+ SET_TO_CLIENT_TIME = 2,
+};
+
#define NFS_PROGRAM ((u_long)100003)
#define NFS_VERSION ((u_long)2)