More NFS Client Bugfixes for Linux 5.8
Bugfixes: - NFS: Fix interrupted slots by using the SEQUENCE operation - SUNRPC: reverted03727b248
to fix unkillable IOs - xprtrdma: Fix double-free in rpcrdma_ep_create() - xprtrdma: Fix recursion into rpcrdma_xprt_disconnect() - xprtrdma: Fix return code from rpcrdma_xprt_connect() - xprtrdma: Fix handling of connect errors - xprtrdma: Fix incorrect header size calculations -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEnZ5MQTpR7cLU7KEp18tUv7ClQOsFAl8SFqQACgkQ18tUv7Cl QOt76Q/9H/SrhERk64bErRLIvp0Gy6fI+U++pvNhDEUQfsPcrSYszMwmjBQ0yVet xZv/TP70GRY3EzKQ7TG8X9dX/PIRRdM9Sg6Xg4dLiJTJfVOj01ddwLHkJ0yt67wS 7TrWtIvL98vAhQRggHBg9E9ZgFFn1mCLmGQSgvBnQM9wlUmIrCf1UptlSNlnuGjn ogoT5DM9L5X5Z2AGDvLGHWviS8+yl55JmBolGz7yoE/wDWcAASCwK23cXPDfdLCe kbUaV06uD/77lIirM0PazIMJWmrZvc4+AyJBu1VOAK6RWkZ1ED47dQq9FMZpyYfK gvrw771Le4bhbZpIG1u4pS5/bpTQGdHJ4TRCA409rkSX5J+FxUsaLYnAcPtRVuiE 2dPOAQYrPgB0P+gb1mKfRD/c34+ooY3KUDfn28RFyaFdN9g4+bkLa0zYkj77q/l8 F938ejd7K3gpsKLssOjLajL+4TJC+f7aFPEAK5qKFpA/t1riH3qTvy8H/wjXumSF MaNezJbPoDRTpLzNbeld8MKN5/4wegnhym2k6MIuobAzTF+rL/VJZA3Ke70PACzy rISzBV0Stp8rT3pZFa6rWsPjYzvTd5rskWyqBD+Ep0XincxHNr0mrgRUKSYfdser +YnPDJb69rPFNz/XyvDFJW4nRKK/SnzHpvMngkBFUyzsdgvHYfs= =LUoM -----END PGP SIGNATURE----- Merge tag 'nfs-for-5.8-3' of git://git.linux-nfs.org/projects/anna/linux-nfs into master Pull NFS client fixes from Anna Schumaker: "A few more NFS client bugfixes for Linux 5.8: NFS: - Fix interrupted slots by using the SEQUENCE operation SUNRPC: - revertd03727b248
to fix unkillable IOs xprtrdma: - Fix double-free in rpcrdma_ep_create() - Fix recursion into rpcrdma_xprt_disconnect() - Fix return code from rpcrdma_xprt_connect() - Fix handling of connect errors - Fix incorrect header size calculations" * tag 'nfs-for-5.8-3' of git://git.linux-nfs.org/projects/anna/linux-nfs: SUNRPC revertingd03727b248
("NFSv4 fix CLOSE not waiting for direct IO compeletion") xprtrdma: fix incorrect header size calculations NFS: Fix interrupted slots by sending a solo SEQUENCE operation xprtrdma: Fix handling of connect errors xprtrdma: Fix return code from rpcrdma_xprt_connect() xprtrdma: Fix recursion into rpcrdma_xprt_disconnect() xprtrdma: Fix double-free in rpcrdma_ep_create()
This commit is contained in:
commit
6a70f89cc5
|
@ -267,6 +267,8 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq)
|
||||||
{
|
{
|
||||||
struct inode *inode = dreq->inode;
|
struct inode *inode = dreq->inode;
|
||||||
|
|
||||||
|
inode_dio_end(inode);
|
||||||
|
|
||||||
if (dreq->iocb) {
|
if (dreq->iocb) {
|
||||||
long res = (long) dreq->error;
|
long res = (long) dreq->error;
|
||||||
if (dreq->count != 0) {
|
if (dreq->count != 0) {
|
||||||
|
@ -278,10 +280,7 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq)
|
||||||
|
|
||||||
complete(&dreq->completion);
|
complete(&dreq->completion);
|
||||||
|
|
||||||
igrab(inode);
|
|
||||||
nfs_direct_req_release(dreq);
|
nfs_direct_req_release(dreq);
|
||||||
inode_dio_end(inode);
|
|
||||||
iput(inode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nfs_direct_read_completion(struct nfs_pgio_header *hdr)
|
static void nfs_direct_read_completion(struct nfs_pgio_header *hdr)
|
||||||
|
@ -411,10 +410,8 @@ static ssize_t nfs_direct_read_schedule_iovec(struct nfs_direct_req *dreq,
|
||||||
* generic layer handle the completion.
|
* generic layer handle the completion.
|
||||||
*/
|
*/
|
||||||
if (requested_bytes == 0) {
|
if (requested_bytes == 0) {
|
||||||
igrab(inode);
|
|
||||||
nfs_direct_req_release(dreq);
|
|
||||||
inode_dio_end(inode);
|
inode_dio_end(inode);
|
||||||
iput(inode);
|
nfs_direct_req_release(dreq);
|
||||||
return result < 0 ? result : -EIO;
|
return result < 0 ? result : -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -867,10 +864,8 @@ static ssize_t nfs_direct_write_schedule_iovec(struct nfs_direct_req *dreq,
|
||||||
* generic layer handle the completion.
|
* generic layer handle the completion.
|
||||||
*/
|
*/
|
||||||
if (requested_bytes == 0) {
|
if (requested_bytes == 0) {
|
||||||
igrab(inode);
|
|
||||||
nfs_direct_req_release(dreq);
|
|
||||||
inode_dio_end(inode);
|
inode_dio_end(inode);
|
||||||
iput(inode);
|
nfs_direct_req_release(dreq);
|
||||||
return result < 0 ? result : -EIO;
|
return result < 0 ? result : -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,6 @@ nfs_file_release(struct inode *inode, struct file *filp)
|
||||||
dprintk("NFS: release(%pD2)\n", filp);
|
dprintk("NFS: release(%pD2)\n", filp);
|
||||||
|
|
||||||
nfs_inc_stats(inode, NFSIOS_VFSRELEASE);
|
nfs_inc_stats(inode, NFSIOS_VFSRELEASE);
|
||||||
inode_dio_wait(inode);
|
|
||||||
nfs_file_clear_open_context(filp);
|
nfs_file_clear_open_context(filp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -774,6 +774,14 @@ static void nfs4_slot_sequence_acked(struct nfs4_slot *slot,
|
||||||
slot->seq_nr_last_acked = seqnr;
|
slot->seq_nr_last_acked = seqnr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void nfs4_probe_sequence(struct nfs_client *client, const struct cred *cred,
|
||||||
|
struct nfs4_slot *slot)
|
||||||
|
{
|
||||||
|
struct rpc_task *task = _nfs41_proc_sequence(client, cred, slot, true);
|
||||||
|
if (!IS_ERR(task))
|
||||||
|
rpc_put_task_async(task);
|
||||||
|
}
|
||||||
|
|
||||||
static int nfs41_sequence_process(struct rpc_task *task,
|
static int nfs41_sequence_process(struct rpc_task *task,
|
||||||
struct nfs4_sequence_res *res)
|
struct nfs4_sequence_res *res)
|
||||||
{
|
{
|
||||||
|
@ -790,6 +798,7 @@ static int nfs41_sequence_process(struct rpc_task *task,
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
session = slot->table->session;
|
session = slot->table->session;
|
||||||
|
clp = session->clp;
|
||||||
|
|
||||||
trace_nfs4_sequence_done(session, res);
|
trace_nfs4_sequence_done(session, res);
|
||||||
|
|
||||||
|
@ -804,7 +813,6 @@ static int nfs41_sequence_process(struct rpc_task *task,
|
||||||
nfs4_slot_sequence_acked(slot, slot->seq_nr);
|
nfs4_slot_sequence_acked(slot, slot->seq_nr);
|
||||||
/* Update the slot's sequence and clientid lease timer */
|
/* Update the slot's sequence and clientid lease timer */
|
||||||
slot->seq_done = 1;
|
slot->seq_done = 1;
|
||||||
clp = session->clp;
|
|
||||||
do_renew_lease(clp, res->sr_timestamp);
|
do_renew_lease(clp, res->sr_timestamp);
|
||||||
/* Check sequence flags */
|
/* Check sequence flags */
|
||||||
nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags,
|
nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags,
|
||||||
|
@ -852,10 +860,18 @@ static int nfs41_sequence_process(struct rpc_task *task,
|
||||||
/*
|
/*
|
||||||
* Were one or more calls using this slot interrupted?
|
* Were one or more calls using this slot interrupted?
|
||||||
* If the server never received the request, then our
|
* If the server never received the request, then our
|
||||||
* transmitted slot sequence number may be too high.
|
* transmitted slot sequence number may be too high. However,
|
||||||
|
* if the server did receive the request then it might
|
||||||
|
* accidentally give us a reply with a mismatched operation.
|
||||||
|
* We can sort this out by sending a lone sequence operation
|
||||||
|
* to the server on the same slot.
|
||||||
*/
|
*/
|
||||||
if ((s32)(slot->seq_nr - slot->seq_nr_last_acked) > 1) {
|
if ((s32)(slot->seq_nr - slot->seq_nr_last_acked) > 1) {
|
||||||
slot->seq_nr--;
|
slot->seq_nr--;
|
||||||
|
if (task->tk_msg.rpc_proc != &nfs4_procedures[NFSPROC4_CLNT_SEQUENCE]) {
|
||||||
|
nfs4_probe_sequence(clp, task->tk_msg.rpc_cred, slot);
|
||||||
|
res->sr_slot = NULL;
|
||||||
|
}
|
||||||
goto retry_nowait;
|
goto retry_nowait;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -71,7 +71,7 @@ static unsigned int rpcrdma_max_call_header_size(unsigned int maxsegs)
|
||||||
size = RPCRDMA_HDRLEN_MIN;
|
size = RPCRDMA_HDRLEN_MIN;
|
||||||
|
|
||||||
/* Maximum Read list size */
|
/* Maximum Read list size */
|
||||||
size = maxsegs * rpcrdma_readchunk_maxsz * sizeof(__be32);
|
size += maxsegs * rpcrdma_readchunk_maxsz * sizeof(__be32);
|
||||||
|
|
||||||
/* Minimal Read chunk size */
|
/* Minimal Read chunk size */
|
||||||
size += sizeof(__be32); /* segment count */
|
size += sizeof(__be32); /* segment count */
|
||||||
|
@ -94,7 +94,7 @@ static unsigned int rpcrdma_max_reply_header_size(unsigned int maxsegs)
|
||||||
size = RPCRDMA_HDRLEN_MIN;
|
size = RPCRDMA_HDRLEN_MIN;
|
||||||
|
|
||||||
/* Maximum Write list size */
|
/* Maximum Write list size */
|
||||||
size = sizeof(__be32); /* segment count */
|
size += sizeof(__be32); /* segment count */
|
||||||
size += maxsegs * rpcrdma_segment_maxsz * sizeof(__be32);
|
size += maxsegs * rpcrdma_segment_maxsz * sizeof(__be32);
|
||||||
size += sizeof(__be32); /* list discriminator */
|
size += sizeof(__be32); /* list discriminator */
|
||||||
|
|
||||||
|
|
|
@ -249,6 +249,11 @@ xprt_rdma_connect_worker(struct work_struct *work)
|
||||||
xprt->stat.connect_start;
|
xprt->stat.connect_start;
|
||||||
xprt_set_connected(xprt);
|
xprt_set_connected(xprt);
|
||||||
rc = -EAGAIN;
|
rc = -EAGAIN;
|
||||||
|
} else {
|
||||||
|
/* Force a call to xprt_rdma_close to clean up */
|
||||||
|
spin_lock(&xprt->transport_lock);
|
||||||
|
set_bit(XPRT_CLOSE_WAIT, &xprt->state);
|
||||||
|
spin_unlock(&xprt->transport_lock);
|
||||||
}
|
}
|
||||||
xprt_wake_pending_tasks(xprt, rc);
|
xprt_wake_pending_tasks(xprt, rc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -281,17 +281,19 @@ rpcrdma_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
|
||||||
break;
|
break;
|
||||||
case RDMA_CM_EVENT_CONNECT_ERROR:
|
case RDMA_CM_EVENT_CONNECT_ERROR:
|
||||||
ep->re_connect_status = -ENOTCONN;
|
ep->re_connect_status = -ENOTCONN;
|
||||||
goto disconnected;
|
goto wake_connect_worker;
|
||||||
case RDMA_CM_EVENT_UNREACHABLE:
|
case RDMA_CM_EVENT_UNREACHABLE:
|
||||||
ep->re_connect_status = -ENETUNREACH;
|
ep->re_connect_status = -ENETUNREACH;
|
||||||
goto disconnected;
|
goto wake_connect_worker;
|
||||||
case RDMA_CM_EVENT_REJECTED:
|
case RDMA_CM_EVENT_REJECTED:
|
||||||
dprintk("rpcrdma: connection to %pISpc rejected: %s\n",
|
dprintk("rpcrdma: connection to %pISpc rejected: %s\n",
|
||||||
sap, rdma_reject_msg(id, event->status));
|
sap, rdma_reject_msg(id, event->status));
|
||||||
ep->re_connect_status = -ECONNREFUSED;
|
ep->re_connect_status = -ECONNREFUSED;
|
||||||
if (event->status == IB_CM_REJ_STALE_CONN)
|
if (event->status == IB_CM_REJ_STALE_CONN)
|
||||||
ep->re_connect_status = -EAGAIN;
|
ep->re_connect_status = -ENOTCONN;
|
||||||
goto disconnected;
|
wake_connect_worker:
|
||||||
|
wake_up_all(&ep->re_connect_wait);
|
||||||
|
return 0;
|
||||||
case RDMA_CM_EVENT_DISCONNECTED:
|
case RDMA_CM_EVENT_DISCONNECTED:
|
||||||
ep->re_connect_status = -ECONNABORTED;
|
ep->re_connect_status = -ECONNABORTED;
|
||||||
disconnected:
|
disconnected:
|
||||||
|
@ -400,14 +402,14 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
|
||||||
|
|
||||||
ep = kzalloc(sizeof(*ep), GFP_NOFS);
|
ep = kzalloc(sizeof(*ep), GFP_NOFS);
|
||||||
if (!ep)
|
if (!ep)
|
||||||
return -EAGAIN;
|
return -ENOTCONN;
|
||||||
ep->re_xprt = &r_xprt->rx_xprt;
|
ep->re_xprt = &r_xprt->rx_xprt;
|
||||||
kref_init(&ep->re_kref);
|
kref_init(&ep->re_kref);
|
||||||
|
|
||||||
id = rpcrdma_create_id(r_xprt, ep);
|
id = rpcrdma_create_id(r_xprt, ep);
|
||||||
if (IS_ERR(id)) {
|
if (IS_ERR(id)) {
|
||||||
rc = PTR_ERR(id);
|
kfree(ep);
|
||||||
goto out_free;
|
return PTR_ERR(id);
|
||||||
}
|
}
|
||||||
__module_get(THIS_MODULE);
|
__module_get(THIS_MODULE);
|
||||||
device = id->device;
|
device = id->device;
|
||||||
|
@ -506,9 +508,6 @@ static int rpcrdma_ep_create(struct rpcrdma_xprt *r_xprt)
|
||||||
out_destroy:
|
out_destroy:
|
||||||
rpcrdma_ep_put(ep);
|
rpcrdma_ep_put(ep);
|
||||||
rdma_destroy_id(id);
|
rdma_destroy_id(id);
|
||||||
out_free:
|
|
||||||
kfree(ep);
|
|
||||||
r_xprt->rx_ep = NULL;
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,8 +523,6 @@ int rpcrdma_xprt_connect(struct rpcrdma_xprt *r_xprt)
|
||||||
struct rpcrdma_ep *ep;
|
struct rpcrdma_ep *ep;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
retry:
|
|
||||||
rpcrdma_xprt_disconnect(r_xprt);
|
|
||||||
rc = rpcrdma_ep_create(r_xprt);
|
rc = rpcrdma_ep_create(r_xprt);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -540,10 +537,6 @@ retry:
|
||||||
rpcrdma_ep_get(ep);
|
rpcrdma_ep_get(ep);
|
||||||
rpcrdma_post_recvs(r_xprt, true);
|
rpcrdma_post_recvs(r_xprt, true);
|
||||||
|
|
||||||
rc = rpcrdma_sendctxs_create(r_xprt);
|
|
||||||
if (rc)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
rc = rdma_connect(ep->re_id, &ep->re_remote_cma);
|
rc = rdma_connect(ep->re_id, &ep->re_remote_cma);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -553,15 +546,19 @@ retry:
|
||||||
wait_event_interruptible(ep->re_connect_wait,
|
wait_event_interruptible(ep->re_connect_wait,
|
||||||
ep->re_connect_status != 0);
|
ep->re_connect_status != 0);
|
||||||
if (ep->re_connect_status <= 0) {
|
if (ep->re_connect_status <= 0) {
|
||||||
if (ep->re_connect_status == -EAGAIN)
|
|
||||||
goto retry;
|
|
||||||
rc = ep->re_connect_status;
|
rc = ep->re_connect_status;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = rpcrdma_sendctxs_create(r_xprt);
|
||||||
|
if (rc) {
|
||||||
|
rc = -ENOTCONN;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
rc = rpcrdma_reqs_setup(r_xprt);
|
rc = rpcrdma_reqs_setup(r_xprt);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
rpcrdma_xprt_disconnect(r_xprt);
|
rc = -ENOTCONN;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
rpcrdma_mrs_create(r_xprt);
|
rpcrdma_mrs_create(r_xprt);
|
||||||
|
|
Loading…
Reference in New Issue