projects/linux·commit 445d9f05

Merge tag 'nfsd-6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux

445d9f05 · Linus Torvalds <[email protected]> · 2024-11-26 12:59:30 -08:00

Pull nfsd updates from Chuck Lever:
 "Jeff Layton contributed a scalability improvement to NFSD's NFSv4
  backchannel session implementation. This improvement is intended to
  increase the rate at which NFSD can safely recall NFSv4 delegations
  from clients, to avoid the need to revoke them. Revoking requires a
  slow state recovery process.

  A wide variety of bug fixes and other incremental improvements make up
  the bulk of commits in this series. As always I am grateful to the
  NFSD contributors, reviewers, testers, and bug reporters who
  participated during this cycle"

* tag 'nfsd-6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: (72 commits)
  nfsd: allow for up to 32 callback session slots
  nfs_common: must not hold RCU while calling nfsd_file_put_local
  nfsd: get rid of include ../internal.h
  nfsd: fix nfs4_openowner leak when concurrent nfsd4_open occur
  NFSD: Add nfsd4_copy time-to-live
  NFSD: Add a laundromat reaper for async copy state
  NFSD: Block DESTROY_CLIENTID only when there are ongoing async COPY operations
  NFSD: Handle an NFS4ERR_DELAY response to CB_OFFLOAD
  NFSD: Free async copy information in nfsd4_cb_offload_release()
  NFSD: Fix nfsd4_shutdown_copy()
  NFSD: Add a tracepoint to record canceled async COPY operations
  nfsd: make nfsd4_session->se_flags a bool
  nfsd: remove nfsd4_session->se_bchannel
  nfsd: make use of warning provided by refcount_t
  nfsd: Don't fail OP_SETCLIENTID when there are too many clients.
  svcrdma: fix miss destroy percpu_counter in svc_rdma_proc_init()
  xdrgen: Remove program_stat_to_errno() call sites
  xdrgen: Update the files included in client-side source code
  xdrgen: Remove check for "nfs_ok" in C templates
  xdrgen: Remove tracepoint call site
  ...
Commit
445d9f05fa149556422f7fdd52dacf487cc8e7be
Parents
44b4d13b · 583772ee

Merge commit. Changes below are compared with the first parent: 44b4d13b.

Changes

78 files changed · +1115 −348

FileStatusAddDelContent
MAINTAINERSmodified+1−0View file
fs/lockd/clntxdr.cmodified+3−2View file
fs/lockd/svc4proc.cmodified+5−15View file
fs/lockd/svclock.cmodified+1−1View file
fs/lockd/svcproc.cmodified+2−13View file
fs/lockd/xdr4.cmodified+0−2View file
fs/nfs_common/nfslocalio.cmodified+3−5View file
fs/nfsd/export.cmodified+49−8View file
fs/nfsd/export.hmodified+4−3View file
fs/nfsd/filecache.cmodified+9−10View file
fs/nfsd/filecache.hmodified+1−1View file
fs/nfsd/lockd.cmodified+11−2View file
fs/nfsd/nfs4acl.cmodified+0−2View file
fs/nfsd/nfs4callback.cmodified+101−38View file
fs/nfsd/nfs4proc.cmodified+93−10View file
fs/nfsd/nfs4recover.cmodified+2−1View file
fs/nfsd/nfs4state.cmodified+82−45View file
fs/nfsd/nfs4xdr.cmodified+42−29View file
fs/nfsd/nfsfh.cmodified+22−19View file
fs/nfsd/nfsfh.hmodified+1−2View file
fs/nfsd/state.hmodified+28−12View file
fs/nfsd/trace.hmodified+25−4View file
fs/nfsd/vfs.cmodified+6−20View file
fs/nfsd/vfs.hmodified+3−3View file
fs/nfsd/xdr4.hmodified+8−0View file
include/linux/lockd/lockd.hmodified+3−3View file
include/linux/lockd/xdr.hmodified+0−2View file
include/linux/nfslocalio.hmodified+15−3View file
include/linux/sunrpc/xdr.hmodified+21−0View file
include/linux/sunrpc/xdrgen/_defs.hmodified+9−0View file
net/sunrpc/cache.cmodified+3−1View file
net/sunrpc/xprtrdma/svc_rdma.cmodified+14−5View file
net/sunrpc/xprtrdma/svc_rdma_recvfrom.cmodified+7−1View file
tools/net/sunrpc/extract.shadded+11−0View file
tools/net/sunrpc/xdrgen/READMEmodified+17−0View file
tools/net/sunrpc/xdrgen/generators/__init__.pymodified+4−0View file
tools/net/sunrpc/xdrgen/generators/enum.pymodified+25−5View file
tools/net/sunrpc/xdrgen/generators/pointer.pymodified+21−5View file
tools/net/sunrpc/xdrgen/generators/struct.pymodified+21−5View file
tools/net/sunrpc/xdrgen/generators/typedef.pymodified+22−6View file
tools/net/sunrpc/xdrgen/generators/union.pymodified+42−10View file
tools/net/sunrpc/xdrgen/grammars/xdr.larkmodified+4−2View file
tools/net/sunrpc/xdrgen/subcmds/definitions.pymodified+21−3View file
tools/net/sunrpc/xdrgen/subcmds/source.pymodified+1−2View file
tools/net/sunrpc/xdrgen/templates/C/enum/declaration/close.j2deleted+0−4View before deletion
tools/net/sunrpc/xdrgen/templates/C/enum/declaration/enum.j2added+4−0View file
tools/net/sunrpc/xdrgen/templates/C/enum/decoder/enum.j2modified+1−1View file
tools/net/sunrpc/xdrgen/templates/C/enum/decoder/enum_be.j2added+14−0View file
tools/net/sunrpc/xdrgen/templates/C/enum/definition/close.j2modified+1−0View file
tools/net/sunrpc/xdrgen/templates/C/enum/definition/close_be.j2added+3−0View file
tools/net/sunrpc/xdrgen/templates/C/enum/encoder/enum.j2modified+1−1View file
tools/net/sunrpc/xdrgen/templates/C/enum/encoder/enum_be.j2added+14−0View file
tools/net/sunrpc/xdrgen/templates/C/enum/maxsize/enum.j2added+2−0View file
tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/variable_length_string.j2 → tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/string.j2renamed+0−0View file
tools/net/sunrpc/xdrgen/templates/C/pointer/definition/variable_length_string.j2 → tools/net/sunrpc/xdrgen/templates/C/pointer/definition/string.j2renamed+0−0View file
tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/variable_length_string.j2 → tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/string.j2renamed+0−0View file
tools/net/sunrpc/xdrgen/templates/C/pointer/maxsize/pointer.j2added+3−0View file
tools/net/sunrpc/xdrgen/templates/C/program/decoder/result.j2modified+0−4View file
tools/net/sunrpc/xdrgen/templates/C/source_top/client.j2modified+7−2View file
tools/net/sunrpc/xdrgen/templates/C/struct/decoder/variable_length_string.j2 → tools/net/sunrpc/xdrgen/templates/C/struct/decoder/string.j2renamed+0−0View file
tools/net/sunrpc/xdrgen/templates/C/struct/definition/variable_length_string.j2 → tools/net/sunrpc/xdrgen/templates/C/struct/definition/string.j2renamed+0−0View file
tools/net/sunrpc/xdrgen/templates/C/struct/encoder/variable_length_string.j2 → tools/net/sunrpc/xdrgen/templates/C/struct/encoder/string.j2renamed+0−0View file
tools/net/sunrpc/xdrgen/templates/C/struct/maxsize/struct.j2added+3−0View file
tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/variable_length_string.j2 → tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/string.j2renamed+0−0View file
tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/variable_length_string.j2 → tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/string.j2renamed+0−0View file
tools/net/sunrpc/xdrgen/templates/C/typedef/definition/variable_length_string.j2 → tools/net/sunrpc/xdrgen/templates/C/typedef/definition/string.j2renamed+0−0View file
tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/variable_length_string.j2 → tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/string.j2renamed+0−0View file
tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/basic.j2added+3−0View file
tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/fixed_length_opaque.j2added+2−0View file
tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/string.j2added+2−0View file
tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/variable_length_array.j2added+2−0View file
tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/variable_length_opaque.j2added+2−0View file
tools/net/sunrpc/xdrgen/templates/C/union/decoder/case_spec_be.j2added+2−0View file
tools/net/sunrpc/xdrgen/templates/C/union/decoder/variable_length_string.j2 → tools/net/sunrpc/xdrgen/templates/C/union/decoder/string.j2renamed+0−0View file
tools/net/sunrpc/xdrgen/templates/C/union/encoder/case_spec_be.j2added+2−0View file
tools/net/sunrpc/xdrgen/templates/C/union/maxsize/union.j2added+3−0View file
tools/net/sunrpc/xdrgen/xdr_ast.pymodified+278−35View file
tools/net/sunrpc/xdrgen/xdrgenmodified+3−1View file

Only the first 600 diff lines are shown. Download the complete patch.

MAINTAINERS

View file
diff --git a/MAINTAINERS b/MAINTAINERS
index 550a74e..e455ca5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12436,6 +12436,7 @@ F: include/trace/misc/sunrpc.h
F: include/uapi/linux/nfsd/
F: include/uapi/linux/sunrpc/
F: net/sunrpc/
+F: tools/net/sunrpc/
KERNEL PACMAN PACKAGING (in addition to generic KERNEL BUILD)
M: Thomas Weißschuh <[email protected]>

fs/lockd/clntxdr.c

View file
diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c
index a3e9727..6ea3448 100644
--- a/fs/lockd/clntxdr.c
+++ b/fs/lockd/clntxdr.c
@@ -2,8 +2,9 @@
/*
* linux/fs/lockd/clntxdr.c
*
- * XDR functions to encode/decode NLM version 3 RPC arguments and results.
- * NLM version 3 is backwards compatible with NLM versions 1 and 2.
+ * XDR functions to encode/decode NLM version 1 and 3 RPC
+ * arguments and results. NLM version 2 is not specified
+ * by a standard, thus it is not implemented.
*
* NLM client-side only.
*

fs/lockd/svc4proc.c

View file
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index 8a72c41..109e5ca 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -46,14 +46,15 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
if (filp != NULL) {
int mode = lock_to_openmode(&lock->fl);
+ lock->fl.c.flc_flags = FL_POSIX;
+
error = nlm_lookup_file(rqstp, &file, lock);
if (error)
goto no_locks;
*filp = file;
/* Set up the missing parts of the file_lock structure */
- lock->fl.c.flc_flags = FL_POSIX;
- lock->fl.c.flc_file = file->f_file[mode];
+ lock->fl.c.flc_file = file->f_file[mode];
lock->fl.c.flc_pid = current->tgid;
lock->fl.fl_start = (loff_t)lock->lock_start;
lock->fl.fl_end = lock->lock_len ?
@@ -108,7 +109,8 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
test_owner = argp->lock.fl.c.flc_owner;
/* Now check for conflicting locks */
- resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie);
+ resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock,
+ &resp->lock);
if (resp->status == nlm_drop_reply)
rc = rpc_drop_reply;
else
@@ -142,18 +144,6 @@ __nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_res *resp)
if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
-#if 0
- /* If supplied state doesn't match current state, we assume it's
- * an old request that time-warped somehow. Any error return would
- * do in this case because it's irrelevant anyway.
- *
- * NB: We don't retrieve the remote host's state yet.
- */
- if (host->h_nsmstate && host->h_nsmstate != argp->state) {
- resp->status = nlm_lck_denied_nolocks;
- } else
-#endif
-
/* Now try to lock the file */
resp->status = nlmsvc_lock(rqstp, file, host, &argp->lock,
argp->block, &argp->cookie,

fs/lockd/svclock.c

View file
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 2359347..c1315df 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -608,7 +608,7 @@ 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_cookie *cookie)
+ struct nlm_lock *conflock)
{
int error;
int mode;

fs/lockd/svcproc.c

View file
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index a03220e..f53d517 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -130,7 +130,8 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
test_owner = argp->lock.fl.c.flc_owner;
/* Now check for conflicting locks */
- resp->status = cast_status(nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie));
+ resp->status = cast_status(nlmsvc_testlock(rqstp, file, host,
+ &argp->lock, &resp->lock));
if (resp->status == nlm_drop_reply)
rc = rpc_drop_reply;
else
@@ -165,18 +166,6 @@ __nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_res *resp)
if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
-#if 0
- /* If supplied state doesn't match current state, we assume it's
- * an old request that time-warped somehow. Any error return would
- * do in this case because it's irrelevant anyway.
- *
- * NB: We don't retrieve the remote host's state yet.
- */
- if (host->h_nsmstate && host->h_nsmstate != argp->state) {
- resp->status = nlm_lck_denied_nolocks;
- } else
-#endif
-
/* Now try to lock the file */
resp->status = cast_status(nlmsvc_lock(rqstp, file, host, &argp->lock,
argp->block, &argp->cookie,

fs/lockd/xdr4.c

View file
diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c
index 3d28b9c..e343c82 100644
--- a/fs/lockd/xdr4.c
+++ b/fs/lockd/xdr4.c
@@ -89,7 +89,6 @@ svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
return false;
locks_init_lock(fl);
- fl->c.flc_flags = FL_POSIX;
fl->c.flc_type = F_RDLCK;
nlm4svc_set_file_lock_range(fl, lock->lock_start, lock->lock_len);
return true;
@@ -268,7 +267,6 @@ nlm4svc_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 = ~(u32)0;

fs/nfs_common/nfslocalio.c

View file
diff --git a/fs/nfs_common/nfslocalio.c b/fs/nfs_common/nfslocalio.c
index 09404d1..a74ec08 100644
--- a/fs/nfs_common/nfslocalio.c
+++ b/fs/nfs_common/nfslocalio.c
@@ -155,11 +155,9 @@ struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *uuid,
/* We have an implied reference to net thanks to nfsd_serv_try_get */
localio = nfs_to->nfsd_open_local_fh(net, uuid->dom, rpc_clnt,
cred, nfs_fh, fmode);
- if (IS_ERR(localio)) {
- rcu_read_lock();
- nfs_to->nfsd_serv_put(net);
- rcu_read_unlock();
- }
+ if (IS_ERR(localio))
+ nfs_to_nfsd_net_put(net);
+
return localio;
}
EXPORT_SYMBOL_GPL(nfs_open_local_fh);

fs/nfsd/export.c

View file
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index c82d8e3..eacafe4 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -40,15 +40,24 @@
#define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS)
#define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1)
-static void expkey_put(struct kref *ref)
+static void expkey_put_work(struct work_struct *work)
{
- struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
+ struct svc_expkey *key =
+ container_of(to_rcu_work(work), struct svc_expkey, ek_rcu_work);
if (test_bit(CACHE_VALID, &key->h.flags) &&
!test_bit(CACHE_NEGATIVE, &key->h.flags))
path_put(&key->ek_path);
auth_domain_put(key->ek_client);
- kfree_rcu(key, ek_rcu);
+ kfree(key);
+}
+
+static void expkey_put(struct kref *ref)
+{
+ struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
+
+ INIT_RCU_WORK(&key->ek_rcu_work, expkey_put_work);
+ queue_rcu_work(system_wq, &key->ek_rcu_work);
}
static int expkey_upcall(struct cache_detail *cd, struct cache_head *h)
@@ -355,16 +364,26 @@ static void export_stats_destroy(struct export_stats *stats)
EXP_STATS_COUNTERS_NUM);
}
-static void svc_export_put(struct kref *ref)
+static void svc_export_put_work(struct work_struct *work)
{
- struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
+ struct svc_export *exp =
+ container_of(to_rcu_work(work), struct svc_export, ex_rcu_work);
+
path_put(&exp->ex_path);
auth_domain_put(exp->ex_client);
nfsd4_fslocs_free(&exp->ex_fslocs);
export_stats_destroy(exp->ex_stats);
kfree(exp->ex_stats);
kfree(exp->ex_uuid);
- kfree_rcu(exp, ex_rcu);
+ kfree(exp);
+}
+
+static void svc_export_put(struct kref *ref)
+{
+ struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
+
+ INIT_RCU_WORK(&exp->ex_rcu_work, svc_export_put_work);
+ queue_rcu_work(system_wq, &exp->ex_rcu_work);
}
static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h)
@@ -1078,12 +1097,14 @@ static struct svc_export *exp_find(struct cache_detail *cd,
* check_nfsd_access - check if access to export is allowed.
* @exp: svc_export that is being accessed.
* @rqstp: svc_rqst attempting to access @exp (will be NULL for LOCALIO).
+ * @may_bypass_gss: reduce strictness of authorization check
*
* Return values:
* %nfs_ok if access is granted, or
* %nfserr_wrongsec if access is denied
*/
-__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
+__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp,
+ bool may_bypass_gss)
{
struct exp_flavor_info *f, *end = exp->ex_flavors + exp->ex_nflavors;
struct svc_xprt *xprt;
@@ -1140,6 +1161,23 @@ ok:
if (nfsd4_spo_must_allow(rqstp))
return nfs_ok;
+ /* Some calls may be processed without authentication
+ * on GSS exports. For example NFS2/3 calls on root
+ * directory, see section 2.3.2 of rfc 2623.
+ * For "may_bypass_gss" check that export has really
+ * enabled some flavor with authentication (GSS or any
+ * other) and also check that the used auth flavor is
+ * without authentication (none or sys).
+ */
+ if (may_bypass_gss && (
+ rqstp->rq_cred.cr_flavor == RPC_AUTH_NULL ||
+ rqstp->rq_cred.cr_flavor == RPC_AUTH_UNIX)) {
+ for (f = exp->ex_flavors; f < end; f++) {
+ if (f->pseudoflavor >= RPC_AUTH_DES)
+ return 0;
+ }
+ }
+
denied:
return nfserr_wrongsec;
}
@@ -1406,9 +1444,12 @@ static int e_show(struct seq_file *m, void *p)
return 0;
}
- exp_get(exp);
+ if (!cache_get_rcu(&exp->h))
+ return 0;
+
if (cache_check(cd, &exp->h, NULL))
return 0;
+
exp_put(exp);
return svc_export_show(m, cd, cp);
}

fs/nfsd/export.h

View file
diff --git a/fs/nfsd/export.h b/fs/nfsd/export.h
index 3794ae2..6f2fbaa 100644
--- a/fs/nfsd/export.h
+++ b/fs/nfsd/export.h
@@ -75,7 +75,7 @@ struct svc_export {
u32 ex_layout_types;
struct nfsd4_deviceid_map *ex_devid_map;
struct cache_detail *cd;
- struct rcu_head ex_rcu;
+ struct rcu_work ex_rcu_work;
unsigned long ex_xprtsec_modes;
struct export_stats *ex_stats;
};
@@ -92,7 +92,7 @@ struct svc_expkey {
u32 ek_fsid[6];
struct path ek_path;
- struct rcu_head ek_rcu;
+ struct rcu_work ek_rcu_work;
};
#define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC))
@@ -101,7 +101,8 @@ struct svc_expkey {
struct svc_cred;
int nfsexp_flags(struct svc_cred *cred, struct svc_export *exp);
-__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
+__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp,
+ bool may_bypass_gss);
/*
* Function declarations

fs/nfsd/filecache.c

View file
diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c
index 09c444e..a1cdba4 100644
--- a/fs/nfsd/filecache.c
+++ b/fs/nfsd/filecache.c
@@ -391,19 +391,19 @@ nfsd_file_put(struct nfsd_file *nf)
}
/**
- * nfsd_file_put_local - put the reference to nfsd_file and local nfsd_serv
- * @nf: nfsd_file of which to put the references
+ * nfsd_file_put_local - put nfsd_file reference and arm nfsd_serv_put in caller
+ * @nf: nfsd_file of which to put the reference
*
- * First put the reference of the nfsd_file and then put the
- * reference to the associated nn->nfsd_serv.
+ * First save the associated net to return to caller, then put
+ * the reference of the nfsd_file.
*/
-void
-nfsd_file_put_local(struct nfsd_file *nf) __must_hold(rcu)
+struct net *
+nfsd_file_put_local(struct nfsd_file *nf)
{
struct net *net = nf->nf_net;
nfsd_file_put(nf);
- nfsd_serv_put(net);
+ return net;
}
/**
@@ -1047,7 +1047,7 @@ retry:
* the last one however, since we should hold another.
*/
if (nfsd_file_lru_remove(nf))
- WARN_ON_ONCE(refcount_dec_and_test(&nf->nf_ref));
+ refcount_dec(&nf->nf_ref);
goto wait_for_construction;
}
@@ -1120,8 +1120,7 @@ open_file:
status = nfs_ok;
trace_nfsd_file_opened(nf, status);
} else {
- ret = nfsd_open_verified(rqstp, fhp, may_flags,
- &nf->nf_file);
+ ret = nfsd_open_verified(fhp, may_flags, &nf->nf_file);
if (ret == -EOPENSTALE && stale_retry) {
stale_retry = false;
nfsd_file_unhash(nf);

fs/nfsd/filecache.h

View file
diff --git a/fs/nfsd/filecache.h b/fs/nfsd/filecache.h
index cadf3c2..d5db6b3 100644
--- a/fs/nfsd/filecache.h
+++ b/fs/nfsd/filecache.h
@@ -55,7 +55,7 @@ void nfsd_file_cache_shutdown(void);
int nfsd_file_cache_start_net(struct net *net);
void nfsd_file_cache_shutdown_net(struct net *net);
void nfsd_file_put(struct nfsd_file *nf);
-void nfsd_file_put_local(struct nfsd_file *nf);
+struct net *nfsd_file_put_local(struct nfsd_file *nf);
struct nfsd_file *nfsd_file_get(struct nfsd_file *nf);
struct file *nfsd_file_file(struct nfsd_file *nf);
void nfsd_file_close_inode_sync(struct inode *inode);

fs/nfsd/lockd.c

View file
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 46a7f9b..edc9f75 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -38,11 +38,20 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp,
memcpy(&fh.fh_handle.fh_raw, f->data, f->size);
fh.fh_export = NULL;
+ /*
+ * Allow BYPASS_GSS as some client implementations use AUTH_SYS
+ * for NLM even when GSS is used for NFS.
+ * Allow OWNER_OVERRIDE as permission might have been changed
+ * after the file was opened.
+ * Pass MAY_NLM so that authentication can be completely bypassed
+ * if NFSEXP_NOAUTHNLM is set. Some older clients use AUTH_NULL
+ * for NLM requests.
+ */
access = (mode == O_WRONLY) ? NFSD_MAY_WRITE : NFSD_MAY_READ;
- access |= NFSD_MAY_LOCK;
+ access |= NFSD_MAY_NLM | NFSD_MAY_OWNER_OVERRIDE | NFSD_MAY_BYPASS_GSS;
nfserr = nfsd_open(rqstp, &fh, S_IFREG, access, filp);
fh_put(&fh);
- /* We return nlm error codes as nlm doesn't know
+ /* We return nlm error codes as nlm doesn't know
* about nfsd, but nfsd does know about nlm..
*/
switch (nfserr) {

fs/nfsd/nfs4acl.c

View file
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 96e786b..936ea1a 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -198,8 +198,6 @@ summarize_posix_acl(struct posix_acl *acl, struct posix_acl_summary *pas)
memset(pas, 0, sizeof(*pas));
pas->mask = 07;
- pe = acl->a_entries + acl->a_count;
-
FOREACH_ACL_ENTRY(pa, acl, pe) {
switch (pa->e_tag) {
case ACL_USER_OBJ:

fs/nfsd/nfs4callback.c

View file
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index b5b3ab9..3877b53 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -287,17 +287,17 @@ static int decode_cb_compound4res(struct xdr_stream *xdr,
u32 length;
__be32 *p;
- p = xdr_inline_decode(xdr, 4 + 4);
+ p = xdr_inline_decode(xdr, XDR_UNIT);
if (unlikely(p == NULL))
goto out_overflow;
- hdr->status = be32_to_cpup(p++);
+ hdr->status = be32_to_cpup(p);
/* Ignore the tag */
- length = be32_to_cpup(p++);
- p = xdr_inline_decode(xdr, length + 4);
- if (unlikely(p == NULL))
+ if (xdr_stream_decode_u32(xdr, &length) < 0)
+ goto out_overflow;
+ if (xdr_inline_decode(xdr, length) == NULL)
+ goto out_overflow;
+ if (xdr_stream_decode_u32(xdr, &hdr->nops) < 0)
goto out_overflow;
- p += XDR_QUADLEN(length);
- hdr->nops = be32_to_cpup(p);
return 0;
out_overflow:
return -EIO;
@@ -364,13 +364,29 @@ encode_cb_getattr4args(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr,
struct nfs4_delegation *dp =
container_of(fattr, struct nfs4_delegation, dl_cb_fattr);
struct knfsd_fh *fh = &dp->dl_stid.sc_file->fi_fhandle;
+ u32 bmap[1];
+
+ bmap[0] = FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE;
encode_nfs_cb_opnum4(xdr, OP_CB_GETATTR);
encode_nfs_fh4(xdr, fh);
- encode_bitmap4(xdr, fattr->ncf_cb_bmap, ARRAY_SIZE(fattr->ncf_cb_bmap));
+ encode_bitmap4(xdr, bmap, ARRAY_SIZE(bmap));
hdr->nops++;
}
+static u32 highest_slotid(struct nfsd4_session *ses)
+{
+ u32 idx;
+
+ spin_lock(&ses->se_lock);
+ idx = fls(~ses->se_cb_slot_avail);
+ if (idx > 0)
+ --idx;
+ idx = max(idx, ses->se_cb_highest_slot);
+ spin_unlock(&ses->se_lock);
+ return idx;
+}
+
/*
* CB_SEQUENCE4args
*
@@ -397,15 +413,40 @@ static void encode_cb_sequence4args(struct xdr_stream *xdr,
encode_sessionid4(xdr, session);
p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4 + 4);
- *p++ = cpu_to_be32(session->se_cb_seq_nr); /* csa_sequenceid */
- *p++ = xdr_zero; /* csa_slotid */
- *p++ = xdr_zero; /* csa_highest_slotid */
+ *p++ = cpu_to_be32(session->se_cb_seq_nr[cb->cb_held_slot]); /* csa_sequenceid */
+ *p++ = cpu_to_be32(cb->cb_held_slot); /* csa_slotid */
+ *p++ = cpu_to_be32(highest_slotid(session)); /* csa_highest_slotid */
*p++ = xdr_zero; /* csa_cachethis */
xdr_encode_empty_array(p); /* csa_referring_call_lists */
hdr->nops++;
}
+static void update_cb_slot_table(struct nfsd4_session *ses, u32 target)
+{
+ /* No need to do anything if nothing changed */
+ if (likely(target == READ_ONCE(ses->se_cb_highest_slot)))
+ return;
+
+ spin_lock(&ses->se_lock);
+ if (target > ses->se_cb_highest_slot) {
+ int i;
+
+ target = min(target, NFSD_BC_SLOT_TABLE_SIZE - 1);
+
+ /*
+ * Growing the slot table. Reset any new sequences to 1.
+ *
+ * NB: There is some debate about whether the RFC requires this,
+ * but the Linux client expects it.
+ */
+ for (i = ses->se_cb_highest_slot + 1; i <= target; ++i)
+ ses->se_cb_seq_nr[i] = 1;
+ }
+ ses->se_cb_highest_slot = target;
+ spin_unlock(&ses->se_lock);
+}
+
/*
* CB_SEQUENCE4resok
*
@@ -433,7 +474,7 @@ static int decode_cb_sequence4resok(struct xdr_stream *xdr,
struct nfsd4_session *session = cb->cb_clp->cl_cb_session;
int status = -ESERVERFAULT;
__be32 *p;
- u32 dummy;
+ u32 seqid, slotid, target;
/*
* If the server returns different values for sessionID, slotID or
@@ -449,21 +490,22 @@ static int decode_cb_sequence4resok(struct xdr_stream *xdr,
}
p += XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN);
- dummy = be32_to_cpup(p++);
- if (dummy != session->se_cb_seq_nr) {
+ seqid = be32_to_cpup(p++);
+ if (seqid != session->se_cb_seq_nr[cb->cb_held_slot]) {
dprintk("NFS: %s Invalid sequence number\n", __func__);
goto out;
}
- dummy = be32_to_cpup(p++);
- if (dummy != 0) {
+ slotid = be32_to_cpup(p++);
+ if (slotid != cb->cb_held_slot) {
dprintk("NFS: %s Invalid slotid\n", __func__);
goto out;
}
- /*
- * FIXME: process highest slotid and target highest slotid
- */
+ p++; // ignore current highest slot value
+
+ target = be32_to_cpup(p++);
+ update_cb_slot_table(session, target);
status = 0;
out:
cb->cb_seq_status = status;
@@ -1164,6 +1206,22 @@ void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn)
spin_unlock(&clp->cl_lock);
}
+static int grab_slot(struct nfsd4_session *ses)
+{
+ int idx;
+
+ spin_lock(&ses->se_lock);
+ idx = ffs(ses->se_cb_slot_avail) - 1;
+ if (idx < 0 || idx > ses->se_cb_highest_slot) {
+ spin_unlock(&ses->se_lock);
+ return -1;
+ }
+ /* clear the bit for the slot */
+ ses->se_cb_slot_avail &= ~BIT(idx);
+ spin_unlock(&ses->se_lock);
+ return idx;
+}
+
/*
* There's currently a single callback channel slot.
* If the slot is available, then mark it busy. Otherwise, set the
@@ -1172,28 +1230,32 @@ void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn)
static bool nfsd41_cb_get_slot(struct nfsd4_callback *cb, struct rpc_task *task)
{
struct nfs4_client *clp = cb->cb_clp;
+ struct nfsd4_session *ses = clp->cl_cb_session;
- if (!cb->cb_holds_slot &&
- test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) {
+ if (cb->cb_held_slot >= 0)
+ return true;
+ cb->cb_held_slot = grab_slot(ses);
+ if (cb->cb_held_slot < 0) {
rpc_sleep_on(&clp->cl_cb_waitq, task, NULL);
/* Race breaker */
- if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) {
- dprintk("%s slot is busy\n", __func__);
+ cb->cb_held_slot = grab_slot(ses);
+ if (cb->cb_held_slot < 0)
return false;

This diff is incomplete. Download the complete patch.

fs/nfsd/nfs4proc.c

View file

This diff is incomplete. Download the complete patch.

fs/nfsd/nfs4recover.c

View file

This diff is incomplete. Download the complete patch.

fs/nfsd/nfs4state.c

View file

This diff is incomplete. Download the complete patch.

fs/nfsd/nfs4xdr.c

View file

This diff is incomplete. Download the complete patch.

fs/nfsd/nfsfh.c

View file

This diff is incomplete. Download the complete patch.

fs/nfsd/nfsfh.h

View file

This diff is incomplete. Download the complete patch.

fs/nfsd/state.h

View file

This diff is incomplete. Download the complete patch.

fs/nfsd/trace.h

View file

This diff is incomplete. Download the complete patch.

fs/nfsd/vfs.c

View file

This diff is incomplete. Download the complete patch.

fs/nfsd/vfs.h

View file

This diff is incomplete. Download the complete patch.

fs/nfsd/xdr4.h

View file

This diff is incomplete. Download the complete patch.

include/linux/lockd/lockd.h

View file

This diff is incomplete. Download the complete patch.

include/linux/lockd/xdr.h

View file

This diff is incomplete. Download the complete patch.

include/linux/nfslocalio.h

View file

This diff is incomplete. Download the complete patch.

include/linux/sunrpc/xdr.h

View file

This diff is incomplete. Download the complete patch.

include/linux/sunrpc/xdrgen/_defs.h

View file

This diff is incomplete. Download the complete patch.

net/sunrpc/cache.c

View file

This diff is incomplete. Download the complete patch.

net/sunrpc/xprtrdma/svc_rdma.c

View file

This diff is incomplete. Download the complete patch.

net/sunrpc/xprtrdma/svc_rdma_recvfrom.c

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/extract.sh

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/README

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/generators/__init__.py

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/generators/enum.py

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/generators/pointer.py

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/generators/struct.py

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/generators/typedef.py

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/generators/union.py

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/grammars/xdr.lark

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/subcmds/definitions.py

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/subcmds/source.py

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/enum/declaration/close.j2

View before deletion

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/enum/declaration/enum.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/enum/decoder/enum.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/enum/decoder/enum_be.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/enum/definition/close.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/enum/definition/close_be.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/enum/encoder/enum.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/enum/encoder/enum_be.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/enum/maxsize/enum.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/pointer/decoder/string.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/pointer/definition/string.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/pointer/encoder/string.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/pointer/maxsize/pointer.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/program/decoder/result.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/source_top/client.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/struct/decoder/string.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/struct/definition/string.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/struct/encoder/string.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/struct/maxsize/struct.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/typedef/declaration/string.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/typedef/decoder/string.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/typedef/definition/string.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/typedef/encoder/string.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/basic.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/fixed_length_opaque.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/string.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/variable_length_array.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/typedef/maxsize/variable_length_opaque.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/union/decoder/case_spec_be.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/union/decoder/string.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/union/encoder/case_spec_be.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/templates/C/union/maxsize/union.j2

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/xdr_ast.py

View file

This diff is incomplete. Download the complete patch.

tools/net/sunrpc/xdrgen/xdrgen

View file

This diff is incomplete. Download the complete patch.