Skip to content

Commit

Permalink
[PATCH] knfsd: Allow lockd to drop replies as appropriate
Browse files Browse the repository at this point in the history
It is possible for the ->fopen callback from lockd into nfsd to find that an
answer cannot be given straight away (an upcall is needed) and so the request
has to be 'dropped', to be retried later.  That error status is not currently
propagated back.

So:
  Change nlm_fopen to return nlm error codes (rather than a private
  protocol) and define a new nlm_drop_reply code.
  Cause nlm_drop_reply to cause the rpc request to get rpc_drop_reply
  when this error comes back.
  Cause svc_process to drop a request which returns a status of
  rpc_drop_reply.

[akpm@osdl.org: fix warning storm]
Cc: Marc Eshel <eshel@almaden.ibm.com>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
NeilBrown authored and Linus Torvalds committed Oct 17, 2006
1 parent 4481d10 commit d343fce
Show file tree
Hide file tree
Showing 9 changed files with 41 additions and 26 deletions.
12 changes: 6 additions & 6 deletions fs/lockd/svc4proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,

/* Obtain client and file */
if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
return rpc_success;
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;

/* Now check for conflicting locks */
resp->status = nlmsvc_testlock(file, &argp->lock, &resp->lock);
Expand Down Expand Up @@ -126,7 +126,7 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,

/* Obtain client and file */
if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
return rpc_success;
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;

#if 0
/* If supplied state doesn't match current state, we assume it's
Expand Down Expand Up @@ -169,7 +169,7 @@ nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,

/* Obtain client and file */
if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
return rpc_success;
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;

/* Try to cancel request. */
resp->status = nlmsvc_cancel_blocked(file, &argp->lock);
Expand Down Expand Up @@ -202,7 +202,7 @@ nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,

/* Obtain client and file */
if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
return rpc_success;
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;

/* Now try to remove the lock */
resp->status = nlmsvc_unlock(file, &argp->lock);
Expand Down Expand Up @@ -339,7 +339,7 @@ nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,

/* Obtain client and file */
if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
return rpc_success;
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;

/* Now try to create the share */
resp->status = nlmsvc_share_file(host, file, argp);
Expand Down Expand Up @@ -372,7 +372,7 @@ nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,

/* Obtain client and file */
if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
return rpc_success;
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;

/* Now try to lock the file */
resp->status = nlmsvc_unshare_file(host, file, argp);
Expand Down
16 changes: 9 additions & 7 deletions fs/lockd/svcproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
struct nlm_host *host = NULL;
struct nlm_file *file = NULL;
struct nlm_lock *lock = &argp->lock;
u32 error;
u32 error = 0;

/* nfsd callbacks must have been installed for this procedure */
if (!nlmsvc_ops)
Expand Down Expand Up @@ -88,6 +88,8 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
no_locks:
if (host)
nlm_release_host(host);
if (error)
return error;
return nlm_lck_denied_nolocks;
}

Expand Down Expand Up @@ -122,7 +124,7 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,

/* Obtain client and file */
if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
return rpc_success;
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;

/* Now check for conflicting locks */
resp->status = cast_status(nlmsvc_testlock(file, &argp->lock, &resp->lock));
Expand Down Expand Up @@ -153,7 +155,7 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,

/* Obtain client and file */
if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
return rpc_success;
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;

#if 0
/* If supplied state doesn't match current state, we assume it's
Expand Down Expand Up @@ -196,7 +198,7 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,

/* Obtain client and file */
if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
return rpc_success;
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;

/* Try to cancel request. */
resp->status = cast_status(nlmsvc_cancel_blocked(file, &argp->lock));
Expand Down Expand Up @@ -229,7 +231,7 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,

/* Obtain client and file */
if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
return rpc_success;
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;

/* Now try to remove the lock */
resp->status = cast_status(nlmsvc_unlock(file, &argp->lock));
Expand Down Expand Up @@ -368,7 +370,7 @@ nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,

/* Obtain client and file */
if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
return rpc_success;
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;

/* Now try to create the share */
resp->status = cast_status(nlmsvc_share_file(host, file, argp));
Expand Down Expand Up @@ -401,7 +403,7 @@ nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,

/* Obtain client and file */
if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
return rpc_success;
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;

/* Now try to unshare the file */
resp->status = cast_status(nlmsvc_unshare_file(host, file, argp));
Expand Down
6 changes: 0 additions & 6 deletions fs/lockd/svcsubs.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,12 +135,6 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,

out_free:
kfree(file);
#ifdef CONFIG_LOCKD_V4
if (nfserr == 1)
nfserr = nlm4_stale_fh;
else
#endif
nfserr = nlm_lck_denied;
goto out_unlock;
}

Expand Down
14 changes: 8 additions & 6 deletions fs/nfsd/lockd.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,20 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
fh_put(&fh);
rqstp->rq_client = NULL;
exp_readunlock();
/* nlm and nfsd don't share error codes.
* we invent: 0 = no error
* 1 = stale file handle
* 2 = other error
/* We return nlm error codes as nlm doesn't know
* about nfsd, but nfsd does know about nlm..
*/
switch (nfserr) {
case nfs_ok:
return 0;
case nfserr_dropit:
return nlm_drop_reply;
#ifdef CONFIG_LOCKD_V4
case nfserr_stale:
return 1;
return nlm4_stale_fh;
#endif
default:
return 2;
return nlm_lck_denied;
}
}

Expand Down
5 changes: 5 additions & 0 deletions include/linux/lockd/bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
#define LINUX_LOCKD_BIND_H

#include <linux/lockd/nlm.h>
/* need xdr-encoded error codes too, so... */
#include <linux/lockd/xdr.h>
#ifdef CONFIG_LOCKD_V4
#include <linux/lockd/xdr4.h>
#endif

/* Dummy declarations */
struct svc_rqst;
Expand Down
4 changes: 4 additions & 0 deletions include/linux/lockd/xdr.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#include <linux/nfs.h>
#include <linux/sunrpc/xdr.h>

struct svc_rqst;

#define NLM_MAXCOOKIELEN 32
#define NLM_MAXSTRLEN 1024

Expand All @@ -22,6 +24,8 @@
#define nlm_lck_blocked __constant_htonl(NLM_LCK_BLOCKED)
#define nlm_lck_denied_grace_period __constant_htonl(NLM_LCK_DENIED_GRACE_PERIOD)

#define nlm_drop_reply __constant_htonl(30000)

/* Lock info passed via NLM */
struct nlm_lock {
char * caller;
Expand Down
4 changes: 3 additions & 1 deletion include/linux/sunrpc/msg_prot.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ enum rpc_accept_stat {
RPC_PROG_MISMATCH = 2,
RPC_PROC_UNAVAIL = 3,
RPC_GARBAGE_ARGS = 4,
RPC_SYSTEM_ERR = 5
RPC_SYSTEM_ERR = 5,
/* internal use only */
RPC_DROP_REPLY = 60000,
};

enum rpc_reject_stat {
Expand Down
1 change: 1 addition & 0 deletions include/linux/sunrpc/xdr.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ struct xdr_buf {
#define rpc_proc_unavail __constant_htonl(RPC_PROC_UNAVAIL)
#define rpc_garbage_args __constant_htonl(RPC_GARBAGE_ARGS)
#define rpc_system_err __constant_htonl(RPC_SYSTEM_ERR)
#define rpc_drop_reply __constant_htonl(RPC_DROP_REPLY)

#define rpc_auth_ok __constant_htonl(RPC_AUTH_OK)
#define rpc_autherr_badcred __constant_htonl(RPC_AUTH_BADCRED)
Expand Down
5 changes: 5 additions & 0 deletions net/sunrpc/svc.c
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,11 @@ svc_process(struct svc_rqst *rqstp)
*statp = procp->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);

/* Encode reply */
if (*statp == rpc_drop_reply) {
if (procp->pc_release)
procp->pc_release(rqstp, NULL, rqstp->rq_resp);
goto dropit;
}
if (*statp == rpc_success && (xdr = procp->pc_encode)
&& !xdr(rqstp, resv->iov_base+resv->iov_len, rqstp->rq_resp)) {
dprintk("svc: failed to encode reply\n");
Expand Down

0 comments on commit d343fce

Please sign in to comment.