iov_iter_truncate(&rqst.rq_iter, rdata->got_bytes);
rc = smb2_verify_signature(&rqst, server);
- if (rc)
+ if (rc) {
cifs_tcon_dbg(VFS, "SMB signature verification returned error = %d\n",
- rc);
+ rc);
+ rdata->subreq.error = rc;
+ rdata->result = rc;
+
+ if (is_replayable_error(rc)) {
+ trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_retry_needed);
+ __set_bit(NETFS_SREQ_NEED_RETRY, &rdata->subreq.flags);
+ } else
+ trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_bad);
+ } else
+ trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_progress);
}
/* FIXME: should this be counted toward the initiating task? */
task_io_account_read(rdata->got_bytes);
if (rdata->got_bytes)
__set_bit(NETFS_SREQ_MADE_PROGRESS, &rdata->subreq.flags);
}
+
+ /* see if we need to retry */
+ if (is_replayable_error(rdata->result) &&
+ smb2_should_replay(tcon,
+ &rdata->retries,
+ &rdata->cur_sleep))
+ rdata->replay = true;
+
trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, rdata->credits.value,
server->credits, server->in_flight,
0, cifs_trace_rw_credits_read_response_clear);
rc = smb2_new_read_req(
(void **) &buf, &total_len, &io_parms, rdata, 0, 0);
if (rc)
- return rc;
+ goto out;
if (smb3_encryption_required(io_parms.tcon))
flags |= CIFS_TRANSFORM_REQ;
shdr = (struct smb2_hdr *)buf;
+ if (rdata->replay) {
+ /* Back-off before retry */
+ if (rdata->cur_sleep)
+ msleep(rdata->cur_sleep);
+ smb2_set_replay(server, &rqst);
+ }
+
if (rdata->credits.value > 0) {
shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(io_parms.length,
SMB2_MAX_BUFFER_SIZE));
async_readv_out:
cifs_small_buf_release(buf);
+
+out:
+ /* if the send error is retryable, let netfs know about it */
+ if (is_replayable_error(rc) &&
+ smb2_should_replay(tcon,
+ &rdata->retries,
+ &rdata->cur_sleep)) {
+ trace_netfs_sreq(&rdata->subreq, netfs_sreq_trace_io_retry_needed);
+ __set_bit(NETFS_SREQ_NEED_RETRY, &rdata->subreq.flags);
+ }
+
return rc;
}
switch (mid->mid_state) {
case MID_RESPONSE_RECEIVED:
- trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_progress);
credits.value = le16_to_cpu(rsp->hdr.CreditRequest);
credits.instance = server->reconnect_instance;
result = smb2_check_receive(mid, server, 0);
if (result != 0) {
- trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_bad);
+ if (is_replayable_error(result)) {
+ trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_retry_needed);
+ __set_bit(NETFS_SREQ_NEED_RETRY, &wdata->subreq.flags);
+ } else {
+ wdata->subreq.error = result;
+ trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_bad);
+ }
break;
}
+ trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_progress);
written = le32_to_cpu(rsp->DataLength);
/*
cifs_stats_bytes_written(tcon, written);
if (written < wdata->subreq.len) {
- wdata->result = -ENOSPC;
+ result = -ENOSPC;
} else if (written > 0) {
wdata->subreq.len = written;
__set_bit(NETFS_SREQ_MADE_PROGRESS, &wdata->subreq.flags);
}
#endif
if (result) {
+ wdata->result = result;
cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
trace_smb3_write_err(wdata->rreq->debug_id,
wdata->subreq.debug_index,
server->credits, server->in_flight,
0, cifs_trace_rw_credits_write_response_clear);
wdata->credits.value = 0;
+
+ /* see if we need to retry */
+ if (is_replayable_error(wdata->result) &&
+ smb2_should_replay(tcon,
+ &wdata->retries,
+ &wdata->cur_sleep))
+ wdata->replay = true;
+
cifs_write_subrequest_terminated(wdata, result ?: written);
release_mid(server, mid);
trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, 0,
}
#endif
- if (wdata->subreq.retry_count > 0)
+ if (wdata->replay) {
+ /* Back-off before retry */
+ if (wdata->cur_sleep)
+ msleep(wdata->cur_sleep);
smb2_set_replay(server, &rqst);
+ }
cifs_dbg(FYI, "async write at %llu %u bytes iter=%zx\n",
io_parms->offset, io_parms->length, iov_iter_count(&wdata->subreq.io_iter));
async_writev_out:
cifs_small_buf_release(req);
out:
+ /* if the send error is retryable, let netfs know about it */
+ if (is_replayable_error(rc) &&
+ smb2_should_replay(tcon,
+ &wdata->retries,
+ &wdata->cur_sleep)) {
+ wdata->replay = true;
+ trace_netfs_sreq(&wdata->subreq, netfs_sreq_trace_io_retry_needed);
+ __set_bit(NETFS_SREQ_NEED_RETRY, &wdata->subreq.flags);
+ }
+
if (rc) {
trace_smb3_rw_credits(wdata->rreq->debug_id,
wdata->subreq.debug_index,