summaryrefslogtreecommitdiff
path: root/fs/lockd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/lockd')
-rw-r--r--fs/lockd/Makefile19
-rw-r--r--fs/lockd/clnt4xdr.c42
-rw-r--r--fs/lockd/clntlock.c2
-rw-r--r--fs/lockd/clntproc.c17
-rw-r--r--fs/lockd/clntxdr.c44
-rw-r--r--fs/lockd/host.c4
-rw-r--r--fs/lockd/lockd.h67
-rw-r--r--fs/lockd/mon.c2
-rw-r--r--fs/lockd/nlm3xdr_gen.c686
-rw-r--r--fs/lockd/nlm3xdr_gen.h30
-rw-r--r--fs/lockd/nlm4xdr_gen.c75
-rw-r--r--fs/lockd/nlm4xdr_gen.h4
-rw-r--r--fs/lockd/share.h12
-rw-r--r--fs/lockd/svc.c4
-rw-r--r--fs/lockd/svc4proc.c136
-rw-r--r--fs/lockd/svclock.c80
-rw-r--r--fs/lockd/svcproc.c1727
-rw-r--r--fs/lockd/svcshare.c44
-rw-r--r--fs/lockd/svcsubs.c141
-rw-r--r--fs/lockd/svcxdr.h142
-rw-r--r--fs/lockd/trace.h16
-rw-r--r--fs/lockd/xdr.c354
-rw-r--r--fs/lockd/xdr.h39
23 files changed, 2311 insertions, 1376 deletions
diff --git a/fs/lockd/Makefile b/fs/lockd/Makefile
index 808f0f2a7be1..3f9569d3ba0e 100644
--- a/fs/lockd/Makefile
+++ b/fs/lockd/Makefile
@@ -8,7 +8,8 @@ ccflags-y += -I$(src) # needed for trace events
obj-$(CONFIG_LOCKD) += lockd.o
lockd-y := clntlock.o clntproc.o clntxdr.o host.o svc.o svclock.o \
- svcshare.o svcproc.o svcsubs.o mon.o trace.o xdr.o netlink.o
+ svcshare.o svcproc.o svcsubs.o mon.o trace.o netlink.o \
+ nlm3xdr_gen.o
lockd-$(CONFIG_LOCKD_V4) += clnt4xdr.o svc4proc.o nlm4xdr_gen.o
lockd-$(CONFIG_PROC_FS) += procfs.o
@@ -25,17 +26,27 @@ lockd-$(CONFIG_PROC_FS) += procfs.o
XDRGEN = ../../tools/net/sunrpc/xdrgen/xdrgen
-XDRGEN_DEFINITIONS = ../../include/linux/sunrpc/xdrgen/nlm4.h
-XDRGEN_DECLARATIONS = nlm4xdr_gen.h
-XDRGEN_SOURCE = nlm4xdr_gen.c
+XDRGEN_DEFINITIONS = ../../include/linux/sunrpc/xdrgen/nlm4.h \
+ ../../include/linux/sunrpc/xdrgen/nlm3.h
+XDRGEN_DECLARATIONS = nlm4xdr_gen.h nlm3xdr_gen.h
+XDRGEN_SOURCE = nlm4xdr_gen.c nlm3xdr_gen.c
xdrgen: $(XDRGEN_DEFINITIONS) $(XDRGEN_DECLARATIONS) $(XDRGEN_SOURCE)
../../include/linux/sunrpc/xdrgen/nlm4.h: ../../Documentation/sunrpc/xdr/nlm4.x
$(XDRGEN) definitions $< > $@
+../../include/linux/sunrpc/xdrgen/nlm3.h: ../../Documentation/sunrpc/xdr/nlm3.x
+ $(XDRGEN) definitions $< > $@
+
nlm4xdr_gen.h: ../../Documentation/sunrpc/xdr/nlm4.x
$(XDRGEN) declarations $< > $@
+nlm3xdr_gen.h: ../../Documentation/sunrpc/xdr/nlm3.x
+ $(XDRGEN) declarations $< > $@
+
nlm4xdr_gen.c: ../../Documentation/sunrpc/xdr/nlm4.x
$(XDRGEN) source --peer server $< > $@
+
+nlm3xdr_gen.c: ../../Documentation/sunrpc/xdr/nlm3.x
+ $(XDRGEN) source --peer server $< > $@
diff --git a/fs/lockd/clnt4xdr.c b/fs/lockd/clnt4xdr.c
index 2058733eacf8..96a4a1e6a6b6 100644
--- a/fs/lockd/clnt4xdr.c
+++ b/fs/lockd/clnt4xdr.c
@@ -63,7 +63,7 @@ static s64 loff_t_to_s64(loff_t offset)
return res;
}
-static void nlm4_compute_offsets(const struct nlm_lock *lock,
+static void nlm4_compute_offsets(const struct lockd_lock *lock,
u64 *l_offset, u64 *l_len)
{
const struct file_lock *fl = &lock->fl;
@@ -132,13 +132,13 @@ static int decode_netobj(struct xdr_stream *xdr,
* netobj cookie;
*/
static void encode_cookie(struct xdr_stream *xdr,
- const struct nlm_cookie *cookie)
+ const struct lockd_cookie *cookie)
{
encode_netobj(xdr, (u8 *)&cookie->data, cookie->len);
}
static int decode_cookie(struct xdr_stream *xdr,
- struct nlm_cookie *cookie)
+ struct lockd_cookie *cookie)
{
u32 length;
__be32 *p;
@@ -238,9 +238,9 @@ out_overflow:
* };
*/
static void encode_nlm4_holder(struct xdr_stream *xdr,
- const struct nlm_res *result)
+ const struct lockd_res *result)
{
- const struct nlm_lock *lock = &result->lock;
+ const struct lockd_lock *lock = &result->lock;
u64 l_offset, l_len;
__be32 *p;
@@ -254,9 +254,9 @@ static void encode_nlm4_holder(struct xdr_stream *xdr,
xdr_encode_hyper(p, l_len);
}
-static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result)
+static int decode_nlm4_holder(struct xdr_stream *xdr, struct lockd_res *result)
{
- struct nlm_lock *lock = &result->lock;
+ struct lockd_lock *lock = &result->lock;
struct file_lock *fl = &lock->fl;
u64 l_offset, l_len;
u32 exclusive;
@@ -317,7 +317,7 @@ static void encode_caller_name(struct xdr_stream *xdr, const char *name)
* };
*/
static void encode_nlm4_lock(struct xdr_stream *xdr,
- const struct nlm_lock *lock)
+ const struct lockd_lock *lock)
{
u64 l_offset, l_len;
__be32 *p;
@@ -354,8 +354,8 @@ static void nlm4_xdr_enc_testargs(struct rpc_rqst *req,
struct xdr_stream *xdr,
const void *data)
{
- const struct nlm_args *args = data;
- const struct nlm_lock *lock = &args->lock;
+ const struct lockd_args *args = data;
+ const struct lockd_lock *lock = &args->lock;
encode_cookie(xdr, &args->cookie);
encode_bool(xdr, lock->fl.c.flc_type == F_WRLCK);
@@ -376,8 +376,8 @@ static void nlm4_xdr_enc_lockargs(struct rpc_rqst *req,
struct xdr_stream *xdr,
const void *data)
{
- const struct nlm_args *args = data;
- const struct nlm_lock *lock = &args->lock;
+ const struct lockd_args *args = data;
+ const struct lockd_lock *lock = &args->lock;
encode_cookie(xdr, &args->cookie);
encode_bool(xdr, args->block);
@@ -399,8 +399,8 @@ static void nlm4_xdr_enc_cancargs(struct rpc_rqst *req,
struct xdr_stream *xdr,
const void *data)
{
- const struct nlm_args *args = data;
- const struct nlm_lock *lock = &args->lock;
+ const struct lockd_args *args = data;
+ const struct lockd_lock *lock = &args->lock;
encode_cookie(xdr, &args->cookie);
encode_bool(xdr, args->block);
@@ -418,8 +418,8 @@ static void nlm4_xdr_enc_unlockargs(struct rpc_rqst *req,
struct xdr_stream *xdr,
const void *data)
{
- const struct nlm_args *args = data;
- const struct nlm_lock *lock = &args->lock;
+ const struct lockd_args *args = data;
+ const struct lockd_lock *lock = &args->lock;
encode_cookie(xdr, &args->cookie);
encode_nlm4_lock(xdr, lock);
@@ -435,7 +435,7 @@ static void nlm4_xdr_enc_res(struct rpc_rqst *req,
struct xdr_stream *xdr,
const void *data)
{
- const struct nlm_res *result = data;
+ const struct lockd_res *result = data;
encode_cookie(xdr, &result->cookie);
encode_nlm4_stat(xdr, result->status);
@@ -458,7 +458,7 @@ static void nlm4_xdr_enc_testres(struct rpc_rqst *req,
struct xdr_stream *xdr,
const void *data)
{
- const struct nlm_res *result = data;
+ const struct lockd_res *result = data;
encode_cookie(xdr, &result->cookie);
encode_nlm4_stat(xdr, result->status);
@@ -489,7 +489,7 @@ static void nlm4_xdr_enc_testres(struct rpc_rqst *req,
* };
*/
static int decode_nlm4_testrply(struct xdr_stream *xdr,
- struct nlm_res *result)
+ struct lockd_res *result)
{
int error;
@@ -506,7 +506,7 @@ static int nlm4_xdr_dec_testres(struct rpc_rqst *req,
struct xdr_stream *xdr,
void *data)
{
- struct nlm_res *result = data;
+ struct lockd_res *result = data;
int error;
error = decode_cookie(xdr, &result->cookie);
@@ -527,7 +527,7 @@ static int nlm4_xdr_dec_res(struct rpc_rqst *req,
struct xdr_stream *xdr,
void *data)
{
- struct nlm_res *result = data;
+ struct lockd_res *result = data;
int error;
error = decode_cookie(xdr, &result->cookie);
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index 8fa30c42c92a..f797cc99f94d 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -158,7 +158,7 @@ int nlmclnt_wait(struct nlm_wait *block, struct nlm_rqst *req, long timeout)
/*
* The server lockd has called us back to tell us the lock was granted
*/
-__be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock)
+__be32 nlmclnt_grant(const struct sockaddr *addr, const struct lockd_lock *lock)
{
const struct file_lock *fl = &lock->fl;
const struct nfs_fh *fh = &lock->fh;
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
index 7f211008a5d2..f8018bfe9c64 100644
--- a/fs/lockd/clntproc.c
+++ b/fs/lockd/clntproc.c
@@ -42,7 +42,7 @@ static const struct rpc_call_ops nlmclnt_cancel_ops;
*/
static atomic_t nlm_cookie = ATOMIC_INIT(0x1234);
-void nlmclnt_next_cookie(struct nlm_cookie *c)
+void nlmclnt_next_cookie(struct lockd_cookie *c)
{
u32 cookie = atomic_inc_return(&nlm_cookie);
@@ -128,8 +128,8 @@ static struct nlm_lockowner *nlmclnt_find_lockowner(struct nlm_host *host, fl_ow
*/
static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl)
{
- struct nlm_args *argp = &req->a_args;
- struct nlm_lock *lock = &argp->lock;
+ struct lockd_args *argp = &req->a_args;
+ struct lockd_lock *lock = &argp->lock;
char *nodename = req->a_host->h_rpcclnt->cl_nodename;
nlmclnt_next_cookie(&argp->cookie);
@@ -266,8 +266,8 @@ nlmclnt_call(const struct cred *cred, struct nlm_rqst *req, u32 proc)
{
struct nlm_host *host = req->a_host;
struct rpc_clnt *clnt;
- struct nlm_args *argp = &req->a_args;
- struct nlm_res *resp = &req->a_res;
+ struct lockd_args *argp = &req->a_args;
+ struct lockd_res *resp = &req->a_res;
struct rpc_message msg = {
.rpc_argp = argp,
.rpc_resp = resp,
@@ -487,9 +487,12 @@ static const struct file_lock_operations nlmclnt_lock_ops = {
static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host)
{
fl->fl_u.nfs_fl.state = 0;
+ fl->fl_ops = NULL;
fl->fl_u.nfs_fl.owner = nlmclnt_find_lockowner(host,
fl->c.flc_owner);
INIT_LIST_HEAD(&fl->fl_u.nfs_fl.list);
+ if (!fl->fl_u.nfs_fl.owner)
+ return;
fl->fl_ops = &nlmclnt_lock_ops;
}
@@ -523,7 +526,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl)
{
const struct cred *cred = nfs_file_cred(fl->c.flc_file);
struct nlm_host *host = req->a_host;
- struct nlm_res *resp = &req->a_res;
+ struct lockd_res *resp = &req->a_res;
struct nlm_wait block;
unsigned char flags = fl->c.flc_flags;
unsigned char type;
@@ -686,7 +689,7 @@ static int
nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl)
{
struct nlm_host *host = req->a_host;
- struct nlm_res *resp = &req->a_res;
+ struct lockd_res *resp = &req->a_res;
int status;
unsigned char flags = fl->c.flc_flags;
diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c
index 65555f5224b1..3789ecb0b984 100644
--- a/fs/lockd/clntxdr.c
+++ b/fs/lockd/clntxdr.c
@@ -60,7 +60,7 @@ static s32 loff_t_to_s32(loff_t offset)
return res;
}
-static void nlm_compute_offsets(const struct nlm_lock *lock,
+static void nlm_compute_offsets(const struct lockd_lock *lock,
u32 *l_offset, u32 *l_len)
{
const struct file_lock *fl = &lock->fl;
@@ -130,13 +130,13 @@ static int decode_netobj(struct xdr_stream *xdr,
* netobj cookie;
*/
static void encode_cookie(struct xdr_stream *xdr,
- const struct nlm_cookie *cookie)
+ const struct lockd_cookie *cookie)
{
encode_netobj(xdr, (u8 *)&cookie->data, cookie->len);
}
static int decode_cookie(struct xdr_stream *xdr,
- struct nlm_cookie *cookie)
+ struct lockd_cookie *cookie)
{
u32 length;
__be32 *p;
@@ -234,9 +234,9 @@ out_overflow:
* };
*/
static void encode_nlm_holder(struct xdr_stream *xdr,
- const struct nlm_res *result)
+ const struct lockd_res *result)
{
- const struct nlm_lock *lock = &result->lock;
+ const struct lockd_lock *lock = &result->lock;
u32 l_offset, l_len;
__be32 *p;
@@ -250,9 +250,9 @@ static void encode_nlm_holder(struct xdr_stream *xdr,
*p = cpu_to_be32(l_len);
}
-static int decode_nlm_holder(struct xdr_stream *xdr, struct nlm_res *result)
+static int decode_nlm_holder(struct xdr_stream *xdr, struct lockd_res *result)
{
- struct nlm_lock *lock = &result->lock;
+ struct lockd_lock *lock = &result->lock;
struct file_lock *fl = &lock->fl;
u32 exclusive, l_offset, l_len;
int error;
@@ -319,7 +319,7 @@ static void encode_caller_name(struct xdr_stream *xdr, const char *name)
* };
*/
static void encode_nlm_lock(struct xdr_stream *xdr,
- const struct nlm_lock *lock)
+ const struct lockd_lock *lock)
{
u32 l_offset, l_len;
__be32 *p;
@@ -355,8 +355,8 @@ static void nlm_xdr_enc_testargs(struct rpc_rqst *req,
struct xdr_stream *xdr,
const void *data)
{
- const struct nlm_args *args = data;
- const struct nlm_lock *lock = &args->lock;
+ const struct lockd_args *args = data;
+ const struct lockd_lock *lock = &args->lock;
encode_cookie(xdr, &args->cookie);
encode_bool(xdr, lock->fl.c.flc_type == F_WRLCK);
@@ -377,8 +377,8 @@ static void nlm_xdr_enc_lockargs(struct rpc_rqst *req,
struct xdr_stream *xdr,
const void *data)
{
- const struct nlm_args *args = data;
- const struct nlm_lock *lock = &args->lock;
+ const struct lockd_args *args = data;
+ const struct lockd_lock *lock = &args->lock;
encode_cookie(xdr, &args->cookie);
encode_bool(xdr, args->block);
@@ -400,8 +400,8 @@ static void nlm_xdr_enc_cancargs(struct rpc_rqst *req,
struct xdr_stream *xdr,
const void *data)
{
- const struct nlm_args *args = data;
- const struct nlm_lock *lock = &args->lock;
+ const struct lockd_args *args = data;
+ const struct lockd_lock *lock = &args->lock;
encode_cookie(xdr, &args->cookie);
encode_bool(xdr, args->block);
@@ -419,8 +419,8 @@ static void nlm_xdr_enc_unlockargs(struct rpc_rqst *req,
struct xdr_stream *xdr,
const void *data)
{
- const struct nlm_args *args = data;
- const struct nlm_lock *lock = &args->lock;
+ const struct lockd_args *args = data;
+ const struct lockd_lock *lock = &args->lock;
encode_cookie(xdr, &args->cookie);
encode_nlm_lock(xdr, lock);
@@ -436,7 +436,7 @@ static void nlm_xdr_enc_res(struct rpc_rqst *req,
struct xdr_stream *xdr,
const void *data)
{
- const struct nlm_res *result = data;
+ const struct lockd_res *result = data;
encode_cookie(xdr, &result->cookie);
encode_nlm_stat(xdr, result->status);
@@ -456,7 +456,7 @@ static void nlm_xdr_enc_res(struct rpc_rqst *req,
* };
*/
static void encode_nlm_testrply(struct xdr_stream *xdr,
- const struct nlm_res *result)
+ const struct lockd_res *result)
{
if (result->status == nlm_lck_denied)
encode_nlm_holder(xdr, result);
@@ -466,7 +466,7 @@ static void nlm_xdr_enc_testres(struct rpc_rqst *req,
struct xdr_stream *xdr,
const void *data)
{
- const struct nlm_res *result = data;
+ const struct lockd_res *result = data;
encode_cookie(xdr, &result->cookie);
encode_nlm_stat(xdr, result->status);
@@ -495,7 +495,7 @@ static void nlm_xdr_enc_testres(struct rpc_rqst *req,
* };
*/
static int decode_nlm_testrply(struct xdr_stream *xdr,
- struct nlm_res *result)
+ struct lockd_res *result)
{
int error;
@@ -512,7 +512,7 @@ static int nlm_xdr_dec_testres(struct rpc_rqst *req,
struct xdr_stream *xdr,
void *data)
{
- struct nlm_res *result = data;
+ struct lockd_res *result = data;
int error;
error = decode_cookie(xdr, &result->cookie);
@@ -533,7 +533,7 @@ static int nlm_xdr_dec_res(struct rpc_rqst *req,
struct xdr_stream *xdr,
void *data)
{
- struct nlm_res *result = data;
+ struct lockd_res *result = data;
int error;
error = decode_cookie(xdr, &result->cookie);
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index ea8a8e166f7e..d572cb27533f 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -552,7 +552,7 @@ struct nlm_host * nlm_get_host(struct nlm_host *host)
static struct nlm_host *next_host_state(struct hlist_head *cache,
struct nsm_handle *nsm,
- const struct nlm_reboot *info)
+ const struct lockd_reboot *info)
{
struct nlm_host *host;
struct hlist_head *chain;
@@ -582,7 +582,7 @@ static struct nlm_host *next_host_state(struct hlist_head *cache,
* We were notified that the specified host has rebooted. Release
* all resources held by that peer.
*/
-void nlm_host_rebooted(const struct net *net, const struct nlm_reboot *info)
+void nlm_host_rebooted(const struct net *net, const struct lockd_reboot *info)
{
struct nsm_handle *nsm;
struct nlm_host *host;
diff --git a/fs/lockd/lockd.h b/fs/lockd/lockd.h
index a7c85ab6d4b5..14cc952fe81a 100644
--- a/fs/lockd/lockd.h
+++ b/fs/lockd/lockd.h
@@ -52,6 +52,14 @@
*/
#define LOCKD_DFLT_TIMEO 10
+/*
+ * Number of leading bytes of nfs_fh.data that file_hash()
+ * digests when bucketing nlm_files[]. Sized for historical
+ * NFSv2 handles; nfs_fh.data must be initialized at least
+ * this far before lookup, regardless of fh.size.
+ */
+#define LOCKD_FH_HASH_SIZE 32
+
/* error codes new to NLMv4 */
#define nlm4_deadlock cpu_to_be32(NLM_DEADLCK)
#define nlm4_rofs cpu_to_be32(NLM_ROFS)
@@ -171,15 +179,15 @@ struct nlm_rqst {
refcount_t a_count;
unsigned int a_flags; /* initial RPC task flags */
struct nlm_host * a_host; /* host handle */
- struct nlm_args a_args; /* arguments */
- struct nlm_res a_res; /* result */
+ struct lockd_args a_args; /* arguments */
+ struct lockd_res a_res; /* result */
struct nlm_block * a_block;
unsigned int a_retries; /* Retry count */
u8 a_owner[NLMCLNT_OHSIZE];
void * a_callback_data; /* sent to nlmclnt_operations callbacks */
};
-struct nlm_share;
+struct lockd_share;
/*
* This struct describes a file held open by lockd on behalf of
@@ -190,7 +198,7 @@ struct nlm_file {
struct nfs_fh f_handle; /* NFS file handle */
struct file * f_file[2]; /* VFS file pointers,
indexed by O_ flags */
- struct nlm_share * f_shares; /* DOS shares */
+ struct lockd_share * f_shares; /* DOS shares */
struct list_head f_blocks; /* blocked locks */
unsigned int f_locks; /* guesstimate # of locks */
unsigned int f_count; /* reference count */
@@ -253,11 +261,11 @@ void nlmclnt_queue_block(struct nlm_wait *block);
__be32 nlmclnt_dequeue_block(struct nlm_wait *block);
int nlmclnt_wait(struct nlm_wait *block, struct nlm_rqst *req, long timeout);
__be32 nlmclnt_grant(const struct sockaddr *addr,
- const struct nlm_lock *lock);
+ const struct lockd_lock *lock);
void nlmclnt_recovery(struct nlm_host *);
int nlmclnt_reclaim(struct nlm_host *, struct file_lock *,
struct nlm_rqst *);
-void nlmclnt_next_cookie(struct nlm_cookie *);
+void nlmclnt_next_cookie(struct lockd_cookie *);
#ifdef CONFIG_LOCKD_V4
extern const struct rpc_version nlm_version4;
@@ -285,7 +293,7 @@ struct nlm_host * nlm_get_host(struct nlm_host *);
void nlm_shutdown_hosts(void);
void nlm_shutdown_hosts_net(struct net *net);
void nlm_host_rebooted(const struct net *net,
- const struct nlm_reboot *);
+ const struct lockd_reboot *);
/*
* Host monitoring
@@ -299,31 +307,31 @@ struct nsm_handle *nsm_get_handle(const struct net *net,
const char *hostname,
const size_t hostname_len);
struct nsm_handle *nsm_reboot_lookup(const struct net *net,
- const struct nlm_reboot *info);
+ const struct lockd_reboot *info);
void nsm_release(struct nsm_handle *nsm);
/*
* This is used in garbage collection and resource reclaim
* A return value != 0 means destroy the lock/block/share
*/
-typedef int (*nlm_host_match_fn_t)(void *cur, struct nlm_host *ref);
+typedef int (*nlm_host_match_fn_t)(void *owner, struct nlm_host *ref);
/*
* Server-side lock handling
*/
int lock_to_openmode(struct file_lock *);
__be32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *,
- struct nlm_host *, struct nlm_lock *, int,
- struct nlm_cookie *, int);
-__be32 nlmsvc_unlock(struct net *net, struct nlm_file *, struct nlm_lock *);
+ struct nlm_host *, struct lockd_lock *, int,
+ struct lockd_cookie *, int);
+__be32 nlmsvc_unlock(struct net *net, struct nlm_file *, struct lockd_lock *);
__be32 nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
- struct nlm_host *host, struct nlm_lock *lock,
- struct nlm_lock *conflock);
-__be32 nlmsvc_cancel_blocked(struct net *net, struct nlm_file *, struct nlm_lock *);
+ struct nlm_host *host, struct lockd_lock *lock,
+ struct lockd_lock *conflock);
+__be32 nlmsvc_cancel_blocked(struct net *net, struct nlm_file *, struct lockd_lock *);
void nlmsvc_retry_blocked(struct svc_rqst *rqstp);
void nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *,
nlm_host_match_fn_t match);
-void nlmsvc_grant_reply(struct nlm_cookie *, __be32);
+void nlmsvc_grant_reply(struct lockd_cookie *, __be32);
void nlmsvc_release_call(struct nlm_rqst *);
void nlmsvc_locks_init_private(struct file_lock *, struct nlm_host *, pid_t);
int nlmsvc_dispatch(struct svc_rqst *rqstp);
@@ -332,10 +340,10 @@ int nlmsvc_dispatch(struct svc_rqst *rqstp);
* File handling for the server personality
*/
__be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **,
- struct nlm_lock *);
+ struct lockd_lock *, int);
void nlm_release_file(struct nlm_file *);
void nlmsvc_put_lockowner(struct nlm_lockowner *);
-void nlmsvc_release_lockowner(struct nlm_lock *);
+void nlmsvc_release_lockowner(struct lockd_lock *);
void nlmsvc_mark_resources(struct net *);
void nlmsvc_free_host_resources(struct nlm_host *);
void nlmsvc_invalidate_all(void);
@@ -423,6 +431,29 @@ static inline int nlm_compare_locks(const struct file_lock *fl1,
}
/**
+ * lockd_set_file_lock_range3 - set the byte range of a file_lock
+ * @fl: file_lock whose length fields are to be initialized
+ * @off: starting offset of the lock, in bytes
+ * @len: length of the byte range, in bytes, or zero
+ *
+ * NLMv3 uses a (start, length) representation for lock byte ranges,
+ * while the kernel's file_lock uses (start, end). Treat a length of
+ * zero or arithmetic overflow (end wrapping negative when the sum
+ * exceeds S32_MAX) as "lock to end of file."
+ */
+static inline void
+lockd_set_file_lock_range3(struct file_lock *fl, u32 off, u32 len)
+{
+ s32 end = off + len - 1;
+
+ fl->fl_start = off;
+ if (len == 0 || end < 0)
+ fl->fl_end = OFFSET_MAX;
+ else
+ fl->fl_end = end;
+}
+
+/**
* lockd_set_file_lock_range4 - set the byte range of a file_lock
* @fl: file_lock whose length fields are to be initialized
* @off: starting offset of the lock, in bytes
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 3d3ee88ca4dc..a8f5ac6f0577 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -377,7 +377,7 @@ retry:
* error occurred.
*/
struct nsm_handle *nsm_reboot_lookup(const struct net *net,
- const struct nlm_reboot *info)
+ const struct lockd_reboot *info)
{
struct nsm_handle *cached;
struct lockd_net *ln = net_generic(net, lockd_net_id);
diff --git a/fs/lockd/nlm3xdr_gen.c b/fs/lockd/nlm3xdr_gen.c
new file mode 100644
index 000000000000..4b6e3ee7a719
--- /dev/null
+++ b/fs/lockd/nlm3xdr_gen.c
@@ -0,0 +1,686 @@
+// SPDX-License-Identifier: GPL-2.0
+// Generated by xdrgen. Manual edits will be lost.
+// XDR specification file: ../../Documentation/sunrpc/xdr/nlm3.x
+// XDR specification modification time: Mon Jun 29 20:42:29 2026
+
+#include <linux/sunrpc/svc.h>
+
+#include "nlm3xdr_gen.h"
+
+static bool __maybe_unused
+xdrgen_decode_netobj(struct xdr_stream *xdr, netobj *ptr)
+{
+ return xdrgen_decode_opaque(xdr, ptr, MAXNETOBJ_SZ);
+}
+
+static bool __maybe_unused
+xdrgen_decode_nlm_stats(struct xdr_stream *xdr, nlm_stats *ptr)
+{
+ __be32 raw;
+ u32 val;
+
+ if (xdr_stream_decode_be32(xdr, &raw) < 0)
+ return false;
+ val = be32_to_cpu(raw);
+ /* Compiler may optimize to a range check for dense enums */
+ switch (val) {
+ case LCK_GRANTED:
+ case LCK_DENIED:
+ case LCK_DENIED_NOLOCKS:
+ case LCK_BLOCKED:
+ case LCK_DENIED_GRACE_PERIOD:
+ break;
+ default:
+ return false;
+ }
+ *ptr = raw;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_nlm_stat(struct xdr_stream *xdr, struct nlm_stat *ptr)
+{
+ if (!xdrgen_decode_nlm_stats(xdr, &ptr->stat))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_nlm_res(struct xdr_stream *xdr, struct nlm_res *ptr)
+{
+ if (!xdrgen_decode_netobj(xdr, &ptr->cookie))
+ return false;
+ if (!xdrgen_decode_nlm_stat(xdr, &ptr->stat))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_nlm_holder(struct xdr_stream *xdr, struct nlm_holder *ptr)
+{
+ if (!xdrgen_decode_bool(xdr, &ptr->exclusive))
+ return false;
+ if (!xdrgen_decode_int(xdr, &ptr->uppid))
+ return false;
+ if (!xdrgen_decode_netobj(xdr, &ptr->oh))
+ return false;
+ if (!xdrgen_decode_unsigned_int(xdr, &ptr->l_offset))
+ return false;
+ if (!xdrgen_decode_unsigned_int(xdr, &ptr->l_len))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_nlm_testrply(struct xdr_stream *xdr, struct nlm_testrply *ptr)
+{
+ if (!xdrgen_decode_nlm_stats(xdr, &ptr->stat))
+ return false;
+ switch (ptr->stat) {
+ case __constant_cpu_to_be32(LCK_DENIED):
+ if (!xdrgen_decode_nlm_holder(xdr, &ptr->u.holder))
+ return false;
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_nlm_testres(struct xdr_stream *xdr, struct nlm_testres *ptr)
+{
+ if (!xdrgen_decode_netobj(xdr, &ptr->cookie))
+ return false;
+ if (!xdrgen_decode_nlm_testrply(xdr, &ptr->test_stat))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_nlm_lock(struct xdr_stream *xdr, struct nlm_lock *ptr)
+{
+ if (!xdrgen_decode_string(xdr, (string *)ptr, LM_MAXSTRLEN))
+ return false;
+ if (!xdrgen_decode_netobj(xdr, &ptr->fh))
+ return false;
+ if (!xdrgen_decode_netobj(xdr, &ptr->oh))
+ return false;
+ if (!xdrgen_decode_int(xdr, &ptr->uppid))
+ return false;
+ if (!xdrgen_decode_unsigned_int(xdr, &ptr->l_offset))
+ return false;
+ if (!xdrgen_decode_unsigned_int(xdr, &ptr->l_len))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_nlm_lockargs(struct xdr_stream *xdr, struct nlm_lockargs *ptr)
+{
+ if (!xdrgen_decode_netobj(xdr, &ptr->cookie))
+ return false;
+ if (!xdrgen_decode_bool(xdr, &ptr->block))
+ return false;
+ if (!xdrgen_decode_bool(xdr, &ptr->exclusive))
+ return false;
+ if (!xdrgen_decode_nlm_lock(xdr, &ptr->alock))
+ return false;
+ if (!xdrgen_decode_bool(xdr, &ptr->reclaim))
+ return false;
+ if (!xdrgen_decode_int(xdr, &ptr->state))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_nlm_cancargs(struct xdr_stream *xdr, struct nlm_cancargs *ptr)
+{
+ if (!xdrgen_decode_netobj(xdr, &ptr->cookie))
+ return false;
+ if (!xdrgen_decode_bool(xdr, &ptr->block))
+ return false;
+ if (!xdrgen_decode_bool(xdr, &ptr->exclusive))
+ return false;
+ if (!xdrgen_decode_nlm_lock(xdr, &ptr->alock))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_nlm_testargs(struct xdr_stream *xdr, struct nlm_testargs *ptr)
+{
+ if (!xdrgen_decode_netobj(xdr, &ptr->cookie))
+ return false;
+ if (!xdrgen_decode_bool(xdr, &ptr->exclusive))
+ return false;
+ if (!xdrgen_decode_nlm_lock(xdr, &ptr->alock))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_nlm_unlockargs(struct xdr_stream *xdr, struct nlm_unlockargs *ptr)
+{
+ if (!xdrgen_decode_netobj(xdr, &ptr->cookie))
+ return false;
+ if (!xdrgen_decode_nlm_lock(xdr, &ptr->alock))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_fsh_mode(struct xdr_stream *xdr, fsh_mode *ptr)
+{
+ u32 val;
+
+ if (xdr_stream_decode_u32(xdr, &val) < 0)
+ return false;
+ /* Compiler may optimize to a range check for dense enums */
+ switch (val) {
+ case fsm_DN:
+ case fsm_DR:
+ case fsm_DW:
+ case fsm_DRW:
+ break;
+ default:
+ return false;
+ }
+ *ptr = val;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_fsh_access(struct xdr_stream *xdr, fsh_access *ptr)
+{
+ u32 val;
+
+ if (xdr_stream_decode_u32(xdr, &val) < 0)
+ return false;
+ /* Compiler may optimize to a range check for dense enums */
+ switch (val) {
+ case fsa_NONE:
+ case fsa_R:
+ case fsa_W:
+ case fsa_RW:
+ break;
+ default:
+ return false;
+ }
+ *ptr = val;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_nlm_share(struct xdr_stream *xdr, struct nlm_share *ptr)
+{
+ if (!xdrgen_decode_string(xdr, (string *)ptr, LM_MAXSTRLEN))
+ return false;
+ if (!xdrgen_decode_netobj(xdr, &ptr->fh))
+ return false;
+ if (!xdrgen_decode_netobj(xdr, &ptr->oh))
+ return false;
+ if (!xdrgen_decode_fsh_mode(xdr, &ptr->mode))
+ return false;
+ if (!xdrgen_decode_fsh_access(xdr, &ptr->access))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_nlm_shareargs(struct xdr_stream *xdr, struct nlm_shareargs *ptr)
+{
+ if (!xdrgen_decode_netobj(xdr, &ptr->cookie))
+ return false;
+ if (!xdrgen_decode_nlm_share(xdr, &ptr->share))
+ return false;
+ if (!xdrgen_decode_bool(xdr, &ptr->reclaim))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_nlm_shareres(struct xdr_stream *xdr, struct nlm_shareres *ptr)
+{
+ if (!xdrgen_decode_netobj(xdr, &ptr->cookie))
+ return false;
+ if (!xdrgen_decode_nlm_stats(xdr, &ptr->stat))
+ return false;
+ if (!xdrgen_decode_int(xdr, &ptr->sequence))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_nlm_notify(struct xdr_stream *xdr, struct nlm_notify *ptr)
+{
+ if (!xdrgen_decode_string(xdr, (string *)ptr, LM_MAXNAMELEN))
+ return false;
+ if (!xdrgen_decode_long(xdr, &ptr->state))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_decode_nlm_notifyargs(struct xdr_stream *xdr, struct nlm_notifyargs *ptr)
+{
+ if (!xdrgen_decode_nlm_notify(xdr, &ptr->notify))
+ return false;
+ if (xdr_stream_decode_opaque_fixed(xdr, ptr->private, SM_PRIV_SIZE) < 0)
+ return false;
+ return true;
+}
+
+/**
+ * nlm_svc_decode_nlm_testargs - Decode a nlm_testargs argument
+ * @rqstp: RPC transaction context
+ * @xdr: source XDR data stream
+ *
+ * Return values:
+ * %true: procedure arguments decoded successfully
+ * %false: decode failed
+ */
+bool nlm_svc_decode_nlm_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+ struct nlm_testargs *argp = rqstp->rq_argp;
+
+ return xdrgen_decode_nlm_testargs(xdr, argp);
+}
+
+/**
+ * nlm_svc_decode_nlm_lockargs - Decode a nlm_lockargs argument
+ * @rqstp: RPC transaction context
+ * @xdr: source XDR data stream
+ *
+ * Return values:
+ * %true: procedure arguments decoded successfully
+ * %false: decode failed
+ */
+bool nlm_svc_decode_nlm_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+ struct nlm_lockargs *argp = rqstp->rq_argp;
+
+ return xdrgen_decode_nlm_lockargs(xdr, argp);
+}
+
+/**
+ * nlm_svc_decode_nlm_cancargs - Decode a nlm_cancargs argument
+ * @rqstp: RPC transaction context
+ * @xdr: source XDR data stream
+ *
+ * Return values:
+ * %true: procedure arguments decoded successfully
+ * %false: decode failed
+ */
+bool nlm_svc_decode_nlm_cancargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+ struct nlm_cancargs *argp = rqstp->rq_argp;
+
+ return xdrgen_decode_nlm_cancargs(xdr, argp);
+}
+
+/**
+ * nlm_svc_decode_nlm_unlockargs - Decode a nlm_unlockargs argument
+ * @rqstp: RPC transaction context
+ * @xdr: source XDR data stream
+ *
+ * Return values:
+ * %true: procedure arguments decoded successfully
+ * %false: decode failed
+ */
+bool nlm_svc_decode_nlm_unlockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+ struct nlm_unlockargs *argp = rqstp->rq_argp;
+
+ return xdrgen_decode_nlm_unlockargs(xdr, argp);
+}
+
+/**
+ * nlm_svc_decode_nlm_testres - Decode a nlm_testres argument
+ * @rqstp: RPC transaction context
+ * @xdr: source XDR data stream
+ *
+ * Return values:
+ * %true: procedure arguments decoded successfully
+ * %false: decode failed
+ */
+bool nlm_svc_decode_nlm_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+ struct nlm_testres *argp = rqstp->rq_argp;
+
+ return xdrgen_decode_nlm_testres(xdr, argp);
+}
+
+/**
+ * nlm_svc_decode_nlm_res - Decode a nlm_res argument
+ * @rqstp: RPC transaction context
+ * @xdr: source XDR data stream
+ *
+ * Return values:
+ * %true: procedure arguments decoded successfully
+ * %false: decode failed
+ */
+bool nlm_svc_decode_nlm_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+ struct nlm_res *argp = rqstp->rq_argp;
+
+ return xdrgen_decode_nlm_res(xdr, argp);
+}
+
+/**
+ * nlm_svc_decode_nlm_notifyargs - Decode a nlm_notifyargs argument
+ * @rqstp: RPC transaction context
+ * @xdr: source XDR data stream
+ *
+ * Return values:
+ * %true: procedure arguments decoded successfully
+ * %false: decode failed
+ */
+bool nlm_svc_decode_nlm_notifyargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+ struct nlm_notifyargs *argp = rqstp->rq_argp;
+
+ return xdrgen_decode_nlm_notifyargs(xdr, argp);
+}
+
+/**
+ * nlm_svc_decode_nlm_shareargs - Decode a nlm_shareargs argument
+ * @rqstp: RPC transaction context
+ * @xdr: source XDR data stream
+ *
+ * Return values:
+ * %true: procedure arguments decoded successfully
+ * %false: decode failed
+ */
+bool nlm_svc_decode_nlm_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+ struct nlm_shareargs *argp = rqstp->rq_argp;
+
+ return xdrgen_decode_nlm_shareargs(xdr, argp);
+}
+
+/**
+ * nlm_svc_decode_nlm_notify - Decode a nlm_notify argument
+ * @rqstp: RPC transaction context
+ * @xdr: source XDR data stream
+ *
+ * Return values:
+ * %true: procedure arguments decoded successfully
+ * %false: decode failed
+ */
+bool nlm_svc_decode_nlm_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+ struct nlm_notify *argp = rqstp->rq_argp;
+
+ return xdrgen_decode_nlm_notify(xdr, argp);
+}
+
+static bool __maybe_unused
+xdrgen_encode_netobj(struct xdr_stream *xdr, const netobj value)
+{
+ return xdr_stream_encode_opaque(xdr, value.data, value.len) >= 0;
+}
+
+static bool __maybe_unused
+xdrgen_encode_nlm_stats(struct xdr_stream *xdr, nlm_stats value)
+{
+ return xdr_stream_encode_be32(xdr, value) == XDR_UNIT;
+}
+
+static bool __maybe_unused
+xdrgen_encode_nlm_stat(struct xdr_stream *xdr, const struct nlm_stat *value)
+{
+ if (!xdrgen_encode_nlm_stats(xdr, value->stat))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_nlm_res(struct xdr_stream *xdr, const struct nlm_res *value)
+{
+ if (!xdrgen_encode_netobj(xdr, value->cookie))
+ return false;
+ if (!xdrgen_encode_nlm_stat(xdr, &value->stat))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_nlm_holder(struct xdr_stream *xdr, const struct nlm_holder *value)
+{
+ if (!xdrgen_encode_bool(xdr, value->exclusive))
+ return false;
+ if (!xdrgen_encode_int(xdr, value->uppid))
+ return false;
+ if (!xdrgen_encode_netobj(xdr, value->oh))
+ return false;
+ if (!xdrgen_encode_unsigned_int(xdr, value->l_offset))
+ return false;
+ if (!xdrgen_encode_unsigned_int(xdr, value->l_len))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_nlm_testrply(struct xdr_stream *xdr, const struct nlm_testrply *ptr)
+{
+ if (!xdrgen_encode_nlm_stats(xdr, ptr->stat))
+ return false;
+ switch (ptr->stat) {
+ case __constant_cpu_to_be32(LCK_DENIED):
+ if (!xdrgen_encode_nlm_holder(xdr, &ptr->u.holder))
+ return false;
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_nlm_testres(struct xdr_stream *xdr, const struct nlm_testres *value)
+{
+ if (!xdrgen_encode_netobj(xdr, value->cookie))
+ return false;
+ if (!xdrgen_encode_nlm_testrply(xdr, &value->test_stat))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_nlm_lock(struct xdr_stream *xdr, const struct nlm_lock *value)
+{
+ if (value->caller_name.len > LM_MAXSTRLEN)
+ return false;
+ if (xdr_stream_encode_opaque(xdr, value->caller_name.data, value->caller_name.len) < 0)
+ return false;
+ if (!xdrgen_encode_netobj(xdr, value->fh))
+ return false;
+ if (!xdrgen_encode_netobj(xdr, value->oh))
+ return false;
+ if (!xdrgen_encode_int(xdr, value->uppid))
+ return false;
+ if (!xdrgen_encode_unsigned_int(xdr, value->l_offset))
+ return false;
+ if (!xdrgen_encode_unsigned_int(xdr, value->l_len))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_nlm_lockargs(struct xdr_stream *xdr, const struct nlm_lockargs *value)
+{
+ if (!xdrgen_encode_netobj(xdr, value->cookie))
+ return false;
+ if (!xdrgen_encode_bool(xdr, value->block))
+ return false;
+ if (!xdrgen_encode_bool(xdr, value->exclusive))
+ return false;
+ if (!xdrgen_encode_nlm_lock(xdr, &value->alock))
+ return false;
+ if (!xdrgen_encode_bool(xdr, value->reclaim))
+ return false;
+ if (!xdrgen_encode_int(xdr, value->state))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_nlm_cancargs(struct xdr_stream *xdr, const struct nlm_cancargs *value)
+{
+ if (!xdrgen_encode_netobj(xdr, value->cookie))
+ return false;
+ if (!xdrgen_encode_bool(xdr, value->block))
+ return false;
+ if (!xdrgen_encode_bool(xdr, value->exclusive))
+ return false;
+ if (!xdrgen_encode_nlm_lock(xdr, &value->alock))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_nlm_testargs(struct xdr_stream *xdr, const struct nlm_testargs *value)
+{
+ if (!xdrgen_encode_netobj(xdr, value->cookie))
+ return false;
+ if (!xdrgen_encode_bool(xdr, value->exclusive))
+ return false;
+ if (!xdrgen_encode_nlm_lock(xdr, &value->alock))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_nlm_unlockargs(struct xdr_stream *xdr, const struct nlm_unlockargs *value)
+{
+ if (!xdrgen_encode_netobj(xdr, value->cookie))
+ return false;
+ if (!xdrgen_encode_nlm_lock(xdr, &value->alock))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_fsh_mode(struct xdr_stream *xdr, fsh_mode value)
+{
+ return xdr_stream_encode_u32(xdr, value) == XDR_UNIT;
+}
+
+static bool __maybe_unused
+xdrgen_encode_fsh_access(struct xdr_stream *xdr, fsh_access value)
+{
+ return xdr_stream_encode_u32(xdr, value) == XDR_UNIT;
+}
+
+static bool __maybe_unused
+xdrgen_encode_nlm_share(struct xdr_stream *xdr, const struct nlm_share *value)
+{
+ if (value->caller_name.len > LM_MAXSTRLEN)
+ return false;
+ if (xdr_stream_encode_opaque(xdr, value->caller_name.data, value->caller_name.len) < 0)
+ return false;
+ if (!xdrgen_encode_netobj(xdr, value->fh))
+ return false;
+ if (!xdrgen_encode_netobj(xdr, value->oh))
+ return false;
+ if (!xdrgen_encode_fsh_mode(xdr, value->mode))
+ return false;
+ if (!xdrgen_encode_fsh_access(xdr, value->access))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_nlm_shareargs(struct xdr_stream *xdr, const struct nlm_shareargs *value)
+{
+ if (!xdrgen_encode_netobj(xdr, value->cookie))
+ return false;
+ if (!xdrgen_encode_nlm_share(xdr, &value->share))
+ return false;
+ if (!xdrgen_encode_bool(xdr, value->reclaim))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_nlm_shareres(struct xdr_stream *xdr, const struct nlm_shareres *value)
+{
+ if (!xdrgen_encode_netobj(xdr, value->cookie))
+ return false;
+ if (!xdrgen_encode_nlm_stats(xdr, value->stat))
+ return false;
+ if (!xdrgen_encode_int(xdr, value->sequence))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_nlm_notify(struct xdr_stream *xdr, const struct nlm_notify *value)
+{
+ if (value->name.len > LM_MAXNAMELEN)
+ return false;
+ if (xdr_stream_encode_opaque(xdr, value->name.data, value->name.len) < 0)
+ return false;
+ if (!xdrgen_encode_long(xdr, value->state))
+ return false;
+ return true;
+}
+
+static bool __maybe_unused
+xdrgen_encode_nlm_notifyargs(struct xdr_stream *xdr, const struct nlm_notifyargs *value)
+{
+ if (!xdrgen_encode_nlm_notify(xdr, &value->notify))
+ return false;
+ if (xdr_stream_encode_opaque_fixed(xdr, value->private, SM_PRIV_SIZE) < 0)
+ return false;
+ return true;
+}
+
+/**
+ * nlm_svc_encode_nlm_testres - Encode a nlm_testres result
+ * @rqstp: RPC transaction context
+ * @xdr: target XDR data stream
+ *
+ * Return values:
+ * %true: procedure results encoded successfully
+ * %false: encode failed
+ */
+bool nlm_svc_encode_nlm_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+ struct nlm_testres *resp = rqstp->rq_resp;
+
+ return xdrgen_encode_nlm_testres(xdr, resp);
+}
+
+/**
+ * nlm_svc_encode_nlm_res - Encode a nlm_res result
+ * @rqstp: RPC transaction context
+ * @xdr: target XDR data stream
+ *
+ * Return values:
+ * %true: procedure results encoded successfully
+ * %false: encode failed
+ */
+bool nlm_svc_encode_nlm_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+ struct nlm_res *resp = rqstp->rq_resp;
+
+ return xdrgen_encode_nlm_res(xdr, resp);
+}
+
+/**
+ * nlm_svc_encode_nlm_shareres - Encode a nlm_shareres result
+ * @rqstp: RPC transaction context
+ * @xdr: target XDR data stream
+ *
+ * Return values:
+ * %true: procedure results encoded successfully
+ * %false: encode failed
+ */
+bool nlm_svc_encode_nlm_shareres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
+{
+ struct nlm_shareres *resp = rqstp->rq_resp;
+
+ return xdrgen_encode_nlm_shareres(xdr, resp);
+}
diff --git a/fs/lockd/nlm3xdr_gen.h b/fs/lockd/nlm3xdr_gen.h
new file mode 100644
index 000000000000..bdbfc26ba0e4
--- /dev/null
+++ b/fs/lockd/nlm3xdr_gen.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Generated by xdrgen. Manual edits will be lost. */
+/* XDR specification file: ../../Documentation/sunrpc/xdr/nlm3.x */
+/* XDR specification modification time: Mon Jun 29 20:42:29 2026 */
+
+#ifndef _LINUX_XDRGEN_NLM3_DECL_H
+#define _LINUX_XDRGEN_NLM3_DECL_H
+
+#include <linux/types.h>
+
+#include <linux/sunrpc/xdr.h>
+#include <linux/sunrpc/xdrgen/_defs.h>
+#include <linux/sunrpc/xdrgen/_builtins.h>
+#include <linux/sunrpc/xdrgen/nlm3.h>
+
+bool nlm_svc_decode_nlm_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
+bool nlm_svc_decode_nlm_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
+bool nlm_svc_decode_nlm_cancargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
+bool nlm_svc_decode_nlm_unlockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
+bool nlm_svc_decode_nlm_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
+bool nlm_svc_decode_nlm_res(struct svc_rqst *rqstp, struct xdr_stream *xdr);
+bool nlm_svc_decode_nlm_notifyargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
+bool nlm_svc_decode_nlm_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
+bool nlm_svc_decode_nlm_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr);
+
+bool nlm_svc_encode_nlm_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
+bool nlm_svc_encode_nlm_res(struct svc_rqst *rqstp, struct xdr_stream *xdr);
+bool nlm_svc_encode_nlm_shareres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
+
+#endif /* _LINUX_XDRGEN_NLM3_DECL_H */
diff --git a/fs/lockd/nlm4xdr_gen.c b/fs/lockd/nlm4xdr_gen.c
index 1c8c221db456..f98d74ee3d41 100644
--- a/fs/lockd/nlm4xdr_gen.c
+++ b/fs/lockd/nlm4xdr_gen.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
// Generated by xdrgen. Manual edits will be lost.
// XDR specification file: ../../Documentation/sunrpc/xdr/nlm4.x
-// XDR specification modification time: Thu Dec 25 13:10:19 2025
+// XDR specification modification time: Mon Jun 29 20:42:29 2026
#include <linux/sunrpc/svc.h>
@@ -20,6 +20,16 @@ xdrgen_decode_fsh4_mode(struct xdr_stream *xdr, fsh4_mode *ptr)
if (xdr_stream_decode_u32(xdr, &val) < 0)
return false;
+ /* Compiler may optimize to a range check for dense enums */
+ switch (val) {
+ case fsm_DN:
+ case fsm_DR:
+ case fsm_DW:
+ case fsm_DRW:
+ break;
+ default:
+ return false;
+ }
*ptr = val;
return true;
}
@@ -31,6 +41,16 @@ xdrgen_decode_fsh4_access(struct xdr_stream *xdr, fsh4_access *ptr)
if (xdr_stream_decode_u32(xdr, &val) < 0)
return false;
+ /* Compiler may optimize to a range check for dense enums */
+ switch (val) {
+ case fsa_NONE:
+ case fsa_R:
+ case fsa_W:
+ case fsa_RW:
+ break;
+ default:
+ return false;
+ }
*ptr = val;
return true;
}
@@ -62,7 +82,30 @@ xdrgen_decode_int32(struct xdr_stream *xdr, int32 *ptr)
static bool __maybe_unused
xdrgen_decode_nlm4_stats(struct xdr_stream *xdr, nlm4_stats *ptr)
{
- return xdr_stream_decode_be32(xdr, ptr) == 0;
+ __be32 raw;
+ u32 val;
+
+ if (xdr_stream_decode_be32(xdr, &raw) < 0)
+ return false;
+ val = be32_to_cpu(raw);
+ /* Compiler may optimize to a range check for dense enums */
+ switch (val) {
+ case NLM4_GRANTED:
+ case NLM4_DENIED:
+ case NLM4_DENIED_NOLOCKS:
+ case NLM4_BLOCKED:
+ case NLM4_DENIED_GRACE_PERIOD:
+ case NLM4_DEADLCK:
+ case NLM4_ROFS:
+ case NLM4_STALE_FH:
+ case NLM4_FBIG:
+ case NLM4_FAILED:
+ break;
+ default:
+ return false;
+ }
+ *ptr = raw;
+ return true;
}
static bool __maybe_unused
@@ -258,20 +301,6 @@ xdrgen_decode_nlm4_notifyargs(struct xdr_stream *xdr, struct nlm4_notifyargs *pt
}
/**
- * nlm4_svc_decode_void - Decode a void argument
- * @rqstp: RPC transaction context
- * @xdr: source XDR data stream
- *
- * Return values:
- * %true: procedure arguments decoded successfully
- * %false: decode failed
- */
-bool nlm4_svc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
- return xdrgen_decode_void(xdr);
-}
-
-/**
* nlm4_svc_decode_nlm4_testargs - Decode a nlm4_testargs argument
* @rqstp: RPC transaction context
* @xdr: source XDR data stream
@@ -662,20 +691,6 @@ xdrgen_encode_nlm4_notifyargs(struct xdr_stream *xdr, const struct nlm4_notifyar
}
/**
- * nlm4_svc_encode_void - Encode a void result
- * @rqstp: RPC transaction context
- * @xdr: target XDR data stream
- *
- * Return values:
- * %true: procedure results encoded successfully
- * %false: encode failed
- */
-bool nlm4_svc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
- return xdrgen_encode_void(xdr);
-}
-
-/**
* nlm4_svc_encode_nlm4_testres - Encode a nlm4_testres result
* @rqstp: RPC transaction context
* @xdr: target XDR data stream
diff --git a/fs/lockd/nlm4xdr_gen.h b/fs/lockd/nlm4xdr_gen.h
index b6008b296a3e..1a72c26ad18a 100644
--- a/fs/lockd/nlm4xdr_gen.h
+++ b/fs/lockd/nlm4xdr_gen.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Generated by xdrgen. Manual edits will be lost. */
/* XDR specification file: ../../Documentation/sunrpc/xdr/nlm4.x */
-/* XDR specification modification time: Thu Dec 25 13:10:19 2025 */
+/* XDR specification modification time: Mon Jun 29 20:42:29 2026 */
#ifndef _LINUX_XDRGEN_NLM4_DECL_H
#define _LINUX_XDRGEN_NLM4_DECL_H
@@ -13,7 +13,6 @@
#include <linux/sunrpc/xdrgen/_builtins.h>
#include <linux/sunrpc/xdrgen/nlm4.h>
-bool nlm4_svc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr);
bool nlm4_svc_decode_nlm4_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
bool nlm4_svc_decode_nlm4_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
bool nlm4_svc_decode_nlm4_cancargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
@@ -24,7 +23,6 @@ bool nlm4_svc_decode_nlm4_notifyargs(struct svc_rqst *rqstp, struct xdr_stream *
bool nlm4_svc_decode_nlm4_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
bool nlm4_svc_decode_nlm4_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr);
-bool nlm4_svc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr);
bool nlm4_svc_encode_nlm4_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
bool nlm4_svc_encode_nlm4_res(struct svc_rqst *rqstp, struct xdr_stream *xdr);
bool nlm4_svc_encode_nlm4_shareres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
diff --git a/fs/lockd/share.h b/fs/lockd/share.h
index 20ea8ee49168..a12b6c454f58 100644
--- a/fs/lockd/share.h
+++ b/fs/lockd/share.h
@@ -8,25 +8,31 @@
#ifndef _LOCKD_SHARE_H
#define _LOCKD_SHARE_H
+#include <linux/bits.h>
+
/* Synthetic svid for lockowner lookup during share operations */
#define LOCKD_SHARE_SVID (~(u32)0)
+/* One bit per (access, deny) pair; index = (access << 2) | deny */
+#define LOCKD_FSH_BIT(a, d) BIT(((a) << 2) | (d))
+
/*
* DOS share for a specific file
*/
-struct nlm_share {
- struct nlm_share * s_next; /* linked list */
+struct lockd_share {
+ struct lockd_share * s_next; /* linked list */
struct nlm_host * s_host; /* client host */
struct nlm_file * s_file; /* shared file */
struct xdr_netobj s_owner; /* owner handle */
u32 s_access; /* access mode */
u32 s_mode; /* deny mode */
+ u16 s_access_deny_bmap; /* held (access, deny) pairs */
};
__be32 nlmsvc_share_file(struct nlm_host *host, struct nlm_file *file,
struct xdr_netobj *oh, u32 access, u32 mode);
__be32 nlmsvc_unshare_file(struct nlm_host *host, struct nlm_file *file,
- struct xdr_netobj *oh);
+ struct xdr_netobj *oh, u32 access, u32 mode);
void nlmsvc_traverse_shares(struct nlm_host *, struct nlm_file *,
nlm_host_match_fn_t);
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 490551369ef2..ee90e743064a 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -47,7 +47,7 @@
static struct svc_program nlmsvc_program;
-const struct nlmsvc_binding *nlmsvc_ops;
+const struct nlmsvc_binding __rcu *nlmsvc_ops;
EXPORT_SYMBOL_GPL(nlmsvc_ops);
static DEFINE_MUTEX(nlmsvc_mutex);
@@ -142,7 +142,7 @@ lockd(void *vrqstp)
nlmsvc_retry_blocked(rqstp);
svc_recv(rqstp, 0);
}
- if (nlmsvc_ops)
+ if (rcu_access_pointer(nlmsvc_ops))
nlmsvc_invalidate_all();
nlm_shutdown_hosts();
cancel_delayed_work_sync(&ln->grace_period_end);
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index 5de41e249534..03c5554ca579 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -26,42 +26,42 @@
#include "nlm4xdr_gen.h"
/*
- * Wrapper structures combine xdrgen types with legacy nlm_lock.
+ * Wrapper structures combine xdrgen types with legacy lockd_lock.
* The xdrgen field must be first so the structure can be cast
* to its XDR type for the RPC dispatch layer.
*/
struct nlm4_testargs_wrapper {
struct nlm4_testargs xdrgen;
- struct nlm_lock lock;
+ struct lockd_lock lock;
};
static_assert(offsetof(struct nlm4_testargs_wrapper, xdrgen) == 0);
struct nlm4_lockargs_wrapper {
struct nlm4_lockargs xdrgen;
- struct nlm_cookie cookie;
- struct nlm_lock lock;
+ struct lockd_cookie cookie;
+ struct lockd_lock lock;
};
static_assert(offsetof(struct nlm4_lockargs_wrapper, xdrgen) == 0);
struct nlm4_cancargs_wrapper {
struct nlm4_cancargs xdrgen;
- struct nlm_lock lock;
+ struct lockd_lock lock;
};
static_assert(offsetof(struct nlm4_cancargs_wrapper, xdrgen) == 0);
struct nlm4_unlockargs_wrapper {
struct nlm4_unlockargs xdrgen;
- struct nlm_lock lock;
+ struct lockd_lock lock;
};
static_assert(offsetof(struct nlm4_unlockargs_wrapper, xdrgen) == 0);
struct nlm4_notifyargs_wrapper {
struct nlm4_notifyargs xdrgen;
- struct nlm_reboot reboot;
+ struct lockd_reboot reboot;
};
static_assert(offsetof(struct nlm4_notifyargs_wrapper, xdrgen) == 0);
@@ -74,12 +74,12 @@ static_assert(offsetof(struct nlm4_notify_wrapper, xdrgen) == 0);
struct nlm4_testres_wrapper {
struct nlm4_testres xdrgen;
- struct nlm_lock lock;
+ struct lockd_lock lock;
};
struct nlm4_shareargs_wrapper {
struct nlm4_shareargs xdrgen;
- struct nlm_lock lock;
+ struct lockd_lock lock;
};
static_assert(offsetof(struct nlm4_shareargs_wrapper, xdrgen) == 0);
@@ -88,7 +88,7 @@ static_assert(offsetof(struct nlm4_testres_wrapper, xdrgen) == 0);
struct nlm4_res_wrapper {
struct nlm4_res xdrgen;
- struct nlm_cookie cookie;
+ struct lockd_cookie cookie;
};
static_assert(offsetof(struct nlm4_res_wrapper, xdrgen) == 0);
@@ -100,7 +100,7 @@ struct nlm4_shareres_wrapper {
static_assert(offsetof(struct nlm4_shareres_wrapper, xdrgen) == 0);
static __be32
-nlm4_netobj_to_cookie(struct nlm_cookie *cookie, netobj *object)
+nlm4_netobj_to_cookie(struct lockd_cookie *cookie, netobj *object)
{
if (object->len > NLM_MAXCOOKIELEN)
return nlm_lck_denied_nolocks;
@@ -110,7 +110,7 @@ nlm4_netobj_to_cookie(struct nlm_cookie *cookie, netobj *object)
}
static __be32
-nlm4_lock_to_nlm_lock(struct nlm_lock *lock, struct nlm4_lock *alock)
+nlm4_lock_to_lockd_lock(struct lockd_lock *lock, struct nlm4_lock *alock)
{
if (alock->fh.len > NFS_MAXFHSIZE)
return nlm_lck_denied;
@@ -119,7 +119,6 @@ nlm4_lock_to_nlm_lock(struct nlm_lock *lock, struct nlm4_lock *alock)
lock->oh.len = alock->oh.len;
lock->oh.data = alock->oh.data;
lock->svid = alock->svid;
- locks_init_lock(&lock->fl);
lockd_set_file_lock_range4(&lock->fl, alock->l_offset, alock->l_len);
return nlm_granted;
}
@@ -129,7 +128,7 @@ nlm4svc_lookup_host(struct svc_rqst *rqstp, string caller, bool monitored)
{
struct nlm_host *host;
- if (!nlmsvc_ops)
+ if (!rcu_access_pointer(nlmsvc_ops))
return NULL;
host = nlmsvc_lookup_host(rqstp, caller.data, caller.len);
if (!host)
@@ -143,17 +142,23 @@ nlm4svc_lookup_host(struct svc_rqst *rqstp, string caller, bool monitored)
static __be32
nlm4svc_lookup_file(struct svc_rqst *rqstp, struct nlm_host *host,
- struct nlm_lock *lock, struct nlm_file **filp,
+ struct lockd_lock *lock, struct nlm_file **filp,
struct nlm4_lock *xdr_lock, unsigned char type)
{
+ bool is_test = (rqstp->rq_proc == NLMPROC4_TEST ||
+ rqstp->rq_proc == NLMPROC4_TEST_MSG);
struct file_lock *fl = &lock->fl;
struct nlm_file *file = NULL;
+ int mode;
__be32 error;
if (xdr_lock->fh.len > NFS_MAXFHSIZE)
return nlm_lck_denied_nolocks;
lock->fh.size = xdr_lock->fh.len;
memcpy(lock->fh.data, xdr_lock->fh.data, xdr_lock->fh.len);
+ if (xdr_lock->fh.len < LOCKD_FH_HASH_SIZE)
+ memset(lock->fh.data + xdr_lock->fh.len, 0,
+ LOCKD_FH_HASH_SIZE - xdr_lock->fh.len);
lock->oh.len = xdr_lock->oh.len;
lock->oh.data = xdr_lock->oh.data;
@@ -170,7 +175,8 @@ nlm4svc_lookup_file(struct svc_rqst *rqstp, struct nlm_host *host,
fl->c.flc_type = type;
lockd_set_file_lock_range4(fl, lock->lock_start, lock->lock_len);
- error = nlm_lookup_file(rqstp, &file, lock);
+ mode = is_test ? O_RDWR : lock_to_openmode(fl);
+ error = nlm_lookup_file(rqstp, &file, lock, mode);
switch (error) {
case nlm_granted:
break;
@@ -184,7 +190,8 @@ nlm4svc_lookup_file(struct svc_rqst *rqstp, struct nlm_host *host,
*filp = file;
fl->c.flc_flags = FL_POSIX;
- fl->c.flc_file = file->f_file[lock_to_openmode(fl)];
+ fl->c.flc_file = is_test ? nlmsvc_file_file(file)
+ : file->f_file[mode];
fl->c.flc_pid = current->tgid;
fl->fl_lmops = &nlmsvc_lock_operations;
nlmsvc_locks_init_private(fl, host, (pid_t)lock->svid);
@@ -265,7 +272,7 @@ static __be32 nlm4svc_proc_test(struct svc_rqst *rqstp)
nlmsvc_release_lockowner(&argp->lock);
if (resp->xdrgen.stat.stat == nlm_lck_denied) {
- struct nlm_lock *conf = &resp->lock;
+ struct lockd_lock *conf = &resp->lock;
struct nlm4_holder *holder = &resp->xdrgen.stat.u.holder;
holder->exclusive = (conf->fl.c.flc_type != F_RDLCK);
@@ -508,12 +515,12 @@ out:
* nlm4_res NLMPROC4_GRANTED(nlm4_testargs) = 5;
*
* Permissible procedure status codes:
- * %NLM4_GRANTED: The requested lock was granted.
- * %NLM4_DENIED: The server could not allocate the resources
- * needed to process the request.
- * %NLM4_DENIED_GRACE_PERIOD: The server has recently restarted and is
- * re-establishing existing locks, and is not
- * yet ready to accept normal service requests.
+ * %NLM4_GRANTED: The granted lock was accepted.
+ * %NLM4_DENIED: The procedure failed, possibly due to
+ * internal resource constraints.
+ * %NLM4_DENIED_GRACE_PERIOD: The client host recently restarted and
+ * its NLM is re-establishing existing locks,
+ * so it is not yet ready to accept callbacks.
*/
static __be32
nlm4svc_proc_granted(struct svc_rqst *rqstp)
@@ -523,8 +530,8 @@ nlm4svc_proc_granted(struct svc_rqst *rqstp)
resp->xdrgen.cookie = argp->xdrgen.cookie;
- resp->xdrgen.stat.stat = nlm4_lock_to_nlm_lock(&argp->lock,
- &argp->xdrgen.alock);
+ resp->xdrgen.stat.stat = nlm4_lock_to_lockd_lock(&argp->lock,
+ &argp->xdrgen.alock);
if (resp->xdrgen.stat.stat)
goto out;
@@ -558,7 +565,7 @@ static const struct rpc_call_ops nlm4svc_callback_ops = {
*/
static __be32
nlm4svc_callback(struct svc_rqst *rqstp, struct nlm_host *host, u32 proc,
- __be32 (*func)(struct svc_rqst *, struct nlm_res *))
+ __be32 (*func)(struct svc_rqst *, struct lockd_res *))
{
struct nlm_rqst *call;
__be32 stat;
@@ -581,7 +588,7 @@ nlm4svc_callback(struct svc_rqst *rqstp, struct nlm_host *host, u32 proc,
}
static __be32
-__nlm4svc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_res *resp)
+__nlm4svc_proc_test_msg(struct svc_rqst *rqstp, struct lockd_res *resp)
{
struct nlm4_testargs_wrapper *argp = rqstp->rq_argp;
unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK;
@@ -641,7 +648,7 @@ static __be32 nlm4svc_proc_test_msg(struct svc_rqst *rqstp)
}
static __be32
-__nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_res *resp)
+__nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct lockd_res *resp)
{
struct nlm4_lockargs_wrapper *argp = rqstp->rq_argp;
unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK;
@@ -664,6 +671,8 @@ __nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_res *resp)
resp->status = nlmsvc_lock(rqstp, file, host, &argp->lock,
argp->xdrgen.block, &resp->cookie,
argp->xdrgen.reclaim);
+ if (resp->status == nlm__int__deadlock)
+ resp->status = nlm4_deadlock;
nlmsvc_release_lockowner(&argp->lock);
out:
@@ -692,7 +701,7 @@ static __be32 nlm4svc_proc_lock_msg(struct svc_rqst *rqstp)
struct nlm4_lockargs_wrapper *argp = rqstp->rq_argp;
struct nlm_host *host;
- host = nlm4svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, true);
+ host = nlm4svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
if (!host)
return rpc_system_err;
@@ -701,7 +710,7 @@ static __be32 nlm4svc_proc_lock_msg(struct svc_rqst *rqstp)
}
static __be32
-__nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_res *resp)
+__nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp, struct lockd_res *resp)
{
struct nlm4_cancargs_wrapper *argp = rqstp->rq_argp;
unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK;
@@ -765,7 +774,7 @@ static __be32 nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp)
}
static __be32
-__nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_res *resp)
+__nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp, struct lockd_res *resp)
{
struct nlm4_unlockargs_wrapper *argp = rqstp->rq_argp;
struct net *net = SVC_NET(rqstp);
@@ -828,7 +837,7 @@ static __be32 nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp)
}
static __be32
-__nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_res *resp)
+__nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct lockd_res *resp)
{
struct nlm4_testargs_wrapper *argp = rqstp->rq_argp;
@@ -836,7 +845,7 @@ __nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_res *resp)
if (nlm4_netobj_to_cookie(&resp->cookie, &argp->xdrgen.cookie))
goto out;
- if (nlm4_lock_to_nlm_lock(&argp->lock, &argp->xdrgen.alock))
+ if (nlm4_lock_to_lockd_lock(&argp->lock, &argp->xdrgen.alock))
goto out;
resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock);
@@ -863,7 +872,8 @@ static __be32 nlm4svc_proc_granted_msg(struct svc_rqst *rqstp)
struct nlm4_testargs_wrapper *argp = rqstp->rq_argp;
struct nlm_host *host;
- host = nlm4svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
+ host = nlmsvc_lookup_host(rqstp, argp->xdrgen.alock.caller_name.data,
+ argp->xdrgen.alock.caller_name.len);
if (!host)
return rpc_system_err;
@@ -885,7 +895,7 @@ static __be32 nlm4svc_proc_granted_res(struct svc_rqst *rqstp)
{
struct nlm4_res_wrapper *argp = rqstp->rq_argp;
- if (!nlmsvc_ops)
+ if (!rcu_access_pointer(nlmsvc_ops))
return rpc_success;
if (nlm4_netobj_to_cookie(&argp->cookie, &argp->xdrgen.cookie))
@@ -912,7 +922,7 @@ static __be32 nlm4svc_proc_granted_res(struct svc_rqst *rqstp)
static __be32 nlm4svc_proc_sm_notify(struct svc_rqst *rqstp)
{
struct nlm4_notifyargs_wrapper *argp = rqstp->rq_argp;
- struct nlm_reboot *reboot = &argp->reboot;
+ struct lockd_reboot *reboot = &argp->reboot;
if (!nlm_privileged_requester(rqstp)) {
char buf[RPC_MAX_ADDRBUFLEN];
@@ -976,7 +986,7 @@ static __be32 nlm4svc_proc_share(struct svc_rqst *rqstp)
{
struct nlm4_shareargs_wrapper *argp = rqstp->rq_argp;
struct nlm4_shareres_wrapper *resp = rqstp->rq_resp;
- struct nlm_lock *lock = &argp->lock;
+ struct lockd_lock *lock = &argp->lock;
struct nlm_host *host = NULL;
struct nlm_file *file = NULL;
struct nlm4_lock xdr_lock = {
@@ -1044,7 +1054,7 @@ static __be32 nlm4svc_proc_unshare(struct svc_rqst *rqstp)
{
struct nlm4_shareargs_wrapper *argp = rqstp->rq_argp;
struct nlm4_shareres_wrapper *resp = rqstp->rq_resp;
- struct nlm_lock *lock = &argp->lock;
+ struct lockd_lock *lock = &argp->lock;
struct nlm4_lock xdr_lock = {
.fh = argp->xdrgen.share.fh,
.oh = argp->xdrgen.share.oh,
@@ -1069,7 +1079,9 @@ static __be32 nlm4svc_proc_unshare(struct svc_rqst *rqstp)
if (resp->xdrgen.stat)
goto out;
- resp->xdrgen.stat = nlmsvc_unshare_file(host, file, &lock->oh);
+ resp->xdrgen.stat = nlmsvc_unshare_file(host, file, &lock->oh,
+ argp->xdrgen.share.access,
+ argp->xdrgen.share.mode);
nlmsvc_release_lockowner(lock);
@@ -1155,8 +1167,8 @@ out:
static const struct svc_procedure nlm4svc_procedures[24] = {
[NLMPROC4_NULL] = {
.pc_func = nlm4svc_proc_null,
- .pc_decode = nlm4_svc_decode_void,
- .pc_encode = nlm4_svc_encode_void,
+ .pc_decode = xdrgen_svc_decode_void,
+ .pc_encode = xdrgen_svc_encode_void,
.pc_argsize = XDR_void,
.pc_argzero = 0,
.pc_ressize = 0,
@@ -1216,7 +1228,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
[NLMPROC4_TEST_MSG] = {
.pc_func = nlm4svc_proc_test_msg,
.pc_decode = nlm4_svc_decode_nlm4_testargs,
- .pc_encode = nlm4_svc_encode_void,
+ .pc_encode = xdrgen_svc_encode_void,
.pc_argsize = sizeof(struct nlm4_testargs_wrapper),
.pc_argzero = 0,
.pc_ressize = 0,
@@ -1226,7 +1238,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
[NLMPROC4_LOCK_MSG] = {
.pc_func = nlm4svc_proc_lock_msg,
.pc_decode = nlm4_svc_decode_nlm4_lockargs,
- .pc_encode = nlm4_svc_encode_void,
+ .pc_encode = xdrgen_svc_encode_void,
.pc_argsize = sizeof(struct nlm4_lockargs_wrapper),
.pc_argzero = 0,
.pc_ressize = 0,
@@ -1236,7 +1248,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
[NLMPROC4_CANCEL_MSG] = {
.pc_func = nlm4svc_proc_cancel_msg,
.pc_decode = nlm4_svc_decode_nlm4_cancargs,
- .pc_encode = nlm4_svc_encode_void,
+ .pc_encode = xdrgen_svc_encode_void,
.pc_argsize = sizeof(struct nlm4_cancargs_wrapper),
.pc_argzero = 0,
.pc_ressize = 0,
@@ -1246,7 +1258,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
[NLMPROC4_UNLOCK_MSG] = {
.pc_func = nlm4svc_proc_unlock_msg,
.pc_decode = nlm4_svc_decode_nlm4_unlockargs,
- .pc_encode = nlm4_svc_encode_void,
+ .pc_encode = xdrgen_svc_encode_void,
.pc_argsize = sizeof(struct nlm4_unlockargs_wrapper),
.pc_argzero = 0,
.pc_ressize = 0,
@@ -1256,7 +1268,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
[NLMPROC4_GRANTED_MSG] = {
.pc_func = nlm4svc_proc_granted_msg,
.pc_decode = nlm4_svc_decode_nlm4_testargs,
- .pc_encode = nlm4_svc_encode_void,
+ .pc_encode = xdrgen_svc_encode_void,
.pc_argsize = sizeof(struct nlm4_testargs_wrapper),
.pc_argzero = 0,
.pc_ressize = 0,
@@ -1266,7 +1278,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
[NLMPROC4_TEST_RES] = {
.pc_func = nlm4svc_proc_null,
.pc_decode = nlm4_svc_decode_nlm4_testres,
- .pc_encode = nlm4_svc_encode_void,
+ .pc_encode = xdrgen_svc_encode_void,
.pc_argsize = sizeof(struct nlm4_testres),
.pc_argzero = 0,
.pc_ressize = 0,
@@ -1276,7 +1288,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
[NLMPROC4_LOCK_RES] = {
.pc_func = nlm4svc_proc_null,
.pc_decode = nlm4_svc_decode_nlm4_res,
- .pc_encode = nlm4_svc_encode_void,
+ .pc_encode = xdrgen_svc_encode_void,
.pc_argsize = sizeof(struct nlm4_res),
.pc_argzero = 0,
.pc_ressize = 0,
@@ -1286,7 +1298,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
[NLMPROC4_CANCEL_RES] = {
.pc_func = nlm4svc_proc_null,
.pc_decode = nlm4_svc_decode_nlm4_res,
- .pc_encode = nlm4_svc_encode_void,
+ .pc_encode = xdrgen_svc_encode_void,
.pc_argsize = sizeof(struct nlm4_res),
.pc_argzero = 0,
.pc_ressize = 0,
@@ -1296,7 +1308,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
[NLMPROC4_UNLOCK_RES] = {
.pc_func = nlm4svc_proc_null,
.pc_decode = nlm4_svc_decode_nlm4_res,
- .pc_encode = nlm4_svc_encode_void,
+ .pc_encode = xdrgen_svc_encode_void,
.pc_argsize = sizeof(struct nlm4_res),
.pc_argzero = 0,
.pc_ressize = 0,
@@ -1306,7 +1318,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
[NLMPROC4_GRANTED_RES] = {
.pc_func = nlm4svc_proc_granted_res,
.pc_decode = nlm4_svc_decode_nlm4_res,
- .pc_encode = nlm4_svc_encode_void,
+ .pc_encode = xdrgen_svc_encode_void,
.pc_argsize = sizeof(struct nlm4_res_wrapper),
.pc_argzero = 0,
.pc_ressize = 0,
@@ -1316,7 +1328,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
[NLMPROC4_SM_NOTIFY] = {
.pc_func = nlm4svc_proc_sm_notify,
.pc_decode = nlm4_svc_decode_nlm4_notifyargs,
- .pc_encode = nlm4_svc_encode_void,
+ .pc_encode = xdrgen_svc_encode_void,
.pc_argsize = sizeof(struct nlm4_notifyargs_wrapper),
.pc_argzero = 0,
.pc_ressize = 0,
@@ -1325,8 +1337,8 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
},
[17] = {
.pc_func = nlm4svc_proc_unused,
- .pc_decode = nlm4_svc_decode_void,
- .pc_encode = nlm4_svc_encode_void,
+ .pc_decode = xdrgen_svc_decode_void,
+ .pc_encode = xdrgen_svc_encode_void,
.pc_argsize = 0,
.pc_argzero = 0,
.pc_ressize = 0,
@@ -1335,8 +1347,8 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
},
[18] = {
.pc_func = nlm4svc_proc_unused,
- .pc_decode = nlm4_svc_decode_void,
- .pc_encode = nlm4_svc_encode_void,
+ .pc_decode = xdrgen_svc_decode_void,
+ .pc_encode = xdrgen_svc_encode_void,
.pc_argsize = 0,
.pc_argzero = 0,
.pc_ressize = 0,
@@ -1345,8 +1357,8 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
},
[19] = {
.pc_func = nlm4svc_proc_unused,
- .pc_decode = nlm4_svc_decode_void,
- .pc_encode = nlm4_svc_encode_void,
+ .pc_decode = xdrgen_svc_decode_void,
+ .pc_encode = xdrgen_svc_encode_void,
.pc_argsize = 0,
.pc_argzero = 0,
.pc_ressize = 0,
@@ -1386,7 +1398,7 @@ static const struct svc_procedure nlm4svc_procedures[24] = {
[NLMPROC4_FREE_ALL] = {
.pc_func = nlm4svc_proc_free_all,
.pc_decode = nlm4_svc_decode_nlm4_notify,
- .pc_encode = nlm4_svc_encode_void,
+ .pc_encode = xdrgen_svc_encode_void,
.pc_argsize = sizeof(struct nlm4_notify_wrapper),
.pc_argzero = 0,
.pc_ressize = 0,
@@ -1411,14 +1423,10 @@ union nlm4svc_xdrstore {
struct nlm4_shareres_wrapper shareres;
};
-static DEFINE_PER_CPU_ALIGNED(unsigned long,
- nlm4svc_call_counters[ARRAY_SIZE(nlm4svc_procedures)]);
-
const struct svc_version nlmsvc_version4 = {
.vs_vers = 4,
.vs_nproc = ARRAY_SIZE(nlm4svc_procedures),
.vs_proc = nlm4svc_procedures,
- .vs_count = nlm4svc_call_counters,
.vs_dispatch = nlmsvc_dispatch,
.vs_xdrsize = sizeof(union nlm4svc_xdrstore),
};
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index b98b1d0ada35..e628b5d35507 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -37,7 +37,7 @@ static void nlmsvc_release_block(struct nlm_block *block);
static void nlmsvc_insert_block(struct nlm_block *block, unsigned long);
static void nlmsvc_remove_block(struct nlm_block *block);
-static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock);
+static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct lockd_lock *lock);
static void nlmsvc_freegrantargs(struct nlm_rqst *call);
static const struct rpc_call_ops nlmsvc_grant_ops;
@@ -47,40 +47,6 @@ static const struct rpc_call_ops nlmsvc_grant_ops;
static LIST_HEAD(nlm_blocked);
static DEFINE_SPINLOCK(nlm_blocked_lock);
-#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
-static const char *nlmdbg_cookie2a(const struct nlm_cookie *cookie)
-{
- /*
- * We can get away with a static buffer because this is only called
- * from lockd, which is single-threaded.
- */
- static char buf[2*NLM_MAXCOOKIELEN+1];
- unsigned int i, len = sizeof(buf);
- char *p = buf;
-
- len--; /* allow for trailing \0 */
- if (len < 3)
- return "???";
- for (i = 0 ; i < cookie->len ; i++) {
- if (len < 2) {
- strcpy(p-3, "...");
- break;
- }
- sprintf(p, "%02x", cookie->data[i]);
- p += 2;
- len -= 2;
- }
- *p = '\0';
-
- return buf;
-}
-#else
-static inline const char *nlmdbg_cookie2a(const struct nlm_cookie *cookie)
-{
- return "???";
-}
-#endif
-
/*
* Insert a blocked lock into the global list
*/
@@ -142,7 +108,7 @@ nlmsvc_remove_block(struct nlm_block *block)
* Find a block for a given lock
*/
static struct nlm_block *
-nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock)
+nlmsvc_lookup_block(struct nlm_file *file, struct lockd_lock *lock)
{
struct nlm_block *block;
struct file_lock *fl;
@@ -155,11 +121,12 @@ nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock)
spin_lock(&nlm_blocked_lock);
list_for_each_entry(block, &nlm_blocked, b_list) {
fl = &block->b_call->a_args.lock.fl;
- dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%s\n",
+ dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%*phN\n",
block->b_file, fl->c.flc_pid,
(long long)fl->fl_start,
(long long)fl->fl_end, fl->c.flc_type,
- nlmdbg_cookie2a(&block->b_call->a_args.cookie));
+ block->b_call->a_args.cookie.len,
+ block->b_call->a_args.cookie.data);
if (block->b_file == file && nlm_compare_locks(fl, &lock->fl)) {
kref_get(&block->b_count);
spin_unlock(&nlm_blocked_lock);
@@ -171,7 +138,7 @@ nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock)
return NULL;
}
-static inline int nlm_cookie_match(struct nlm_cookie *a, struct nlm_cookie *b)
+static int lockd_cookie_match(struct lockd_cookie *a, struct lockd_cookie *b)
{
if (a->len != b->len)
return 0;
@@ -184,13 +151,13 @@ static inline int nlm_cookie_match(struct nlm_cookie *a, struct nlm_cookie *b)
* Find a block with a given NLM cookie.
*/
static inline struct nlm_block *
-nlmsvc_find_block(struct nlm_cookie *cookie)
+nlmsvc_find_block(struct lockd_cookie *cookie)
{
struct nlm_block *block;
spin_lock(&nlm_blocked_lock);
list_for_each_entry(block, &nlm_blocked, b_list) {
- if (nlm_cookie_match(&block->b_call->a_args.cookie,cookie))
+ if (lockd_cookie_match(&block->b_call->a_args.cookie, cookie))
goto found;
}
spin_unlock(&nlm_blocked_lock);
@@ -198,7 +165,8 @@ nlmsvc_find_block(struct nlm_cookie *cookie)
return NULL;
found:
- dprintk("nlmsvc_find_block(%s): block=%p\n", nlmdbg_cookie2a(cookie), block);
+ dprintk("nlmsvc_find_block(%*phN): block=%p\n",
+ cookie->len, cookie->data, block);
kref_get(&block->b_count);
spin_unlock(&nlm_blocked_lock);
return block;
@@ -221,8 +189,8 @@ found:
*/
static struct nlm_block *
nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_host *host,
- struct nlm_file *file, struct nlm_lock *lock,
- struct nlm_cookie *cookie)
+ struct nlm_file *file, struct lockd_lock *lock,
+ struct lockd_cookie *cookie)
{
struct nlm_block *block;
struct nlm_rqst *call = NULL;
@@ -399,7 +367,7 @@ static struct nlm_lockowner *nlmsvc_find_lockowner(struct nlm_host *host, pid_t
}
void
-nlmsvc_release_lockowner(struct nlm_lock *lock)
+nlmsvc_release_lockowner(struct lockd_lock *lock)
{
if (lock->fl.c.flc_owner)
nlmsvc_put_lockowner(lock->fl.c.flc_owner);
@@ -415,7 +383,7 @@ void nlmsvc_locks_init_private(struct file_lock *fl, struct nlm_host *host,
* Initialize arguments for GRANTED call. The nlm_rqst structure
* has been cleared already.
*/
-static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock)
+static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct lockd_lock *lock)
{
locks_copy_lock(&call->a_args.lock.fl, &lock->fl);
memcpy(&call->a_args.lock.fh, &lock->fh, sizeof(call->a_args.lock.fh));
@@ -476,8 +444,8 @@ nlmsvc_defer_lock_rqst(struct svc_rqst *rqstp, struct nlm_block *block)
*/
__be32
nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
- struct nlm_host *host, struct nlm_lock *lock, int wait,
- struct nlm_cookie *cookie, int reclaim)
+ struct nlm_host *host, struct lockd_lock *lock, int wait,
+ struct lockd_cookie *cookie, int reclaim)
{
struct inode *inode __maybe_unused = nlmsvc_file_inode(file);
struct nlm_block *block = NULL;
@@ -609,11 +577,10 @@ out:
*/
__be32
nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
- struct nlm_host *host, struct nlm_lock *lock,
- struct nlm_lock *conflock)
+ struct nlm_host *host, struct lockd_lock *lock,
+ struct lockd_lock *conflock)
{
int error;
- int mode;
__be32 ret;
dprintk("lockd: nlmsvc_testlock(%s/%llu, ty=%d, %Ld-%Ld)\n",
@@ -631,14 +598,13 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
goto out;
}
- mode = lock_to_openmode(&lock->fl);
locks_init_lock(&conflock->fl);
/* vfs_test_lock only uses start, end, and owner, but tests flc_file */
conflock->fl.c.flc_file = lock->fl.c.flc_file;
conflock->fl.fl_start = lock->fl.fl_start;
conflock->fl.fl_end = lock->fl.fl_end;
conflock->fl.c.flc_owner = lock->fl.c.flc_owner;
- error = vfs_test_lock(file->f_file[mode], &conflock->fl);
+ error = vfs_test_lock(lock->fl.c.flc_file, &conflock->fl);
if (error) {
ret = nlm_lck_denied_nolocks;
goto out;
@@ -671,7 +637,7 @@ out:
* must be removed.
*/
__be32
-nlmsvc_unlock(struct net *net, struct nlm_file *file, struct nlm_lock *lock)
+nlmsvc_unlock(struct net *net, struct nlm_file *file, struct lockd_lock *lock)
{
int error = 0;
@@ -709,7 +675,7 @@ nlmsvc_unlock(struct net *net, struct nlm_file *file, struct nlm_lock *lock)
* The calling procedure must check whether the file can be closed.
*/
__be32
-nlmsvc_cancel_blocked(struct net *net, struct nlm_file *file, struct nlm_lock *lock)
+nlmsvc_cancel_blocked(struct net *net, struct nlm_file *file, struct lockd_lock *lock)
{
struct nlm_block *block;
int status = 0;
@@ -850,7 +816,7 @@ static void
nlmsvc_grant_blocked(struct nlm_block *block)
{
struct nlm_file *file = block->b_file;
- struct nlm_lock *lock = &block->b_call->a_args.lock;
+ struct lockd_lock *lock = &block->b_call->a_args.lock;
int mode;
int error;
loff_t fl_start, fl_end;
@@ -984,7 +950,7 @@ static const struct rpc_call_ops nlmsvc_grant_ops = {
* block.
*/
void
-nlmsvc_grant_reply(struct nlm_cookie *cookie, __be32 status)
+nlmsvc_grant_reply(struct lockd_cookie *cookie, __be32 status)
{
struct nlm_block *block;
struct file_lock *fl;
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 749abf8886ba..a8b5195c2c6b 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -13,11 +13,196 @@
#include <linux/sunrpc/svc_xprt.h>
#include "lockd.h"
+
+/*
+ * xdr.h defines SM_PRIV_SIZE as a macro. nlm3xdr_gen.h defines
+ * it as an enum constant. Undefine the macro before including
+ * the generated header.
+ */
+#undef SM_PRIV_SIZE
+
#include "share.h"
+#include "nlm3xdr_gen.h"
+
+/*
+ * Size of an NFSv2 file handle, in bytes, which is 32.
+ * Defined locally to avoid including uapi/linux/nfs2.h.
+ */
+#define NLM3_FHSIZE 32
+
+/*
+ * Wrapper structures combine xdrgen types with legacy lockd_lock.
+ * The xdrgen field must be first so the structure can be cast
+ * to its XDR type for the RPC dispatch layer.
+ */
+struct nlm_testargs_wrapper {
+ struct nlm_testargs xdrgen;
+ struct lockd_lock lock;
+};
+
+static_assert(offsetof(struct nlm_testargs_wrapper, xdrgen) == 0);
+
+struct nlm_testres_wrapper {
+ struct nlm_testres xdrgen;
+ struct lockd_lock lock;
+};
+
+static_assert(offsetof(struct nlm_testres_wrapper, xdrgen) == 0);
+
+struct nlm_lockargs_wrapper {
+ struct nlm_lockargs xdrgen;
+ struct lockd_cookie cookie;
+ struct lockd_lock lock;
+};
+
+static_assert(offsetof(struct nlm_lockargs_wrapper, xdrgen) == 0);
+
+struct nlm_res_wrapper {
+ struct nlm_res xdrgen;
+ struct lockd_cookie cookie;
+};
+
+static_assert(offsetof(struct nlm_res_wrapper, xdrgen) == 0);
+
+struct nlm_cancargs_wrapper {
+ struct nlm_cancargs xdrgen;
+ struct lockd_lock lock;
+};
+
+static_assert(offsetof(struct nlm_cancargs_wrapper, xdrgen) == 0);
+
+struct nlm_unlockargs_wrapper {
+ struct nlm_unlockargs xdrgen;
+ struct lockd_lock lock;
+};
+
+static_assert(offsetof(struct nlm_unlockargs_wrapper, xdrgen) == 0);
+
+struct nlm_notifyargs_wrapper {
+ struct nlm_notifyargs xdrgen;
+ struct lockd_reboot reboot;
+};
+
+static_assert(offsetof(struct nlm_notifyargs_wrapper, xdrgen) == 0);
+
+struct nlm_shareargs_wrapper {
+ struct nlm_shareargs xdrgen;
+ struct lockd_lock lock;
+};
+
+static_assert(offsetof(struct nlm_shareargs_wrapper, xdrgen) == 0);
+
+struct nlm_shareres_wrapper {
+ struct nlm_shareres xdrgen;
+};
+
+static_assert(offsetof(struct nlm_shareres_wrapper, xdrgen) == 0);
+
+struct nlm_notify_wrapper {
+ struct nlm_notify xdrgen;
+};
+
+static_assert(offsetof(struct nlm_notify_wrapper, xdrgen) == 0);
+
+static __be32
+nlm_netobj_to_cookie(struct lockd_cookie *cookie, netobj *object)
+{
+ if (object->len > NLM_MAXCOOKIELEN)
+ return nlm_lck_denied_nolocks;
+ cookie->len = object->len;
+ memcpy(cookie->data, object->data, object->len);
+ return nlm_granted;
+}
+
+static __be32
+nlm_lock_to_lockd_lock(struct lockd_lock *lock, struct nlm_lock *alock)
+{
+ if (alock->fh.len != NLM3_FHSIZE)
+ return nlm_lck_denied;
+ lock->fh.size = alock->fh.len;
+ memcpy(lock->fh.data, alock->fh.data, alock->fh.len);
+ lock->oh.len = alock->oh.len;
+ lock->oh.data = alock->oh.data;
+ lock->svid = alock->uppid;
+ lockd_set_file_lock_range3(&lock->fl, alock->l_offset, alock->l_len);
+ return nlm_granted;
+}
+
+static struct nlm_host *
+nlm3svc_lookup_host(struct svc_rqst *rqstp, string caller, bool monitored)
+{
+ struct nlm_host *host;
+
+ if (!rcu_access_pointer(nlmsvc_ops))
+ return NULL;
+ host = nlmsvc_lookup_host(rqstp, caller.data, caller.len);
+ if (!host)
+ return NULL;
+ if (monitored && nsm_monitor(host) < 0) {
+ nlmsvc_release_host(host);
+ return NULL;
+ }
+ return host;
+}
+
+static __be32
+nlm3svc_lookup_file(struct svc_rqst *rqstp, struct nlm_host *host,
+ struct lockd_lock *lock, struct nlm_file **filp,
+ struct nlm_lock *xdr_lock, unsigned char type)
+{
+ bool is_test = (rqstp->rq_proc == NLMPROC_TEST ||
+ rqstp->rq_proc == NLMPROC_TEST_MSG);
+ struct file_lock *fl = &lock->fl;
+ struct nlm_file *file = NULL;
+ __be32 error;
+ int mode;
+
+ if (xdr_lock->fh.len != NLM3_FHSIZE)
+ return nlm_lck_denied_nolocks;
+ lock->fh.size = xdr_lock->fh.len;
+ memcpy(lock->fh.data, xdr_lock->fh.data, xdr_lock->fh.len);
+
+ lock->oh.len = xdr_lock->oh.len;
+ lock->oh.data = xdr_lock->oh.data;
+
+ lock->svid = xdr_lock->uppid;
+ lock->lock_start = xdr_lock->l_offset;
+ lock->lock_len = xdr_lock->l_len;
+
+ locks_init_lock(fl);
+ fl->c.flc_type = type;
+ lockd_set_file_lock_range3(fl, lock->lock_start, lock->lock_len);
+
+ mode = lock_to_openmode(fl);
+ if (is_test)
+ mode = O_RDWR;
+
+ error = nlm_lookup_file(rqstp, &file, lock, mode);
+ switch (error) {
+ case nlm_granted:
+ break;
+ case nlm__int__stale_fh:
+ case nlm__int__failed:
+ return nlm_lck_denied_nolocks;
+ default:
+ return error;
+ }
+ *filp = file;
-#define NLMDBG_FACILITY NLMDBG_CLIENT
+ fl->c.flc_flags = FL_POSIX;
+ if (is_test)
+ fl->c.flc_file = nlmsvc_file_file(file);
+ else
+ fl->c.flc_file = file->f_file[mode];
+ fl->c.flc_pid = current->tgid;
+ fl->fl_lmops = &nlmsvc_lock_operations;
+ nlmsvc_locks_init_private(fl, host, (pid_t)lock->svid);
+ if (!fl->c.flc_owner)
+ return nlm_lck_denied_nolocks;
+
+ return nlm_granted;
+}
-#ifdef CONFIG_LOCKD_V4
static inline __be32 cast_status(__be32 status)
{
switch (status) {
@@ -32,275 +217,330 @@ static inline __be32 cast_status(__be32 status)
status = nlm_lck_denied;
break;
default:
+ pr_warn_once("lockd: unhandled internal status %u\n",
+ be32_to_cpu(status));
status = nlm_lck_denied_nolocks;
- }
-
- return status;
-}
-#else
-static inline __be32 cast_status(__be32 status)
-{
- 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
-
-/*
- * Obtain client and file from arguments
- */
-static __be32
-nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
- struct nlm_host **hostp, struct nlm_file **filp)
-{
- struct nlm_host *host = NULL;
- struct nlm_file *file = NULL;
- struct nlm_lock *lock = &argp->lock;
- int mode;
- __be32 error = 0;
-
- /* nfsd callbacks must have been installed for this procedure */
- if (!nlmsvc_ops)
- return nlm_lck_denied_nolocks;
- /* Obtain host handle */
- if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len))
- || (argp->monitor && nsm_monitor(host) < 0))
- goto no_locks;
- *hostp = host;
-
- /* Obtain file pointer. Not used by FREE_ALL call. */
- if (filp != NULL) {
- error = cast_status(nlm_lookup_file(rqstp, &file, lock));
- if (error != 0)
- goto no_locks;
- *filp = file;
-
- /* Set up the missing parts of the file_lock structure */
- mode = lock_to_openmode(&lock->fl);
- lock->fl.c.flc_flags = FL_POSIX;
- lock->fl.c.flc_file = file->f_file[mode];
- lock->fl.c.flc_pid = current->tgid;
- lock->fl.fl_lmops = &nlmsvc_lock_operations;
- nlmsvc_locks_init_private(&lock->fl, host, (pid_t)lock->svid);
- if (!lock->fl.c.flc_owner) {
- /* lockowner allocation has failed */
- nlmsvc_release_host(host);
- return nlm_lck_denied_nolocks;
- }
- }
-
- return 0;
-
-no_locks:
- nlmsvc_release_host(host);
- if (error)
- return error;
- return nlm_lck_denied_nolocks;
-}
-
-/*
- * NULL: Test for presence of service
+/**
+ * nlmsvc_proc_null - NULL: Test for presence of service
+ * @rqstp: RPC transaction context
+ *
+ * Return:
+ * %rpc_success: RPC executed successfully
+ *
+ * RPC synopsis:
+ * void NLM_NULL(void) = 0;
*/
-static __be32
-nlmsvc_proc_null(struct svc_rqst *rqstp)
+static __be32 nlmsvc_proc_null(struct svc_rqst *rqstp)
{
- dprintk("lockd: NULL called\n");
return rpc_success;
}
-/*
- * TEST: Check for conflicting lock
+/**
+ * nlmsvc_proc_test - TEST: Check for conflicting lock
+ * @rqstp: RPC transaction context
+ *
+ * Returns:
+ * %rpc_success: RPC executed successfully.
+ * %rpc_drop_reply: Do not send an RPC reply.
+ *
+ * RPC synopsis:
+ * nlm_testres NLM_TEST(nlm_testargs) = 1;
+ *
+ * Permissible procedure status codes:
+ * %LCK_GRANTED: The server would be able to grant the
+ * requested lock.
+ * %LCK_DENIED: The requested lock conflicted with existing
+ * lock reservations for the file.
+ * %LCK_DENIED_NOLOCKS: The server could not allocate the resources
+ * needed to process the request.
+ * %LCK_DENIED_GRACE_PERIOD: The server has recently restarted and is
+ * re-establishing existing locks, and is not
+ * yet ready to accept normal service requests.
*/
-static __be32
-__nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
+static __be32 nlmsvc_proc_test(struct svc_rqst *rqstp)
{
- struct nlm_args *argp = rqstp->rq_argp;
+ struct nlm_testargs_wrapper *argp = rqstp->rq_argp;
+ unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK;
+ struct nlm_testres_wrapper *resp = rqstp->rq_resp;
+ struct nlm_file *file = NULL;
struct nlm_host *host;
- struct nlm_file *file;
- __be32 rc = rpc_success;
- dprintk("lockd: TEST called\n");
- resp->cookie = argp->cookie;
+ resp->xdrgen.cookie = argp->xdrgen.cookie;
- /* Obtain client and file */
- if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
- return resp->status == nlm__int__drop_reply ?
- rpc_drop_reply : rpc_success;
+ resp->xdrgen.test_stat.stat = nlm_lck_denied_nolocks;
+ host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
+ if (!host)
+ goto out;
- /* Now check for conflicting locks */
- resp->status = cast_status(nlmsvc_testlock(rqstp, file, host,
- &argp->lock, &resp->lock));
- if (resp->status == nlm__int__drop_reply)
- rc = rpc_drop_reply;
- else
- dprintk("lockd: TEST status %d vers %d\n",
- ntohl(resp->status), rqstp->rq_vers);
+ resp->xdrgen.test_stat.stat =
+ nlm3svc_lookup_file(rqstp, host, &argp->lock, &file,
+ &argp->xdrgen.alock, type);
+ if (resp->xdrgen.test_stat.stat)
+ goto out;
+ resp->xdrgen.test_stat.stat =
+ cast_status(nlmsvc_testlock(rqstp, file, host, &argp->lock,
+ &resp->lock));
nlmsvc_release_lockowner(&argp->lock);
- nlmsvc_release_host(host);
- nlm_release_file(file);
- return rc;
-}
-static __be32
-nlmsvc_proc_test(struct svc_rqst *rqstp)
-{
- return __nlmsvc_proc_test(rqstp, rqstp->rq_resp);
+ if (resp->xdrgen.test_stat.stat == nlm_lck_denied) {
+ struct lockd_lock *conf = &resp->lock;
+ struct nlm_holder *holder = &resp->xdrgen.test_stat.u.holder;
+
+ holder->exclusive = (conf->fl.c.flc_type != F_RDLCK);
+ holder->uppid = conf->svid;
+ holder->oh.len = conf->oh.len;
+ holder->oh.data = conf->oh.data;
+ holder->l_offset = min_t(loff_t, conf->fl.fl_start,
+ NLM_OFFSET_MAX);
+ if (conf->fl.fl_end == OFFSET_MAX)
+ holder->l_len = 0;
+ else
+ holder->l_len = min_t(loff_t,
+ conf->fl.fl_end -
+ conf->fl.fl_start + 1,
+ NLM_OFFSET_MAX);
+ }
+
+out:
+ if (file)
+ nlm_release_file(file);
+ nlmsvc_release_host(host);
+ return resp->xdrgen.test_stat.stat == nlm__int__drop_reply ?
+ rpc_drop_reply : rpc_success;
}
static __be32
-__nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_res *resp)
+nlmsvc_do_lock(struct svc_rqst *rqstp, bool monitored)
{
- struct nlm_args *argp = rqstp->rq_argp;
- struct nlm_host *host;
- struct nlm_file *file;
- __be32 rc = rpc_success;
-
- dprintk("lockd: LOCK called\n");
-
- resp->cookie = argp->cookie;
-
- /* Obtain client and file */
- if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
- return resp->status == nlm__int__drop_reply ?
- rpc_drop_reply : rpc_success;
-
- /* Now try to lock the file */
- resp->status = cast_status(nlmsvc_lock(rqstp, file, host, &argp->lock,
- argp->block, &argp->cookie,
- argp->reclaim));
- if (resp->status == nlm__int__drop_reply)
- rc = rpc_drop_reply;
- else
- dprintk("lockd: LOCK status %d\n", ntohl(resp->status));
+ struct nlm_lockargs_wrapper *argp = rqstp->rq_argp;
+ unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK;
+ struct nlm_res_wrapper *resp = rqstp->rq_resp;
+ struct nlm_file *file = NULL;
+ struct nlm_host *host = NULL;
+
+ resp->xdrgen.cookie = argp->xdrgen.cookie;
+
+ resp->xdrgen.stat.stat = nlm_netobj_to_cookie(&argp->cookie,
+ &argp->xdrgen.cookie);
+ if (resp->xdrgen.stat.stat)
+ goto out;
+
+ resp->xdrgen.stat.stat = nlm_lck_denied_nolocks;
+ host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name,
+ monitored);
+ if (!host)
+ goto out;
+
+ resp->xdrgen.stat.stat = nlm3svc_lookup_file(rqstp, host, &argp->lock,
+ &file, &argp->xdrgen.alock,
+ type);
+ if (resp->xdrgen.stat.stat)
+ goto out;
+
+ resp->xdrgen.stat.stat = cast_status(nlmsvc_lock(rqstp, file, host,
+ &argp->lock,
+ argp->xdrgen.block,
+ &argp->cookie,
+ argp->xdrgen.reclaim));
nlmsvc_release_lockowner(&argp->lock);
+
+out:
+ if (file)
+ nlm_release_file(file);
nlmsvc_release_host(host);
- nlm_release_file(file);
- return rc;
+ return resp->xdrgen.stat.stat == nlm__int__drop_reply ?
+ rpc_drop_reply : rpc_success;
}
+/**
+ * nlmsvc_proc_lock - LOCK: Establish a monitored lock
+ * @rqstp: RPC transaction context
+ *
+ * Returns:
+ * %rpc_success: RPC executed successfully.
+ * %rpc_drop_reply: Do not send an RPC reply.
+ *
+ * RPC synopsis:
+ * nlm_res NLM_LOCK(nlm_lockargs) = 2;
+ *
+ * Permissible procedure status codes:
+ * %LCK_GRANTED: The requested lock was granted.
+ * %LCK_DENIED: The requested lock conflicted with existing
+ * lock reservations for the file.
+ * %LCK_DENIED_NOLOCKS: The server could not allocate the resources
+ * needed to process the request.
+ * %LCK_BLOCKED: The blocking request cannot be granted
+ * immediately. The server will send an
+ * NLM_GRANTED callback to the client when
+ * the lock can be granted.
+ * %LCK_DENIED_GRACE_PERIOD: The server has recently restarted and is
+ * re-establishing existing locks, and is not
+ * yet ready to accept normal service requests.
+ */
static __be32
nlmsvc_proc_lock(struct svc_rqst *rqstp)
{
- return __nlmsvc_proc_lock(rqstp, rqstp->rq_resp);
+ return nlmsvc_do_lock(rqstp, true);
}
+/**
+ * nlmsvc_proc_cancel - CANCEL: Cancel an outstanding blocked lock request
+ * @rqstp: RPC transaction context
+ *
+ * Returns:
+ * %rpc_success: RPC executed successfully.
+ * %rpc_drop_reply: Do not send an RPC reply.
+ *
+ * RPC synopsis:
+ * nlm_res NLM_CANCEL(nlm_cancargs) = 3;
+ *
+ * Permissible procedure status codes:
+ * %LCK_GRANTED: The requested lock was canceled.
+ * %LCK_DENIED: There was no lock to cancel.
+ * %LCK_DENIED_GRACE_PERIOD: The server has recently restarted and is
+ * re-establishing existing locks, and is not
+ * yet ready to accept normal service requests.
+ *
+ * The Linux NLM server implementation also returns:
+ * %LCK_DENIED_NOLOCKS: A needed resource could not be allocated.
+ */
static __be32
-__nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_res *resp)
+nlmsvc_proc_cancel(struct svc_rqst *rqstp)
{
- struct nlm_args *argp = rqstp->rq_argp;
- struct nlm_host *host;
- struct nlm_file *file;
+ struct nlm_cancargs_wrapper *argp = rqstp->rq_argp;
+ unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK;
+ struct nlm_res_wrapper *resp = rqstp->rq_resp;
struct net *net = SVC_NET(rqstp);
+ struct nlm_host *host = NULL;
+ struct nlm_file *file = NULL;
- dprintk("lockd: CANCEL called\n");
+ resp->xdrgen.cookie = argp->xdrgen.cookie;
- resp->cookie = argp->cookie;
-
- /* Don't accept requests during grace period */
- if (locks_in_grace(net)) {
- resp->status = nlm_lck_denied_grace_period;
- return rpc_success;
- }
+ resp->xdrgen.stat.stat = nlm_lck_denied_grace_period;
+ if (locks_in_grace(net))
+ goto out;
- /* Obtain client and file */
- if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
- return resp->status == nlm__int__drop_reply ?
- rpc_drop_reply : rpc_success;
+ resp->xdrgen.stat.stat = nlm_lck_denied_nolocks;
+ host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
+ if (!host)
+ goto out;
- /* Try to cancel request. */
- resp->status = cast_status(nlmsvc_cancel_blocked(net, file, &argp->lock));
+ resp->xdrgen.stat.stat = nlm3svc_lookup_file(rqstp, host, &argp->lock,
+ &file, &argp->xdrgen.alock,
+ type);
+ if (resp->xdrgen.stat.stat)
+ goto out;
- dprintk("lockd: CANCEL status %d\n", ntohl(resp->status));
+ resp->xdrgen.stat.stat = nlmsvc_cancel_blocked(net, file, &argp->lock);
nlmsvc_release_lockowner(&argp->lock);
- nlmsvc_release_host(host);
- nlm_release_file(file);
- return rpc_success;
-}
-static __be32
-nlmsvc_proc_cancel(struct svc_rqst *rqstp)
-{
- return __nlmsvc_proc_cancel(rqstp, rqstp->rq_resp);
+out:
+ if (file)
+ nlm_release_file(file);
+ nlmsvc_release_host(host);
+ return resp->xdrgen.stat.stat == nlm__int__drop_reply ?
+ rpc_drop_reply : rpc_success;
}
-/*
- * UNLOCK: release a lock
+/**
+ * nlmsvc_proc_unlock - UNLOCK: Remove a lock
+ * @rqstp: RPC transaction context
+ *
+ * Returns:
+ * %rpc_success: RPC executed successfully.
+ * %rpc_drop_reply: Do not send an RPC reply.
+ *
+ * RPC synopsis:
+ * nlm_res NLM_UNLOCK(nlm_unlockargs) = 4;
+ *
+ * Permissible procedure status codes:
+ * %LCK_GRANTED: The requested lock was released.
+ * %LCK_DENIED_GRACE_PERIOD: The server has recently restarted and is
+ * re-establishing existing locks, and is not
+ * yet ready to accept normal service requests.
+ *
+ * The Linux NLM server implementation also returns:
+ * %LCK_DENIED_NOLOCKS: A needed resource could not be allocated.
*/
static __be32
-__nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_res *resp)
+nlmsvc_proc_unlock(struct svc_rqst *rqstp)
{
- struct nlm_args *argp = rqstp->rq_argp;
- struct nlm_host *host;
- struct nlm_file *file;
+ struct nlm_unlockargs_wrapper *argp = rqstp->rq_argp;
+ struct nlm_res_wrapper *resp = rqstp->rq_resp;
struct net *net = SVC_NET(rqstp);
+ struct nlm_host *host = NULL;
+ struct nlm_file *file = NULL;
- dprintk("lockd: UNLOCK called\n");
+ resp->xdrgen.cookie = argp->xdrgen.cookie;
- resp->cookie = argp->cookie;
+ resp->xdrgen.stat.stat = nlm_lck_denied_grace_period;
+ if (locks_in_grace(net))
+ goto out;
- /* Don't accept new lock requests during grace period */
- if (locks_in_grace(net)) {
- resp->status = nlm_lck_denied_grace_period;
- return rpc_success;
- }
-
- /* Obtain client and file */
- if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
- return resp->status == nlm__int__drop_reply ?
- rpc_drop_reply : rpc_success;
+ resp->xdrgen.stat.stat = nlm_lck_denied_nolocks;
+ host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
+ if (!host)
+ goto out;
- /* Now try to remove the lock */
- resp->status = cast_status(nlmsvc_unlock(net, file, &argp->lock));
+ resp->xdrgen.stat.stat = nlm3svc_lookup_file(rqstp, host, &argp->lock,
+ &file, &argp->xdrgen.alock,
+ F_UNLCK);
+ if (resp->xdrgen.stat.stat)
+ goto out;
- dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status));
+ resp->xdrgen.stat.stat = nlmsvc_unlock(net, file, &argp->lock);
nlmsvc_release_lockowner(&argp->lock);
- nlmsvc_release_host(host);
- nlm_release_file(file);
- return rpc_success;
-}
-static __be32
-nlmsvc_proc_unlock(struct svc_rqst *rqstp)
-{
- return __nlmsvc_proc_unlock(rqstp, rqstp->rq_resp);
+out:
+ if (file)
+ nlm_release_file(file);
+ nlmsvc_release_host(host);
+ return resp->xdrgen.stat.stat == nlm__int__drop_reply ?
+ rpc_drop_reply : rpc_success;
}
-/*
- * GRANTED: A server calls us to tell that a process' lock request
- * was granted
+/**
+ * nlmsvc_proc_granted - GRANTED: Blocked lock has been granted
+ * @rqstp: RPC transaction context
+ *
+ * Returns:
+ * %rpc_success: RPC executed successfully.
+ *
+ * RPC synopsis:
+ * nlm_res NLM_GRANTED(nlm_testargs) = 5;
+ *
+ * Permissible procedure status codes:
+ * %LCK_GRANTED: The granted lock was accepted.
+ * %LCK_DENIED: The procedure failed, possibly due to
+ * internal resource constraints.
+ * %LCK_DENIED_GRACE_PERIOD: The client host recently restarted and
+ * its NLM is re-establishing existing locks,
+ * so it is not yet ready to accept callbacks.
*/
static __be32
-__nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_res *resp)
+nlmsvc_proc_granted(struct svc_rqst *rqstp)
{
- struct nlm_args *argp = rqstp->rq_argp;
+ struct nlm_testargs_wrapper *argp = rqstp->rq_argp;
+ struct nlm_res_wrapper *resp = rqstp->rq_resp;
- resp->cookie = argp->cookie;
+ resp->xdrgen.cookie = argp->xdrgen.cookie;
- dprintk("lockd: GRANTED called\n");
- resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock);
- dprintk("lockd: GRANTED status %d\n", ntohl(resp->status));
- return rpc_success;
-}
+ resp->xdrgen.stat.stat = nlm_lock_to_lockd_lock(&argp->lock,
+ &argp->xdrgen.alock);
+ if (resp->xdrgen.stat.stat)
+ goto out;
-static __be32
-nlmsvc_proc_granted(struct svc_rqst *rqstp)
-{
- return __nlmsvc_proc_granted(rqstp, rqstp->rq_resp);
+ resp->xdrgen.stat.stat = nlmclnt_grant(svc_addr(rqstp), &argp->lock);
+
+out:
+ return rpc_success;
}
/*
@@ -333,20 +573,13 @@ static const struct rpc_call_ops nlmsvc_callback_ops = {
* because we send the callback before the reply proper. I hope this
* doesn't break any clients.
*/
-static __be32 nlmsvc_callback(struct svc_rqst *rqstp, u32 proc,
- __be32 (*func)(struct svc_rqst *, struct nlm_res *))
+static __be32
+nlmsvc_callback(struct svc_rqst *rqstp, struct nlm_host *host, u32 proc,
+ __be32 (*func)(struct svc_rqst *, struct lockd_res *))
{
- struct nlm_args *argp = rqstp->rq_argp;
- struct nlm_host *host;
struct nlm_rqst *call;
__be32 stat;
- host = nlmsvc_lookup_host(rqstp,
- argp->lock.caller,
- argp->lock.len);
- if (host == NULL)
- return rpc_system_err;
-
call = nlm_alloc_call(host);
nlmsvc_release_host(host);
if (call == NULL)
@@ -364,440 +597,822 @@ static __be32 nlmsvc_callback(struct svc_rqst *rqstp, u32 proc,
return rpc_success;
}
-static __be32 nlmsvc_proc_test_msg(struct svc_rqst *rqstp)
+static __be32
+__nlmsvc_proc_test_msg(struct svc_rqst *rqstp, struct lockd_res *resp)
{
- dprintk("lockd: TEST_MSG called\n");
- return nlmsvc_callback(rqstp, NLMPROC_TEST_RES, __nlmsvc_proc_test);
+ struct nlm_testargs_wrapper *argp = rqstp->rq_argp;
+ unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK;
+ struct nlm_lockowner *owner;
+ struct nlm_file *file = NULL;
+ struct nlm_host *host = NULL;
+
+ resp->status = nlm_lck_denied_nolocks;
+ if (nlm_netobj_to_cookie(&resp->cookie, &argp->xdrgen.cookie))
+ goto out;
+
+ host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
+ if (!host)
+ goto out;
+
+ resp->status = nlm3svc_lookup_file(rqstp, host, &argp->lock,
+ &file, &argp->xdrgen.alock, type);
+ if (resp->status)
+ goto out;
+
+ owner = argp->lock.fl.c.flc_owner;
+ resp->status = cast_status(nlmsvc_testlock(rqstp, file, host,
+ &argp->lock, &resp->lock));
+ nlmsvc_put_lockowner(owner);
+
+out:
+ if (file)
+ nlm_release_file(file);
+ nlmsvc_release_host(host);
+ return resp->status == nlm__int__drop_reply ? rpc_drop_reply : rpc_success;
}
-static __be32 nlmsvc_proc_lock_msg(struct svc_rqst *rqstp)
+/**
+ * nlmsvc_proc_test_msg - TEST_MSG: Check for conflicting lock
+ * @rqstp: RPC transaction context
+ *
+ * Returns:
+ * %rpc_success: RPC executed successfully.
+ * %rpc_drop_reply: Do not send an RPC reply.
+ * %rpc_garbage_args: The request arguments are malformed.
+ * %rpc_system_err: RPC execution failed.
+ *
+ * RPC synopsis:
+ * void NLMPROC_TEST_MSG(nlm_testargs) = 6;
+ *
+ * The response to this request is delivered via the TEST_RES procedure.
+ */
+static __be32 nlmsvc_proc_test_msg(struct svc_rqst *rqstp)
{
- dprintk("lockd: LOCK_MSG called\n");
- return nlmsvc_callback(rqstp, NLMPROC_LOCK_RES, __nlmsvc_proc_lock);
+ struct nlm_testargs_wrapper *argp = rqstp->rq_argp;
+ struct nlm_host *host;
+
+ if (argp->xdrgen.cookie.len > NLM_MAXCOOKIELEN)
+ return rpc_garbage_args;
+
+ host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
+ if (!host)
+ return rpc_system_err;
+
+ return nlmsvc_callback(rqstp, host, NLMPROC_TEST_RES,
+ __nlmsvc_proc_test_msg);
}
-static __be32 nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp)
+static __be32
+__nlmsvc_proc_lock_msg(struct svc_rqst *rqstp, struct lockd_res *resp)
{
- dprintk("lockd: CANCEL_MSG called\n");
- return nlmsvc_callback(rqstp, NLMPROC_CANCEL_RES, __nlmsvc_proc_cancel);
+ struct nlm_lockargs_wrapper *argp = rqstp->rq_argp;
+ unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK;
+ struct nlm_file *file = NULL;
+ struct nlm_host *host = NULL;
+
+ resp->status = nlm_lck_denied_nolocks;
+ if (nlm_netobj_to_cookie(&resp->cookie, &argp->xdrgen.cookie))
+ goto out;
+
+ host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, true);
+ if (!host)
+ goto out;
+
+ resp->status = nlm3svc_lookup_file(rqstp, host, &argp->lock,
+ &file, &argp->xdrgen.alock, type);
+ if (resp->status)
+ goto out;
+
+ resp->status = cast_status(nlmsvc_lock(rqstp, file, host, &argp->lock,
+ argp->xdrgen.block, &resp->cookie,
+ argp->xdrgen.reclaim));
+ nlmsvc_release_lockowner(&argp->lock);
+
+out:
+ if (file)
+ nlm_release_file(file);
+ nlmsvc_release_host(host);
+ return resp->status == nlm__int__drop_reply ? rpc_drop_reply : rpc_success;
}
-static __be32
-nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp)
+/**
+ * nlmsvc_proc_lock_msg - LOCK_MSG: Establish a monitored lock
+ * @rqstp: RPC transaction context
+ *
+ * Returns:
+ * %rpc_success: RPC executed successfully.
+ * %rpc_drop_reply: Do not send an RPC reply.
+ * %rpc_garbage_args: The request arguments are malformed.
+ * %rpc_system_err: RPC execution failed.
+ *
+ * RPC synopsis:
+ * void NLMPROC_LOCK_MSG(nlm_lockargs) = 7;
+ *
+ * The response to this request is delivered via the LOCK_RES procedure.
+ */
+static __be32 nlmsvc_proc_lock_msg(struct svc_rqst *rqstp)
{
- dprintk("lockd: UNLOCK_MSG called\n");
- return nlmsvc_callback(rqstp, NLMPROC_UNLOCK_RES, __nlmsvc_proc_unlock);
+ struct nlm_lockargs_wrapper *argp = rqstp->rq_argp;
+ struct nlm_host *host;
+
+ if (argp->xdrgen.cookie.len > NLM_MAXCOOKIELEN)
+ return rpc_garbage_args;
+
+ host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
+ if (!host)
+ return rpc_system_err;
+
+ return nlmsvc_callback(rqstp, host, NLMPROC_LOCK_RES,
+ __nlmsvc_proc_lock_msg);
}
static __be32
-nlmsvc_proc_granted_msg(struct svc_rqst *rqstp)
+__nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp, struct lockd_res *resp)
{
- dprintk("lockd: GRANTED_MSG called\n");
- return nlmsvc_callback(rqstp, NLMPROC_GRANTED_RES, __nlmsvc_proc_granted);
+ struct nlm_cancargs_wrapper *argp = rqstp->rq_argp;
+ unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK;
+ struct net *net = SVC_NET(rqstp);
+ struct nlm_file *file = NULL;
+ struct nlm_host *host = NULL;
+
+ resp->status = nlm_lck_denied_nolocks;
+ if (nlm_netobj_to_cookie(&resp->cookie, &argp->xdrgen.cookie))
+ goto out;
+
+ resp->status = nlm_lck_denied_grace_period;
+ if (locks_in_grace(net))
+ goto out;
+
+ resp->status = nlm_lck_denied_nolocks;
+ host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
+ if (!host)
+ goto out;
+
+ resp->status = nlm3svc_lookup_file(rqstp, host, &argp->lock,
+ &file, &argp->xdrgen.alock, type);
+ if (resp->status)
+ goto out;
+
+ resp->status = nlmsvc_cancel_blocked(net, file, &argp->lock);
+ nlmsvc_release_lockowner(&argp->lock);
+
+out:
+ if (file)
+ nlm_release_file(file);
+ nlmsvc_release_host(host);
+ return resp->status == nlm__int__drop_reply ? rpc_drop_reply : rpc_success;
}
-/*
- * SHARE: create a DOS share or alter existing share.
+/**
+ * nlmsvc_proc_cancel_msg - CANCEL_MSG: Cancel an outstanding lock request
+ * @rqstp: RPC transaction context
+ *
+ * Returns:
+ * %rpc_success: RPC executed successfully.
+ * %rpc_drop_reply: Do not send an RPC reply.
+ * %rpc_garbage_args: The request arguments are malformed.
+ * %rpc_system_err: RPC execution failed.
+ *
+ * RPC synopsis:
+ * void NLMPROC_CANCEL_MSG(nlm_cancargs) = 8;
+ *
+ * The response to this request is delivered via the CANCEL_RES procedure.
*/
-static __be32
-nlmsvc_proc_share(struct svc_rqst *rqstp)
+static __be32 nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp)
{
- struct nlm_args *argp = rqstp->rq_argp;
- struct nlm_res *resp = rqstp->rq_resp;
- struct nlm_host *host;
- struct nlm_file *file;
+ struct nlm_cancargs_wrapper *argp = rqstp->rq_argp;
+ struct nlm_host *host;
- dprintk("lockd: SHARE called\n");
+ if (argp->xdrgen.cookie.len > NLM_MAXCOOKIELEN)
+ return rpc_garbage_args;
- resp->cookie = argp->cookie;
+ host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
+ if (!host)
+ return rpc_system_err;
- /* Don't accept new lock requests during grace period */
- if (locks_in_grace(SVC_NET(rqstp)) && !argp->reclaim) {
- resp->status = nlm_lck_denied_grace_period;
- return rpc_success;
- }
+ return nlmsvc_callback(rqstp, host, NLMPROC_CANCEL_RES,
+ __nlmsvc_proc_cancel_msg);
+}
- /* Obtain client and file */
- if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
- return resp->status == nlm__int__drop_reply ?
- rpc_drop_reply : rpc_success;
+static __be32
+__nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp, struct lockd_res *resp)
+{
+ struct nlm_unlockargs_wrapper *argp = rqstp->rq_argp;
+ struct net *net = SVC_NET(rqstp);
+ struct nlm_file *file = NULL;
+ struct nlm_host *host = NULL;
+
+ resp->status = nlm_lck_denied_nolocks;
+ if (nlm_netobj_to_cookie(&resp->cookie, &argp->xdrgen.cookie))
+ goto out;
+
+ resp->status = nlm_lck_denied_grace_period;
+ if (locks_in_grace(net))
+ goto out;
- /* Now try to create the share */
- resp->status = cast_status(nlmsvc_share_file(host, file, &argp->lock.oh,
- argp->fsm_access,
- argp->fsm_mode));
+ resp->status = nlm_lck_denied_nolocks;
+ host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
+ if (!host)
+ goto out;
- dprintk("lockd: SHARE status %d\n", ntohl(resp->status));
+ resp->status = nlm3svc_lookup_file(rqstp, host, &argp->lock,
+ &file, &argp->xdrgen.alock, F_UNLCK);
+ if (resp->status)
+ goto out;
+
+ resp->status = nlmsvc_unlock(net, file, &argp->lock);
nlmsvc_release_lockowner(&argp->lock);
+
+out:
+ if (file)
+ nlm_release_file(file);
nlmsvc_release_host(host);
- nlm_release_file(file);
- return rpc_success;
+ return resp->status == nlm__int__drop_reply ? rpc_drop_reply : rpc_success;
}
-/*
- * UNSHARE: Release a DOS share.
+/**
+ * nlmsvc_proc_unlock_msg - UNLOCK_MSG: Remove an existing lock
+ * @rqstp: RPC transaction context
+ *
+ * Returns:
+ * %rpc_success: RPC executed successfully.
+ * %rpc_drop_reply: Do not send an RPC reply.
+ * %rpc_garbage_args: The request arguments are malformed.
+ * %rpc_system_err: RPC execution failed.
+ *
+ * RPC synopsis:
+ * void NLMPROC_UNLOCK_MSG(nlm_unlockargs) = 9;
+ *
+ * The response to this request is delivered via the UNLOCK_RES procedure.
*/
-static __be32
-nlmsvc_proc_unshare(struct svc_rqst *rqstp)
+static __be32 nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp)
{
- struct nlm_args *argp = rqstp->rq_argp;
- struct nlm_res *resp = rqstp->rq_resp;
- struct nlm_host *host;
- struct nlm_file *file;
+ struct nlm_unlockargs_wrapper *argp = rqstp->rq_argp;
+ struct nlm_host *host;
- dprintk("lockd: UNSHARE called\n");
+ if (argp->xdrgen.cookie.len > NLM_MAXCOOKIELEN)
+ return rpc_garbage_args;
- resp->cookie = argp->cookie;
+ host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
+ if (!host)
+ return rpc_system_err;
- /* Don't accept requests during grace period */
- if (locks_in_grace(SVC_NET(rqstp))) {
- resp->status = nlm_lck_denied_grace_period;
- return rpc_success;
- }
+ return nlmsvc_callback(rqstp, host, NLMPROC_UNLOCK_RES,
+ __nlmsvc_proc_unlock_msg);
+}
- /* Obtain client and file */
- if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
- return resp->status == nlm__int__drop_reply ?
- rpc_drop_reply : rpc_success;
+static __be32
+__nlmsvc_proc_granted_msg(struct svc_rqst *rqstp, struct lockd_res *resp)
+{
+ struct nlm_testargs_wrapper *argp = rqstp->rq_argp;
- /* Now try to unshare the file */
- resp->status = cast_status(nlmsvc_unshare_file(host, file,
- &argp->lock.oh));
+ resp->status = nlm_lck_denied;
+ if (nlm_netobj_to_cookie(&resp->cookie, &argp->xdrgen.cookie))
+ goto out;
- dprintk("lockd: UNSHARE status %d\n", ntohl(resp->status));
- nlmsvc_release_lockowner(&argp->lock);
- nlmsvc_release_host(host);
- nlm_release_file(file);
+ if (nlm_lock_to_lockd_lock(&argp->lock, &argp->xdrgen.alock))
+ goto out;
+
+ resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock);
+
+out:
return rpc_success;
}
-/*
- * NM_LOCK: Create an unmonitored lock
+/**
+ * nlmsvc_proc_granted_msg - GRANTED_MSG: Blocked lock has been granted
+ * @rqstp: RPC transaction context
+ *
+ * Returns:
+ * %rpc_success: RPC executed successfully.
+ * %rpc_garbage_args: The request arguments are malformed.
+ * %rpc_system_err: RPC execution failed.
+ *
+ * RPC synopsis:
+ * void NLMPROC_GRANTED_MSG(nlm_testargs) = 10;
+ *
+ * The response to this request is delivered via the GRANTED_RES procedure.
*/
-static __be32
-nlmsvc_proc_nm_lock(struct svc_rqst *rqstp)
+static __be32 nlmsvc_proc_granted_msg(struct svc_rqst *rqstp)
{
- struct nlm_args *argp = rqstp->rq_argp;
+ struct nlm_testargs_wrapper *argp = rqstp->rq_argp;
+ struct nlm_host *host;
- dprintk("lockd: NM_LOCK called\n");
+ if (argp->xdrgen.cookie.len > NLM_MAXCOOKIELEN)
+ return rpc_garbage_args;
- argp->monitor = 0; /* just clean the monitor flag */
- return nlmsvc_proc_lock(rqstp);
+ host = nlmsvc_lookup_host(rqstp, argp->xdrgen.alock.caller_name.data,
+ argp->xdrgen.alock.caller_name.len);
+ if (!host)
+ return rpc_system_err;
+
+ return nlmsvc_callback(rqstp, host, NLMPROC_GRANTED_RES,
+ __nlmsvc_proc_granted_msg);
}
-/*
- * FREE_ALL: Release all locks and shares held by client
+/**
+ * nlmsvc_proc_granted_res - GRANTED_RES: Lock Granted result
+ * @rqstp: RPC transaction context
+ *
+ * Returns:
+ * %rpc_success: RPC executed successfully.
+ *
+ * RPC synopsis:
+ * void NLMPROC_GRANTED_RES(nlm_res) = 15;
*/
-static __be32
-nlmsvc_proc_free_all(struct svc_rqst *rqstp)
+static __be32 nlmsvc_proc_granted_res(struct svc_rqst *rqstp)
{
- struct nlm_args *argp = rqstp->rq_argp;
- struct nlm_host *host;
+ struct nlm_res_wrapper *argp = rqstp->rq_argp;
- /* Obtain client */
- if (nlmsvc_retrieve_args(rqstp, argp, &host, NULL))
+ if (!rcu_access_pointer(nlmsvc_ops))
return rpc_success;
- nlmsvc_free_host_resources(host);
- nlmsvc_release_host(host);
+ if (nlm_netobj_to_cookie(&argp->cookie, &argp->xdrgen.cookie))
+ return rpc_success;
+ nlmsvc_grant_reply(&argp->cookie, argp->xdrgen.stat.stat);
+
return rpc_success;
}
-/*
- * SM_NOTIFY: private callback from statd (not part of official NLM proto)
+/**
+ * nlmsvc_proc_sm_notify - SM_NOTIFY: Peer has rebooted
+ * @rqstp: RPC transaction context
+ *
+ * Returns:
+ * %rpc_success: RPC executed successfully.
+ * %rpc_system_err: RPC execution failed.
+ *
+ * The SM_NOTIFY procedure is a private callback from Linux statd and is
+ * not part of the official NLM protocol.
+ *
+ * RPC synopsis:
+ * void NLM_SM_NOTIFY(nlm_notifyargs) = 16;
*/
-static __be32
-nlmsvc_proc_sm_notify(struct svc_rqst *rqstp)
+static __be32 nlmsvc_proc_sm_notify(struct svc_rqst *rqstp)
{
- struct nlm_reboot *argp = rqstp->rq_argp;
-
- dprintk("lockd: SM_NOTIFY called\n");
+ struct nlm_notifyargs_wrapper *argp = rqstp->rq_argp;
+ struct lockd_reboot *reboot = &argp->reboot;
if (!nlm_privileged_requester(rqstp)) {
char buf[RPC_MAX_ADDRBUFLEN];
- printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
- svc_print_addr(rqstp, buf, sizeof(buf)));
+
+ pr_warn("lockd: rejected NSM callback from %s\n",
+ svc_print_addr(rqstp, buf, sizeof(buf)));
return rpc_system_err;
}
- nlm_host_rebooted(SVC_NET(rqstp), argp);
+ reboot->len = argp->xdrgen.notify.name.len;
+ reboot->mon = (char *)argp->xdrgen.notify.name.data;
+ reboot->state = argp->xdrgen.notify.state;
+ memcpy(&reboot->priv.data, argp->xdrgen.private,
+ sizeof(reboot->priv.data));
+
+ nlm_host_rebooted(SVC_NET(rqstp), reboot);
+
return rpc_success;
}
-/*
- * client sent a GRANTED_RES, let's remove the associated block
+/**
+ * nlmsvc_proc_unused - stub for unused procedures
+ * @rqstp: RPC transaction context
+ *
+ * Returns:
+ * %rpc_proc_unavail: Program can't support procedure.
*/
-static __be32
-nlmsvc_proc_granted_res(struct svc_rqst *rqstp)
+static __be32 nlmsvc_proc_unused(struct svc_rqst *rqstp)
{
- struct nlm_res *argp = rqstp->rq_argp;
-
- if (!nlmsvc_ops)
- return rpc_success;
+ return rpc_proc_unavail;
+}
- dprintk("lockd: GRANTED_RES called\n");
+/**
+ * nlmsvc_proc_share - SHARE: Open a file using DOS file-sharing modes
+ * @rqstp: RPC transaction context
+ *
+ * Returns:
+ * %rpc_success: RPC executed successfully.
+ * %rpc_drop_reply: Do not send an RPC reply.
+ *
+ * RPC synopsis:
+ * nlm_shareres NLM_SHARE(nlm_shareargs) = 20;
+ *
+ * Permissible procedure status codes:
+ * %LCK_GRANTED: The requested share lock was granted.
+ * %LCK_DENIED: The requested lock conflicted with existing
+ * lock reservations for the file.
+ * %LCK_DENIED_GRACE_PERIOD: The server has recently restarted and is
+ * re-establishing existing locks, and is not
+ * yet ready to accept normal service requests.
+ *
+ * The Linux NLM server implementation also returns:
+ * %LCK_DENIED_NOLOCKS: A needed resource could not be allocated.
+ */
+static __be32 nlmsvc_proc_share(struct svc_rqst *rqstp)
+{
+ struct nlm_shareargs_wrapper *argp = rqstp->rq_argp;
+ struct nlm_shareres_wrapper *resp = rqstp->rq_resp;
+ struct lockd_lock *lock = &argp->lock;
+ struct nlm_host *host = NULL;
+ struct nlm_file *file = NULL;
+ struct nlm_lock xdr_lock = {
+ .fh = argp->xdrgen.share.fh,
+ .oh = argp->xdrgen.share.oh,
+ .uppid = LOCKD_SHARE_SVID,
+ };
+
+ resp->xdrgen.cookie = argp->xdrgen.cookie;
+
+ resp->xdrgen.stat = nlm_lck_denied_grace_period;
+ if (locks_in_grace(SVC_NET(rqstp)) && !argp->xdrgen.reclaim)
+ goto out;
+
+ resp->xdrgen.stat = nlm_lck_denied_nolocks;
+ host = nlm3svc_lookup_host(rqstp, argp->xdrgen.share.caller_name, false);
+ if (!host)
+ goto out;
+
+ resp->xdrgen.stat = nlm3svc_lookup_file(rqstp, host, lock, &file,
+ &xdr_lock, F_RDLCK);
+ if (resp->xdrgen.stat)
+ goto out;
+
+ resp->xdrgen.stat = nlmsvc_share_file(host, file, &lock->oh,
+ argp->xdrgen.share.access,
+ argp->xdrgen.share.mode);
+
+ nlmsvc_release_lockowner(lock);
+
+out:
+ if (file)
+ nlm_release_file(file);
+ nlmsvc_release_host(host);
+ return resp->xdrgen.stat == nlm__int__drop_reply ?
+ rpc_drop_reply : rpc_success;
+}
- nlmsvc_grant_reply(&argp->cookie, argp->status);
- return rpc_success;
+/**
+ * nlmsvc_proc_unshare - UNSHARE: Release a share reservation
+ * @rqstp: RPC transaction context
+ *
+ * Returns:
+ * %rpc_success: RPC executed successfully.
+ * %rpc_drop_reply: Do not send an RPC reply.
+ *
+ * RPC synopsis:
+ * nlm_shareres NLM_UNSHARE(nlm_shareargs) = 21;
+ *
+ * Permissible procedure status codes:
+ * %LCK_GRANTED: The share reservation was released.
+ * %LCK_DENIED_GRACE_PERIOD: The server has recently restarted and is
+ * re-establishing existing locks, and is not
+ * yet ready to accept normal service requests.
+ *
+ * The Linux NLM server implementation also returns:
+ * %LCK_DENIED_NOLOCKS: A needed resource could not be allocated.
+ */
+static __be32 nlmsvc_proc_unshare(struct svc_rqst *rqstp)
+{
+ struct nlm_shareargs_wrapper *argp = rqstp->rq_argp;
+ struct nlm_shareres_wrapper *resp = rqstp->rq_resp;
+ struct lockd_lock *lock = &argp->lock;
+ struct nlm_lock xdr_lock = {
+ .fh = argp->xdrgen.share.fh,
+ .oh = argp->xdrgen.share.oh,
+ .uppid = LOCKD_SHARE_SVID,
+ };
+ struct nlm_host *host = NULL;
+ struct nlm_file *file = NULL;
+
+ resp->xdrgen.cookie = argp->xdrgen.cookie;
+
+ resp->xdrgen.stat = nlm_lck_denied_grace_period;
+ if (locks_in_grace(SVC_NET(rqstp)))
+ goto out;
+
+ resp->xdrgen.stat = nlm_lck_denied_nolocks;
+ host = nlm3svc_lookup_host(rqstp, argp->xdrgen.share.caller_name, false);
+ if (!host)
+ goto out;
+
+ resp->xdrgen.stat = nlm3svc_lookup_file(rqstp, host, lock, &file,
+ &xdr_lock, F_RDLCK);
+ if (resp->xdrgen.stat)
+ goto out;
+
+ resp->xdrgen.stat = nlmsvc_unshare_file(host, file, &lock->oh,
+ argp->xdrgen.share.access,
+ argp->xdrgen.share.mode);
+
+ nlmsvc_release_lockowner(lock);
+
+out:
+ if (file)
+ nlm_release_file(file);
+ nlmsvc_release_host(host);
+ return resp->xdrgen.stat == nlm__int__drop_reply ?
+ rpc_drop_reply : rpc_success;
}
-static __be32
-nlmsvc_proc_unused(struct svc_rqst *rqstp)
+/**
+ * nlmsvc_proc_nm_lock - NM_LOCK: Establish a non-monitored lock
+ * @rqstp: RPC transaction context
+ *
+ * Returns:
+ * %rpc_success: RPC executed successfully.
+ * %rpc_drop_reply: Do not send an RPC reply.
+ *
+ * RPC synopsis:
+ * nlm_res NLM_NM_LOCK(nlm_lockargs) = 22;
+ *
+ * Permissible procedure status codes:
+ * %LCK_GRANTED: The requested lock was granted.
+ * %LCK_DENIED: The requested lock conflicted with existing
+ * lock reservations for the file.
+ * %LCK_DENIED_NOLOCKS: The server could not allocate the resources
+ * needed to process the request.
+ * %LCK_BLOCKED: The blocking request cannot be granted
+ * immediately. The server will send an
+ * NLM_GRANTED callback to the client when
+ * the lock can be granted.
+ * %LCK_DENIED_GRACE_PERIOD: The server has recently restarted and is
+ * re-establishing existing locks, and is not
+ * yet ready to accept normal service requests.
+ */
+static __be32 nlmsvc_proc_nm_lock(struct svc_rqst *rqstp)
{
- return rpc_proc_unavail;
+ return nlmsvc_do_lock(rqstp, false);
}
-/*
- * NLM Server procedures.
+/**
+ * nlmsvc_proc_free_all - FREE_ALL: Discard client's lock and share state
+ * @rqstp: RPC transaction context
+ *
+ * Returns:
+ * %rpc_success: RPC executed successfully.
+ *
+ * RPC synopsis:
+ * void NLMPROC_FREE_ALL(nlm_notify) = 23;
*/
+static __be32 nlmsvc_proc_free_all(struct svc_rqst *rqstp)
+{
+ struct nlm_notify_wrapper *argp = rqstp->rq_argp;
+ struct nlm_host *host;
+
+ host = nlm3svc_lookup_host(rqstp, argp->xdrgen.name, false);
+ if (!host)
+ goto out;
-struct nlm_void { int dummy; };
+ nlmsvc_free_host_resources(host);
+
+ nlmsvc_release_host(host);
+
+out:
+ return rpc_success;
+}
-#define Ck (1+XDR_QUADLEN(NLM_MAXCOOKIELEN)) /* cookie */
-#define St 1 /* status */
-#define No (1+1024/4) /* Net Obj */
-#define Rg 2 /* range - offset + size */
+/*
+ * NLMv3 Server procedures.
+ */
static const struct svc_procedure nlmsvc_procedures[24] = {
- [NLMPROC_NULL] = {
- .pc_func = nlmsvc_proc_null,
- .pc_decode = nlmsvc_decode_void,
- .pc_encode = nlmsvc_encode_void,
- .pc_argsize = sizeof(struct nlm_void),
- .pc_argzero = sizeof(struct nlm_void),
- .pc_ressize = sizeof(struct nlm_void),
- .pc_xdrressize = St,
- .pc_name = "NULL",
+ [NLM_NULL] = {
+ .pc_func = nlmsvc_proc_null,
+ .pc_decode = xdrgen_svc_decode_void,
+ .pc_encode = xdrgen_svc_encode_void,
+ .pc_argsize = XDR_void,
+ .pc_argzero = 0,
+ .pc_ressize = 0,
+ .pc_xdrressize = XDR_void,
+ .pc_name = "NULL",
},
- [NLMPROC_TEST] = {
- .pc_func = nlmsvc_proc_test,
- .pc_decode = nlmsvc_decode_testargs,
- .pc_encode = nlmsvc_encode_testres,
- .pc_argsize = sizeof(struct nlm_args),
- .pc_argzero = sizeof(struct nlm_args),
- .pc_ressize = sizeof(struct nlm_res),
- .pc_xdrressize = Ck+St+2+No+Rg,
- .pc_name = "TEST",
+ [NLM_TEST] = {
+ .pc_func = nlmsvc_proc_test,
+ .pc_decode = nlm_svc_decode_nlm_testargs,
+ .pc_encode = nlm_svc_encode_nlm_testres,
+ .pc_argsize = sizeof(struct nlm_testargs_wrapper),
+ .pc_argzero = 0,
+ .pc_ressize = sizeof(struct nlm_testres_wrapper),
+ .pc_xdrressize = NLM3_nlm_testres_sz,
+ .pc_name = "TEST",
},
- [NLMPROC_LOCK] = {
- .pc_func = nlmsvc_proc_lock,
- .pc_decode = nlmsvc_decode_lockargs,
- .pc_encode = nlmsvc_encode_res,
- .pc_argsize = sizeof(struct nlm_args),
- .pc_argzero = sizeof(struct nlm_args),
- .pc_ressize = sizeof(struct nlm_res),
- .pc_xdrressize = Ck+St,
- .pc_name = "LOCK",
+ [NLM_LOCK] = {
+ .pc_func = nlmsvc_proc_lock,
+ .pc_decode = nlm_svc_decode_nlm_lockargs,
+ .pc_encode = nlm_svc_encode_nlm_res,
+ .pc_argsize = sizeof(struct nlm_lockargs_wrapper),
+ .pc_argzero = 0,
+ .pc_ressize = sizeof(struct nlm_res_wrapper),
+ .pc_xdrressize = NLM3_nlm_res_sz,
+ .pc_name = "LOCK",
},
- [NLMPROC_CANCEL] = {
- .pc_func = nlmsvc_proc_cancel,
- .pc_decode = nlmsvc_decode_cancargs,
- .pc_encode = nlmsvc_encode_res,
- .pc_argsize = sizeof(struct nlm_args),
- .pc_argzero = sizeof(struct nlm_args),
- .pc_ressize = sizeof(struct nlm_res),
- .pc_xdrressize = Ck+St,
- .pc_name = "CANCEL",
+ [NLM_CANCEL] = {
+ .pc_func = nlmsvc_proc_cancel,
+ .pc_decode = nlm_svc_decode_nlm_cancargs,
+ .pc_encode = nlm_svc_encode_nlm_res,
+ .pc_argsize = sizeof(struct nlm_cancargs_wrapper),
+ .pc_argzero = 0,
+ .pc_ressize = sizeof(struct nlm_res_wrapper),
+ .pc_xdrressize = NLM3_nlm_res_sz,
+ .pc_name = "CANCEL",
},
- [NLMPROC_UNLOCK] = {
- .pc_func = nlmsvc_proc_unlock,
- .pc_decode = nlmsvc_decode_unlockargs,
- .pc_encode = nlmsvc_encode_res,
- .pc_argsize = sizeof(struct nlm_args),
- .pc_argzero = sizeof(struct nlm_args),
- .pc_ressize = sizeof(struct nlm_res),
- .pc_xdrressize = Ck+St,
- .pc_name = "UNLOCK",
+ [NLM_UNLOCK] = {
+ .pc_func = nlmsvc_proc_unlock,
+ .pc_decode = nlm_svc_decode_nlm_unlockargs,
+ .pc_encode = nlm_svc_encode_nlm_res,
+ .pc_argsize = sizeof(struct nlm_unlockargs_wrapper),
+ .pc_argzero = 0,
+ .pc_ressize = sizeof(struct nlm_res_wrapper),
+ .pc_xdrressize = NLM3_nlm_res_sz,
+ .pc_name = "UNLOCK",
},
- [NLMPROC_GRANTED] = {
- .pc_func = nlmsvc_proc_granted,
- .pc_decode = nlmsvc_decode_testargs,
- .pc_encode = nlmsvc_encode_res,
- .pc_argsize = sizeof(struct nlm_args),
- .pc_argzero = sizeof(struct nlm_args),
- .pc_ressize = sizeof(struct nlm_res),
- .pc_xdrressize = Ck+St,
- .pc_name = "GRANTED",
+ [NLM_GRANTED] = {
+ .pc_func = nlmsvc_proc_granted,
+ .pc_decode = nlm_svc_decode_nlm_testargs,
+ .pc_encode = nlm_svc_encode_nlm_res,
+ .pc_argsize = sizeof(struct nlm_testargs_wrapper),
+ .pc_argzero = 0,
+ .pc_ressize = sizeof(struct nlm_res_wrapper),
+ .pc_xdrressize = NLM3_nlm_res_sz,
+ .pc_name = "GRANTED",
},
- [NLMPROC_TEST_MSG] = {
- .pc_func = nlmsvc_proc_test_msg,
- .pc_decode = nlmsvc_decode_testargs,
- .pc_encode = nlmsvc_encode_void,
- .pc_argsize = sizeof(struct nlm_args),
- .pc_argzero = sizeof(struct nlm_args),
- .pc_ressize = sizeof(struct nlm_void),
- .pc_xdrressize = St,
- .pc_name = "TEST_MSG",
+ [NLM_TEST_MSG] = {
+ .pc_func = nlmsvc_proc_test_msg,
+ .pc_decode = nlm_svc_decode_nlm_testargs,
+ .pc_encode = xdrgen_svc_encode_void,
+ .pc_argsize = sizeof(struct nlm_testargs_wrapper),
+ .pc_argzero = 0,
+ .pc_ressize = 0,
+ .pc_xdrressize = XDR_void,
+ .pc_name = "TEST_MSG",
},
- [NLMPROC_LOCK_MSG] = {
- .pc_func = nlmsvc_proc_lock_msg,
- .pc_decode = nlmsvc_decode_lockargs,
- .pc_encode = nlmsvc_encode_void,
- .pc_argsize = sizeof(struct nlm_args),
- .pc_argzero = sizeof(struct nlm_args),
- .pc_ressize = sizeof(struct nlm_void),
- .pc_xdrressize = St,
- .pc_name = "LOCK_MSG",
+ [NLM_LOCK_MSG] = {
+ .pc_func = nlmsvc_proc_lock_msg,
+ .pc_decode = nlm_svc_decode_nlm_lockargs,
+ .pc_encode = xdrgen_svc_encode_void,
+ .pc_argsize = sizeof(struct nlm_lockargs_wrapper),
+ .pc_argzero = 0,
+ .pc_ressize = 0,
+ .pc_xdrressize = XDR_void,
+ .pc_name = "LOCK_MSG",
},
- [NLMPROC_CANCEL_MSG] = {
- .pc_func = nlmsvc_proc_cancel_msg,
- .pc_decode = nlmsvc_decode_cancargs,
- .pc_encode = nlmsvc_encode_void,
- .pc_argsize = sizeof(struct nlm_args),
- .pc_argzero = sizeof(struct nlm_args),
- .pc_ressize = sizeof(struct nlm_void),
- .pc_xdrressize = St,
- .pc_name = "CANCEL_MSG",
+ [NLM_CANCEL_MSG] = {
+ .pc_func = nlmsvc_proc_cancel_msg,
+ .pc_decode = nlm_svc_decode_nlm_cancargs,
+ .pc_encode = xdrgen_svc_encode_void,
+ .pc_argsize = sizeof(struct nlm_cancargs_wrapper),
+ .pc_argzero = 0,
+ .pc_ressize = 0,
+ .pc_xdrressize = XDR_void,
+ .pc_name = "CANCEL_MSG",
},
- [NLMPROC_UNLOCK_MSG] = {
- .pc_func = nlmsvc_proc_unlock_msg,
- .pc_decode = nlmsvc_decode_unlockargs,
- .pc_encode = nlmsvc_encode_void,
- .pc_argsize = sizeof(struct nlm_args),
- .pc_argzero = sizeof(struct nlm_args),
- .pc_ressize = sizeof(struct nlm_void),
- .pc_xdrressize = St,
- .pc_name = "UNLOCK_MSG",
+ [NLM_UNLOCK_MSG] = {
+ .pc_func = nlmsvc_proc_unlock_msg,
+ .pc_decode = nlm_svc_decode_nlm_unlockargs,
+ .pc_encode = xdrgen_svc_encode_void,
+ .pc_argsize = sizeof(struct nlm_unlockargs_wrapper),
+ .pc_argzero = 0,
+ .pc_ressize = 0,
+ .pc_xdrressize = XDR_void,
+ .pc_name = "UNLOCK_MSG",
},
- [NLMPROC_GRANTED_MSG] = {
- .pc_func = nlmsvc_proc_granted_msg,
- .pc_decode = nlmsvc_decode_testargs,
- .pc_encode = nlmsvc_encode_void,
- .pc_argsize = sizeof(struct nlm_args),
- .pc_argzero = sizeof(struct nlm_args),
- .pc_ressize = sizeof(struct nlm_void),
- .pc_xdrressize = St,
- .pc_name = "GRANTED_MSG",
+ [NLM_GRANTED_MSG] = {
+ .pc_func = nlmsvc_proc_granted_msg,
+ .pc_decode = nlm_svc_decode_nlm_testargs,
+ .pc_encode = xdrgen_svc_encode_void,
+ .pc_argsize = sizeof(struct nlm_testargs_wrapper),
+ .pc_argzero = 0,
+ .pc_ressize = 0,
+ .pc_xdrressize = XDR_void,
+ .pc_name = "GRANTED_MSG",
},
- [NLMPROC_TEST_RES] = {
- .pc_func = nlmsvc_proc_null,
- .pc_decode = nlmsvc_decode_void,
- .pc_encode = nlmsvc_encode_void,
- .pc_argsize = sizeof(struct nlm_res),
- .pc_argzero = sizeof(struct nlm_res),
- .pc_ressize = sizeof(struct nlm_void),
- .pc_xdrressize = St,
- .pc_name = "TEST_RES",
+ [NLM_TEST_RES] = {
+ .pc_func = nlmsvc_proc_null,
+ .pc_decode = nlm_svc_decode_nlm_testres,
+ .pc_encode = xdrgen_svc_encode_void,
+ .pc_argsize = sizeof(struct nlm_testres),
+ .pc_argzero = 0,
+ .pc_ressize = 0,
+ .pc_xdrressize = XDR_void,
+ .pc_name = "TEST_RES",
},
- [NLMPROC_LOCK_RES] = {
- .pc_func = nlmsvc_proc_null,
- .pc_decode = nlmsvc_decode_void,
- .pc_encode = nlmsvc_encode_void,
- .pc_argsize = sizeof(struct nlm_res),
- .pc_argzero = sizeof(struct nlm_res),
- .pc_ressize = sizeof(struct nlm_void),
- .pc_xdrressize = St,
- .pc_name = "LOCK_RES",
+ [NLM_LOCK_RES] = {
+ .pc_func = nlmsvc_proc_null,
+ .pc_decode = nlm_svc_decode_nlm_res,
+ .pc_encode = xdrgen_svc_encode_void,
+ .pc_argsize = sizeof(struct nlm_res),
+ .pc_argzero = 0,
+ .pc_ressize = 0,
+ .pc_xdrressize = XDR_void,
+ .pc_name = "LOCK_RES",
},
- [NLMPROC_CANCEL_RES] = {
- .pc_func = nlmsvc_proc_null,
- .pc_decode = nlmsvc_decode_void,
- .pc_encode = nlmsvc_encode_void,
- .pc_argsize = sizeof(struct nlm_res),
- .pc_argzero = sizeof(struct nlm_res),
- .pc_ressize = sizeof(struct nlm_void),
- .pc_xdrressize = St,
- .pc_name = "CANCEL_RES",
+ [NLM_CANCEL_RES] = {
+ .pc_func = nlmsvc_proc_null,
+ .pc_decode = nlm_svc_decode_nlm_res,
+ .pc_encode = xdrgen_svc_encode_void,
+ .pc_argsize = sizeof(struct nlm_res),
+ .pc_argzero = 0,
+ .pc_ressize = 0,
+ .pc_xdrressize = XDR_void,
+ .pc_name = "CANCEL_RES",
},
- [NLMPROC_UNLOCK_RES] = {
- .pc_func = nlmsvc_proc_null,
- .pc_decode = nlmsvc_decode_void,
- .pc_encode = nlmsvc_encode_void,
- .pc_argsize = sizeof(struct nlm_res),
- .pc_argzero = sizeof(struct nlm_res),
- .pc_ressize = sizeof(struct nlm_void),
- .pc_xdrressize = St,
- .pc_name = "UNLOCK_RES",
+ [NLM_UNLOCK_RES] = {
+ .pc_func = nlmsvc_proc_null,
+ .pc_decode = nlm_svc_decode_nlm_res,
+ .pc_encode = xdrgen_svc_encode_void,
+ .pc_argsize = sizeof(struct nlm_res),
+ .pc_argzero = 0,
+ .pc_ressize = 0,
+ .pc_xdrressize = XDR_void,
+ .pc_name = "UNLOCK_RES",
},
- [NLMPROC_GRANTED_RES] = {
- .pc_func = nlmsvc_proc_granted_res,
- .pc_decode = nlmsvc_decode_res,
- .pc_encode = nlmsvc_encode_void,
- .pc_argsize = sizeof(struct nlm_res),
- .pc_argzero = sizeof(struct nlm_res),
- .pc_ressize = sizeof(struct nlm_void),
- .pc_xdrressize = St,
- .pc_name = "GRANTED_RES",
+ [NLM_GRANTED_RES] = {
+ .pc_func = nlmsvc_proc_granted_res,
+ .pc_decode = nlm_svc_decode_nlm_res,
+ .pc_encode = xdrgen_svc_encode_void,
+ .pc_argsize = sizeof(struct nlm_res_wrapper),
+ .pc_argzero = 0,
+ .pc_ressize = 0,
+ .pc_xdrressize = XDR_void,
+ .pc_name = "GRANTED_RES",
},
- [NLMPROC_NSM_NOTIFY] = {
- .pc_func = nlmsvc_proc_sm_notify,
- .pc_decode = nlmsvc_decode_reboot,
- .pc_encode = nlmsvc_encode_void,
- .pc_argsize = sizeof(struct nlm_reboot),
- .pc_argzero = sizeof(struct nlm_reboot),
- .pc_ressize = sizeof(struct nlm_void),
- .pc_xdrressize = St,
- .pc_name = "SM_NOTIFY",
+ [NLM_SM_NOTIFY] = {
+ .pc_func = nlmsvc_proc_sm_notify,
+ .pc_decode = nlm_svc_decode_nlm_notifyargs,
+ .pc_encode = xdrgen_svc_encode_void,
+ .pc_argsize = sizeof(struct nlm_notifyargs_wrapper),
+ .pc_argzero = 0,
+ .pc_ressize = 0,
+ .pc_xdrressize = XDR_void,
+ .pc_name = "SM_NOTIFY",
},
[17] = {
- .pc_func = nlmsvc_proc_unused,
- .pc_decode = nlmsvc_decode_void,
- .pc_encode = nlmsvc_encode_void,
- .pc_argsize = sizeof(struct nlm_void),
- .pc_argzero = sizeof(struct nlm_void),
- .pc_ressize = sizeof(struct nlm_void),
- .pc_xdrressize = St,
- .pc_name = "UNUSED",
+ .pc_func = nlmsvc_proc_unused,
+ .pc_decode = xdrgen_svc_decode_void,
+ .pc_encode = xdrgen_svc_encode_void,
+ .pc_argsize = 0,
+ .pc_argzero = 0,
+ .pc_ressize = 0,
+ .pc_xdrressize = XDR_void,
+ .pc_name = "UNUSED",
},
[18] = {
- .pc_func = nlmsvc_proc_unused,
- .pc_decode = nlmsvc_decode_void,
- .pc_encode = nlmsvc_encode_void,
- .pc_argsize = sizeof(struct nlm_void),
- .pc_argzero = sizeof(struct nlm_void),
- .pc_ressize = sizeof(struct nlm_void),
- .pc_xdrressize = St,
- .pc_name = "UNUSED",
+ .pc_func = nlmsvc_proc_unused,
+ .pc_decode = xdrgen_svc_decode_void,
+ .pc_encode = xdrgen_svc_encode_void,
+ .pc_argsize = 0,
+ .pc_argzero = 0,
+ .pc_ressize = 0,
+ .pc_xdrressize = XDR_void,
+ .pc_name = "UNUSED",
},
[19] = {
- .pc_func = nlmsvc_proc_unused,
- .pc_decode = nlmsvc_decode_void,
- .pc_encode = nlmsvc_encode_void,
- .pc_argsize = sizeof(struct nlm_void),
- .pc_argzero = sizeof(struct nlm_void),
- .pc_ressize = sizeof(struct nlm_void),
- .pc_xdrressize = St,
- .pc_name = "UNUSED",
+ .pc_func = nlmsvc_proc_unused,
+ .pc_decode = xdrgen_svc_decode_void,
+ .pc_encode = xdrgen_svc_encode_void,
+ .pc_argsize = 0,
+ .pc_argzero = 0,
+ .pc_ressize = 0,
+ .pc_xdrressize = XDR_void,
+ .pc_name = "UNUSED",
},
- [NLMPROC_SHARE] = {
- .pc_func = nlmsvc_proc_share,
- .pc_decode = nlmsvc_decode_shareargs,
- .pc_encode = nlmsvc_encode_shareres,
- .pc_argsize = sizeof(struct nlm_args),
- .pc_argzero = sizeof(struct nlm_args),
- .pc_ressize = sizeof(struct nlm_res),
- .pc_xdrressize = Ck+St+1,
- .pc_name = "SHARE",
+ [NLM_SHARE] = {
+ .pc_func = nlmsvc_proc_share,
+ .pc_decode = nlm_svc_decode_nlm_shareargs,
+ .pc_encode = nlm_svc_encode_nlm_shareres,
+ .pc_argsize = sizeof(struct nlm_shareargs_wrapper),
+ .pc_argzero = 0,
+ .pc_ressize = sizeof(struct nlm_shareres_wrapper),
+ .pc_xdrressize = NLM3_nlm_shareres_sz,
+ .pc_name = "SHARE",
},
- [NLMPROC_UNSHARE] = {
- .pc_func = nlmsvc_proc_unshare,
- .pc_decode = nlmsvc_decode_shareargs,
- .pc_encode = nlmsvc_encode_shareres,
- .pc_argsize = sizeof(struct nlm_args),
- .pc_argzero = sizeof(struct nlm_args),
- .pc_ressize = sizeof(struct nlm_res),
- .pc_xdrressize = Ck+St+1,
- .pc_name = "UNSHARE",
+ [NLM_UNSHARE] = {
+ .pc_func = nlmsvc_proc_unshare,
+ .pc_decode = nlm_svc_decode_nlm_shareargs,
+ .pc_encode = nlm_svc_encode_nlm_shareres,
+ .pc_argsize = sizeof(struct nlm_shareargs_wrapper),
+ .pc_argzero = 0,
+ .pc_ressize = sizeof(struct nlm_shareres_wrapper),
+ .pc_xdrressize = NLM3_nlm_shareres_sz,
+ .pc_name = "UNSHARE",
},
- [NLMPROC_NM_LOCK] = {
- .pc_func = nlmsvc_proc_nm_lock,
- .pc_decode = nlmsvc_decode_lockargs,
- .pc_encode = nlmsvc_encode_res,
- .pc_argsize = sizeof(struct nlm_args),
- .pc_argzero = sizeof(struct nlm_args),
- .pc_ressize = sizeof(struct nlm_res),
- .pc_xdrressize = Ck+St,
- .pc_name = "NM_LOCK",
+ [NLM_NM_LOCK] = {
+ .pc_func = nlmsvc_proc_nm_lock,
+ .pc_decode = nlm_svc_decode_nlm_lockargs,
+ .pc_encode = nlm_svc_encode_nlm_res,
+ .pc_argsize = sizeof(struct nlm_lockargs_wrapper),
+ .pc_argzero = 0,
+ .pc_ressize = sizeof(struct nlm_res_wrapper),
+ .pc_xdrressize = NLM3_nlm_res_sz,
+ .pc_name = "NM_LOCK",
},
- [NLMPROC_FREE_ALL] = {
- .pc_func = nlmsvc_proc_free_all,
- .pc_decode = nlmsvc_decode_notify,
- .pc_encode = nlmsvc_encode_void,
- .pc_argsize = sizeof(struct nlm_args),
- .pc_argzero = sizeof(struct nlm_args),
- .pc_ressize = sizeof(struct nlm_void),
- .pc_xdrressize = 0,
- .pc_name = "FREE_ALL",
+ [NLM_FREE_ALL] = {
+ .pc_func = nlmsvc_proc_free_all,
+ .pc_decode = nlm_svc_decode_nlm_notify,
+ .pc_encode = xdrgen_svc_encode_void,
+ .pc_argsize = sizeof(struct nlm_notify_wrapper),
+ .pc_argzero = 0,
+ .pc_ressize = 0,
+ .pc_xdrressize = XDR_void,
+ .pc_name = "FREE_ALL",
},
};
@@ -805,34 +1420,34 @@ static const struct svc_procedure nlmsvc_procedures[24] = {
* Storage requirements for XDR arguments and results
*/
union nlmsvc_xdrstore {
- struct nlm_args args;
- struct nlm_res res;
- struct nlm_reboot reboot;
+ struct nlm_testargs_wrapper testargs;
+ struct nlm_lockargs_wrapper lockargs;
+ struct nlm_cancargs_wrapper cancargs;
+ struct nlm_unlockargs_wrapper unlockargs;
+ struct nlm_notifyargs_wrapper notifyargs;
+ struct nlm_shareargs_wrapper shareargs;
+ struct nlm_notify_wrapper notify;
+ struct nlm_testres_wrapper testres;
+ struct nlm_res_wrapper res;
+ struct nlm_shareres_wrapper shareres;
};
/*
* NLMv1 defines only procedures 1 - 15. Linux lockd also implements
* procedures 0 (NULL) and 16 (SM_NOTIFY).
*/
-static DEFINE_PER_CPU_ALIGNED(unsigned long, nlm1svc_call_counters[17]);
-
const struct svc_version nlmsvc_version1 = {
.vs_vers = 1,
.vs_nproc = 17,
.vs_proc = nlmsvc_procedures,
- .vs_count = nlm1svc_call_counters,
.vs_dispatch = nlmsvc_dispatch,
.vs_xdrsize = sizeof(union nlmsvc_xdrstore),
};
-static DEFINE_PER_CPU_ALIGNED(unsigned long,
- nlm3svc_call_counters[ARRAY_SIZE(nlmsvc_procedures)]);
-
const struct svc_version nlmsvc_version3 = {
.vs_vers = 3,
.vs_nproc = ARRAY_SIZE(nlmsvc_procedures),
.vs_proc = nlmsvc_procedures,
- .vs_count = nlm3svc_call_counters,
.vs_dispatch = nlmsvc_dispatch,
.vs_xdrsize = sizeof(union nlmsvc_xdrstore),
};
diff --git a/fs/lockd/svcshare.c b/fs/lockd/svcshare.c
index 53f5655c128c..a58b7035b58b 100644
--- a/fs/lockd/svcshare.c
+++ b/fs/lockd/svcshare.c
@@ -19,12 +19,31 @@
#include "share.h"
static inline int
-nlm_cmp_owner(struct nlm_share *share, struct xdr_netobj *oh)
+nlm_cmp_owner(struct lockd_share *share, struct xdr_netobj *oh)
{
return share->s_owner.len == oh->len
&& !memcmp(share->s_owner.data, oh->data, oh->len);
}
+/*
+ * Recompute s_access / s_mode as the union of every (access, deny) pair
+ * whose bit is currently set in s_access_deny_bmap.
+ */
+static void nlm_recompute_share(struct lockd_share *share)
+{
+ u32 new_access = 0, new_mode = 0;
+ unsigned int i;
+
+ for (i = 0; i < 16; i++) {
+ if (share->s_access_deny_bmap & BIT(i)) {
+ new_access |= i >> 2;
+ new_mode |= i & 3;
+ }
+ }
+ share->s_access = new_access;
+ share->s_mode = new_mode;
+}
+
/**
* nlmsvc_share_file - create a share
* @host: Network client peer
@@ -39,7 +58,7 @@ __be32
nlmsvc_share_file(struct nlm_host *host, struct nlm_file *file,
struct xdr_netobj *oh, u32 access, u32 mode)
{
- struct nlm_share *share;
+ struct lockd_share *share;
u8 *ohdata;
if (nlmsvc_file_cannot_lock(file))
@@ -64,12 +83,13 @@ nlmsvc_share_file(struct nlm_host *host, struct nlm_file *file,
share->s_host = host;
share->s_owner.data = ohdata;
share->s_owner.len = oh->len;
+ share->s_access_deny_bmap = 0;
share->s_next = file->f_shares;
file->f_shares = share;
update:
- share->s_access = access;
- share->s_mode = mode;
+ share->s_access_deny_bmap |= LOCKD_FSH_BIT(access, mode);
+ nlm_recompute_share(share);
return nlm_granted;
}
@@ -78,14 +98,16 @@ update:
* @host: Network client peer
* @file: File to be unshared
* @oh: Share owner handle
+ * @access: Access mode of the SHARE being released
+ * @mode: Deny mode of the SHARE being released
*
* Returns an NLM status code.
*/
__be32
nlmsvc_unshare_file(struct nlm_host *host, struct nlm_file *file,
- struct xdr_netobj *oh)
+ struct xdr_netobj *oh, u32 access, u32 mode)
{
- struct nlm_share *share, **shpp;
+ struct lockd_share *share, **shpp;
if (nlmsvc_file_cannot_lock(file))
return nlm_lck_denied_nolocks;
@@ -93,8 +115,12 @@ nlmsvc_unshare_file(struct nlm_host *host, struct nlm_file *file,
for (shpp = &file->f_shares; (share = *shpp) != NULL;
shpp = &share->s_next) {
if (share->s_host == host && nlm_cmp_owner(share, oh)) {
- *shpp = share->s_next;
- kfree(share);
+ share->s_access_deny_bmap &= ~LOCKD_FSH_BIT(access, mode);
+ nlm_recompute_share(share);
+ if (!share->s_access_deny_bmap) {
+ *shpp = share->s_next;
+ kfree(share);
+ }
return nlm_granted;
}
}
@@ -111,7 +137,7 @@ nlmsvc_unshare_file(struct nlm_host *host, struct nlm_file *file,
void nlmsvc_traverse_shares(struct nlm_host *host, struct nlm_file *file,
nlm_host_match_fn_t match)
{
- struct nlm_share *share, **shpp;
+ struct lockd_share *share, **shpp;
shpp = &file->f_shares;
while ((share = *shpp) != NULL) {
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index 344e6c187cde..ffab76278bb2 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -17,7 +17,6 @@
#include <linux/sunrpc/addr.h>
#include <linux/module.h>
#include <linux/mount.h>
-#include <uapi/linux/nfs2.h>
#include "lockd.h"
#include "share.h"
@@ -67,7 +66,7 @@ static inline unsigned int file_hash(struct nfs_fh *f)
{
unsigned int tmp=0;
int i;
- for (i=0; i<NFS2_FHSIZE;i++)
+ for (i = 0; i < LOCKD_FH_HASH_SIZE; i++)
tmp += f->data[i];
return tmp & (FILE_NRHASH - 1);
}
@@ -83,23 +82,49 @@ int lock_to_openmode(struct file_lock *lock)
*
* We have to make sure we have the right credential to open
* the file.
+ *
+ * @mode is O_RDONLY, O_WRONLY, or O_RDWR. O_RDWR means success
+ * is achieved with EITHER O_RDONLY or O_WRONLY; it does not
+ * require both.
*/
static __be32 nlm_do_fopen(struct svc_rqst *rqstp,
struct nlm_file *file, int mode)
{
- struct file **fp = &file->f_file[mode];
- __be32 nlmerr = nlm_granted;
+ const struct nlmsvc_binding *ops;
+ __be32 nlmerr = nlm__int__failed;
+ __be32 deferred = 0;
int error;
+ int m;
+
+ rcu_read_lock();
+ ops = rcu_dereference(nlmsvc_ops);
+ if (!ops || !try_module_get(ops->owner)) {
+ rcu_read_unlock();
+ return nlm__int__failed;
+ }
+ rcu_read_unlock();
+
+ for (m = O_RDONLY; m <= O_WRONLY; m++) {
+ struct file **fp = &file->f_file[m];
- if (*fp)
- return nlmerr;
+ if (mode != O_RDWR && mode != m)
+ continue;
+ if (*fp) {
+ module_put(ops->owner);
+ return nlm_granted;
+ }
+
+ error = ops->fopen(rqstp, &file->f_handle, fp, m);
+ if (!error) {
+ module_put(ops->owner);
+ return nlm_granted;
+ }
- 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;
+ deferred = nlmerr;
break;
case -ESTALE:
nlmerr = nlm__int__stale_fh;
@@ -110,7 +135,8 @@ static __be32 nlm_do_fopen(struct svc_rqst *rqstp,
}
}
- return nlmerr;
+ module_put(ops->owner);
+ return deferred ? deferred : nlmerr;
}
/*
@@ -119,17 +145,15 @@ static __be32 nlm_do_fopen(struct svc_rqst *rqstp,
*/
__be32
nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
- struct nlm_lock *lock)
+ struct lockd_lock *lock, int mode)
{
struct nlm_file *file;
unsigned int hash;
__be32 nfserr;
- int mode;
nlm_debug_print_fh("nlm_lookup_file", &lock->fh);
hash = file_hash(&lock->fh);
- mode = lock_to_openmode(&lock->fl);
/* Lock file table */
mutex_lock(&nlm_file_mutex);
@@ -139,6 +163,8 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
mutex_lock(&file->f_mutex);
nfserr = nlm_do_fopen(rqstp, file, mode);
mutex_unlock(&file->f_mutex);
+ if (nfserr)
+ goto out_unlock;
goto found;
}
nlm_debug_print_fh("creating file for", &lock->fh);
@@ -155,7 +181,7 @@ nlm_lookup_file(struct svc_rqst *rqstp, struct nlm_file **result,
nfserr = nlm_do_fopen(rqstp, file, mode);
if (nfserr)
- goto out_unlock;
+ goto out_free;
hlist_add_head(&file->f_list, &nlm_files[hash]);
@@ -174,6 +200,33 @@ out_free:
}
/*
+ * Release the struct file references held by a nlm_file.
+ */
+static void nlm_release_files(struct nlm_file *file)
+{
+ const struct nlmsvc_binding *ops;
+ bool have_ops;
+
+ rcu_read_lock();
+ ops = rcu_dereference(nlmsvc_ops);
+ have_ops = ops && try_module_get(ops->owner);
+ rcu_read_unlock();
+
+ if (have_ops) {
+ if (file->f_file[O_RDONLY])
+ ops->fclose(file->f_file[O_RDONLY]);
+ if (file->f_file[O_WRONLY])
+ ops->fclose(file->f_file[O_WRONLY]);
+ module_put(ops->owner);
+ } else {
+ if (file->f_file[O_RDONLY])
+ fput(file->f_file[O_RDONLY]);
+ if (file->f_file[O_WRONLY])
+ fput(file->f_file[O_WRONLY]);
+ }
+}
+
+/*
* Delete a file after having released all locks, blocks and shares
*/
static inline void
@@ -182,10 +235,7 @@ nlm_delete_file(struct nlm_file *file)
nlm_debug_print_file("closing file", file);
if (!hlist_unhashed(&file->f_list)) {
hlist_del(&file->f_list);
- if (file->f_file[O_RDONLY])
- nlmsvc_ops->fclose(file->f_file[O_RDONLY]);
- if (file->f_file[O_WRONLY])
- nlmsvc_ops->fclose(file->f_file[O_WRONLY]);
+ nlm_release_files(file);
kfree(file);
} else {
printk(KERN_WARNING "lockd: attempt to release unknown file!\n");
@@ -300,12 +350,10 @@ nlm_file_inuse(struct nlm_file *file)
return 0;
}
-static void nlm_close_files(struct nlm_file *file)
+static void nlm_file_release(struct nlm_file *file)
{
- if (file->f_file[O_RDONLY])
- nlmsvc_ops->fclose(file->f_file[O_RDONLY]);
- if (file->f_file[O_WRONLY])
- nlmsvc_ops->fclose(file->f_file[O_WRONLY]);
+ if (!nlm_file_inuse(file))
+ nlm_delete_file(file);
}
/*
@@ -315,32 +363,41 @@ static int
nlm_traverse_files(void *data, nlm_host_match_fn_t match,
int (*is_failover_file)(void *data, struct nlm_file *file))
{
- struct hlist_node *next;
- struct nlm_file *file;
+ struct nlm_file *file, *next;
int i, ret = 0;
mutex_lock(&nlm_file_mutex);
for (i = 0; i < FILE_NRHASH; i++) {
- hlist_for_each_entry_safe(file, next, &nlm_files[i], f_list) {
- if (is_failover_file && !is_failover_file(data, file))
- continue;
+ file = hlist_entry_safe(nlm_files[i].first,
+ struct nlm_file, f_list);
+ if (file)
file->f_count++;
- mutex_unlock(&nlm_file_mutex);
-
- /* Traverse locks, blocks and shares of this file
- * and update file->f_locks count */
- if (nlm_inspect_file(data, file, match))
- ret = 1;
+ while (file) {
+ /*
+ * Pin the next neighbour before we drop the mutex
+ * for nlm_inspect_file(); a concurrent
+ * nlm_release_file() under the same mutex would
+ * otherwise be free to unlink and kfree it during
+ * the unlock window, leaving us to dereference a
+ * freed slab when we walked to next afterwards.
+ */
+ next = hlist_entry_safe(file->f_list.next,
+ struct nlm_file, f_list);
+ if (next)
+ next->f_count++;
+
+ if (!is_failover_file || is_failover_file(data, file)) {
+ mutex_unlock(&nlm_file_mutex);
+
+ if (nlm_inspect_file(data, file, match))
+ ret = 1;
+
+ mutex_lock(&nlm_file_mutex);
+ }
- mutex_lock(&nlm_file_mutex);
file->f_count--;
- /* No more references to this file. Let go of it. */
- if (list_empty(&file->f_blocks) && !file->f_locks
- && !file->f_shares && !file->f_count) {
- hlist_del(&file->f_list);
- nlm_close_files(file);
- kfree(file);
- }
+ nlm_file_release(file);
+ file = next;
}
}
mutex_unlock(&nlm_file_mutex);
@@ -500,7 +557,7 @@ EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_sb);
static int
nlmsvc_match_ip(void *datap, struct nlm_host *host)
{
- return rpc_cmp_addr(nlm_srcaddr(host), datap);
+ return rpc_cmp_addr(nlm_srcaddr(datap), (struct sockaddr *)host);
}
/**
diff --git a/fs/lockd/svcxdr.h b/fs/lockd/svcxdr.h
deleted file mode 100644
index 4f1a451da5ba..000000000000
--- a/fs/lockd/svcxdr.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Encode/decode NLM basic data types
- *
- * Basic NLMv3 XDR data types are not defined in an IETF standards
- * document. X/Open has a description of these data types that
- * is useful. See Chapter 10 of "Protocols for Interworking:
- * XNFS, Version 3W".
- *
- * Basic NLMv4 XDR data types are defined in Appendix II.1.4 of
- * RFC 1813: "NFS Version 3 Protocol Specification".
- *
- * Author: Chuck Lever <chuck.lever@oracle.com>
- *
- * Copyright (c) 2020, Oracle and/or its affiliates.
- */
-
-#ifndef _LOCKD_SVCXDR_H_
-#define _LOCKD_SVCXDR_H_
-
-static inline bool
-svcxdr_decode_stats(struct xdr_stream *xdr, __be32 *status)
-{
- __be32 *p;
-
- p = xdr_inline_decode(xdr, XDR_UNIT);
- if (!p)
- return false;
- *status = *p;
-
- return true;
-}
-
-static inline bool
-svcxdr_encode_stats(struct xdr_stream *xdr, __be32 status)
-{
- __be32 *p;
-
- p = xdr_reserve_space(xdr, XDR_UNIT);
- if (!p)
- return false;
- *p = status;
-
- return true;
-}
-
-static inline bool
-svcxdr_decode_string(struct xdr_stream *xdr, char **data, unsigned int *data_len)
-{
- __be32 *p;
- u32 len;
-
- if (xdr_stream_decode_u32(xdr, &len) < 0)
- return false;
- if (len > NLM_MAXSTRLEN)
- return false;
- p = xdr_inline_decode(xdr, len);
- if (!p)
- return false;
- *data_len = len;
- *data = (char *)p;
-
- return true;
-}
-
-/*
- * NLM cookies are defined by specification to be a variable-length
- * XDR opaque no longer than 1024 bytes. However, this implementation
- * limits their length to 32 bytes, and treats zero-length cookies
- * specially.
- */
-static inline bool
-svcxdr_decode_cookie(struct xdr_stream *xdr, struct nlm_cookie *cookie)
-{
- __be32 *p;
- u32 len;
-
- if (xdr_stream_decode_u32(xdr, &len) < 0)
- return false;
- if (len > NLM_MAXCOOKIELEN)
- return false;
- if (!len)
- goto out_hpux;
-
- p = xdr_inline_decode(xdr, len);
- if (!p)
- return false;
- cookie->len = len;
- memcpy(cookie->data, p, len);
-
- return true;
-
- /* apparently HPUX can return empty cookies */
-out_hpux:
- cookie->len = 4;
- memset(cookie->data, 0, 4);
- return true;
-}
-
-static inline bool
-svcxdr_encode_cookie(struct xdr_stream *xdr, const struct nlm_cookie *cookie)
-{
- __be32 *p;
-
- if (xdr_stream_encode_u32(xdr, cookie->len) < 0)
- return false;
- p = xdr_reserve_space(xdr, cookie->len);
- if (!p)
- return false;
- memcpy(p, cookie->data, cookie->len);
-
- return true;
-}
-
-static inline bool
-svcxdr_decode_owner(struct xdr_stream *xdr, struct xdr_netobj *obj)
-{
- __be32 *p;
- u32 len;
-
- if (xdr_stream_decode_u32(xdr, &len) < 0)
- return false;
- if (len > XDR_MAX_NETOBJ)
- return false;
- p = xdr_inline_decode(xdr, len);
- if (!p)
- return false;
- obj->len = len;
- obj->data = (u8 *)p;
-
- return true;
-}
-
-static inline bool
-svcxdr_encode_owner(struct xdr_stream *xdr, const struct xdr_netobj *obj)
-{
- if (obj->len > XDR_MAX_NETOBJ)
- return false;
- return xdr_stream_encode_opaque(xdr, obj->data, obj->len) > 0;
-}
-
-#endif /* _LOCKD_SVCXDR_H_ */
diff --git a/fs/lockd/trace.h b/fs/lockd/trace.h
index 7214d7e96a42..a11d04e8c835 100644
--- a/fs/lockd/trace.h
+++ b/fs/lockd/trace.h
@@ -48,7 +48,7 @@ NLM_STATUS_LIST
DECLARE_EVENT_CLASS(nlmclnt_lock_event,
TP_PROTO(
- const struct nlm_lock *lock,
+ const struct lockd_lock *lock,
const struct sockaddr *addr,
unsigned int addrlen,
__be32 status
@@ -61,8 +61,8 @@ DECLARE_EVENT_CLASS(nlmclnt_lock_event,
__field(u32, svid)
__field(u32, fh)
__field(unsigned long, status)
- __field(u64, start)
- __field(u64, len)
+ __field(loff_t, start)
+ __field(loff_t, end)
__sockaddr(addr, addrlen)
),
@@ -70,16 +70,16 @@ DECLARE_EVENT_CLASS(nlmclnt_lock_event,
__entry->oh = ~crc32_le(0xffffffff, lock->oh.data, lock->oh.len);
__entry->svid = lock->svid;
__entry->fh = nfs_fhandle_hash(&lock->fh);
- __entry->start = lock->lock_start;
- __entry->len = lock->lock_len;
+ __entry->start = lock->fl.fl_start;
+ __entry->end = lock->fl.fl_end;
__entry->status = be32_to_cpu(status);
__assign_sockaddr(addr, addr, addrlen);
),
TP_printk(
- "addr=%pISpc oh=0x%08x svid=0x%08x fh=0x%08x start=%llu len=%llu status=%s",
+ "addr=%pISpc oh=0x%08x svid=0x%08x fh=0x%08x start=%lld end=%lld status=%s",
__get_sockaddr(addr), __entry->oh, __entry->svid,
- __entry->fh, __entry->start, __entry->len,
+ __entry->fh, __entry->start, __entry->end,
show_nlm_status(__entry->status)
)
);
@@ -87,7 +87,7 @@ DECLARE_EVENT_CLASS(nlmclnt_lock_event,
#define DEFINE_NLMCLNT_EVENT(name) \
DEFINE_EVENT(nlmclnt_lock_event, name, \
TP_PROTO( \
- const struct nlm_lock *lock, \
+ const struct lockd_lock *lock, \
const struct sockaddr *addr, \
unsigned int addrlen, \
__be32 status \
diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c
deleted file mode 100644
index dfca8b8dab73..000000000000
--- a/fs/lockd/xdr.c
+++ /dev/null
@@ -1,354 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * linux/fs/lockd/xdr.c
- *
- * XDR support for lockd and the lock client.
- *
- * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
- */
-
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/nfs.h>
-
-#include <linux/sunrpc/xdr.h>
-#include <linux/sunrpc/clnt.h>
-#include <linux/sunrpc/svc.h>
-#include <linux/sunrpc/stats.h>
-
-#include <uapi/linux/nfs2.h>
-
-#include "lockd.h"
-#include "share.h"
-#include "svcxdr.h"
-
-static inline loff_t
-s32_to_loff_t(__s32 offset)
-{
- return (loff_t)offset;
-}
-
-static inline __s32
-loff_t_to_s32(loff_t offset)
-{
- __s32 res;
- if (offset >= NLM_OFFSET_MAX)
- res = NLM_OFFSET_MAX;
- else if (offset <= -NLM_OFFSET_MAX)
- res = -NLM_OFFSET_MAX;
- else
- res = offset;
- return res;
-}
-
-/*
- * NLM file handles are defined by specification to be a variable-length
- * XDR opaque no longer than 1024 bytes. However, this implementation
- * constrains their length to exactly the length of an NFSv2 file
- * handle.
- */
-static bool
-svcxdr_decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
-{
- __be32 *p;
- u32 len;
-
- if (xdr_stream_decode_u32(xdr, &len) < 0)
- return false;
- if (len != NFS2_FHSIZE)
- return false;
-
- p = xdr_inline_decode(xdr, len);
- if (!p)
- return false;
- fh->size = NFS2_FHSIZE;
- memcpy(fh->data, p, len);
- memset(fh->data + NFS2_FHSIZE, 0, sizeof(fh->data) - NFS2_FHSIZE);
-
- return true;
-}
-
-static bool
-svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
-{
- struct file_lock *fl = &lock->fl;
- s32 start, len, end;
-
- if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
- return false;
- if (!svcxdr_decode_fhandle(xdr, &lock->fh))
- return false;
- if (!svcxdr_decode_owner(xdr, &lock->oh))
- return false;
- if (xdr_stream_decode_u32(xdr, &lock->svid) < 0)
- return false;
- if (xdr_stream_decode_u32(xdr, &start) < 0)
- return false;
- if (xdr_stream_decode_u32(xdr, &len) < 0)
- return false;
-
- locks_init_lock(fl);
- fl->c.flc_flags = FL_POSIX;
- fl->c.flc_type = F_RDLCK;
- end = start + len - 1;
- fl->fl_start = s32_to_loff_t(start);
- if (len == 0 || end < 0)
- fl->fl_end = OFFSET_MAX;
- else
- fl->fl_end = s32_to_loff_t(end);
-
- return true;
-}
-
-static bool
-svcxdr_encode_holder(struct xdr_stream *xdr, const struct nlm_lock *lock)
-{
- const struct file_lock *fl = &lock->fl;
- s32 start, len;
-
- /* exclusive */
- if (xdr_stream_encode_bool(xdr, fl->c.flc_type != F_RDLCK) < 0)
- return false;
- if (xdr_stream_encode_u32(xdr, lock->svid) < 0)
- return false;
- if (!svcxdr_encode_owner(xdr, &lock->oh))
- return false;
- start = loff_t_to_s32(fl->fl_start);
- if (fl->fl_end == OFFSET_MAX)
- len = 0;
- else
- len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1);
- if (xdr_stream_encode_u32(xdr, start) < 0)
- return false;
- if (xdr_stream_encode_u32(xdr, len) < 0)
- return false;
-
- return true;
-}
-
-static bool
-svcxdr_encode_testrply(struct xdr_stream *xdr, const struct nlm_res *resp)
-{
- if (!svcxdr_encode_stats(xdr, resp->status))
- return false;
- switch (resp->status) {
- case nlm_lck_denied:
- if (!svcxdr_encode_holder(xdr, &resp->lock))
- return false;
- }
-
- return true;
-}
-
-
-/*
- * Decode Call arguments
- */
-
-bool
-nlmsvc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
- return true;
-}
-
-bool
-nlmsvc_decode_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
- struct nlm_args *argp = rqstp->rq_argp;
- u32 exclusive;
-
- if (!svcxdr_decode_cookie(xdr, &argp->cookie))
- return false;
- if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
- return false;
- if (!svcxdr_decode_lock(xdr, &argp->lock))
- return false;
- if (exclusive)
- argp->lock.fl.c.flc_type = F_WRLCK;
-
- return true;
-}
-
-bool
-nlmsvc_decode_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
- struct nlm_args *argp = rqstp->rq_argp;
- u32 exclusive;
-
- if (!svcxdr_decode_cookie(xdr, &argp->cookie))
- return false;
- if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
- return false;
- if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
- return false;
- if (!svcxdr_decode_lock(xdr, &argp->lock))
- return false;
- if (exclusive)
- argp->lock.fl.c.flc_type = F_WRLCK;
- if (xdr_stream_decode_bool(xdr, &argp->reclaim) < 0)
- return false;
- if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
- return false;
- argp->monitor = 1; /* monitor client by default */
-
- return true;
-}
-
-bool
-nlmsvc_decode_cancargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
- struct nlm_args *argp = rqstp->rq_argp;
- u32 exclusive;
-
- if (!svcxdr_decode_cookie(xdr, &argp->cookie))
- return false;
- if (xdr_stream_decode_bool(xdr, &argp->block) < 0)
- return false;
- if (xdr_stream_decode_bool(xdr, &exclusive) < 0)
- return false;
- if (!svcxdr_decode_lock(xdr, &argp->lock))
- return false;
- if (exclusive)
- argp->lock.fl.c.flc_type = F_WRLCK;
-
- return true;
-}
-
-bool
-nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
- struct nlm_args *argp = rqstp->rq_argp;
-
- if (!svcxdr_decode_cookie(xdr, &argp->cookie))
- return false;
- if (!svcxdr_decode_lock(xdr, &argp->lock))
- return false;
- argp->lock.fl.c.flc_type = F_UNLCK;
-
- return true;
-}
-
-bool
-nlmsvc_decode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
- struct nlm_res *resp = rqstp->rq_argp;
-
- if (!svcxdr_decode_cookie(xdr, &resp->cookie))
- return false;
- if (!svcxdr_decode_stats(xdr, &resp->status))
- return false;
-
- return true;
-}
-
-bool
-nlmsvc_decode_reboot(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
- struct nlm_reboot *argp = rqstp->rq_argp;
- __be32 *p;
- u32 len;
-
- if (xdr_stream_decode_u32(xdr, &len) < 0)
- return false;
- if (len > SM_MAXSTRLEN)
- return false;
- p = xdr_inline_decode(xdr, len);
- if (!p)
- return false;
- argp->len = len;
- argp->mon = (char *)p;
- if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
- return false;
- p = xdr_inline_decode(xdr, SM_PRIV_SIZE);
- if (!p)
- return false;
- memcpy(&argp->priv.data, p, sizeof(argp->priv.data));
-
- return true;
-}
-
-bool
-nlmsvc_decode_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
- struct nlm_args *argp = rqstp->rq_argp;
- struct nlm_lock *lock = &argp->lock;
-
- memset(lock, 0, sizeof(*lock));
- locks_init_lock(&lock->fl);
- lock->svid = LOCKD_SHARE_SVID;
-
- if (!svcxdr_decode_cookie(xdr, &argp->cookie))
- return false;
- if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
- return false;
- if (!svcxdr_decode_fhandle(xdr, &lock->fh))
- return false;
- if (!svcxdr_decode_owner(xdr, &lock->oh))
- return false;
- /* XXX: Range checks are missing in the original code */
- if (xdr_stream_decode_u32(xdr, &argp->fsm_mode) < 0)
- return false;
- if (xdr_stream_decode_u32(xdr, &argp->fsm_access) < 0)
- return false;
-
- return true;
-}
-
-bool
-nlmsvc_decode_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
- struct nlm_args *argp = rqstp->rq_argp;
- struct nlm_lock *lock = &argp->lock;
-
- if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len))
- return false;
- if (xdr_stream_decode_u32(xdr, &argp->state) < 0)
- return false;
-
- return true;
-}
-
-
-/*
- * Encode Reply results
- */
-
-bool
-nlmsvc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
- return true;
-}
-
-bool
-nlmsvc_encode_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
- struct nlm_res *resp = rqstp->rq_resp;
-
- return svcxdr_encode_cookie(xdr, &resp->cookie) &&
- svcxdr_encode_testrply(xdr, resp);
-}
-
-bool
-nlmsvc_encode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
- struct nlm_res *resp = rqstp->rq_resp;
-
- return svcxdr_encode_cookie(xdr, &resp->cookie) &&
- svcxdr_encode_stats(xdr, resp->status);
-}
-
-bool
-nlmsvc_encode_shareres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
-{
- struct nlm_res *resp = rqstp->rq_resp;
-
- if (!svcxdr_encode_cookie(xdr, &resp->cookie))
- return false;
- if (!svcxdr_encode_stats(xdr, resp->status))
- return false;
- /* sequence */
- if (xdr_stream_encode_u32(xdr, 0) < 0)
- return false;
-
- return true;
-}
diff --git a/fs/lockd/xdr.h b/fs/lockd/xdr.h
index 3c60817c4349..a1126cca98c6 100644
--- a/fs/lockd/xdr.h
+++ b/fs/lockd/xdr.h
@@ -20,8 +20,6 @@ struct nsm_private {
unsigned char data[SM_PRIV_SIZE];
};
-struct svc_rqst;
-
#define NLM_MAXCOOKIELEN 32
#define NLM_MAXSTRLEN 1024
@@ -32,7 +30,7 @@ struct svc_rqst;
#define nlm_lck_denied_grace_period cpu_to_be32(NLM_LCK_DENIED_GRACE_PERIOD)
/* Lock info passed via NLM */
-struct nlm_lock {
+struct lockd_lock {
char * caller;
unsigned int len; /* length of "caller" */
struct nfs_fh fh;
@@ -49,8 +47,7 @@ struct nlm_lock {
* 32 bytes.
*/
-struct nlm_cookie
-{
+struct lockd_cookie {
unsigned char data[NLM_MAXCOOKIELEN];
unsigned int len;
};
@@ -58,49 +55,31 @@ struct nlm_cookie
/*
* Generic lockd arguments for all but sm_notify
*/
-struct nlm_args {
- struct nlm_cookie cookie;
- struct nlm_lock lock;
+struct lockd_args {
+ struct lockd_cookie cookie;
+ struct lockd_lock lock;
u32 block;
u32 reclaim;
u32 state;
- u32 monitor;
- u32 fsm_access;
- u32 fsm_mode;
};
/*
* Generic lockd result
*/
-struct nlm_res {
- struct nlm_cookie cookie;
+struct lockd_res {
+ struct lockd_cookie cookie;
__be32 status;
- struct nlm_lock lock;
+ struct lockd_lock lock;
};
/*
* statd callback when client has rebooted
*/
-struct nlm_reboot {
+struct lockd_reboot {
char *mon;
unsigned int len;
u32 state;
struct nsm_private priv;
};
-bool nlmsvc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr);
-bool nlmsvc_decode_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
-bool nlmsvc_decode_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
-bool nlmsvc_decode_cancargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
-bool nlmsvc_decode_unlockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
-bool nlmsvc_decode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr);
-bool nlmsvc_decode_reboot(struct svc_rqst *rqstp, struct xdr_stream *xdr);
-bool nlmsvc_decode_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr);
-bool nlmsvc_decode_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr);
-
-bool nlmsvc_encode_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
-bool nlmsvc_encode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr);
-bool nlmsvc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr);
-bool nlmsvc_encode_shareres(struct svc_rqst *rqstp, struct xdr_stream *xdr);
-
#endif /* _LOCKD_XDR_H */