Skip to content

Commit ebc551f

Browse files
committed
Merge tag 'nfsd-5.1' of git://linux-nfs.org/~bfields/linux
Pull NFS server updates from Bruce Fields: "Miscellaneous NFS server fixes. Probably the most visible bug is one that could artificially limit NFSv4.1 performance by limiting the number of oustanding rpcs from a single client. Neil Brown also gets a special mention for fixing a 14.5-year-old memory-corruption bug in the encoding of NFSv3 readdir responses" * tag 'nfsd-5.1' of git://linux-nfs.org/~bfields/linux: nfsd: allow nfsv3 readdir request to be larger. nfsd: fix wrong check in write_v4_end_grace() nfsd: fix memory corruption caused by readdir nfsd: fix performance-limiting session calculation svcrpc: fix UDP on servers with lots of threads svcrdma: Remove syslog warnings in work completion handlers svcrdma: Squelch compiler warning when SUNRPC_DEBUG is disabled svcrdma: Use struct_size() in kmalloc() svcrpc: fix unlikely races preventing queueing of sockets svcrpc: svc_xprt_has_something_to_do seems a little long SUNRPC: Don't allow compiler optimisation of svc_xprt_release_slot() nfsd: fix an IS_ERR() vs NULL check
2 parents a5adcfc + f875a79 commit ebc551f

File tree

11 files changed

+65
-58
lines changed

11 files changed

+65
-58
lines changed

fs/nfsd/nfs3proc.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -463,8 +463,19 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp)
463463
&resp->common, nfs3svc_encode_entry);
464464
memcpy(resp->verf, argp->verf, 8);
465465
resp->count = resp->buffer - argp->buffer;
466-
if (resp->offset)
467-
xdr_encode_hyper(resp->offset, argp->cookie);
466+
if (resp->offset) {
467+
loff_t offset = argp->cookie;
468+
469+
if (unlikely(resp->offset1)) {
470+
/* we ended up with offset on a page boundary */
471+
*resp->offset = htonl(offset >> 32);
472+
*resp->offset1 = htonl(offset & 0xffffffff);
473+
resp->offset1 = NULL;
474+
} else {
475+
xdr_encode_hyper(resp->offset, offset);
476+
}
477+
resp->offset = NULL;
478+
}
468479

469480
RETURN_STATUS(nfserr);
470481
}
@@ -533,6 +544,7 @@ nfsd3_proc_readdirplus(struct svc_rqst *rqstp)
533544
} else {
534545
xdr_encode_hyper(resp->offset, offset);
535546
}
547+
resp->offset = NULL;
536548
}
537549

538550
RETURN_STATUS(nfserr);
@@ -576,7 +588,7 @@ nfsd3_proc_fsinfo(struct svc_rqst *rqstp)
576588
resp->f_wtmax = max_blocksize;
577589
resp->f_wtpref = max_blocksize;
578590
resp->f_wtmult = PAGE_SIZE;
579-
resp->f_dtpref = PAGE_SIZE;
591+
resp->f_dtpref = max_blocksize;
580592
resp->f_maxfilesize = ~(u32) 0;
581593
resp->f_properties = NFS3_FSF_DEFAULT;
582594

fs/nfsd/nfs3xdr.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,14 +573,16 @@ int
573573
nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p)
574574
{
575575
struct nfsd3_readdirargs *args = rqstp->rq_argp;
576+
u32 max_blocksize = svc_max_payload(rqstp);
577+
576578
p = decode_fh(p, &args->fh);
577579
if (!p)
578580
return 0;
579581
p = xdr_decode_hyper(p, &args->cookie);
580582
args->verf = p; p += 2;
581583
args->dircount = ~0;
582584
args->count = ntohl(*p++);
583-
args->count = min_t(u32, args->count, PAGE_SIZE);
585+
args->count = min_t(u32, args->count, max_blocksize);
584586
args->buffer = page_address(*(rqstp->rq_next_page++));
585587

586588
return xdr_argsize_check(rqstp, p);
@@ -921,6 +923,7 @@ encode_entry(struct readdir_cd *ccd, const char *name, int namlen,
921923
} else {
922924
xdr_encode_hyper(cd->offset, offset64);
923925
}
926+
cd->offset = NULL;
924927
}
925928

926929
/*

fs/nfsd/nfs4callback.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -900,9 +900,9 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
900900
return PTR_ERR(client);
901901
}
902902
cred = get_backchannel_cred(clp, client, ses);
903-
if (IS_ERR(cred)) {
903+
if (!cred) {
904904
rpc_shutdown_client(client);
905-
return PTR_ERR(cred);
905+
return -ENOMEM;
906906
}
907907
clp->cl_cb_client = client;
908908
clp->cl_cb_cred = cred;

fs/nfsd/nfs4state.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,16 +1544,16 @@ static u32 nfsd4_get_drc_mem(struct nfsd4_channel_attrs *ca)
15441544
{
15451545
u32 slotsize = slot_bytes(ca);
15461546
u32 num = ca->maxreqs;
1547-
int avail;
1547+
unsigned long avail, total_avail;
15481548

15491549
spin_lock(&nfsd_drc_lock);
1550-
avail = min((unsigned long)NFSD_MAX_MEM_PER_SESSION,
1551-
nfsd_drc_max_mem - nfsd_drc_mem_used);
1550+
total_avail = nfsd_drc_max_mem - nfsd_drc_mem_used;
1551+
avail = min((unsigned long)NFSD_MAX_MEM_PER_SESSION, total_avail);
15521552
/*
15531553
* Never use more than a third of the remaining memory,
15541554
* unless it's the only way to give this client a slot:
15551555
*/
1556-
avail = clamp_t(int, avail, slotsize, avail/3);
1556+
avail = clamp_t(int, avail, slotsize, total_avail/3);
15571557
num = min_t(int, num, avail / slotsize);
15581558
nfsd_drc_mem_used += num * slotsize;
15591559
spin_unlock(&nfsd_drc_lock);

fs/nfsd/nfsctl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1126,7 +1126,7 @@ static ssize_t write_v4_end_grace(struct file *file, char *buf, size_t size)
11261126
case 'Y':
11271127
case 'y':
11281128
case '1':
1129-
if (nn->nfsd_serv)
1129+
if (!nn->nfsd_serv)
11301130
return -EBUSY;
11311131
nfsd4_end_grace(nn);
11321132
break;

net/sunrpc/svc_xprt.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -357,15 +357,29 @@ static void svc_xprt_release_slot(struct svc_rqst *rqstp)
357357
struct svc_xprt *xprt = rqstp->rq_xprt;
358358
if (test_and_clear_bit(RQ_DATA, &rqstp->rq_flags)) {
359359
atomic_dec(&xprt->xpt_nr_rqsts);
360+
smp_wmb(); /* See smp_rmb() in svc_xprt_ready() */
360361
svc_xprt_enqueue(xprt);
361362
}
362363
}
363364

364-
static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt)
365+
static bool svc_xprt_ready(struct svc_xprt *xprt)
365366
{
366-
if (xprt->xpt_flags & ((1<<XPT_CONN)|(1<<XPT_CLOSE)))
367+
unsigned long xpt_flags;
368+
369+
/*
370+
* If another cpu has recently updated xpt_flags,
371+
* sk_sock->flags, xpt_reserved, or xpt_nr_rqsts, we need to
372+
* know about it; otherwise it's possible that both that cpu and
373+
* this one could call svc_xprt_enqueue() without either
374+
* svc_xprt_enqueue() recognizing that the conditions below
375+
* are satisfied, and we could stall indefinitely:
376+
*/
377+
smp_rmb();
378+
xpt_flags = READ_ONCE(xprt->xpt_flags);
379+
380+
if (xpt_flags & (BIT(XPT_CONN) | BIT(XPT_CLOSE)))
367381
return true;
368-
if (xprt->xpt_flags & ((1<<XPT_DATA)|(1<<XPT_DEFERRED))) {
382+
if (xpt_flags & (BIT(XPT_DATA) | BIT(XPT_DEFERRED))) {
369383
if (xprt->xpt_ops->xpo_has_wspace(xprt) &&
370384
svc_xprt_slots_in_range(xprt))
371385
return true;
@@ -381,7 +395,7 @@ void svc_xprt_do_enqueue(struct svc_xprt *xprt)
381395
struct svc_rqst *rqstp = NULL;
382396
int cpu;
383397

384-
if (!svc_xprt_has_something_to_do(xprt))
398+
if (!svc_xprt_ready(xprt))
385399
return;
386400

387401
/* Mark transport as busy. It will remain in this state until
@@ -475,7 +489,7 @@ void svc_reserve(struct svc_rqst *rqstp, int space)
475489
if (xprt && space < rqstp->rq_reserved) {
476490
atomic_sub((rqstp->rq_reserved - space), &xprt->xpt_reserved);
477491
rqstp->rq_reserved = space;
478-
492+
smp_wmb(); /* See smp_rmb() in svc_xprt_ready() */
479493
svc_xprt_enqueue(xprt);
480494
}
481495
}

net/sunrpc/svcsock.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -349,12 +349,16 @@ static ssize_t svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov,
349349
/*
350350
* Set socket snd and rcv buffer lengths
351351
*/
352-
static void svc_sock_setbufsize(struct socket *sock, unsigned int snd,
353-
unsigned int rcv)
352+
static void svc_sock_setbufsize(struct svc_sock *svsk, unsigned int nreqs)
354353
{
354+
unsigned int max_mesg = svsk->sk_xprt.xpt_server->sv_max_mesg;
355+
struct socket *sock = svsk->sk_sock;
356+
357+
nreqs = min(nreqs, INT_MAX / 2 / max_mesg);
358+
355359
lock_sock(sock->sk);
356-
sock->sk->sk_sndbuf = snd * 2;
357-
sock->sk->sk_rcvbuf = rcv * 2;
360+
sock->sk->sk_sndbuf = nreqs * max_mesg * 2;
361+
sock->sk->sk_rcvbuf = nreqs * max_mesg * 2;
358362
sock->sk->sk_write_space(sock->sk);
359363
release_sock(sock->sk);
360364
}
@@ -516,9 +520,7 @@ static int svc_udp_recvfrom(struct svc_rqst *rqstp)
516520
* provides an upper bound on the number of threads
517521
* which will access the socket.
518522
*/
519-
svc_sock_setbufsize(svsk->sk_sock,
520-
(serv->sv_nrthreads+3) * serv->sv_max_mesg,
521-
(serv->sv_nrthreads+3) * serv->sv_max_mesg);
523+
svc_sock_setbufsize(svsk, serv->sv_nrthreads + 3);
522524

523525
clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
524526
skb = NULL;
@@ -681,9 +683,7 @@ static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv)
681683
* receive and respond to one request.
682684
* svc_udp_recvfrom will re-adjust if necessary
683685
*/
684-
svc_sock_setbufsize(svsk->sk_sock,
685-
3 * svsk->sk_xprt.xpt_server->sv_max_mesg,
686-
3 * svsk->sk_xprt.xpt_server->sv_max_mesg);
686+
svc_sock_setbufsize(svsk, 3);
687687

688688
/* data might have come in before data_ready set up */
689689
set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);

net/sunrpc/xprtrdma/svc_rdma_recvfrom.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -272,11 +272,8 @@ bool svc_rdma_post_recvs(struct svcxprt_rdma *rdma)
272272
return false;
273273
ctxt->rc_temp = true;
274274
ret = __svc_rdma_post_recv(rdma, ctxt);
275-
if (ret) {
276-
pr_err("svcrdma: failure posting recv buffers: %d\n",
277-
ret);
275+
if (ret)
278276
return false;
279-
}
280277
}
281278
return true;
282279
}
@@ -314,17 +311,14 @@ static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
314311

315312
spin_lock(&rdma->sc_rq_dto_lock);
316313
list_add_tail(&ctxt->rc_list, &rdma->sc_rq_dto_q);
317-
spin_unlock(&rdma->sc_rq_dto_lock);
314+
/* Note the unlock pairs with the smp_rmb in svc_xprt_ready: */
318315
set_bit(XPT_DATA, &rdma->sc_xprt.xpt_flags);
316+
spin_unlock(&rdma->sc_rq_dto_lock);
319317
if (!test_bit(RDMAXPRT_CONN_PENDING, &rdma->sc_flags))
320318
svc_xprt_enqueue(&rdma->sc_xprt);
321319
goto out;
322320

323321
flushed:
324-
if (wc->status != IB_WC_WR_FLUSH_ERR)
325-
pr_err("svcrdma: Recv: %s (%u/0x%x)\n",
326-
ib_wc_status_msg(wc->status),
327-
wc->status, wc->vendor_err);
328322
post_err:
329323
svc_rdma_recv_ctxt_put(rdma, ctxt);
330324
set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags);

net/sunrpc/xprtrdma/svc_rdma_rw.c

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,7 @@ svc_rdma_get_rw_ctxt(struct svcxprt_rdma *rdma, unsigned int sges)
6464
spin_unlock(&rdma->sc_rw_ctxt_lock);
6565
} else {
6666
spin_unlock(&rdma->sc_rw_ctxt_lock);
67-
ctxt = kmalloc(sizeof(*ctxt) +
68-
SG_CHUNK_SIZE * sizeof(struct scatterlist),
67+
ctxt = kmalloc(struct_size(ctxt, rw_first_sgl, SG_CHUNK_SIZE),
6968
GFP_KERNEL);
7069
if (!ctxt)
7170
goto out;
@@ -213,13 +212,8 @@ static void svc_rdma_write_done(struct ib_cq *cq, struct ib_wc *wc)
213212
atomic_add(cc->cc_sqecount, &rdma->sc_sq_avail);
214213
wake_up(&rdma->sc_send_wait);
215214

216-
if (unlikely(wc->status != IB_WC_SUCCESS)) {
215+
if (unlikely(wc->status != IB_WC_SUCCESS))
217216
set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags);
218-
if (wc->status != IB_WC_WR_FLUSH_ERR)
219-
pr_err("svcrdma: write ctx: %s (%u/0x%x)\n",
220-
ib_wc_status_msg(wc->status),
221-
wc->status, wc->vendor_err);
222-
}
223217

224218
svc_rdma_write_info_free(info);
225219
}
@@ -278,18 +272,15 @@ static void svc_rdma_wc_read_done(struct ib_cq *cq, struct ib_wc *wc)
278272

279273
if (unlikely(wc->status != IB_WC_SUCCESS)) {
280274
set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags);
281-
if (wc->status != IB_WC_WR_FLUSH_ERR)
282-
pr_err("svcrdma: read ctx: %s (%u/0x%x)\n",
283-
ib_wc_status_msg(wc->status),
284-
wc->status, wc->vendor_err);
285275
svc_rdma_recv_ctxt_put(rdma, info->ri_readctxt);
286276
} else {
287277
spin_lock(&rdma->sc_rq_dto_lock);
288278
list_add_tail(&info->ri_readctxt->rc_list,
289279
&rdma->sc_read_complete_q);
280+
/* Note the unlock pairs with the smp_rmb in svc_xprt_ready: */
281+
set_bit(XPT_DATA, &rdma->sc_xprt.xpt_flags);
290282
spin_unlock(&rdma->sc_rq_dto_lock);
291283

292-
set_bit(XPT_DATA, &rdma->sc_xprt.xpt_flags);
293284
svc_xprt_enqueue(&rdma->sc_xprt);
294285
}
295286

net/sunrpc/xprtrdma/svc_rdma_sendto.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -272,10 +272,6 @@ static void svc_rdma_wc_send(struct ib_cq *cq, struct ib_wc *wc)
272272
if (unlikely(wc->status != IB_WC_SUCCESS)) {
273273
set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags);
274274
svc_xprt_enqueue(&rdma->sc_xprt);
275-
if (wc->status != IB_WC_WR_FLUSH_ERR)
276-
pr_err("svcrdma: Send: %s (%u/0x%x)\n",
277-
ib_wc_status_msg(wc->status),
278-
wc->status, wc->vendor_err);
279275
}
280276

281277
svc_xprt_put(&rdma->sc_xprt);

net/sunrpc/xprtrdma/svc_rdma_transport.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -390,8 +390,8 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
390390
struct ib_qp_init_attr qp_attr;
391391
unsigned int ctxts, rq_depth;
392392
struct ib_device *dev;
393-
struct sockaddr *sap;
394393
int ret = 0;
394+
RPC_IFDEBUG(struct sockaddr *sap);
395395

396396
listen_rdma = container_of(xprt, struct svcxprt_rdma, sc_xprt);
397397
clear_bit(XPT_CONN, &xprt->xpt_flags);
@@ -525,6 +525,7 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
525525
if (ret)
526526
goto errout;
527527

528+
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
528529
dprintk("svcrdma: new connection %p accepted:\n", newxprt);
529530
sap = (struct sockaddr *)&newxprt->sc_cm_id->route.addr.src_addr;
530531
dprintk(" local address : %pIS:%u\n", sap, rpc_get_port(sap));
@@ -535,6 +536,7 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
535536
dprintk(" rdma_rw_ctxs : %d\n", ctxts);
536537
dprintk(" max_requests : %d\n", newxprt->sc_max_requests);
537538
dprintk(" ord : %d\n", conn_param.initiator_depth);
539+
#endif
538540

539541
trace_svcrdma_xprt_accept(&newxprt->sc_xprt);
540542
return &newxprt->sc_xprt;
@@ -588,11 +590,6 @@ static void __svc_rdma_free(struct work_struct *work)
588590
if (rdma->sc_qp && !IS_ERR(rdma->sc_qp))
589591
ib_drain_qp(rdma->sc_qp);
590592

591-
/* We should only be called from kref_put */
592-
if (kref_read(&xprt->xpt_ref) != 0)
593-
pr_err("svcrdma: sc_xprt still in use? (%d)\n",
594-
kref_read(&xprt->xpt_ref));
595-
596593
svc_rdma_flush_recv_queues(rdma);
597594

598595
/* Final put of backchannel client transport */

0 commit comments

Comments
 (0)