Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=e0bb89ef031f76dcb9c9d920d18b13948f1418da
Commit:     e0bb89ef031f76dcb9c9d920d18b13948f1418da
Parent:     021d3a72459191a76e8e482ee4937ba6bc9fd712
Author:     J.Bruce Fields <[EMAIL PROTECTED]>
AuthorDate: Wed Dec 13 00:35:25 2006 -0800
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Wed Dec 13 09:05:54 2006 -0800

    [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 <[EMAIL PROTECTED]>
    Signed-off-by: Neil Brown <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 fs/nfsd/export.c                  |   11 ++++++++---
 fs/nfsd/nfsfh.c                   |    6 ++++--
 fs/nfsd/vfs.c                     |    2 +-
 net/sunrpc/auth_gss/svcauth_gss.c |    2 +-
 net/sunrpc/cache.c                |   11 +++++++----
 net/sunrpc/svcauth_unix.c         |    1 +
 6 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index b0591cd..1137d09 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -787,15 +787,20 @@ exp_get_by_name(svc_client *clp, struct vfsmount *mnt, 
struct dentry *dentry,
        key.ex_dentry = dentry;
 
        exp = svc_export_lookup(&key);
-       if (exp != NULL) 
-               switch (cache_check(&svc_export_cache, &exp->h, reqp)) {
+       if (exp != NULL)  {
+               int err;
+
+               err = cache_check(&svc_export_cache, &exp->h, reqp);
+               switch (err) {
                case 0: break;
                case -EAGAIN:
-                       exp = ERR_PTR(-EAGAIN);
+               case -ETIMEDOUT:
+                       exp = ERR_PTR(err);
                        break;
                default:
                        exp = NULL;
                }
+       }
 
        return exp;
 }
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 727ab3b..b06bf9f 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -169,9 +169,11 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int 
type, int access)
                        exp = exp_find(rqstp->rq_client, 0, tfh, 
&rqstp->rq_chandle);
                }
 
-               error = nfserr_dropit;
-               if (IS_ERR(exp) && PTR_ERR(exp) == -EAGAIN)
+               if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN
+                               || PTR_ERR(exp) == -ETIMEDOUT)) {
+                       error = nfserrno(PTR_ERR(exp));
                        goto out;
+               }
 
                error = nfserr_stale; 
                if (!exp || IS_ERR(exp))
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 4883d75..7a79c23 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -99,7 +99,7 @@ static struct raparm_hbucket  raparm_hash[RAPARM_HASH_SIZE];
 /* 
  * Called from nfsd_lookup and encode_dirent. Check if we have crossed 
  * a mount point.
- * Returns -EAGAIN leaving *dpp and *expp unchanged, 
+ * Returns -EAGAIN or -ETIMEDOUT leaving *dpp and *expp unchanged,
  *  or nfs_ok having possibly changed *dpp and *expp
  */
 int
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c 
b/net/sunrpc/auth_gss/svcauth_gss.c
index 3bf3520..066c64a 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -1066,7 +1066,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
                }
                switch(cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle)) {
                case -EAGAIN:
-                       goto drop;
+               case -ETIMEDOUT:
                case -ENOENT:
                        goto drop;
                case 0:
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 80aff04..824e853 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)
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index a0a953a..177f816 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -435,6 +435,7 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
                default:
                        BUG();
                case -EAGAIN:
+               case -ETIMEDOUT:
                        return SVC_DROP;
                case -ENOENT:
                        return SVC_DENIED;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to