summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/lockd/svc4proc.c18
-rw-r--r--fs/lockd/svcproc.c14
-rw-r--r--fs/lockd/svcsubs.c27
-rw-r--r--fs/nfsd/lockd.c50
-rw-r--r--include/linux/lockd/bind.h8
-rw-r--r--include/linux/lockd/lockd.h2
6 files changed, 82 insertions, 37 deletions
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index 55b6dcc56db1..4ceb27cc72e4 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -73,9 +73,21 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
no_locks:
nlmsvc_release_host(host);
- if (error)
- return error;
- return nlm_lck_denied_nolocks;
+ switch (error) {
+ case nlm_granted:
+ return nlm_lck_denied_nolocks;
+ case nlm__int__stale_fh:
+ return nlm4_stale_fh;
+ case nlm__int__failed:
+ return nlm4_failed;
+ default:
+ if (be32_to_cpu(error) >= 30000) {
+ pr_warn_once("lockd: unhandled internal status %u\n",
+ be32_to_cpu(error));
+ return nlm4_failed;
+ }
+ return error;
+ }
}
/*
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 27ed71935e45..272c8f36ed2a 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -39,8 +39,20 @@ static inline __be32 cast_status(__be32 status)
#else
static inline __be32 cast_status(__be32 status)
{
- if (status == nlm__int__deadlock)
+ switch (status) {
+ case nlm__int__deadlock:
status = nlm_lck_denied;
+ break;
+ case nlm__int__stale_fh:
+ case nlm__int__failed:
+ status = nlm_lck_denied_nolocks;
+ break;
+ default:
+ if (be32_to_cpu(status) >= 30000)
+ pr_warn_once("lockd: unhandled internal status %u\n",
+ be32_to_cpu(status));
+ break;
+ }
return status;
}
#endif
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index dd0214dcb695..967739d2aa90 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -87,14 +87,29 @@ static __be32 nlm_do_fopen(struct svc_rqst *rqstp,
struct nlm_file *file, int mode)
{
struct file **fp = &file->f_file[mode];
- __be32 nfserr;
+ __be32 nlmerr = nlm_granted;
+ int error;
if (*fp)
- return 0;
- nfserr = nlmsvc_ops->fopen(rqstp, &file->f_handle, fp, mode);
- if (nfserr)
- dprintk("lockd: open failed (error %d)\n", nfserr);
- return nfserr;
+ return nlmerr;
+
+ error = nlmsvc_ops->fopen(rqstp, &file->f_handle, fp, mode);
+ if (error) {
+ dprintk("lockd: open failed (errno %d)\n", error);
+ switch (error) {
+ case -EWOULDBLOCK:
+ nlmerr = nlm__int__drop_reply;
+ break;
+ case -ESTALE:
+ nlmerr = nlm__int__stale_fh;
+ break;
+ default:
+ nlmerr = nlm__int__failed;
+ break;
+ }
+ }
+
+ return nlmerr;
}
/*
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 8c230ccd6645..6fe1325815e0 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -14,19 +14,20 @@
#define NFSDDBG_FACILITY NFSDDBG_LOCKD
-#ifdef CONFIG_LOCKD_V4
-#define nlm_stale_fh nlm4_stale_fh
-#define nlm_failed nlm4_failed
-#else
-#define nlm_stale_fh nlm_lck_denied_nolocks
-#define nlm_failed nlm_lck_denied_nolocks
-#endif
-/*
- * Note: we hold the dentry use count while the file is open.
+/**
+ * nlm_fopen - Open an NFSD file
+ * @rqstp: NLM RPC procedure execution context
+ * @f: NFS file handle to be opened
+ * @filp: OUT: an opened struct file
+ * @flags: the POSIX open flags to use
+ *
+ * nlm_fopen() holds the dentry reference until nlm_fclose() releases it.
+ *
+ * Returns zero on success or a negative errno value if the file
+ * cannot be opened.
*/
-static __be32
-nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp,
- int mode)
+static int nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f,
+ struct file **filp, int flags)
{
__be32 nfserr;
int access;
@@ -47,18 +48,17 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp,
* if NFSEXP_NOAUTHNLM is set. Some older clients use AUTH_NULL
* for NLM requests.
*/
- access = (mode == O_WRONLY) ? NFSD_MAY_WRITE : NFSD_MAY_READ;
+ access = (flags == O_WRONLY) ? NFSD_MAY_WRITE : NFSD_MAY_READ;
access |= NFSD_MAY_NLM | NFSD_MAY_OWNER_OVERRIDE | NFSD_MAY_BYPASS_GSS;
nfserr = nfsd_open(rqstp, &fh, S_IFREG, access, filp);
fh_put(&fh);
- /* 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;
+ break;
case nfserr_jukebox:
- /* this error can indicate a presence of a conflicting
+ /*
+ * This error can indicate a presence of a conflicting
* delegation to an NLM lock request. Options are:
* (1) For now, drop this request and make the client
* retry. When delegation is returned, client's lock retry
@@ -66,19 +66,25 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp,
* (2) NLM4_DENIED as per "spec" signals to the client
* that the lock is unavailable now but client can retry.
* Linux client implementation does not. It treats
- * NLM4_DENIED same as NLM4_FAILED and errors the request.
+ * NLM4_DENIED same as NLM4_FAILED and fails the request.
* (3) For the future, treat this as blocked lock and try
* to callback when the delegation is returned but might
* not have a proper lock request to block on.
*/
- return nlm__int__drop_reply;
+ return -EWOULDBLOCK;
case nfserr_stale:
- return nlm_stale_fh;
+ return -ESTALE;
default:
- return nlm_failed;
+ return -ENOLCK;
}
+
+ return 0;
}
+/**
+ * nlm_fclose - Close an NFSD file
+ * @filp: a struct file that was opened by nlm_fopen()
+ */
static void
nlm_fclose(struct file *filp)
{
diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h
index c53c81242e72..2f5dd9e943ee 100644
--- a/include/linux/lockd/bind.h
+++ b/include/linux/lockd/bind.h
@@ -26,11 +26,9 @@ struct rpc_clnt;
* This is the set of functions for lockd->nfsd communication
*/
struct nlmsvc_binding {
- __be32 (*fopen)(struct svc_rqst *,
- struct nfs_fh *,
- struct file **,
- int mode);
- void (*fclose)(struct file *);
+ int (*fopen)(struct svc_rqst *rqstp, struct nfs_fh *f,
+ struct file **filp, int flags);
+ void (*fclose)(struct file *filp);
};
extern const struct nlmsvc_binding *nlmsvc_ops;
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
index 793691912137..195e6ce28f6e 100644
--- a/include/linux/lockd/lockd.h
+++ b/include/linux/lockd/lockd.h
@@ -44,6 +44,8 @@
*/
#define nlm__int__drop_reply cpu_to_be32(30000)
#define nlm__int__deadlock cpu_to_be32(30001)
+#define nlm__int__stale_fh cpu_to_be32(30002)
+#define nlm__int__failed cpu_to_be32(30003)
/*
* Lockd host handle (used both by the client and server personality).