Commit 1ddd8739 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'nfsd-5.7-rc-1' of git://git.linux-nfs.org/projects/cel/cel-2.6

Pull nfsd fixes from Chuck Lever:
 "The first set of 5.7-rc fixes for NFS server issues.

  These were all unresolved at the time the 5.7 window opened, and
  needed some additional time to ensure they were correctly addressed.
  They are ready now.

  At the moment I know of one more urgent issue regarding the NFS
  server. A fix has been tested and is under review. I expect to send
  one more pull request, containing this fix (which now consists of 3
  patches).

  Fixes:

   - Address several use-after-free and memory leak bugs

   - Prevent a backchannel livelock"

* tag 'nfsd-5.7-rc-1' of git://git.linux-nfs.org/projects/cel/cel-2.6:
  svcrdma: Fix leak of svc_rdma_recv_ctxt objects
  svcrdma: Fix trace point use-after-free race
  SUNRPC: Fix backchannel RPC soft lockups
  SUNRPC/cache: Fix unsafe traverse caused double-free in cache_purge
  nfsd: memory corruption in nfsd4_lock()
parents 6f8cd037 23cf1ee1
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -1312,6 +1312,7 @@ nfsd4_run_cb_work(struct work_struct *work)
		container_of(work, struct nfsd4_callback, cb_work);
	struct nfs4_client *clp = cb->cb_clp;
	struct rpc_clnt *clnt;
	int flags;

	if (cb->cb_need_restart) {
		cb->cb_need_restart = false;
@@ -1340,7 +1341,8 @@ nfsd4_run_cb_work(struct work_struct *work)
	}

	cb->cb_msg.rpc_cred = clp->cl_cb_cred;
	rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
	flags = clp->cl_minorversion ? RPC_TASK_NOCONNECT : RPC_TASK_SOFTCONN;
	rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | flags,
			cb->cb_ops ? &nfsd4_cb_ops : &nfsd4_cb_probe_ops, cb);
}

+2 −0
Original line number Diff line number Diff line
@@ -267,6 +267,8 @@ find_or_allocate_block(struct nfs4_lockowner *lo, struct knfsd_fh *fh,
	if (!nbl) {
		nbl= kmalloc(sizeof(*nbl), GFP_KERNEL);
		if (nbl) {
			INIT_LIST_HEAD(&nbl->nbl_list);
			INIT_LIST_HEAD(&nbl->nbl_lru);
			fh_copy_shallow(&nbl->nbl_fh, fh);
			locks_init_lock(&nbl->nbl_lock);
			nfsd4_init_cb(&nbl->nbl_cb, lo->lo_owner.so_client,
+1 −0
Original line number Diff line number Diff line
@@ -170,6 +170,7 @@ extern bool svc_rdma_post_recvs(struct svcxprt_rdma *rdma);
extern void svc_rdma_recv_ctxt_put(struct svcxprt_rdma *rdma,
				   struct svc_rdma_recv_ctxt *ctxt);
extern void svc_rdma_flush_recv_queues(struct svcxprt_rdma *rdma);
extern void svc_rdma_release_rqst(struct svc_rqst *rqstp);
extern int svc_rdma_recvfrom(struct svc_rqst *);

/* svc_rdma_rw.c */
+36 −14
Original line number Diff line number Diff line
@@ -1695,17 +1695,15 @@ DECLARE_EVENT_CLASS(svcrdma_sendcomp_event,

TRACE_EVENT(svcrdma_post_send,
	TP_PROTO(
		const struct ib_send_wr *wr,
		int status
		const struct ib_send_wr *wr
	),

	TP_ARGS(wr, status),
	TP_ARGS(wr),

	TP_STRUCT__entry(
		__field(const void *, cqe)
		__field(unsigned int, num_sge)
		__field(u32, inv_rkey)
		__field(int, status)
	),

	TP_fast_assign(
@@ -1713,12 +1711,11 @@ TRACE_EVENT(svcrdma_post_send,
		__entry->num_sge = wr->num_sge;
		__entry->inv_rkey = (wr->opcode == IB_WR_SEND_WITH_INV) ?
					wr->ex.invalidate_rkey : 0;
		__entry->status = status;
	),

	TP_printk("cqe=%p num_sge=%u inv_rkey=0x%08x status=%d",
	TP_printk("cqe=%p num_sge=%u inv_rkey=0x%08x",
		__entry->cqe, __entry->num_sge,
		__entry->inv_rkey, __entry->status
		__entry->inv_rkey
	)
);

@@ -1783,26 +1780,23 @@ TRACE_EVENT(svcrdma_wc_receive,
TRACE_EVENT(svcrdma_post_rw,
	TP_PROTO(
		const void *cqe,
		int sqecount,
		int status
		int sqecount
	),

	TP_ARGS(cqe, sqecount, status),
	TP_ARGS(cqe, sqecount),

	TP_STRUCT__entry(
		__field(const void *, cqe)
		__field(int, sqecount)
		__field(int, status)
	),

	TP_fast_assign(
		__entry->cqe = cqe;
		__entry->sqecount = sqecount;
		__entry->status = status;
	),

	TP_printk("cqe=%p sqecount=%d status=%d",
		__entry->cqe, __entry->sqecount, __entry->status
	TP_printk("cqe=%p sqecount=%d",
		__entry->cqe, __entry->sqecount
	)
);

@@ -1870,6 +1864,34 @@ DECLARE_EVENT_CLASS(svcrdma_sendqueue_event,
DEFINE_SQ_EVENT(full);
DEFINE_SQ_EVENT(retry);

TRACE_EVENT(svcrdma_sq_post_err,
	TP_PROTO(
		const struct svcxprt_rdma *rdma,
		int status
	),

	TP_ARGS(rdma, status),

	TP_STRUCT__entry(
		__field(int, avail)
		__field(int, depth)
		__field(int, status)
		__string(addr, rdma->sc_xprt.xpt_remotebuf)
	),

	TP_fast_assign(
		__entry->avail = atomic_read(&rdma->sc_sq_avail);
		__entry->depth = rdma->sc_sq_depth;
		__entry->status = status;
		__assign_str(addr, rdma->sc_xprt.xpt_remotebuf);
	),

	TP_printk("addr=%s sc_sq_avail=%d/%d status=%d",
		__get_str(addr), __entry->avail, __entry->depth,
		__entry->status
	)
);

#endif /* _TRACE_RPCRDMA_H */

#include <trace/define_trace.h>
+3 −2
Original line number Diff line number Diff line
@@ -529,7 +529,6 @@ void cache_purge(struct cache_detail *detail)
{
	struct cache_head *ch = NULL;
	struct hlist_head *head = NULL;
	struct hlist_node *tmp = NULL;
	int i = 0;

	spin_lock(&detail->hash_lock);
@@ -541,7 +540,9 @@ void cache_purge(struct cache_detail *detail)
	dprintk("RPC: %d entries in %s cache\n", detail->entries, detail->name);
	for (i = 0; i < detail->hash_size; i++) {
		head = &detail->hash_table[i];
		hlist_for_each_entry_safe(ch, tmp, head, cache_list) {
		while (!hlist_empty(head)) {
			ch = hlist_entry(head->first, struct cache_head,
					 cache_list);
			sunrpc_begin_cache_remove_entry(ch, detail);
			spin_unlock(&detail->hash_lock);
			sunrpc_end_cache_remove_entry(ch, detail);
Loading