Skip to content

Commit 445d9f0

Browse files
committed
Merge tag 'nfsd-6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
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 ...
2 parents 44b4d13 + 583772e commit 445d9f0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+1115
-348
lines changed

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12436,6 +12436,7 @@ F: include/trace/misc/sunrpc.h
1243612436
F: include/uapi/linux/nfsd/
1243712437
F: include/uapi/linux/sunrpc/
1243812438
F: net/sunrpc/
12439+
F: tools/net/sunrpc/
1243912440

1244012441
KERNEL PACMAN PACKAGING (in addition to generic KERNEL BUILD)
1244112442
M: Thomas Weißschuh <linux@weissschuh.net>

fs/lockd/clntxdr.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
/*
33
* linux/fs/lockd/clntxdr.c
44
*
5-
* XDR functions to encode/decode NLM version 3 RPC arguments and results.
6-
* NLM version 3 is backwards compatible with NLM versions 1 and 2.
5+
* XDR functions to encode/decode NLM version 1 and 3 RPC
6+
* arguments and results. NLM version 2 is not specified
7+
* by a standard, thus it is not implemented.
78
*
89
* NLM client-side only.
910
*

fs/lockd/svc4proc.c

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,15 @@ nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
4646
if (filp != NULL) {
4747
int mode = lock_to_openmode(&lock->fl);
4848

49+
lock->fl.c.flc_flags = FL_POSIX;
50+
4951
error = nlm_lookup_file(rqstp, &file, lock);
5052
if (error)
5153
goto no_locks;
5254
*filp = file;
5355

5456
/* Set up the missing parts of the file_lock structure */
55-
lock->fl.c.flc_flags = FL_POSIX;
56-
lock->fl.c.flc_file = file->f_file[mode];
57+
lock->fl.c.flc_file = file->f_file[mode];
5758
lock->fl.c.flc_pid = current->tgid;
5859
lock->fl.fl_start = (loff_t)lock->lock_start;
5960
lock->fl.fl_end = lock->lock_len ?
@@ -108,7 +109,8 @@ __nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
108109

109110
test_owner = argp->lock.fl.c.flc_owner;
110111
/* Now check for conflicting locks */
111-
resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie);
112+
resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock,
113+
&resp->lock);
112114
if (resp->status == nlm_drop_reply)
113115
rc = rpc_drop_reply;
114116
else
@@ -142,18 +144,6 @@ __nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_res *resp)
142144
if ((resp->status = nlm4svc_retrieve_args(rqstp, argp, &host, &file)))
143145
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
144146

145-
#if 0
146-
/* If supplied state doesn't match current state, we assume it's
147-
* an old request that time-warped somehow. Any error return would
148-
* do in this case because it's irrelevant anyway.
149-
*
150-
* NB: We don't retrieve the remote host's state yet.
151-
*/
152-
if (host->h_nsmstate && host->h_nsmstate != argp->state) {
153-
resp->status = nlm_lck_denied_nolocks;
154-
} else
155-
#endif
156-
157147
/* Now try to lock the file */
158148
resp->status = nlmsvc_lock(rqstp, file, host, &argp->lock,
159149
argp->block, &argp->cookie,

fs/lockd/svclock.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -608,7 +608,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
608608
__be32
609609
nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
610610
struct nlm_host *host, struct nlm_lock *lock,
611-
struct nlm_lock *conflock, struct nlm_cookie *cookie)
611+
struct nlm_lock *conflock)
612612
{
613613
int error;
614614
int mode;

fs/lockd/svcproc.c

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
130130
test_owner = argp->lock.fl.c.flc_owner;
131131

132132
/* Now check for conflicting locks */
133-
resp->status = cast_status(nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie));
133+
resp->status = cast_status(nlmsvc_testlock(rqstp, file, host,
134+
&argp->lock, &resp->lock));
134135
if (resp->status == nlm_drop_reply)
135136
rc = rpc_drop_reply;
136137
else
@@ -165,18 +166,6 @@ __nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_res *resp)
165166
if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
166167
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
167168

168-
#if 0
169-
/* If supplied state doesn't match current state, we assume it's
170-
* an old request that time-warped somehow. Any error return would
171-
* do in this case because it's irrelevant anyway.
172-
*
173-
* NB: We don't retrieve the remote host's state yet.
174-
*/
175-
if (host->h_nsmstate && host->h_nsmstate != argp->state) {
176-
resp->status = nlm_lck_denied_nolocks;
177-
} else
178-
#endif
179-
180169
/* Now try to lock the file */
181170
resp->status = cast_status(nlmsvc_lock(rqstp, file, host, &argp->lock,
182171
argp->block, &argp->cookie,

fs/lockd/xdr4.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock)
8989
return false;
9090

9191
locks_init_lock(fl);
92-
fl->c.flc_flags = FL_POSIX;
9392
fl->c.flc_type = F_RDLCK;
9493
nlm4svc_set_file_lock_range(fl, lock->lock_start, lock->lock_len);
9594
return true;
@@ -268,7 +267,6 @@ nlm4svc_decode_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
268267
struct nlm_args *argp = rqstp->rq_argp;
269268
struct nlm_lock *lock = &argp->lock;
270269

271-
memset(lock, 0, sizeof(*lock));
272270
locks_init_lock(&lock->fl);
273271
lock->svid = ~(u32)0;
274272

fs/nfs_common/nfslocalio.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,9 @@ struct nfsd_file *nfs_open_local_fh(nfs_uuid_t *uuid,
155155
/* We have an implied reference to net thanks to nfsd_serv_try_get */
156156
localio = nfs_to->nfsd_open_local_fh(net, uuid->dom, rpc_clnt,
157157
cred, nfs_fh, fmode);
158-
if (IS_ERR(localio)) {
159-
rcu_read_lock();
160-
nfs_to->nfsd_serv_put(net);
161-
rcu_read_unlock();
162-
}
158+
if (IS_ERR(localio))
159+
nfs_to_nfsd_net_put(net);
160+
163161
return localio;
164162
}
165163
EXPORT_SYMBOL_GPL(nfs_open_local_fh);

fs/nfsd/export.c

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,24 @@
4040
#define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS)
4141
#define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1)
4242

43-
static void expkey_put(struct kref *ref)
43+
static void expkey_put_work(struct work_struct *work)
4444
{
45-
struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
45+
struct svc_expkey *key =
46+
container_of(to_rcu_work(work), struct svc_expkey, ek_rcu_work);
4647

4748
if (test_bit(CACHE_VALID, &key->h.flags) &&
4849
!test_bit(CACHE_NEGATIVE, &key->h.flags))
4950
path_put(&key->ek_path);
5051
auth_domain_put(key->ek_client);
51-
kfree_rcu(key, ek_rcu);
52+
kfree(key);
53+
}
54+
55+
static void expkey_put(struct kref *ref)
56+
{
57+
struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
58+
59+
INIT_RCU_WORK(&key->ek_rcu_work, expkey_put_work);
60+
queue_rcu_work(system_wq, &key->ek_rcu_work);
5261
}
5362

5463
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)
355364
EXP_STATS_COUNTERS_NUM);
356365
}
357366

358-
static void svc_export_put(struct kref *ref)
367+
static void svc_export_put_work(struct work_struct *work)
359368
{
360-
struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
369+
struct svc_export *exp =
370+
container_of(to_rcu_work(work), struct svc_export, ex_rcu_work);
371+
361372
path_put(&exp->ex_path);
362373
auth_domain_put(exp->ex_client);
363374
nfsd4_fslocs_free(&exp->ex_fslocs);
364375
export_stats_destroy(exp->ex_stats);
365376
kfree(exp->ex_stats);
366377
kfree(exp->ex_uuid);
367-
kfree_rcu(exp, ex_rcu);
378+
kfree(exp);
379+
}
380+
381+
static void svc_export_put(struct kref *ref)
382+
{
383+
struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
384+
385+
INIT_RCU_WORK(&exp->ex_rcu_work, svc_export_put_work);
386+
queue_rcu_work(system_wq, &exp->ex_rcu_work);
368387
}
369388

370389
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,
10781097
* check_nfsd_access - check if access to export is allowed.
10791098
* @exp: svc_export that is being accessed.
10801099
* @rqstp: svc_rqst attempting to access @exp (will be NULL for LOCALIO).
1100+
* @may_bypass_gss: reduce strictness of authorization check
10811101
*
10821102
* Return values:
10831103
* %nfs_ok if access is granted, or
10841104
* %nfserr_wrongsec if access is denied
10851105
*/
1086-
__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
1106+
__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp,
1107+
bool may_bypass_gss)
10871108
{
10881109
struct exp_flavor_info *f, *end = exp->ex_flavors + exp->ex_nflavors;
10891110
struct svc_xprt *xprt;
@@ -1140,6 +1161,23 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)
11401161
if (nfsd4_spo_must_allow(rqstp))
11411162
return nfs_ok;
11421163

1164+
/* Some calls may be processed without authentication
1165+
* on GSS exports. For example NFS2/3 calls on root
1166+
* directory, see section 2.3.2 of rfc 2623.
1167+
* For "may_bypass_gss" check that export has really
1168+
* enabled some flavor with authentication (GSS or any
1169+
* other) and also check that the used auth flavor is
1170+
* without authentication (none or sys).
1171+
*/
1172+
if (may_bypass_gss && (
1173+
rqstp->rq_cred.cr_flavor == RPC_AUTH_NULL ||
1174+
rqstp->rq_cred.cr_flavor == RPC_AUTH_UNIX)) {
1175+
for (f = exp->ex_flavors; f < end; f++) {
1176+
if (f->pseudoflavor >= RPC_AUTH_DES)
1177+
return 0;
1178+
}
1179+
}
1180+
11431181
denied:
11441182
return nfserr_wrongsec;
11451183
}
@@ -1406,9 +1444,12 @@ static int e_show(struct seq_file *m, void *p)
14061444
return 0;
14071445
}
14081446

1409-
exp_get(exp);
1447+
if (!cache_get_rcu(&exp->h))
1448+
return 0;
1449+
14101450
if (cache_check(cd, &exp->h, NULL))
14111451
return 0;
1452+
14121453
exp_put(exp);
14131454
return svc_export_show(m, cd, cp);
14141455
}

fs/nfsd/export.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ struct svc_export {
7575
u32 ex_layout_types;
7676
struct nfsd4_deviceid_map *ex_devid_map;
7777
struct cache_detail *cd;
78-
struct rcu_head ex_rcu;
78+
struct rcu_work ex_rcu_work;
7979
unsigned long ex_xprtsec_modes;
8080
struct export_stats *ex_stats;
8181
};
@@ -92,7 +92,7 @@ struct svc_expkey {
9292
u32 ek_fsid[6];
9393

9494
struct path ek_path;
95-
struct rcu_head ek_rcu;
95+
struct rcu_work ek_rcu_work;
9696
};
9797

9898
#define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC))
@@ -101,7 +101,8 @@ struct svc_expkey {
101101

102102
struct svc_cred;
103103
int nfsexp_flags(struct svc_cred *cred, struct svc_export *exp);
104-
__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
104+
__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp,
105+
bool may_bypass_gss);
105106

106107
/*
107108
* Function declarations

fs/nfsd/filecache.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -391,19 +391,19 @@ nfsd_file_put(struct nfsd_file *nf)
391391
}
392392

393393
/**
394-
* nfsd_file_put_local - put the reference to nfsd_file and local nfsd_serv
395-
* @nf: nfsd_file of which to put the references
394+
* nfsd_file_put_local - put nfsd_file reference and arm nfsd_serv_put in caller
395+
* @nf: nfsd_file of which to put the reference
396396
*
397-
* First put the reference of the nfsd_file and then put the
398-
* reference to the associated nn->nfsd_serv.
397+
* First save the associated net to return to caller, then put
398+
* the reference of the nfsd_file.
399399
*/
400-
void
401-
nfsd_file_put_local(struct nfsd_file *nf) __must_hold(rcu)
400+
struct net *
401+
nfsd_file_put_local(struct nfsd_file *nf)
402402
{
403403
struct net *net = nf->nf_net;
404404

405405
nfsd_file_put(nf);
406-
nfsd_serv_put(net);
406+
return net;
407407
}
408408

409409
/**
@@ -1047,7 +1047,7 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct net *net,
10471047
* the last one however, since we should hold another.
10481048
*/
10491049
if (nfsd_file_lru_remove(nf))
1050-
WARN_ON_ONCE(refcount_dec_and_test(&nf->nf_ref));
1050+
refcount_dec(&nf->nf_ref);
10511051
goto wait_for_construction;
10521052
}
10531053

@@ -1120,8 +1120,7 @@ nfsd_file_do_acquire(struct svc_rqst *rqstp, struct net *net,
11201120
status = nfs_ok;
11211121
trace_nfsd_file_opened(nf, status);
11221122
} else {
1123-
ret = nfsd_open_verified(rqstp, fhp, may_flags,
1124-
&nf->nf_file);
1123+
ret = nfsd_open_verified(fhp, may_flags, &nf->nf_file);
11251124
if (ret == -EOPENSTALE && stale_retry) {
11261125
stale_retry = false;
11271126
nfsd_file_unhash(nf);

0 commit comments

Comments
 (0)