summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorNeil Brown <neilb@cse.unsw.edu.au>2003-06-17 06:38:50 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2003-06-17 06:38:50 -0700
commit74001bcdb263608b699b7be5a8955cd5910045d2 (patch)
tree005068e901d7d33e120b1b0fe71b88d9837aa45f /net
parente927119b1953543ab677e0e74eb95cc39beb1fee (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.c40
-rw-r--r--net/sunrpc/svc.c2
-rw-r--r--net/sunrpc/svcauth_unix.c6
-rw-r--r--net/sunrpc/svcsock.c4
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;