diff options
Diffstat (limited to 'nfs')
-rw-r--r-- | nfs/cache.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/nfs/cache.c b/nfs/cache.c index 3a14ef27..9b76fd73 100644 --- a/nfs/cache.c +++ b/nfs/cache.c @@ -20,10 +20,84 @@ #include "nfs.h" +#include <string.h> +#define CACHESIZE 512 +static struct node *nodehash [CACHESIZE]; +static inline int +hash (void *fhandle) +{ + unsigned int h = 0; + int i; + for (i = 0; i < NFS_FHSIZE; i++) + h += ((char *)fhandle)[i]; + + return h % CACHESIZE; +} + +struct node * +lookup_fhandle (void *fhandle) +{ + struct node *np; + struct netnode *nn; + int h = hash (fhandle); + spin_lock (&netfs_node_refcnt_lock); + for (np = nodehash[h]; np; np = np->nn->hnext) + { + if (bcmp (np->nn->handle, fhandle, NFS_FHSIZE) != 0) + continue; + + np->references++; + spin_unlock (&netfs_node_refcnt_lock); + mutex_lock (&np->lock); + return np; + } + + nn = malloc (sizeof (struct netnode)); + bcopy (fhandle, nn->handle, NFS_FHSIZE); + nn->stat_updated = 0; + np = netfs_make_node (nn); + mutex_lock (&np->lock); + nn->hnext = nodehash[h]; + if (nn->hnext) + nn->hnext->nn->hprevp = &nn->hnext; + nn->hprevp = &nodehash[h]; + + spin_unlock (&netfs_node_refcnt_lock); + return np; +} + +void +netfs_node_norefs (struct node *np) +{ + if (np->nn->dead_dir) + { + np->references++; + spin_unlock (&diskfs_node_refcnt_lock); + + netfs_attempt_unlink ((struct netcred *)-1, np->nn->dead_dir, + np->nn->dead_name); + diskfs_nrele (np->nn->dead_dir); + free (np->nn->dead_name); + np->nn->dead_dir = 0; + np->nn->dead_name = 0; + diskfs_nput (np); + + /* Caller expects us to leave this locked... */ + spin_lock (&diskfs_node_refcnt_lock); + } + else + { + *np->nn->hprevp = np->nn->hnext; + if (np->nn->hnext) + np->nn->hnext->nn->hprevp = np->nn->hprevp; + free (np->nn); + free (np); + } +} |