Skip to content

Commit a86b83f

Browse files
committed
Merge tag 'v6.11-rc6-cifs-client-fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull smb client fixes from Steve French: - fix potential mount hang - fix retry problem in two types of compound operations - important netfs integration fix in SMB1 read paths - fix potential uninitialized zero point of inode - minor patch to improve debugging for potential crediting problems * tag 'v6.11-rc6-cifs-client-fixes' of git://git.samba.org/sfrench/cifs-2.6: netfs, cifs: Improve some debugging bits cifs: Fix SMB1 readv/writev callback in the same way as SMB2/3 cifs: Fix zero_point init on inode initialisation smb: client: fix double put of @CFILE in smb2_set_path_size() smb: client: fix double put of @CFILE in smb2_rename_path() smb: client: fix hang in wait_for_response() for negproto
2 parents 9d4c304 + ab85218 commit a86b83f

File tree

6 files changed

+70
-13
lines changed

6 files changed

+70
-13
lines changed

fs/netfs/io.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ static void netfs_reset_subreq_iter(struct netfs_io_request *rreq,
270270
if (count == remaining)
271271
return;
272272

273-
_debug("R=%08x[%u] ITER RESUB-MISMATCH %zx != %zx-%zx-%llx %x\n",
273+
_debug("R=%08x[%u] ITER RESUB-MISMATCH %zx != %zx-%zx-%llx %x",
274274
rreq->debug_id, subreq->debug_index,
275275
iov_iter_count(&subreq->io_iter), subreq->transferred,
276276
subreq->len, rreq->i_size,

fs/smb/client/cifssmb.c

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1261,16 +1261,32 @@ CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms, int *oplock,
12611261
return rc;
12621262
}
12631263

1264+
static void cifs_readv_worker(struct work_struct *work)
1265+
{
1266+
struct cifs_io_subrequest *rdata =
1267+
container_of(work, struct cifs_io_subrequest, subreq.work);
1268+
1269+
netfs_subreq_terminated(&rdata->subreq,
1270+
(rdata->result == 0 || rdata->result == -EAGAIN) ?
1271+
rdata->got_bytes : rdata->result, true);
1272+
}
1273+
12641274
static void
12651275
cifs_readv_callback(struct mid_q_entry *mid)
12661276
{
12671277
struct cifs_io_subrequest *rdata = mid->callback_data;
1278+
struct netfs_inode *ictx = netfs_inode(rdata->rreq->inode);
12681279
struct cifs_tcon *tcon = tlink_tcon(rdata->req->cfile->tlink);
12691280
struct TCP_Server_Info *server = tcon->ses->server;
12701281
struct smb_rqst rqst = { .rq_iov = rdata->iov,
12711282
.rq_nvec = 2,
12721283
.rq_iter = rdata->subreq.io_iter };
1273-
struct cifs_credits credits = { .value = 1, .instance = 0 };
1284+
struct cifs_credits credits = {
1285+
.value = 1,
1286+
.instance = 0,
1287+
.rreq_debug_id = rdata->rreq->debug_id,
1288+
.rreq_debug_index = rdata->subreq.debug_index,
1289+
};
12741290

12751291
cifs_dbg(FYI, "%s: mid=%llu state=%d result=%d bytes=%zu\n",
12761292
__func__, mid->mid, mid->mid_state, rdata->result,
@@ -1282,6 +1298,7 @@ cifs_readv_callback(struct mid_q_entry *mid)
12821298
if (server->sign) {
12831299
int rc = 0;
12841300

1301+
iov_iter_truncate(&rqst.rq_iter, rdata->got_bytes);
12851302
rc = cifs_verify_signature(&rqst, server,
12861303
mid->sequence_number);
12871304
if (rc)
@@ -1306,13 +1323,21 @@ cifs_readv_callback(struct mid_q_entry *mid)
13061323
rdata->result = -EIO;
13071324
}
13081325

1309-
if (rdata->result == 0 || rdata->result == -EAGAIN)
1310-
iov_iter_advance(&rdata->subreq.io_iter, rdata->got_bytes);
1326+
if (rdata->result == -ENODATA) {
1327+
__set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
1328+
rdata->result = 0;
1329+
} else {
1330+
if (rdata->got_bytes < rdata->actual_len &&
1331+
rdata->subreq.start + rdata->subreq.transferred + rdata->got_bytes ==
1332+
ictx->remote_i_size) {
1333+
__set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
1334+
rdata->result = 0;
1335+
}
1336+
}
1337+
13111338
rdata->credits.value = 0;
1312-
netfs_subreq_terminated(&rdata->subreq,
1313-
(rdata->result == 0 || rdata->result == -EAGAIN) ?
1314-
rdata->got_bytes : rdata->result,
1315-
false);
1339+
INIT_WORK(&rdata->subreq.work, cifs_readv_worker);
1340+
queue_work(cifsiod_wq, &rdata->subreq.work);
13161341
release_mid(mid);
13171342
add_credits(server, &credits, 0);
13181343
}
@@ -1619,9 +1644,15 @@ static void
16191644
cifs_writev_callback(struct mid_q_entry *mid)
16201645
{
16211646
struct cifs_io_subrequest *wdata = mid->callback_data;
1647+
struct TCP_Server_Info *server = wdata->server;
16221648
struct cifs_tcon *tcon = tlink_tcon(wdata->req->cfile->tlink);
16231649
WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
1624-
struct cifs_credits credits = { .value = 1, .instance = 0 };
1650+
struct cifs_credits credits = {
1651+
.value = 1,
1652+
.instance = 0,
1653+
.rreq_debug_id = wdata->rreq->debug_id,
1654+
.rreq_debug_index = wdata->subreq.debug_index,
1655+
};
16251656
ssize_t result;
16261657
size_t written;
16271658

@@ -1657,9 +1688,16 @@ cifs_writev_callback(struct mid_q_entry *mid)
16571688
break;
16581689
}
16591690

1691+
trace_smb3_rw_credits(credits.rreq_debug_id, credits.rreq_debug_index,
1692+
wdata->credits.value,
1693+
server->credits, server->in_flight,
1694+
0, cifs_trace_rw_credits_write_response_clear);
16601695
wdata->credits.value = 0;
16611696
cifs_write_subrequest_terminated(wdata, result, true);
16621697
release_mid(mid);
1698+
trace_smb3_rw_credits(credits.rreq_debug_id, credits.rreq_debug_index, 0,
1699+
server->credits, server->in_flight,
1700+
credits.value, cifs_trace_rw_credits_write_response_add);
16631701
add_credits(tcon->ses->server, &credits, 0);
16641702
}
16651703

fs/smb/client/connect.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,19 @@ allocate_buffers(struct TCP_Server_Info *server)
656656
static bool
657657
server_unresponsive(struct TCP_Server_Info *server)
658658
{
659+
/*
660+
* If we're in the process of mounting a share or reconnecting a session
661+
* and the server abruptly shut down (e.g. socket wasn't closed, packet
662+
* had been ACK'ed but no SMB response), don't wait longer than 20s to
663+
* negotiate protocol.
664+
*/
665+
spin_lock(&server->srv_lock);
666+
if (server->tcpStatus == CifsInNegotiate &&
667+
time_after(jiffies, server->lstrp + 20 * HZ)) {
668+
spin_unlock(&server->srv_lock);
669+
cifs_reconnect(server, false);
670+
return true;
671+
}
659672
/*
660673
* We need to wait 3 echo intervals to make sure we handle such
661674
* situations right:
@@ -667,7 +680,6 @@ server_unresponsive(struct TCP_Server_Info *server)
667680
* 65s kernel_recvmsg times out, and we see that we haven't gotten
668681
* a response in >60s.
669682
*/
670-
spin_lock(&server->srv_lock);
671683
if ((server->tcpStatus == CifsGood ||
672684
server->tcpStatus == CifsNeedNegotiate) &&
673685
(!server->ops->can_echo || server->ops->can_echo(server)) &&

fs/smb/client/inode.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr,
172172
CIFS_I(inode)->time = 0; /* force reval */
173173
return -ESTALE;
174174
}
175+
if (inode->i_state & I_NEW)
176+
CIFS_I(inode)->netfs.zero_point = fattr->cf_eof;
175177

176178
cifs_revalidate_cache(inode, fattr);
177179

fs/smb/client/smb2inode.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,8 @@ int smb2_rename_path(const unsigned int xid,
11061106
co, DELETE, SMB2_OP_RENAME, cfile, source_dentry);
11071107
if (rc == -EINVAL) {
11081108
cifs_dbg(FYI, "invalid lease key, resending request without lease");
1109+
cifs_get_writable_path(tcon, from_name,
1110+
FIND_WR_WITH_DELETE, &cfile);
11091111
rc = smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
11101112
co, DELETE, SMB2_OP_RENAME, cfile, NULL);
11111113
}
@@ -1149,6 +1151,7 @@ smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
11491151
cfile, NULL, NULL, dentry);
11501152
if (rc == -EINVAL) {
11511153
cifs_dbg(FYI, "invalid lease key, resending request without lease");
1154+
cifs_get_writable_path(tcon, full_path, FIND_WR_ANY, &cfile);
11521155
rc = smb2_compound_op(xid, tcon, cifs_sb,
11531156
full_path, &oparms, &in_iov,
11541157
&(int){SMB2_OP_SET_EOF}, 1,

fs/smb/client/smb2ops.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,8 @@ smb2_adjust_credits(struct TCP_Server_Info *server,
316316
cifs_trace_rw_credits_no_adjust_up);
317317
trace_smb3_too_many_credits(server->CurrentMid,
318318
server->conn_id, server->hostname, 0, credits->value - new_val, 0);
319-
cifs_server_dbg(VFS, "request has less credits (%d) than required (%d)",
319+
cifs_server_dbg(VFS, "R=%x[%x] request has less credits (%d) than required (%d)",
320+
subreq->rreq->debug_id, subreq->subreq.debug_index,
320321
credits->value, new_val);
321322

322323
return -EOPNOTSUPP;
@@ -338,8 +339,9 @@ smb2_adjust_credits(struct TCP_Server_Info *server,
338339
trace_smb3_reconnect_detected(server->CurrentMid,
339340
server->conn_id, server->hostname, scredits,
340341
credits->value - new_val, in_flight);
341-
cifs_server_dbg(VFS, "trying to return %d credits to old session\n",
342-
credits->value - new_val);
342+
cifs_server_dbg(VFS, "R=%x[%x] trying to return %d credits to old session\n",
343+
subreq->rreq->debug_id, subreq->subreq.debug_index,
344+
credits->value - new_val);
343345
return -EAGAIN;
344346
}
345347

0 commit comments

Comments
 (0)