From 823869e64ce6326ad59f62d4296ab2f6fdba0c89 Mon Sep 17 00:00:00 2001 From: Thomas Bushnell Date: Thu, 15 Aug 1996 19:50:20 +0000 Subject: *** empty log message *** --- nfs/ChangeLog | 30 ++++++ nfs/cache.c | 63 +++++++++---- nfs/mount.c | 3 +- nfs/nfs.c | 250 +++++++++++++++++++++++++++++++++++++++----------- nfs/nfs.h | 17 +++- nfs/ops.c | 15 +-- nfs/rpcsvc/nfs_prot.h | 8 ++ 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 + + * 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 + * nfs.c (xdr_encode_fhandle): Second arg now a `struct fhandle *'. + Encode v3 fhandle if appropriate. + * cache.c: Include . + (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 +#include /* 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 #include +/* 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) -- cgit v1.2.3