Skip to content

Commit 911d137

Browse files
committed
Merge tag 'nfsd-5.5' of git://linux-nfs.org/~bfields/linux
Pull nfsd updates from Bruce Fields: "This is a relatively quiet cycle for nfsd, mainly various bugfixes. Possibly most interesting is Trond's fixes for some callback races that were due to my incomplete understanding of rpc client shutdown. Unfortunately at the last minute I've started noticing a new intermittent failure to send callbacks. As the logic seems basically correct, I'm leaving Trond's patches in for now, and hope to find a fix in the next week so I don't have to revert those patches" * tag 'nfsd-5.5' of git://linux-nfs.org/~bfields/linux: (24 commits) nfsd: depend on CRYPTO_MD5 for legacy client tracking NFSD fixing possible null pointer derefering in copy offload nfsd: check for EBUSY from vfs_rmdir/vfs_unink. nfsd: Ensure CLONE persists data and metadata changes to the target file SUNRPC: Fix backchannel latency metrics nfsd: restore NFSv3 ACL support nfsd: v4 support requires CRYPTO_SHA256 nfsd: Fix cld_net->cn_tfm initialization lockd: remove __KERNEL__ ifdefs sunrpc: remove __KERNEL__ ifdefs race in exportfs_decode_fh() nfsd: Drop LIST_HEAD where the variable it declares is never used. nfsd: document callback_wq serialization of callback code nfsd: mark cb path down on unknown errors nfsd: Fix races between nfsd4_cb_release() and nfsd4_shutdown_callback() nfsd: minor 4.1 callback cleanup SUNRPC: Fix svcauth_gss_proxy_init() SUNRPC: Trace gssproxy upcall results sunrpc: fix crash when cache_head become valid before update nfsd: remove private bin2hex implementation ...
2 parents fb9bf40 + 38a2204 commit 911d137

37 files changed

+343
-137
lines changed

fs/nfsd/Kconfig

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ config NFSD_V4
7373
select NFSD_V3
7474
select FS_POSIX_ACL
7575
select SUNRPC_GSS
76-
select CRYPTO
76+
select CRYPTO_MD5
77+
select CRYPTO_SHA256
7778
select GRACE_PERIOD
7879
help
7980
This option enables support in your system's NFS server for

fs/nfsd/filecache.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -685,8 +685,6 @@ nfsd_file_cache_purge(struct net *net)
685685
void
686686
nfsd_file_cache_shutdown(void)
687687
{
688-
LIST_HEAD(dispose);
689-
690688
set_bit(NFSD_FILE_SHUTDOWN, &nfsd_file_lru_flags);
691689

692690
lease_unregister_notifier(&nfsd_file_lease_notifier);

fs/nfsd/nfs4callback.c

Lines changed: 85 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,31 @@ static int max_cb_time(struct net *net)
826826
return max(nn->nfsd4_lease/10, (time_t)1) * HZ;
827827
}
828828

829+
static struct workqueue_struct *callback_wq;
830+
831+
static bool nfsd4_queue_cb(struct nfsd4_callback *cb)
832+
{
833+
return queue_work(callback_wq, &cb->cb_work);
834+
}
835+
836+
static void nfsd41_cb_inflight_begin(struct nfs4_client *clp)
837+
{
838+
atomic_inc(&clp->cl_cb_inflight);
839+
}
840+
841+
static void nfsd41_cb_inflight_end(struct nfs4_client *clp)
842+
{
843+
844+
if (atomic_dec_and_test(&clp->cl_cb_inflight))
845+
wake_up_var(&clp->cl_cb_inflight);
846+
}
847+
848+
static void nfsd41_cb_inflight_wait_complete(struct nfs4_client *clp)
849+
{
850+
wait_var_event(&clp->cl_cb_inflight,
851+
!atomic_read(&clp->cl_cb_inflight));
852+
}
853+
829854
static const struct cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc_clnt *client, struct nfsd4_session *ses)
830855
{
831856
if (clp->cl_minorversion == 0) {
@@ -937,14 +962,21 @@ static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata)
937962
clp->cl_cb_state = NFSD4_CB_UP;
938963
}
939964

965+
static void nfsd4_cb_probe_release(void *calldata)
966+
{
967+
struct nfs4_client *clp = container_of(calldata, struct nfs4_client, cl_cb_null);
968+
969+
nfsd41_cb_inflight_end(clp);
970+
971+
}
972+
940973
static const struct rpc_call_ops nfsd4_cb_probe_ops = {
941974
/* XXX: release method to ensure we set the cb channel down if
942975
* necessary on early failure? */
943976
.rpc_call_done = nfsd4_cb_probe_done,
977+
.rpc_release = nfsd4_cb_probe_release,
944978
};
945979

946-
static struct workqueue_struct *callback_wq;
947-
948980
/*
949981
* Poke the callback thread to process any updates to the callback
950982
* parameters, and send a null probe.
@@ -975,9 +1007,12 @@ void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn)
9751007
* If the slot is available, then mark it busy. Otherwise, set the
9761008
* thread for sleeping on the callback RPC wait queue.
9771009
*/
978-
static bool nfsd41_cb_get_slot(struct nfs4_client *clp, struct rpc_task *task)
1010+
static bool nfsd41_cb_get_slot(struct nfsd4_callback *cb, struct rpc_task *task)
9791011
{
980-
if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) {
1012+
struct nfs4_client *clp = cb->cb_clp;
1013+
1014+
if (!cb->cb_holds_slot &&
1015+
test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) {
9811016
rpc_sleep_on(&clp->cl_cb_waitq, task, NULL);
9821017
/* Race breaker */
9831018
if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) {
@@ -986,9 +1021,31 @@ static bool nfsd41_cb_get_slot(struct nfs4_client *clp, struct rpc_task *task)
9861021
}
9871022
rpc_wake_up_queued_task(&clp->cl_cb_waitq, task);
9881023
}
1024+
cb->cb_holds_slot = true;
9891025
return true;
9901026
}
9911027

1028+
static void nfsd41_cb_release_slot(struct nfsd4_callback *cb)
1029+
{
1030+
struct nfs4_client *clp = cb->cb_clp;
1031+
1032+
if (cb->cb_holds_slot) {
1033+
cb->cb_holds_slot = false;
1034+
clear_bit(0, &clp->cl_cb_slot_busy);
1035+
rpc_wake_up_next(&clp->cl_cb_waitq);
1036+
}
1037+
}
1038+
1039+
static void nfsd41_destroy_cb(struct nfsd4_callback *cb)
1040+
{
1041+
struct nfs4_client *clp = cb->cb_clp;
1042+
1043+
nfsd41_cb_release_slot(cb);
1044+
if (cb->cb_ops && cb->cb_ops->release)
1045+
cb->cb_ops->release(cb);
1046+
nfsd41_cb_inflight_end(clp);
1047+
}
1048+
9921049
/*
9931050
* TODO: cb_sequence should support referring call lists, cachethis, multiple
9941051
* slots, and mark callback channel down on communication errors.
@@ -1005,11 +1062,8 @@ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
10051062
*/
10061063
cb->cb_seq_status = 1;
10071064
cb->cb_status = 0;
1008-
if (minorversion) {
1009-
if (!cb->cb_holds_slot && !nfsd41_cb_get_slot(clp, task))
1010-
return;
1011-
cb->cb_holds_slot = true;
1012-
}
1065+
if (minorversion && !nfsd41_cb_get_slot(cb, task))
1066+
return;
10131067
rpc_call_start(task);
10141068
}
10151069

@@ -1072,13 +1126,12 @@ static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback
10721126
}
10731127
break;
10741128
default:
1129+
nfsd4_mark_cb_fault(cb->cb_clp, cb->cb_seq_status);
10751130
dprintk("%s: unprocessed error %d\n", __func__,
10761131
cb->cb_seq_status);
10771132
}
10781133

1079-
cb->cb_holds_slot = false;
1080-
clear_bit(0, &clp->cl_cb_slot_busy);
1081-
rpc_wake_up_next(&clp->cl_cb_waitq);
1134+
nfsd41_cb_release_slot(cb);
10821135
dprintk("%s: freed slot, new seqid=%d\n", __func__,
10831136
clp->cl_cb_session->se_cb_seq_nr);
10841137

@@ -1091,8 +1144,10 @@ static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback
10911144
ret = false;
10921145
goto out;
10931146
need_restart:
1094-
task->tk_status = 0;
1095-
cb->cb_need_restart = true;
1147+
if (!test_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags)) {
1148+
task->tk_status = 0;
1149+
cb->cb_need_restart = true;
1150+
}
10961151
return false;
10971152
}
10981153

@@ -1134,9 +1189,9 @@ static void nfsd4_cb_release(void *calldata)
11341189
struct nfsd4_callback *cb = calldata;
11351190

11361191
if (cb->cb_need_restart)
1137-
nfsd4_run_cb(cb);
1192+
nfsd4_queue_cb(cb);
11381193
else
1139-
cb->cb_ops->release(cb);
1194+
nfsd41_destroy_cb(cb);
11401195

11411196
}
11421197

@@ -1170,6 +1225,7 @@ void nfsd4_shutdown_callback(struct nfs4_client *clp)
11701225
*/
11711226
nfsd4_run_cb(&clp->cl_cb_null);
11721227
flush_workqueue(callback_wq);
1228+
nfsd41_cb_inflight_wait_complete(clp);
11731229
}
11741230

11751231
/* requires cl_lock: */
@@ -1187,6 +1243,12 @@ static struct nfsd4_conn * __nfsd4_find_backchannel(struct nfs4_client *clp)
11871243
return NULL;
11881244
}
11891245

1246+
/*
1247+
* Note there isn't a lot of locking in this code; instead we depend on
1248+
* the fact that it is run from the callback_wq, which won't run two
1249+
* work items at once. So, for example, callback_wq handles all access
1250+
* of cl_cb_client and all calls to rpc_create or rpc_shutdown_client.
1251+
*/
11901252
static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
11911253
{
11921254
struct nfs4_cb_conn conn;
@@ -1255,8 +1317,7 @@ nfsd4_run_cb_work(struct work_struct *work)
12551317
clnt = clp->cl_cb_client;
12561318
if (!clnt) {
12571319
/* Callback channel broken, or client killed; give up: */
1258-
if (cb->cb_ops && cb->cb_ops->release)
1259-
cb->cb_ops->release(cb);
1320+
nfsd41_destroy_cb(cb);
12601321
return;
12611322
}
12621323

@@ -1265,6 +1326,7 @@ nfsd4_run_cb_work(struct work_struct *work)
12651326
*/
12661327
if (!cb->cb_ops && clp->cl_minorversion) {
12671328
clp->cl_cb_state = NFSD4_CB_UP;
1329+
nfsd41_destroy_cb(cb);
12681330
return;
12691331
}
12701332

@@ -1290,5 +1352,9 @@ void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp,
12901352

12911353
void nfsd4_run_cb(struct nfsd4_callback *cb)
12921354
{
1293-
queue_work(callback_wq, &cb->cb_work);
1355+
struct nfs4_client *clp = cb->cb_clp;
1356+
1357+
nfsd41_cb_inflight_begin(clp);
1358+
if (!nfsd4_queue_cb(cb))
1359+
nfsd41_cb_inflight_end(clp);
12941360
}

fs/nfsd/nfs4proc.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,7 +1077,8 @@ nfsd4_clone(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
10771077
goto out;
10781078

10791079
status = nfsd4_clone_file_range(src->nf_file, clone->cl_src_pos,
1080-
dst->nf_file, clone->cl_dst_pos, clone->cl_count);
1080+
dst->nf_file, clone->cl_dst_pos, clone->cl_count,
1081+
EX_ISSYNC(cstate->current_fh.fh_export));
10811082

10821083
nfsd_file_put(dst);
10831084
nfsd_file_put(src);
@@ -1297,7 +1298,8 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
12971298
out:
12981299
return status;
12991300
out_err:
1300-
cleanup_async_copy(async_copy);
1301+
if (async_copy)
1302+
cleanup_async_copy(async_copy);
13011303
goto out;
13021304
}
13031305

fs/nfsd/nfs4recover.c

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,6 +1578,7 @@ nfsd4_cld_tracking_init(struct net *net)
15781578
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
15791579
bool running;
15801580
int retries = 10;
1581+
struct crypto_shash *tfm;
15811582

15821583
status = nfs4_cld_state_init(net);
15831584
if (status)
@@ -1586,11 +1587,6 @@ nfsd4_cld_tracking_init(struct net *net)
15861587
status = __nfsd4_init_cld_pipe(net);
15871588
if (status)
15881589
goto err_shutdown;
1589-
nn->cld_net->cn_tfm = crypto_alloc_shash("sha256", 0, 0);
1590-
if (IS_ERR(nn->cld_net->cn_tfm)) {
1591-
status = PTR_ERR(nn->cld_net->cn_tfm);
1592-
goto err_remove;
1593-
}
15941590

15951591
/*
15961592
* rpc pipe upcalls take 30 seconds to time out, so we don't want to
@@ -1607,6 +1603,12 @@ nfsd4_cld_tracking_init(struct net *net)
16071603
status = -ETIMEDOUT;
16081604
goto err_remove;
16091605
}
1606+
tfm = crypto_alloc_shash("sha256", 0, 0);
1607+
if (IS_ERR(tfm)) {
1608+
status = PTR_ERR(tfm);
1609+
goto err_remove;
1610+
}
1611+
nn->cld_net->cn_tfm = tfm;
16101612

16111613
status = nfsd4_cld_get_version(nn);
16121614
if (status == -EOPNOTSUPP)
@@ -1850,19 +1852,14 @@ nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *env0, char *env1)
18501852
static char *
18511853
bin_to_hex_dup(const unsigned char *src, int srclen)
18521854
{
1853-
int i;
1854-
char *buf, *hex;
1855+
char *buf;
18551856

18561857
/* +1 for terminating NULL */
1857-
buf = kmalloc((srclen * 2) + 1, GFP_KERNEL);
1858+
buf = kzalloc((srclen * 2) + 1, GFP_KERNEL);
18581859
if (!buf)
18591860
return buf;
18601861

1861-
hex = buf;
1862-
for (i = 0; i < srclen; i++) {
1863-
sprintf(hex, "%2.2x", *src++);
1864-
hex += 2;
1865-
}
1862+
bin2hex(buf, src, srclen);
18661863
return buf;
18671864
}
18681865

fs/nfsd/nfs4state.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2382,10 +2382,10 @@ static int nfs4_show_open(struct seq_file *s, struct nfs4_stid *st)
23822382
access = bmap_to_share_mode(ols->st_access_bmap);
23832383
deny = bmap_to_share_mode(ols->st_deny_bmap);
23842384

2385-
seq_printf(s, "access: \%s\%s, ",
2385+
seq_printf(s, "access: %s%s, ",
23862386
access & NFS4_SHARE_ACCESS_READ ? "r" : "-",
23872387
access & NFS4_SHARE_ACCESS_WRITE ? "w" : "-");
2388-
seq_printf(s, "deny: \%s\%s, ",
2388+
seq_printf(s, "deny: %s%s, ",
23892389
deny & NFS4_SHARE_ACCESS_READ ? "r" : "-",
23902390
deny & NFS4_SHARE_ACCESS_WRITE ? "w" : "-");
23912391

@@ -3548,12 +3548,17 @@ static bool replay_matches_cache(struct svc_rqst *rqstp,
35483548
(bool)seq->cachethis)
35493549
return false;
35503550
/*
3551-
* If there's an error than the reply can have fewer ops than
3552-
* the call. But if we cached a reply with *more* ops than the
3553-
* call you're sending us now, then this new call is clearly not
3554-
* really a replay of the old one:
3551+
* If there's an error then the reply can have fewer ops than
3552+
* the call.
35553553
*/
3556-
if (slot->sl_opcnt < argp->opcnt)
3554+
if (slot->sl_opcnt < argp->opcnt && !slot->sl_status)
3555+
return false;
3556+
/*
3557+
* But if we cached a reply with *more* ops than the call you're
3558+
* sending us now, then this new call is clearly not really a
3559+
* replay of the old one:
3560+
*/
3561+
if (slot->sl_opcnt > argp->opcnt)
35573562
return false;
35583563
/* This is the only check explicitly called by spec: */
35593564
if (!same_creds(&rqstp->rq_cred, &slot->sl_cred))

fs/nfsd/nfs4xdr.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3452,7 +3452,6 @@ static __be32 nfsd4_encode_splice_read(
34523452
struct xdr_stream *xdr = &resp->xdr;
34533453
struct xdr_buf *buf = xdr->buf;
34543454
u32 eof;
3455-
long len;
34563455
int space_left;
34573456
__be32 nfserr;
34583457
__be32 *p = xdr->p - 2;
@@ -3461,7 +3460,6 @@ static __be32 nfsd4_encode_splice_read(
34613460
if (xdr->end - xdr->p < 1)
34623461
return nfserr_resource;
34633462

3464-
len = maxcount;
34653463
nfserr = nfsd_splice_read(read->rd_rqstp, read->rd_fhp,
34663464
file, read->rd_offset, &maxcount, &eof);
34673465
read->rd_length = maxcount;

fs/nfsd/nfsd.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,8 @@ void nfsd_lockd_shutdown(void);
280280
#define nfserr_union_notsupp cpu_to_be32(NFS4ERR_UNION_NOTSUPP)
281281
#define nfserr_offload_denied cpu_to_be32(NFS4ERR_OFFLOAD_DENIED)
282282
#define nfserr_wrong_lfs cpu_to_be32(NFS4ERR_WRONG_LFS)
283-
#define nfserr_badlabel cpu_to_be32(NFS4ERR_BADLABEL)
283+
#define nfserr_badlabel cpu_to_be32(NFS4ERR_BADLABEL)
284+
#define nfserr_file_open cpu_to_be32(NFS4ERR_FILE_OPEN)
284285

285286
/* error codes for internal use */
286287
/* if a request fails due to kmalloc failure, it gets dropped.

fs/nfsd/nfssvc.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,11 @@ static const struct svc_version *nfsd_acl_version[] = {
9595

9696
#define NFSD_ACL_MINVERS 2
9797
#define NFSD_ACL_NRVERS ARRAY_SIZE(nfsd_acl_version)
98-
static const struct svc_version *nfsd_acl_versions[NFSD_ACL_NRVERS];
9998

10099
static struct svc_program nfsd_acl_program = {
101100
.pg_prog = NFS_ACL_PROGRAM,
102101
.pg_nvers = NFSD_ACL_NRVERS,
103-
.pg_vers = nfsd_acl_versions,
102+
.pg_vers = nfsd_acl_version,
104103
.pg_name = "nfsacl",
105104
.pg_class = "nfsd",
106105
.pg_stats = &nfsd_acl_svcstats,

fs/nfsd/state.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ struct nfs4_client {
367367
struct net *net;
368368
struct list_head async_copies; /* list of async copies */
369369
spinlock_t async_lock; /* lock for async copies */
370+
atomic_t cl_cb_inflight; /* Outstanding callbacks */
370371
};
371372

372373
/* struct nfs4_client_reset

0 commit comments

Comments
 (0)