Skip to content

Commit 8a5203c

Browse files
committed
Merge tag 'v7.0-rc-part1-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull smb client updates from Steve French: - multichannel improvements, including making add channel async at mount time - fix potential double free in open path - retry fixes - locking improvements - fix potential directory lease races - cleanup patches for client headers - patches to better split out SMB1 code - minor cleanup of structs for gcc 14 warnings - error handling improvements * tag 'v7.0-rc-part1-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6: (74 commits) cifs: Fix the copyright banner on smb1maperror.c smb: common: add header guards to fs/smb/common/smb2status.h smb: client: Avoid a dozen -Wflex-array-member-not-at-end warnings smb/client: remove useless comment in mapping_table_ERRSRV smb/client: remove some literal NT error codes from ntstatus_to_dos_map smb/client: add NT_STATUS_VOLUME_NOT_UPGRADED smb/client: add NT_STATUS_NO_USER_KEYS smb/client: add NT_STATUS_WRONG_EFS smb/client: add NT_STATUS_NO_EFS smb/client: add NT_STATUS_NO_RECOVERY_POLICY smb/client: add NT_STATUS_RANGE_NOT_FOUND smb/client: add NT_STATUS_DECRYPTION_FAILED smb/client: add NT_STATUS_ENCRYPTION_FAILED smb/client: add NT_STATUS_DIRECTORY_IS_A_REPARSE_POINT smb/client: add NT_STATUS_VOLUME_DISMOUNTED smb/client: add NT_STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT smb/client: add NT_STATUS_VARIABLE_NOT_FOUND smb/client: rename ERRinvlevel to ERRunknownlevel smb/client: add NT_STATUS_OS2_INVALID_LEVEL smb/client: map NT_STATUS_INVALID_INFO_CLASS to ERRbadpipe ...
2 parents af23fd9 + 9508064 commit 8a5203c

71 files changed

Lines changed: 8650 additions & 10506 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

fs/netfs/read_collect.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,15 @@ void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq)
546546
}
547547
}
548548

549+
/* If need retry is set, error should not matter unless we hit too many
550+
* retries. Pause the generation of new subreqs
551+
*/
552+
if (test_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags)) {
553+
trace_netfs_rreq(rreq, netfs_rreq_trace_set_pause);
554+
set_bit(NETFS_RREQ_PAUSE, &rreq->flags);
555+
goto skip_error_checks;
556+
}
557+
549558
if (unlikely(subreq->error < 0)) {
550559
trace_netfs_failure(rreq, subreq, subreq->error, netfs_fail_read);
551560
if (subreq->source == NETFS_READ_FROM_CACHE) {
@@ -559,6 +568,7 @@ void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq)
559568
set_bit(NETFS_RREQ_PAUSE, &rreq->flags);
560569
}
561570

571+
skip_error_checks:
562572
trace_netfs_sreq(subreq, netfs_sreq_trace_terminated);
563573
netfs_subreq_clear_in_progress(subreq);
564574
netfs_put_subrequest(subreq, netfs_sreq_trace_put_terminated);

fs/netfs/read_retry.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
static void netfs_reissue_read(struct netfs_io_request *rreq,
1313
struct netfs_io_subrequest *subreq)
1414
{
15+
subreq->error = 0;
1516
__clear_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags);
1617
__set_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags);
1718
netfs_stat(&netfs_n_rh_retry_read_subreq);
@@ -242,8 +243,7 @@ static void netfs_retry_read_subrequests(struct netfs_io_request *rreq)
242243
subreq = list_next_entry(subreq, rreq_link);
243244
abandon:
244245
list_for_each_entry_from(subreq, &stream->subrequests, rreq_link) {
245-
if (!subreq->error &&
246-
!test_bit(NETFS_SREQ_FAILED, &subreq->flags) &&
246+
if (!test_bit(NETFS_SREQ_FAILED, &subreq->flags) &&
247247
!test_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags))
248248
continue;
249249
subreq->error = -ENOMEM;

fs/netfs/write_collect.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -492,11 +492,11 @@ void netfs_write_subrequest_terminated(void *_op, ssize_t transferred_or_error)
492492

493493
if (IS_ERR_VALUE(transferred_or_error)) {
494494
subreq->error = transferred_or_error;
495-
if (subreq->error == -EAGAIN)
496-
set_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
497-
else
495+
/* if need retry is set, error should not matter */
496+
if (!test_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags)) {
498497
set_bit(NETFS_SREQ_FAILED, &subreq->flags);
499-
trace_netfs_failure(wreq, subreq, transferred_or_error, netfs_fail_write);
498+
trace_netfs_failure(wreq, subreq, transferred_or_error, netfs_fail_write);
499+
}
500500

501501
switch (subreq->source) {
502502
case NETFS_WRITE_TO_CACHE:

fs/netfs/write_issue.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ void netfs_reissue_write(struct netfs_io_stream *stream,
250250
iov_iter_truncate(&subreq->io_iter, size);
251251

252252
subreq->retry_count++;
253+
subreq->error = 0;
253254
__clear_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags);
254255
__set_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags);
255256
netfs_stat(&netfs_n_wh_retry_write_subreq);

fs/netfs/write_retry.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,
9898
subreq->start = start;
9999
subreq->len = len;
100100
__clear_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
101-
subreq->retry_count++;
102101
trace_netfs_sreq(subreq, netfs_sreq_trace_retry);
103102

104103
/* Renegotiate max_len (wsize) */

fs/smb/Kconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,20 @@ config SMBFS
99
tristate
1010
default y if CIFS=y || SMB_SERVER=y
1111
default m if CIFS=m || SMB_SERVER=m
12+
13+
config SMB_KUNIT_TESTS
14+
tristate "KUnit tests for SMB" if !KUNIT_ALL_TESTS
15+
depends on SMBFS && KUNIT
16+
default KUNIT_ALL_TESTS
17+
help
18+
This builds the SMB KUnit tests.
19+
20+
KUnit tests run during boot and output the results to the debug log
21+
in TAP format (https://testanything.org/). Only useful for kernel devs
22+
running KUnit test harness and are not for inclusion into a production
23+
build.
24+
25+
For more information on KUnit and unit tests in general please refer
26+
to the KUnit documentation in Documentation/dev-tools/kunit/.
27+
28+
If unsure, say N.

fs/smb/client/Makefile

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,28 @@ cifs-$(CONFIG_CIFS_SMB_DIRECT) += smbdirect.o
3232

3333
cifs-$(CONFIG_CIFS_ROOT) += cifsroot.o
3434

35-
cifs-$(CONFIG_CIFS_ALLOW_INSECURE_LEGACY) += smb1ops.o cifssmb.o cifstransport.o
35+
cifs-$(CONFIG_CIFS_ALLOW_INSECURE_LEGACY) += \
36+
cifssmb.o \
37+
smb1debug.o \
38+
smb1encrypt.o \
39+
smb1maperror.o \
40+
smb1misc.o \
41+
smb1ops.o \
42+
smb1session.o \
43+
smb1transport.o
3644

3745
cifs-$(CONFIG_CIFS_COMPRESSION) += compress.o compress/lz77.o
46+
47+
#
48+
# Build the SMB2 error mapping table from smb2status.h
49+
#
50+
$(obj)/smb2_mapping_table.c: $(src)/../common/smb2status.h \
51+
$(src)/gen_smb2_mapping
52+
$(call cmd,gen_smb2_mapping)
53+
54+
$(obj)/smb2maperror.o: $(obj)/smb2_mapping_table.c
55+
56+
quiet_cmd_gen_smb2_mapping = GEN $@
57+
cmd_gen_smb2_mapping = perl $(src)/gen_smb2_mapping $< $@
58+
59+
clean-files += smb2_mapping_table.c

fs/smb/client/cached_dir.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
154154
struct cached_fid *cfid;
155155
struct cached_fids *cfids;
156156
const char *npath;
157-
int retries = 0, cur_sleep = 1;
157+
int retries = 0, cur_sleep = 0;
158158
__le32 lease_flags = 0;
159159

160160
if (cifs_sb->root == NULL)
@@ -304,6 +304,10 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
304304
smb2_set_related(&rqst[1]);
305305

306306
if (retries) {
307+
/* Back-off before retry */
308+
if (cur_sleep)
309+
msleep(cur_sleep);
310+
307311
smb2_set_replay(server, &rqst[0]);
308312
smb2_set_replay(server, &rqst[1]);
309313
}
@@ -788,11 +792,11 @@ static void cfids_laundromat_worker(struct work_struct *work)
788792
cfid->dentry = NULL;
789793

790794
if (cfid->is_open) {
791-
spin_lock(&cifs_tcp_ses_lock);
795+
spin_lock(&cfid->tcon->tc_lock);
792796
++cfid->tcon->tc_count;
793797
trace_smb3_tcon_ref(cfid->tcon->debug_id, cfid->tcon->tc_count,
794798
netfs_trace_tcon_ref_get_cached_laundromat);
795-
spin_unlock(&cifs_tcp_ses_lock);
799+
spin_unlock(&cfid->tcon->tc_lock);
796800
queue_work(serverclose_wq, &cfid->close_work);
797801
} else
798802
/*

fs/smb/client/cached_dir.h

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ struct cached_fid {
3636
struct list_head entry;
3737
struct cached_fids *cfids;
3838
const char *path;
39-
bool has_lease:1;
40-
bool is_open:1;
41-
bool on_list:1;
42-
bool file_all_info_is_valid:1;
39+
bool has_lease;
40+
bool is_open;
41+
bool on_list;
42+
bool file_all_info_is_valid;
4343
unsigned long time; /* jiffies of when lease was taken */
4444
unsigned long last_access_time; /* jiffies of when last accessed */
4545
struct kref refcount;
@@ -48,8 +48,10 @@ struct cached_fid {
4848
struct dentry *dentry;
4949
struct work_struct put_work;
5050
struct work_struct close_work;
51-
struct smb2_file_all_info file_all_info;
5251
struct cached_dirents dirents;
52+
53+
/* Must be last as it ends in a flexible-array member. */
54+
struct smb2_file_all_info file_all_info;
5355
};
5456

5557
/* default MAX_CACHED_FIDS is 16 */
@@ -77,22 +79,18 @@ is_valid_cached_dir(struct cached_fid *cfid)
7779
return cfid->time && cfid->has_lease;
7880
}
7981

80-
extern struct cached_fids *init_cached_dirs(void);
81-
extern void free_cached_dirs(struct cached_fids *cfids);
82-
extern int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
83-
const char *path,
84-
struct cifs_sb_info *cifs_sb,
85-
bool lookup_only, struct cached_fid **cfid);
86-
extern int open_cached_dir_by_dentry(struct cifs_tcon *tcon,
87-
struct dentry *dentry,
88-
struct cached_fid **cfid);
89-
extern void close_cached_dir(struct cached_fid *cfid);
90-
extern void drop_cached_dir_by_name(const unsigned int xid,
91-
struct cifs_tcon *tcon,
92-
const char *name,
93-
struct cifs_sb_info *cifs_sb);
94-
extern void close_all_cached_dirs(struct cifs_sb_info *cifs_sb);
95-
extern void invalidate_all_cached_dirs(struct cifs_tcon *tcon);
96-
extern bool cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16]);
82+
struct cached_fids *init_cached_dirs(void);
83+
void free_cached_dirs(struct cached_fids *cfids);
84+
int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon, const char *path,
85+
struct cifs_sb_info *cifs_sb, bool lookup_only,
86+
struct cached_fid **ret_cfid);
87+
int open_cached_dir_by_dentry(struct cifs_tcon *tcon, struct dentry *dentry,
88+
struct cached_fid **ret_cfid);
89+
void close_cached_dir(struct cached_fid *cfid);
90+
void drop_cached_dir_by_name(const unsigned int xid, struct cifs_tcon *tcon,
91+
const char *name, struct cifs_sb_info *cifs_sb);
92+
void close_all_cached_dirs(struct cifs_sb_info *cifs_sb);
93+
void invalidate_all_cached_dirs(struct cifs_tcon *tcon);
94+
bool cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16]);
9795

9896
#endif /* _CACHED_DIR_H */

fs/smb/client/cifs_debug.c

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#include <linux/proc_fs.h>
1414
#include <linux/uaccess.h>
1515
#include <uapi/linux/ethtool.h>
16-
#include "cifspdu.h"
1716
#include "cifsglob.h"
1817
#include "cifsproto.h"
1918
#include "cifs_debug.h"
@@ -37,21 +36,6 @@ cifs_dump_mem(char *label, void *data, int length)
3736
data, length, true);
3837
}
3938

40-
void cifs_dump_detail(void *buf, size_t buf_len, struct TCP_Server_Info *server)
41-
{
42-
#ifdef CONFIG_CIFS_DEBUG2
43-
struct smb_hdr *smb = buf;
44-
45-
cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d Wct: %d\n",
46-
smb->Command, smb->Status.CifsError, smb->Flags,
47-
smb->Flags2, smb->Mid, smb->Pid, smb->WordCount);
48-
if (!server->ops->check_message(buf, buf_len, server->total_read, server)) {
49-
cifs_dbg(VFS, "smb buf %p len %u\n", smb,
50-
server->ops->calc_smb_size(smb));
51-
}
52-
#endif /* CONFIG_CIFS_DEBUG2 */
53-
}
54-
5539
void cifs_dump_mids(struct TCP_Server_Info *server)
5640
{
5741
#ifdef CONFIG_CIFS_DEBUG2
@@ -79,7 +63,7 @@ void cifs_dump_mids(struct TCP_Server_Info *server)
7963
cifs_dbg(VFS, "IsMult: %d IsEnd: %d\n",
8064
mid_entry->multiRsp, mid_entry->multiEnd);
8165
if (mid_entry->resp_buf) {
82-
cifs_dump_detail(mid_entry->resp_buf,
66+
server->ops->dump_detail(mid_entry->resp_buf,
8367
mid_entry->response_pdu_len, server);
8468
cifs_dump_mem("existing buf: ", mid_entry->resp_buf, 62);
8569
}

0 commit comments

Comments
 (0)