Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

lockd: Have nlm_fopen() return errno values

The nlm_fopen() function is part of the API between nfsd and lockd.

Currently its return value is an on-the-wire NLM status code. But
that forces NFSD to include NLM wire protocol definitions despite
having no other dependency on the NLM wire protocol.

In addition, a CONFIG_LOCKD_V4 Kconfig symbol appears in the middle
of NFSD source code.

Refactor: Let's not use on-the-wire values as part of a high-level
API between two Linux kernel modules. That's what we have errno for,
right?

And, instead of simply moving the CONFIG_LOCKD_V4 check, we can get
rid of it entirely and let the decision of what actual NLM status
code goes on the wire to be left up to NLM version-specific code.

Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

+82 -37
+15 -3
fs/lockd/svc4proc.c
··· 73 73 74 74 no_locks: 75 75 nlmsvc_release_host(host); 76 - if (error) 77 - return error; 78 - return nlm_lck_denied_nolocks; 76 + switch (error) { 77 + case nlm_granted: 78 + return nlm_lck_denied_nolocks; 79 + case nlm__int__stale_fh: 80 + return nlm4_stale_fh; 81 + case nlm__int__failed: 82 + return nlm4_failed; 83 + default: 84 + if (be32_to_cpu(error) >= 30000) { 85 + pr_warn_once("lockd: unhandled internal status %u\n", 86 + be32_to_cpu(error)); 87 + return nlm4_failed; 88 + } 89 + return error; 90 + } 79 91 } 80 92 81 93 /*
+13 -1
fs/lockd/svcproc.c
··· 39 39 #else 40 40 static inline __be32 cast_status(__be32 status) 41 41 { 42 - if (status == nlm__int__deadlock) 42 + switch (status) { 43 + case nlm__int__deadlock: 43 44 status = nlm_lck_denied; 45 + break; 46 + case nlm__int__stale_fh: 47 + case nlm__int__failed: 48 + status = nlm_lck_denied_nolocks; 49 + break; 50 + default: 51 + if (be32_to_cpu(status) >= 30000) 52 + pr_warn_once("lockd: unhandled internal status %u\n", 53 + be32_to_cpu(status)); 54 + break; 55 + } 44 56 return status; 45 57 } 46 58 #endif
+21 -6
fs/lockd/svcsubs.c
··· 87 87 struct nlm_file *file, int mode) 88 88 { 89 89 struct file **fp = &file->f_file[mode]; 90 - __be32 nfserr; 90 + __be32 nlmerr = nlm_granted; 91 + int error; 91 92 92 93 if (*fp) 93 - return 0; 94 - nfserr = nlmsvc_ops->fopen(rqstp, &file->f_handle, fp, mode); 95 - if (nfserr) 96 - dprintk("lockd: open failed (error %d)\n", nfserr); 97 - return nfserr; 94 + return nlmerr; 95 + 96 + error = nlmsvc_ops->fopen(rqstp, &file->f_handle, fp, mode); 97 + if (error) { 98 + dprintk("lockd: open failed (errno %d)\n", error); 99 + switch (error) { 100 + case -EWOULDBLOCK: 101 + nlmerr = nlm__int__drop_reply; 102 + break; 103 + case -ESTALE: 104 + nlmerr = nlm__int__stale_fh; 105 + break; 106 + default: 107 + nlmerr = nlm__int__failed; 108 + break; 109 + } 110 + } 111 + 112 + return nlmerr; 98 113 } 99 114 100 115 /*
+28 -22
fs/nfsd/lockd.c
··· 14 14 15 15 #define NFSDDBG_FACILITY NFSDDBG_LOCKD 16 16 17 - #ifdef CONFIG_LOCKD_V4 18 - #define nlm_stale_fh nlm4_stale_fh 19 - #define nlm_failed nlm4_failed 20 - #else 21 - #define nlm_stale_fh nlm_lck_denied_nolocks 22 - #define nlm_failed nlm_lck_denied_nolocks 23 - #endif 24 - /* 25 - * Note: we hold the dentry use count while the file is open. 17 + /** 18 + * nlm_fopen - Open an NFSD file 19 + * @rqstp: NLM RPC procedure execution context 20 + * @f: NFS file handle to be opened 21 + * @filp: OUT: an opened struct file 22 + * @flags: the POSIX open flags to use 23 + * 24 + * nlm_fopen() holds the dentry reference until nlm_fclose() releases it. 25 + * 26 + * Returns zero on success or a negative errno value if the file 27 + * cannot be opened. 26 28 */ 27 - static __be32 28 - nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp, 29 - int mode) 29 + static int nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, 30 + struct file **filp, int flags) 30 31 { 31 32 __be32 nfserr; 32 33 int access; ··· 48 47 * if NFSEXP_NOAUTHNLM is set. Some older clients use AUTH_NULL 49 48 * for NLM requests. 50 49 */ 51 - access = (mode == O_WRONLY) ? NFSD_MAY_WRITE : NFSD_MAY_READ; 50 + access = (flags == O_WRONLY) ? NFSD_MAY_WRITE : NFSD_MAY_READ; 52 51 access |= NFSD_MAY_NLM | NFSD_MAY_OWNER_OVERRIDE | NFSD_MAY_BYPASS_GSS; 53 52 nfserr = nfsd_open(rqstp, &fh, S_IFREG, access, filp); 54 53 fh_put(&fh); 55 - /* We return nlm error codes as nlm doesn't know 56 - * about nfsd, but nfsd does know about nlm.. 57 - */ 54 + 58 55 switch (nfserr) { 59 56 case nfs_ok: 60 - return 0; 57 + break; 61 58 case nfserr_jukebox: 62 - /* this error can indicate a presence of a conflicting 59 + /* 60 + * This error can indicate a presence of a conflicting 63 61 * delegation to an NLM lock request. Options are: 64 62 * (1) For now, drop this request and make the client 65 63 * retry. When delegation is returned, client's lock retry ··· 66 66 * (2) NLM4_DENIED as per "spec" signals to the client 67 67 * that the lock is unavailable now but client can retry. 68 68 * Linux client implementation does not. It treats 69 - * NLM4_DENIED same as NLM4_FAILED and errors the request. 69 + * NLM4_DENIED same as NLM4_FAILED and fails the request. 70 70 * (3) For the future, treat this as blocked lock and try 71 71 * to callback when the delegation is returned but might 72 72 * not have a proper lock request to block on. 73 73 */ 74 - return nlm__int__drop_reply; 74 + return -EWOULDBLOCK; 75 75 case nfserr_stale: 76 - return nlm_stale_fh; 76 + return -ESTALE; 77 77 default: 78 - return nlm_failed; 78 + return -ENOLCK; 79 79 } 80 + 81 + return 0; 80 82 } 81 83 84 + /** 85 + * nlm_fclose - Close an NFSD file 86 + * @filp: a struct file that was opened by nlm_fopen() 87 + */ 82 88 static void 83 89 nlm_fclose(struct file *filp) 84 90 {
+3 -5
include/linux/lockd/bind.h
··· 26 26 * This is the set of functions for lockd->nfsd communication 27 27 */ 28 28 struct nlmsvc_binding { 29 - __be32 (*fopen)(struct svc_rqst *, 30 - struct nfs_fh *, 31 - struct file **, 32 - int mode); 33 - void (*fclose)(struct file *); 29 + int (*fopen)(struct svc_rqst *rqstp, struct nfs_fh *f, 30 + struct file **filp, int flags); 31 + void (*fclose)(struct file *filp); 34 32 }; 35 33 36 34 extern const struct nlmsvc_binding *nlmsvc_ops;
+2
include/linux/lockd/lockd.h
··· 44 44 */ 45 45 #define nlm__int__drop_reply cpu_to_be32(30000) 46 46 #define nlm__int__deadlock cpu_to_be32(30001) 47 + #define nlm__int__stale_fh cpu_to_be32(30002) 48 + #define nlm__int__failed cpu_to_be32(30003) 47 49 48 50 /* 49 51 * Lockd host handle (used both by the client and server personality).