diff options
| author | Neil Brown <neilb@cse.unsw.edu.au> | 2003-06-17 06:38:50 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2003-06-17 06:38:50 -0700 |
| commit | 74001bcdb263608b699b7be5a8955cd5910045d2 (patch) | |
| tree | 005068e901d7d33e120b1b0fe71b88d9837aa45f /net | |
| parent | e927119b1953543ab677e0e74eb95cc39beb1fee (diff) | |
[PATCH] kNFSd: Assorted fixed for NFS export cache
The most significant fix is cleaning up properly when
nfs service is stopped.
Also fix some refcounting problems and other little bits.
Diffstat (limited to 'net')
| -rw-r--r-- | net/sunrpc/cache.c | 40 | ||||
| -rw-r--r-- | net/sunrpc/svc.c | 2 | ||||
| -rw-r--r-- | net/sunrpc/svcauth_unix.c | 6 | ||||
| -rw-r--r-- | net/sunrpc/svcsock.c | 4 |
4 files changed, 41 insertions, 11 deletions
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 9a8c6b39f18c..aa85c0b5e250 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -310,14 +310,17 @@ int cache_clean(void) cp = & current_detail->hash_table[current_index]; ch = *cp; for (; ch; cp= & ch->next, ch= *cp) { - if (atomic_read(&ch->refcnt)) - continue; - if (ch->expiry_time < get_seconds() - || ch->last_refresh < current_detail->flush_time - ) - break; if (current_detail->nextcheck > ch->expiry_time) current_detail->nextcheck = ch->expiry_time+1; + if (ch->expiry_time >= get_seconds() + && ch->last_refresh >= current_detail->flush_time + ) + continue; + if (test_and_clear_bit(CACHE_PENDING, &ch->flags)) + queue_loose(current_detail, ch); + + if (atomic_read(&ch->refcnt)) + continue; } if (ch) { cache_get(ch); @@ -467,6 +470,31 @@ void cache_revisit_request(struct cache_head *item) } } +void cache_clean_deferred(void *owner) +{ + struct cache_deferred_req *dreq, *tmp; + struct list_head pending; + + + INIT_LIST_HEAD(&pending); + spin_lock(&cache_defer_lock); + + list_for_each_entry_safe(dreq, tmp, &cache_defer_list, recent) { + if (dreq->owner == owner) { + list_del(&dreq->hash); + list_move(&dreq->recent, &pending); + cache_defer_cnt--; + } + } + spin_unlock(&cache_defer_lock); + + while (!list_empty(&pending)) { + dreq = list_entry(pending.next, struct cache_deferred_req, recent); + list_del_init(&dreq->recent); + dreq->revisit(dreq, 1); + } +} + /* * communicate with user-space * diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index beadf395b863..686d5cbdb7a7 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -98,6 +98,8 @@ svc_destroy(struct svc_serv *serv) sk_list); svc_delete_socket(svsk); } + + cache_clean_deferred(serv); /* Unregister service with the portmapper */ svc_register(serv, 0, 0); diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 3397f58011e7..1aee12c44c99 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c @@ -195,12 +195,12 @@ static int ip_map_parse(struct cache_detail *cd, ipm.m_addr.s_addr = htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4); ipm.h.flags = 0; - if (dom) + if (dom) { ipm.m_client = container_of(dom, struct unix_domain, h); - else + ipm.m_add_change = ipm.m_client->addr_changes; + } else set_bit(CACHE_NEGATIVE, &ipm.h.flags); ipm.h.expiry_time = expiry; - ipm.m_add_change = ipm.m_client->addr_changes; ipmp = ip_map_lookup(&ipm, 1); if (ipmp) diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index f1230fdafa93..b17f4494cd5e 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -1443,7 +1443,7 @@ svc_makesock(struct svc_serv *serv, int protocol, unsigned short port) static void svc_revisit(struct cache_deferred_req *dreq, int too_many) { struct svc_deferred_req *dr = container_of(dreq, struct svc_deferred_req, handle); - struct svc_serv *serv = dr->serv; + struct svc_serv *serv = dreq->owner; struct svc_sock *svsk; if (too_many) { @@ -1481,7 +1481,7 @@ svc_defer(struct cache_req *req) if (dr == NULL) return NULL; - dr->serv = rqstp->rq_server; + dr->handle.owner = rqstp->rq_server; dr->prot = rqstp->rq_prot; dr->addr = rqstp->rq_addr; dr->argslen = rqstp->rq_arg.len >> 2; |
