Skip to content

Commit 38104c0

Browse files
committed
Merge tag '5.1-rc1-cifs-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull smb3 fixes from Steve French: - two fixes for stable for guest mount problems with smb3.1.1 - two fixes for crediting (SMB3 flow control) on resent requests - a byte range lock leak fix - two fixes for incorrect rc mappings * tag '5.1-rc1-cifs-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6: cifs: update internal module version number SMB3: Fix SMB3.1.1 guest mounts to Samba cifs: Fix slab-out-of-bounds when tracing SMB tcon cifs: allow guest mounts to work for smb3.11 fix incorrect error code mapping for OBJECTID_NOT_FOUND cifs: fix that return -EINVAL when do dedupe operation CIFS: Fix an issue with re-sending rdata when transport returning -EAGAIN CIFS: Fix an issue with re-sending wdata when transport returning -EAGAIN
2 parents e0046bb + cf7d624 commit 38104c0

File tree

6 files changed

+102
-70
lines changed

6 files changed

+102
-70
lines changed

fs/cifs/cifsfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1008,7 +1008,7 @@ static loff_t cifs_remap_file_range(struct file *src_file, loff_t off,
10081008
unsigned int xid;
10091009
int rc;
10101010

1011-
if (remap_flags & ~REMAP_FILE_ADVISORY)
1011+
if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY))
10121012
return -EINVAL;
10131013

10141014
cifs_dbg(FYI, "clone range\n");

fs/cifs/cifsfs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,5 +150,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
150150
extern const struct export_operations cifs_export_ops;
151151
#endif /* CONFIG_CIFS_NFSD_EXPORT */
152152

153-
#define CIFS_VERSION "2.18"
153+
#define CIFS_VERSION "2.19"
154154
#endif /* _CIFSFS_H */

fs/cifs/file.c

Lines changed: 86 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2632,43 +2632,56 @@ cifs_resend_wdata(struct cifs_writedata *wdata, struct list_head *wdata_list,
26322632
struct TCP_Server_Info *server =
26332633
tlink_tcon(wdata->cfile->tlink)->ses->server;
26342634

2635-
/*
2636-
* Wait for credits to resend this wdata.
2637-
* Note: we are attempting to resend the whole wdata not in segments
2638-
*/
26392635
do {
2640-
rc = server->ops->wait_mtu_credits(server, wdata->bytes, &wsize,
2641-
&credits);
2636+
if (wdata->cfile->invalidHandle) {
2637+
rc = cifs_reopen_file(wdata->cfile, false);
2638+
if (rc == -EAGAIN)
2639+
continue;
2640+
else if (rc)
2641+
break;
2642+
}
26422643

2643-
if (rc)
2644-
goto out;
26452644

2646-
if (wsize < wdata->bytes) {
2647-
add_credits_and_wake_if(server, &credits, 0);
2648-
msleep(1000);
2649-
}
2650-
} while (wsize < wdata->bytes);
2645+
/*
2646+
* Wait for credits to resend this wdata.
2647+
* Note: we are attempting to resend the whole wdata not in
2648+
* segments
2649+
*/
2650+
do {
2651+
rc = server->ops->wait_mtu_credits(server, wdata->bytes,
2652+
&wsize, &credits);
2653+
if (rc)
2654+
goto fail;
2655+
2656+
if (wsize < wdata->bytes) {
2657+
add_credits_and_wake_if(server, &credits, 0);
2658+
msleep(1000);
2659+
}
2660+
} while (wsize < wdata->bytes);
2661+
wdata->credits = credits;
26512662

2652-
wdata->credits = credits;
2653-
rc = -EAGAIN;
2654-
while (rc == -EAGAIN) {
2655-
rc = 0;
2656-
if (wdata->cfile->invalidHandle)
2657-
rc = cifs_reopen_file(wdata->cfile, false);
2658-
if (!rc)
2659-
rc = server->ops->async_writev(wdata,
2663+
rc = adjust_credits(server, &wdata->credits, wdata->bytes);
2664+
2665+
if (!rc) {
2666+
if (wdata->cfile->invalidHandle)
2667+
rc = -EAGAIN;
2668+
else
2669+
rc = server->ops->async_writev(wdata,
26602670
cifs_uncached_writedata_release);
2661-
}
2671+
}
26622672

2663-
if (!rc) {
2664-
list_add_tail(&wdata->list, wdata_list);
2665-
return 0;
2666-
}
2673+
/* If the write was successfully sent, we are done */
2674+
if (!rc) {
2675+
list_add_tail(&wdata->list, wdata_list);
2676+
return 0;
2677+
}
26672678

2668-
add_credits_and_wake_if(server, &wdata->credits, 0);
2669-
out:
2670-
kref_put(&wdata->refcount, cifs_uncached_writedata_release);
2679+
/* Roll back credits and retry if needed */
2680+
add_credits_and_wake_if(server, &wdata->credits, 0);
2681+
} while (rc == -EAGAIN);
26712682

2683+
fail:
2684+
kref_put(&wdata->refcount, cifs_uncached_writedata_release);
26722685
return rc;
26732686
}
26742687

@@ -2896,12 +2909,12 @@ static void collect_uncached_write_data(struct cifs_aio_ctx *ctx)
28962909
wdata->bytes, &tmp_from,
28972910
ctx->cfile, cifs_sb, &tmp_list,
28982911
ctx);
2912+
2913+
kref_put(&wdata->refcount,
2914+
cifs_uncached_writedata_release);
28992915
}
29002916

29012917
list_splice(&tmp_list, &ctx->list);
2902-
2903-
kref_put(&wdata->refcount,
2904-
cifs_uncached_writedata_release);
29052918
goto restart_loop;
29062919
}
29072920
}
@@ -3348,44 +3361,55 @@ static int cifs_resend_rdata(struct cifs_readdata *rdata,
33483361
struct TCP_Server_Info *server =
33493362
tlink_tcon(rdata->cfile->tlink)->ses->server;
33503363

3351-
/*
3352-
* Wait for credits to resend this rdata.
3353-
* Note: we are attempting to resend the whole rdata not in segments
3354-
*/
33553364
do {
3356-
rc = server->ops->wait_mtu_credits(server, rdata->bytes,
3365+
if (rdata->cfile->invalidHandle) {
3366+
rc = cifs_reopen_file(rdata->cfile, true);
3367+
if (rc == -EAGAIN)
3368+
continue;
3369+
else if (rc)
3370+
break;
3371+
}
3372+
3373+
/*
3374+
* Wait for credits to resend this rdata.
3375+
* Note: we are attempting to resend the whole rdata not in
3376+
* segments
3377+
*/
3378+
do {
3379+
rc = server->ops->wait_mtu_credits(server, rdata->bytes,
33573380
&rsize, &credits);
33583381

3359-
if (rc)
3360-
goto out;
3382+
if (rc)
3383+
goto fail;
33613384

3362-
if (rsize < rdata->bytes) {
3363-
add_credits_and_wake_if(server, &credits, 0);
3364-
msleep(1000);
3365-
}
3366-
} while (rsize < rdata->bytes);
3385+
if (rsize < rdata->bytes) {
3386+
add_credits_and_wake_if(server, &credits, 0);
3387+
msleep(1000);
3388+
}
3389+
} while (rsize < rdata->bytes);
3390+
rdata->credits = credits;
33673391

3368-
rdata->credits = credits;
3369-
rc = -EAGAIN;
3370-
while (rc == -EAGAIN) {
3371-
rc = 0;
3372-
if (rdata->cfile->invalidHandle)
3373-
rc = cifs_reopen_file(rdata->cfile, true);
3374-
if (!rc)
3375-
rc = server->ops->async_readv(rdata);
3376-
}
3392+
rc = adjust_credits(server, &rdata->credits, rdata->bytes);
3393+
if (!rc) {
3394+
if (rdata->cfile->invalidHandle)
3395+
rc = -EAGAIN;
3396+
else
3397+
rc = server->ops->async_readv(rdata);
3398+
}
33773399

3378-
if (!rc) {
3379-
/* Add to aio pending list */
3380-
list_add_tail(&rdata->list, rdata_list);
3381-
return 0;
3382-
}
3400+
/* If the read was successfully sent, we are done */
3401+
if (!rc) {
3402+
/* Add to aio pending list */
3403+
list_add_tail(&rdata->list, rdata_list);
3404+
return 0;
3405+
}
33833406

3384-
add_credits_and_wake_if(server, &rdata->credits, 0);
3385-
out:
3386-
kref_put(&rdata->refcount,
3387-
cifs_uncached_readdata_release);
3407+
/* Roll back credits and retry if needed */
3408+
add_credits_and_wake_if(server, &rdata->credits, 0);
3409+
} while (rc == -EAGAIN);
33883410

3411+
fail:
3412+
kref_put(&rdata->refcount, cifs_uncached_readdata_release);
33893413
return rc;
33903414
}
33913415

fs/cifs/smb2maperror.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1036,7 +1036,8 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
10361036
{STATUS_UNFINISHED_CONTEXT_DELETED, -EIO,
10371037
"STATUS_UNFINISHED_CONTEXT_DELETED"},
10381038
{STATUS_NO_TGT_REPLY, -EIO, "STATUS_NO_TGT_REPLY"},
1039-
{STATUS_OBJECTID_NOT_FOUND, -EIO, "STATUS_OBJECTID_NOT_FOUND"},
1039+
/* Note that ENOATTTR and ENODATA are the same errno */
1040+
{STATUS_OBJECTID_NOT_FOUND, -ENODATA, "STATUS_OBJECTID_NOT_FOUND"},
10401041
{STATUS_NO_IP_ADDRESSES, -EIO, "STATUS_NO_IP_ADDRESSES"},
10411042
{STATUS_WRONG_CREDENTIAL_HANDLE, -EIO,
10421043
"STATUS_WRONG_CREDENTIAL_HANDLE"},

fs/cifs/smb2pdu.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1628,9 +1628,16 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
16281628
iov[1].iov_base = unc_path;
16291629
iov[1].iov_len = unc_path_len;
16301630

1631-
/* 3.11 tcon req must be signed if not encrypted. See MS-SMB2 3.2.4.1.1 */
1631+
/*
1632+
* 3.11 tcon req must be signed if not encrypted. See MS-SMB2 3.2.4.1.1
1633+
* unless it is guest or anonymous user. See MS-SMB2 3.2.5.3.1
1634+
* (Samba servers don't always set the flag so also check if null user)
1635+
*/
16321636
if ((ses->server->dialect == SMB311_PROT_ID) &&
1633-
!smb3_encryption_required(tcon))
1637+
!smb3_encryption_required(tcon) &&
1638+
!(ses->session_flags &
1639+
(SMB2_SESSION_FLAG_IS_GUEST|SMB2_SESSION_FLAG_IS_NULL)) &&
1640+
((ses->user_name != NULL) || (ses->sectype == Kerberos)))
16341641
req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
16351642

16361643
memset(&rqst, 0, sizeof(struct smb_rqst));

fs/cifs/trace.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -549,19 +549,19 @@ DECLARE_EVENT_CLASS(smb3_tcon_class,
549549
__field(unsigned int, xid)
550550
__field(__u32, tid)
551551
__field(__u64, sesid)
552-
__field(const char *, unc_name)
552+
__string(name, unc_name)
553553
__field(int, rc)
554554
),
555555
TP_fast_assign(
556556
__entry->xid = xid;
557557
__entry->tid = tid;
558558
__entry->sesid = sesid;
559-
__entry->unc_name = unc_name;
559+
__assign_str(name, unc_name);
560560
__entry->rc = rc;
561561
),
562562
TP_printk("xid=%u sid=0x%llx tid=0x%x unc_name=%s rc=%d",
563563
__entry->xid, __entry->sesid, __entry->tid,
564-
__entry->unc_name, __entry->rc)
564+
__get_str(name), __entry->rc)
565565
)
566566

567567
#define DEFINE_SMB3_TCON_EVENT(name) \

0 commit comments

Comments
 (0)