From 4d75b660a263b510e2a2b2176196c20a8af58851 Mon Sep 17 00:00:00 2001 From: Thomas Bushnell Date: Tue, 29 Jul 1997 20:57:33 +0000 Subject: Tue Jul 29 15:38:15 1997 Thomas Bushnell, n/BSG * name-cache.c (check_lookup_cache): Use name_cache_neg_timeout in preference to name_cache_timeout for negative hits. * nfs.h (name_cache_neg_timeout): New variable. * main.c (DEFAULT_NAME_CACHE_NEG_TIMEOUT): New macro. (name_cache_neg_timeout): Initialize new variable. (OPT_NCACHE_NEG_TO): New option key. (common_options): Add --name-cache-neg-timeout switch. (parse_common_opt): Process OPT_NCACHE_NEG_TO option key. * ops.c (netfs_attempt_lookup): Do cast of -1 correctly to match check_lookup_cache and ANSI C rules. * name-cache.c (check_lookup_cache): Unlock DIR correctly before returning a negative cache hit. * rpc.c (rpc_receive_thread): Don't print "dropping reply" messages any more. * ops.c (netfs_attempt_lookup): Cash all lookups, both positive and negative. (netfs_attempt_mkdir): Purge cache before creating directory entry. (netfs_attempt_link): Likewise. (netfs_attempt_create_file): Likewise. * ops.c (netfs_attempt_lookup): Pass correct node to enter_lookup_cache as the child. Thu Jul 24 13:15:56 1997 Thomas Bushnell, n/BSG * name-cache.c: New file. * ops.c (netfs_attempt_lookup): Check lookup cache before trying RPC. After successful lookup, make cache entry. (netfs_attempt_unlink): Purge cache before doing operation. (netfs_attempt_rmdir): Likewise. (netfs_attempt_rename): Purge cache for both names before operation. * nfs.h (enter_lookup_cache, purge_lookup_cache, check_lookup_cache): New prototypes. * Makefile (SRCS): Add name-cache.c. * nfs.h (name_cache_timeout): New variable. * main.c (DEFAULT_NAME_CACHE_TIMEOUT): New macro. (name_cache_timeout): Initialize new variable. (OPT_NCACHE_TO): New option key. (common_options): Add --name-cache-timeout switch. (parse_common_opt): Process OPT_NCACHE_TO option key. * cache.c (lookup_fhandle): Don't parse NFS XDR format, instead take a length arg. Return void. All callers changed to use new function xdr_decode_fhandle. * nfs.c (xdr_decode_fhandle): New function. * nfs.h (xdr_decode_fhandle): New prototype. (lookup_fhandle): Update prototype. --- nfs/ChangeLog | 57 ++++++++++++ nfs/Makefile | 4 +- nfs/cache.c | 23 ++--- nfs/main.c | 22 +++++ nfs/mount.c | 4 +- nfs/name-cache.c | 272 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ nfs/nfs.c | 12 +++ nfs/nfs.h | 14 ++- nfs/ops.c | 49 +++++++++- nfs/rpc.c | 4 +- 10 files changed, 437 insertions(+), 24 deletions(-) create mode 100644 nfs/name-cache.c diff --git a/nfs/ChangeLog b/nfs/ChangeLog index 33845ac1..084a1bf2 100644 --- a/nfs/ChangeLog +++ b/nfs/ChangeLog @@ -1,3 +1,60 @@ +Tue Jul 29 15:38:15 1997 Thomas Bushnell, n/BSG + + * name-cache.c (check_lookup_cache): Use name_cache_neg_timeout in + preference to name_cache_timeout for negative hits. + + * nfs.h (name_cache_neg_timeout): New variable. + * main.c (DEFAULT_NAME_CACHE_NEG_TIMEOUT): New macro. + (name_cache_neg_timeout): Initialize new variable. + (OPT_NCACHE_NEG_TO): New option key. + (common_options): Add --name-cache-neg-timeout switch. + (parse_common_opt): Process OPT_NCACHE_NEG_TO option key. + + * ops.c (netfs_attempt_lookup): Do cast of -1 correctly to match + check_lookup_cache and ANSI C rules. + + * name-cache.c (check_lookup_cache): Unlock DIR correctly before + returning a negative cache hit. + + * rpc.c (rpc_receive_thread): Don't print "dropping reply" + messages any more. + + * ops.c (netfs_attempt_lookup): Cash all lookups, both positive + and negative. + (netfs_attempt_mkdir): Purge cache before creating directory + entry. + (netfs_attempt_link): Likewise. + (netfs_attempt_create_file): Likewise. + + * ops.c (netfs_attempt_lookup): Pass correct node to + enter_lookup_cache as the child. + +Thu Jul 24 13:15:56 1997 Thomas Bushnell, n/BSG + + * name-cache.c: New file. + * ops.c (netfs_attempt_lookup): Check lookup cache before trying + RPC. After successful lookup, make cache entry. + (netfs_attempt_unlink): Purge cache before doing operation. + (netfs_attempt_rmdir): Likewise. + (netfs_attempt_rename): Purge cache for both names before operation. + * nfs.h (enter_lookup_cache, purge_lookup_cache, + check_lookup_cache): New prototypes. + * Makefile (SRCS): Add name-cache.c. + + * nfs.h (name_cache_timeout): New variable. + * main.c (DEFAULT_NAME_CACHE_TIMEOUT): New macro. + (name_cache_timeout): Initialize new variable. + (OPT_NCACHE_TO): New option key. + (common_options): Add --name-cache-timeout switch. + (parse_common_opt): Process OPT_NCACHE_TO option key. + + * cache.c (lookup_fhandle): Don't parse NFS XDR format, instead + take a length arg. Return void. All callers changed to use new + function xdr_decode_fhandle. + * nfs.c (xdr_decode_fhandle): New function. + * nfs.h (xdr_decode_fhandle): New prototype. + (lookup_fhandle): Update prototype. + 1997-07-23 Miles Bader * main.c: Include . diff --git a/nfs/Makefile b/nfs/Makefile index f7a7d3bf..05fbd90c 100644 --- a/nfs/Makefile +++ b/nfs/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 1995, 1996 Free Software Foundation +# Copyright (C) 1995, 1996, 1997 Free Software Foundation # Written by Michael I. Bushnell. # # This file is part of the GNU Hurd. @@ -23,7 +23,7 @@ makemode := server target = nfs LCLHDRS = nfs.h mount.h nfs-spec.h -SRCS = ops.c rpc.c mount.c nfs.c cache.c consts.c main.c +SRCS = ops.c rpc.c mount.c nfs.c cache.c consts.c main.c name-cache.c OBJS = $(subst .c,.o,$(SRCS)) HURDLIBS=ports netfs fshelp threads iohelp diff --git a/nfs/cache.c b/nfs/cache.c index e09b7c38..f854949c 100644 --- a/nfs/cache.c +++ b/nfs/cache.c @@ -1,5 +1,5 @@ /* Node cache management for NFS client implementation - Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. Written by Michael I. Bushnell, p/BSG. This file is part of the GNU Hurd. @@ -41,23 +41,17 @@ hash (int *data, size_t len) return h % CACHESIZE; } -/* 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 in *NPP. Return the address in the RPC result - after the file handle. */ -int * -lookup_fhandle (int *p, struct node **npp) +/* Lookup the file handle P (length LEN) 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 in *NPP. */ +void +lookup_fhandle (void *p, size_t len, struct node **npp) { struct node *np; struct netnode *nn; - 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); @@ -71,7 +65,7 @@ lookup_fhandle (int *p, struct node **npp) spin_unlock (&netfs_node_refcnt_lock); mutex_lock (&np->lock); *npp = np; - return p + len / sizeof (int); + return; } nn = malloc (sizeof (struct netnode)); @@ -93,7 +87,6 @@ lookup_fhandle (int *p, struct node **npp) spin_unlock (&netfs_node_refcnt_lock); *npp = np; - return p + len / sizeof (int); } /* Called by libnetfs when node NP has no more references. (See diff --git a/nfs/main.c b/nfs/main.c index add6ecc8..d9702ecb 100644 --- a/nfs/main.c +++ b/nfs/main.c @@ -42,6 +42,12 @@ extern char *localhost (); /* Default number of seconds to timeout cached file contents. */ #define DEFAULT_CACHE_TIMEOUT 3 +/* Default number of seconds to timeout cache positive dir hits. */ +#define DEFAULT_NAME_CACHE_TIMEOUT 3 + +/* Default number of seconds to timeout cache negative dir hits. */ +#define DEFAULT_NAME_CACHE_NEG_TIMEOUT 3 + /* Default maximum number of bytes to read at once. */ #define DEFAULT_READ_SIZE 8192 @@ -55,6 +61,12 @@ int stat_timeout = DEFAULT_STAT_TIMEOUT; /* Number of seconds to timeout cached file contents. */ int cache_timeout = DEFAULT_CACHE_TIMEOUT; +/* Number of seconds to timeout cached positive dir hits. */ +int name_cache_timeout = DEFAULT_NAME_CACHE_TIMEOUT; + +/* Number of seconds to timeout cached negative dir hits. */ +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; @@ -89,6 +101,8 @@ int write_size = DEFAULT_WRITE_SIZE; #define OPT_MNT_PROG -11 #define OPT_NFS_PROG -12 #define OPT_PMAP_PORT -13 +#define OPT_NCACHE_TO -14 +#define OPT_NCACHE_NEG_TO -15 /* Return a string corresponding to the printed rep of DEFAULT_what */ #define ___D(what) #what @@ -118,6 +132,12 @@ static const struct argp_option common_options[] = "Timeout for cached stat information (default " _D(STAT_TIMEOUT) ")"}, {"cache-timeout", OPT_CACHE_TO, "SEC", 0, "Timeout for cached file data (default " _D(CACHE_TIMEOUT) ")"}, + {"name-cache-timeout", OPT_NCACHE_TO, "SEC", 0, + "Timeout for positive directory cache entries (default " + _D(NAME_CACHE_TIMEOUT) ")"}, + {"name-cache-neg-timeout", OPT_NCACHE_NEG_TO, "SEC", 0, + "Timeout for negative directory cache entires (default " + _D(NAME_CACHE_NEG_TIMEOUT) ")"}, {"init-transmit-timeout", OPT_INIT_TR_TO,"SEC", 0}, {"max-transmit-timeout", OPT_MAX_TR_TO, "SEC", 0}, @@ -145,6 +165,8 @@ parse_common_opt (int key, char *arg, struct argp_state *state) case OPT_CACHE_TO: cache_timeout = atoi (arg); break; case OPT_INIT_TR_TO: initial_transmit_timeout = atoi (arg); break; case OPT_MAX_TR_TO: max_transmit_timeout = atoi (arg); break; + case OPT_NCACHE_TO: name_cache_timeout = atoi (arg); break; + case OPT_NCACHE_NEG_TO: name_cache_neg_timeout = atoi (arg); break; default: return ARGP_ERR_UNKNOWN; diff --git a/nfs/mount.c b/nfs/mount.c index 965d00a9..5c9ec3bc 100644 --- a/nfs/mount.c +++ b/nfs/mount.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. Written by Michael I. Bushnell, p/BSG. This file is part of the GNU Hurd. @@ -181,7 +181,7 @@ mount_root (char *name, char *host) } /* Create the node for root */ - lookup_fhandle (p, &np); + xdr_decode_fhandle (p, &np); free (rpcbuf); mutex_unlock (&np->lock); diff --git a/nfs/name-cache.c b/nfs/name-cache.c new file mode 100644 index 00000000..314867d7 --- /dev/null +++ b/nfs/name-cache.c @@ -0,0 +1,272 @@ +/* Directory name lookup caching + + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Written by Thomas Bushnell, n/BSG, & Miles Bader. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include "nfs.h" +#include +#include + + +/* Maximum number of names to cache at once */ +#define MAXCACHE 200 + +/* Maximum length of file name we bother caching */ +#define CACHE_NAME_LEN 100 + +/* Cache entry */ +struct lookup_cache +{ + struct cacheq_hdr hdr; + + /* File handles and lengths for cache entries. 0 for NODE_CACHE_LEN + means a `negative' entry -- recording that there's definitely no node with + this name. */ + char dir_cache_fh[NFS3_FHSIZE], node_cache_fh[NFS3_FHSIZE]; + size_t dir_cache_len, node_cache_len; + + /* Name of the node NODE_CACHE_ID in the directory DIR_CACHE_ID. Entries + with names too long to fit in this buffer aren't cached at all. */ + char name[CACHE_NAME_LEN]; + + /* Strlen of NAME. If this is zero, it's an unused entry. */ + size_t name_len; + + /* Time that this cache entry was created. */ + time_t cache_stamp; + + /* XXX */ + int stati; +}; + +/* The contents of the cache in no particular order */ +static struct cacheq lookup_cache = { sizeof (struct lookup_cache) }; + +static spin_lock_t cache_lock = SPIN_LOCK_INITIALIZER; + +/* Buffer to hold statistics */ +static struct stats +{ + long pos_hits; + long neg_hits; + long miss; + long fetch_errors; +} statistics; + +#define PARTIAL_THRESH 100 +#define NPARTIALS MAXCACHE / PARTIAL_THRESH +struct stats partial_stats [NPARTIALS]; + + +/* If there's an entry for NAME, of length NAME_LEN, in directory DIR in the + cache, return its entry, otherwise 0. CACHE_LOCK must be held. */ +static struct lookup_cache * +find_cache (char *dir, size_t len, const char *name, size_t name_len) +{ + struct lookup_cache *c; + int i; + + /* Search the list. All unused entries are contiguous at the end of the + list, so we can stop searching when we see the first one. */ + for (i = 0, c = lookup_cache.mru; + c && c->name_len; + c = c->hdr.next, i++) + if (c->name_len == name_len + && c->dir_cache_len == len + && c->name[0] == name[0] + && bcmp (c->dir_cache_fh, dir, len) == 0 + && strcmp (c->name, name) == 0) + { + c->stati = i / 100; + return c; + } + + return 0; +} + +/* Node NP has just been found in DIR with NAME. If NP is null, that + means that this name has been confirmed as absent in the directory. + DIR is the fhandle of the directory; its length is LEN. */ +void +enter_lookup_cache (char *dir, size_t len, struct node *np, char *name) +{ + struct lookup_cache *c; + size_t name_len = strlen (name); + + if (name_len > CACHE_NAME_LEN - 1) + return; + + spin_lock (&cache_lock); + + if (lookup_cache.length == 0) + /* There should always be an lru_cache; this being zero means that the + cache hasn't been initialized yet. Do so. */ + cacheq_set_length (&lookup_cache, MAXCACHE); + + /* See if there's an old entry for NAME in DIR. If not, replace the least + recently used entry. */ + c = find_cache (dir, len, name, name_len) ?: lookup_cache.lru; + + /* Fill C with the new entry. */ + bcopy (dir, c->dir_cache_fh, len); + c->dir_cache_len = len; + if (np) + bcopy (np->nn->handle.data, c->node_cache_fh, np->nn->handle.size); + c->node_cache_len = np ? np->nn->handle.size : 0; + strcpy (c->name, name); + c->name_len = name_len; + c->cache_stamp = mapped_time->seconds; + + /* Now C becomes the MRU entry! */ + cacheq_make_mru (&lookup_cache, c); + + spin_unlock (&cache_lock); +} + +/* Purge all references in the cache to NAME within directory DIR. */ +void +purge_lookup_cache (struct node *dp, char *name, size_t namelen) +{ + struct lookup_cache *c, *next; + + spin_lock (&cache_lock); + for (c = lookup_cache.mru; c; c = next) + { + /* Save C->hdr.next, since we may move C from this position. */ + next = c->hdr.next; + + if (c->name_len == namelen + && c->dir_cache_len == dp->nn->handle.size + && bcmp (c->dir_cache_fh, dp->nn->handle.data, c->dir_cache_len) == 0 + && strcmp (c->name, name) == 0) + { + c->name_len = 0; + cacheq_make_lru (&lookup_cache, c); /* Use C as the next free + entry. */ + } + } + spin_unlock (&cache_lock); +} + +/* Register a negative hit for an entry in the Nth stat class */ +void +register_neg_hit (int n) +{ + int i; + + statistics.neg_hits++; + + for (i = 0; i < n; i++) + partial_stats[i].miss++; + for (; i < NPARTIALS; i++) + partial_stats[i].neg_hits++; +} + +/* Register a positive hit for an entry in the Nth stat class */ +void +register_pos_hit (int n) +{ + int i; + + statistics.pos_hits++; + + for (i = 0; i < n; i++) + partial_stats[i].miss++; + for (; i < NPARTIALS; i++) + partial_stats[i].pos_hits++; +} + +/* Register a miss */ +void +register_miss () +{ + int i; + + statistics.miss++; + for (i = 0; i < NPARTIALS; i++) + partial_stats[i].miss++; +} + + + +/* Scan the cache looking for NAME inside DIR. If we don't know + anything entry at all, then return 0. If the entry is confirmed to + not exist, then return -1. Otherwise, return NP for the entry, with + a newly allocated reference. For any return value but 0, unlock + DP before returning. */ +struct node * +check_lookup_cache (struct node *dir, char *name) +{ + struct lookup_cache *c; + + spin_lock (&cache_lock); + + c = find_cache (dir->nn->handle.data, dir->nn->handle.size, + name, strlen (name)); + if (c) + { + int timeout = c->node_cache_len + ? name_cache_timeout + : name_cache_neg_timeout; + + /* Make sure the entry is still usable; if not, zap it now. */ + if (mapped_time->seconds - c->cache_stamp >= timeout) + { + register_neg_hit (c->stati); + c->name_len = 0; + cacheq_make_lru (&lookup_cache, c); + spin_unlock (&cache_lock); + return 0; + } + + cacheq_make_mru (&lookup_cache, c); /* Record C as recently used. */ + + if (c->node_cache_len == 0) + /* A negative cache entry. */ + { + register_neg_hit (c->stati); + spin_unlock (&cache_lock); + mutex_unlock (&dir->lock); + return (struct node *)-1; + } + else + { + struct node *np; + char handle[NFS3_FHSIZE]; + size_t len; + + register_pos_hit (c->stati); + mutex_unlock (&dir->lock); + + bcopy (c->node_cache_fh, handle, c->node_cache_len); + len = c->node_cache_len; + + spin_unlock (&cache_lock); + + lookup_fhandle (handle, len, &np); + + return np; + } + } + + register_miss (); + spin_unlock (&cache_lock); + + return 0; +} diff --git a/nfs/nfs.c b/nfs/nfs.c index 5ccf7186..f71e82ca 100644 --- a/nfs/nfs.c +++ b/nfs/nfs.c @@ -371,6 +371,18 @@ xdr_decode_64bit (int *p, long long *n) return p; } +/* Decode *P into an fhandle and look up the associated node. Return + the address of the following data. */ +int * +xdr_decode_fhandle (int *p, struct node **npp) +{ + size_t len; + + len = protocol_version == 2 ? NFS2_FHSIZE : ntohl (*p++); + lookup_fhandle (p, len, npp); + return p + len / sizeof (int); +} + /* Decode *P into a stat structure; return the address of the following data. */ int * diff --git a/nfs/nfs.h b/nfs/nfs.h index 51cd3e46..5a3dd8a9 100644 --- a/nfs/nfs.h +++ b/nfs/nfs.h @@ -88,6 +88,12 @@ extern int stat_timeout; /* How long to keep around file contents caches */ extern int cache_timeout; +/* How long to keep around positive dir cache entries */ +extern int name_cache_timeout; + +/* How long to keep around negative dir cache entries */ +extern int name_cache_neg_timeout; + /* How long to wait for replies before re-sending RPC's. */ extern int initial_transmit_timeout; extern int max_transmit_timeout; @@ -160,6 +166,7 @@ int *xdr_encode_sattr_stat (int *, struct stat *); int *xdr_encode_create_state (int *, mode_t, uid_t); int *xdr_decode_fattr (int *, struct stat *); int *xdr_decode_string (int *, char *); +int *xdr_decode_fhandle (int *, struct node **); int *nfs_initialize_rpc (int, struct iouser *, size_t, void **, struct node *, uid_t); error_t nfs_error_trans (int); @@ -177,5 +184,10 @@ void timeout_service_thread (void); void rpc_receive_thread (void); /* cache.c */ -int *lookup_fhandle (int *, struct node **); +void lookup_fhandle (void *, size_t, struct node **); int *recache_handle (int *, struct node *); + +/* name-cache.c */ +void enter_lookup_cache (char *, size_t, struct node *, char *); +void purge_lookup_cache (struct node *, char *, size_t); +struct node *check_lookup_cache (struct node *, char *); diff --git a/nfs/ops.c b/nfs/ops.c index 877b697f..d9060154 100644 --- a/nfs/ops.c +++ b/nfs/ops.c @@ -543,6 +543,9 @@ verify_nonexistent (struct iouser *cred, struct node *dir, void *rpcbuf; error_t err; + /* Don't use the lookup cache for this; we want a full sync to + get as close to real exclusive create behavior as possible. */ + assert (protocol_version == 2); p = nfs_initialize_rpc (NFSPROC_LOOKUP (protocol_version), @@ -569,12 +572,32 @@ netfs_attempt_lookup (struct iouser *cred, struct node *np, int *p; void *rpcbuf; error_t err; + char dirhandle[NFS3_FHSIZE]; + size_t dirlen; + + /* Check the cache first. */ + *newnp = check_lookup_cache (np, name); + if (*newnp) + { + if (*newnp == (struct node *) -1) + { + *newnp = 0; + return ENOENT; + } + else + return 0; + } p = nfs_initialize_rpc (NFSPROC_LOOKUP (protocol_version), cred, 0, &rpcbuf, np, -1); p = xdr_encode_fhandle (p, &np->nn->handle); p = xdr_encode_string (p, name); + /* Remember the directory handle for later cache use. */ + + dirlen = np->nn->handle.size; + bcopy (np->nn->handle.data, dirhandle, dirlen); + mutex_unlock (&np->lock); err = conduct_rpc (&rpcbuf, &p); @@ -583,7 +606,7 @@ netfs_attempt_lookup (struct iouser *cred, struct node *np, err = nfs_error_trans (ntohl (*p++)); if (!err) { - p = lookup_fhandle (p, newnp); + p = xdr_decode_fhandle (p, newnp); p = process_returned_stat (*newnp, p, 1); } if (err) @@ -602,6 +625,9 @@ netfs_attempt_lookup (struct iouser *cred, struct node *np, else *newnp = 0; + /* Notify the cache of the hit or miss. */ + enter_lookup_cache (dirhandle, dirlen, *newnp, name); + free (rpcbuf); return err; @@ -628,6 +654,8 @@ netfs_attempt_mkdir (struct iouser *cred, struct node *np, mode &= ~S_ISUID; } + purge_lookup_cache (np, name, strlen (name)); + p = nfs_initialize_rpc (NFSPROC_MKDIR (protocol_version), cred, 0, &rpcbuf, np, -1); p = xdr_encode_fhandle (p, &np->nn->handle); @@ -638,7 +666,7 @@ netfs_attempt_mkdir (struct iouser *cred, struct node *np, if (!err) err = nfs_error_trans (ntohl (*p++)); - p = lookup_fhandle (p, &newnp); + p = xdr_decode_fhandle (p, &newnp); p = process_returned_stat (newnp, p, 1); /* Did we set the owner correctly? If not, try, but ignore failures. */ @@ -664,6 +692,8 @@ netfs_attempt_rmdir (struct iouser *cred, struct node *np, /* Should we do the same sort of thing here as with attempt_unlink? */ + purge_lookup_cache (np, name, strlen (name)); + p = nfs_initialize_rpc (NFSPROC_RMDIR (protocol_version), cred, 0, &rpcbuf, np, -1); p = xdr_encode_fhandle (p, &np->nn->handle); @@ -712,6 +742,8 @@ netfs_attempt_link (struct iouser *cred, struct node *dir, mutex_unlock (&np->lock); mutex_lock (&dir->lock); + purge_lookup_cache (dir, name, strlen (name)); + p = xdr_encode_fhandle (p, &dir->nn->handle); p = xdr_encode_string (p, name); @@ -755,6 +787,8 @@ netfs_attempt_link (struct iouser *cred, struct node *dir, mutex_unlock (&np->lock); mutex_lock (&dir->lock); + + purge_lookup_cache (dir, name, strlen (name)); err = conduct_rpc (&rpcbuf, &p); if (!err) { @@ -840,6 +874,7 @@ netfs_attempt_link (struct iouser *cred, struct node *dir, mutex_unlock (&np->lock); mutex_lock (&dir->lock); + purge_lookup_cache (dir, name, strlen (name)); err = conduct_rpc (&rpcbuf, &p); if (!err) err = nfs_error_trans (ntohl (*p++)); @@ -878,6 +913,7 @@ netfs_attempt_link (struct iouser *cred, struct node *dir, } mutex_unlock (&np->lock); + purge_lookup_cache (dir, name, strlen (name)); err = conduct_rpc (&rpcbuf, &p); if (!err) { @@ -998,6 +1034,8 @@ netfs_attempt_create_file (struct iouser *cred, struct node *np, } } + purge_lookup_cache (np, name, strlen (name)); + p = nfs_initialize_rpc (NFSPROC_CREATE (protocol_version), cred, 0, &rpcbuf, np, -1); p = xdr_encode_fhandle (p, &np->nn->handle); @@ -1024,7 +1062,7 @@ netfs_attempt_create_file (struct iouser *cred, struct node *np, err = nfs_error_trans (ntohl (*p++)); if (!err) { - p = lookup_fhandle (p, newnp); + p = xdr_decode_fhandle (p, newnp); p = process_returned_stat (*newnp, p, 1); } if (err) @@ -1112,6 +1150,9 @@ netfs_attempt_unlink (struct iouser *cred, struct node *dir, netfs_nput (np); mutex_lock (&dir->lock); + + purge_lookup_cache (dir, name, strlen (name)); + p = nfs_initialize_rpc (NFSPROC_REMOVE (protocol_version), cred, 0, &rpcbuf, dir, -1); p = xdr_encode_fhandle (p, &dir->nn->handle); @@ -1145,6 +1186,7 @@ netfs_attempt_rename (struct iouser *cred, struct node *fromdir, return EOPNOTSUPP; /* XXX */ mutex_lock (&fromdir->lock); + purge_lookup_cache (fromdir, fromname, strlen (fromname)); p = nfs_initialize_rpc (NFSPROC_RENAME (protocol_version), cred, 0, &rpcbuf, fromdir, -1); p = xdr_encode_fhandle (p, &fromdir->nn->handle); @@ -1152,6 +1194,7 @@ netfs_attempt_rename (struct iouser *cred, struct node *fromdir, mutex_unlock (&fromdir->lock); mutex_lock (&todir->lock); + purge_lookup_cache (todir, toname, strlen (toname)); p = xdr_encode_fhandle (p, &todir->nn->handle); p = xdr_encode_string (p, toname); mutex_unlock (&todir->lock); diff --git a/nfs/rpc.c b/nfs/rpc.c index 8068e0ff..90d534ba 100644 --- a/nfs/rpc.c +++ b/nfs/rpc.c @@ -1,5 +1,5 @@ /* SunRPC management for NFS client - Copyright (C) 1994, 1995, 1996 Free Software Foundation + Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -368,8 +368,10 @@ rpc_receive_thread () break; } } +#if notanymore if (!r) fprintf (stderr, "NFS dropping reply xid %d\n", xid); +#endif mutex_unlock (&outstanding_lock); } } -- cgit v1.2.3