Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f3415787 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull NFS client bugfixes from Trond Myklebust:

 - Fix a list corruption in xprt_release()

 - Fix a workqueue lockdep warning due to unsafe use of
   cancel_work_sync()

* tag 'nfs-for-4.14-4' of git://git.linux-nfs.org/projects/trondmy/linux-nfs:
  SUNRPC: Destroy transport from the system workqueue
  SUNRPC: fix a list corruption issue in xprt_release()
parents ae59df03 528fd354
Loading
Loading
Loading
Loading
+25 −11
Original line number Diff line number Diff line
@@ -1333,7 +1333,7 @@ void xprt_release(struct rpc_task *task)
		rpc_count_iostats(task, task->tk_client->cl_metrics);
	spin_lock(&xprt->recv_lock);
	if (!list_empty(&req->rq_list)) {
		list_del(&req->rq_list);
		list_del_init(&req->rq_list);
		xprt_wait_on_pinned_rqst(req);
	}
	spin_unlock(&xprt->recv_lock);
@@ -1445,6 +1445,23 @@ struct rpc_xprt *xprt_create_transport(struct xprt_create *args)
	return xprt;
}

static void xprt_destroy_cb(struct work_struct *work)
{
	struct rpc_xprt *xprt =
		container_of(work, struct rpc_xprt, task_cleanup);

	rpc_xprt_debugfs_unregister(xprt);
	rpc_destroy_wait_queue(&xprt->binding);
	rpc_destroy_wait_queue(&xprt->pending);
	rpc_destroy_wait_queue(&xprt->sending);
	rpc_destroy_wait_queue(&xprt->backlog);
	kfree(xprt->servername);
	/*
	 * Tear down transport state and free the rpc_xprt
	 */
	xprt->ops->destroy(xprt);
}

/**
 * xprt_destroy - destroy an RPC transport, killing off all requests.
 * @xprt: transport to destroy
@@ -1454,22 +1471,19 @@ static void xprt_destroy(struct rpc_xprt *xprt)
{
	dprintk("RPC:       destroying transport %p\n", xprt);

	/* Exclude transport connect/disconnect handlers */
	/*
	 * Exclude transport connect/disconnect handlers and autoclose
	 */
	wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_UNINTERRUPTIBLE);

	del_timer_sync(&xprt->timer);

	rpc_xprt_debugfs_unregister(xprt);
	rpc_destroy_wait_queue(&xprt->binding);
	rpc_destroy_wait_queue(&xprt->pending);
	rpc_destroy_wait_queue(&xprt->sending);
	rpc_destroy_wait_queue(&xprt->backlog);
	cancel_work_sync(&xprt->task_cleanup);
	kfree(xprt->servername);
	/*
	 * Tear down transport state and free the rpc_xprt
	 * Destroy sockets etc from the system workqueue so they can
	 * safely flush receive work running on rpciod.
	 */
	xprt->ops->destroy(xprt);
	INIT_WORK(&xprt->task_cleanup, xprt_destroy_cb);
	schedule_work(&xprt->task_cleanup);
}

static void xprt_destroy_kref(struct kref *kref)