summaryrefslogtreecommitdiffstats
path: root/net/sunrpc/cache.c
diff options
context:
space:
mode:
authorJ.Bruce Fields <bfields@fieldses.org>2006-12-13 00:35:25 -0800
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-13 09:05:54 -0800
commite0bb89ef031f76dcb9c9d920d18b13948f1418da (patch)
tree6016032b160db2cf697eea19cd0f12ace946c7cc /net/sunrpc/cache.c
parent021d3a72459191a76e8e482ee4937ba6bc9fd712 (diff)
downloadlinux-e0bb89ef031f76dcb9c9d920d18b13948f1418da.tar.bz2
[PATCH] knfsd: nfsd: don't drop silently on upcall deferral
To avoid tying up server threads when nfsd makes an upcall (to mountd, to get export options, to idmapd, for nfsv4 name<->id mapping, etc.), we temporarily "drop" the request and save enough information so that we can revisit it later. Certain failures during the deferral process can cause us to really drop the request and never revisit it. This is often less than ideal, and is unacceptable in the NFSv4 case--rfc 3530 forbids the server from dropping a request without also closing the connection. As a first step, we modify the deferral code to return -ETIMEDOUT (which is translated to nfserr_jukebox in the v3 and v4 cases, and remains a drop in the v2 case). Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'net/sunrpc/cache.c')
-rw-r--r--net/sunrpc/cache.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 80aff0474572..824e8534e022 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -34,7 +34,7 @@
#define RPCDBG_FACILITY RPCDBG_CACHE
-static void cache_defer_req(struct cache_req *req, struct cache_head *item);
+static int cache_defer_req(struct cache_req *req, struct cache_head *item);
static void cache_revisit_request(struct cache_head *item);
static void cache_init(struct cache_head *h)
@@ -185,6 +185,7 @@ static int cache_make_upcall(struct cache_detail *detail, struct cache_head *h);
*
* Returns 0 if the cache_head can be used, or cache_puts it and returns
* -EAGAIN if upcall is pending,
+ * -ETIMEDOUT if upcall failed and should be retried,
* -ENOENT if cache entry was negative
*/
int cache_check(struct cache_detail *detail,
@@ -236,7 +237,8 @@ int cache_check(struct cache_detail *detail,
}
if (rv == -EAGAIN)
- cache_defer_req(rqstp, h);
+ if (cache_defer_req(rqstp, h) != 0)
+ rv = -ETIMEDOUT;
if (rv)
cache_put(h, detail);
@@ -523,14 +525,14 @@ static LIST_HEAD(cache_defer_list);
static struct list_head cache_defer_hash[DFR_HASHSIZE];
static int cache_defer_cnt;
-static void cache_defer_req(struct cache_req *req, struct cache_head *item)
+static int cache_defer_req(struct cache_req *req, struct cache_head *item)
{
struct cache_deferred_req *dreq;
int hash = DFR_HASH(item);
dreq = req->defer(req);
if (dreq == NULL)
- return;
+ return -ETIMEDOUT;
dreq->item = item;
dreq->recv_time = get_seconds();
@@ -571,6 +573,7 @@ static void cache_defer_req(struct cache_req *req, struct cache_head *item)
/* must have just been validated... */
cache_revisit_request(item);
}
+ return 0;
}
static void cache_revisit_request(struct cache_head *item)