Skip to content

Commit 0c947b8

Browse files
committed
Merge tag '5.17-rc-part1-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs updates from Steve French: - multichannel patches mostly related to improving reconnect behavior - minor cleanup patches * tag '5.17-rc-part1-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6: cifs: fix FILE_BOTH_DIRECTORY_INFO definition cifs: move superblock magic defitions to magic.h cifs: Fix smb311_update_preauth_hash() kernel-doc comment cifs: avoid race during socket reconnect between send and recv cifs: maintain a state machine for tcp/smb/tcon sessions cifs: fix hang on cifs_get_next_mid() cifs: take cifs_tcp_ses_lock for status checks cifs: reconnect only the connection and not smb session where possible cifs: add WARN_ON for when chan_count goes below minimum cifs: adjust DebugData to use chans_need_reconnect for conn status cifs: use the chans_need_reconnect bitmap for reconnect status cifs: track individual channel status using chans_need_reconnect cifs: remove redundant assignment to pointer p
2 parents a609718 + 9bbf866 commit 0c947b8

23 files changed

+723
-325
lines changed

fs/cifs/cifs_debug.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,11 +416,17 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
416416
from_kuid(&init_user_ns, ses->cred_uid));
417417

418418
spin_lock(&ses->chan_lock);
419+
if (CIFS_CHAN_NEEDS_RECONNECT(ses, 0))
420+
seq_puts(m, "\tPrimary channel: DISCONNECTED ");
421+
419422
if (ses->chan_count > 1) {
420423
seq_printf(m, "\n\n\tExtra Channels: %zu ",
421424
ses->chan_count-1);
422-
for (j = 1; j < ses->chan_count; j++)
425+
for (j = 1; j < ses->chan_count; j++) {
423426
cifs_dump_channel(m, j, &ses->chans[j]);
427+
if (CIFS_CHAN_NEEDS_RECONNECT(ses, j))
428+
seq_puts(m, "\tDISCONNECTED ");
429+
}
424430
}
425431
spin_unlock(&ses->chan_lock);
426432

fs/cifs/cifs_spnego.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ struct key_type cifs_spnego_key_type = {
8484

8585
/* get a key struct with a SPNEGO security blob, suitable for session setup */
8686
struct key *
87-
cifs_get_spnego_key(struct cifs_ses *sesInfo)
87+
cifs_get_spnego_key(struct cifs_ses *sesInfo,
88+
struct TCP_Server_Info *server)
8889
{
89-
struct TCP_Server_Info *server = cifs_ses_server(sesInfo);
9090
struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr;
9191
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr;
9292
char *description, *dp;

fs/cifs/cifs_spnego.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ struct cifs_spnego_msg {
2929

3030
#ifdef __KERNEL__
3131
extern struct key_type cifs_spnego_key_type;
32-
extern struct key *cifs_get_spnego_key(struct cifs_ses *sesInfo);
32+
extern struct key *cifs_get_spnego_key(struct cifs_ses *sesInfo,
33+
struct TCP_Server_Info *server);
3334
#endif /* KERNEL */
3435

3536
#endif /* _CIFS_SPNEGO_H */

fs/cifs/cifs_swn.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -498,10 +498,10 @@ static int cifs_swn_reconnect(struct cifs_tcon *tcon, struct sockaddr_storage *a
498498
goto unlock;
499499
}
500500

501-
spin_lock(&GlobalMid_Lock);
501+
spin_lock(&cifs_tcp_ses_lock);
502502
if (tcon->ses->server->tcpStatus != CifsExiting)
503503
tcon->ses->server->tcpStatus = CifsNeedReconnect;
504-
spin_unlock(&GlobalMid_Lock);
504+
spin_unlock(&cifs_tcp_ses_lock);
505505

506506
unlock:
507507
mutex_unlock(&tcon->ses->server->srv_mutex);

fs/cifs/cifsencrypt.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,13 @@ int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server,
141141
if ((cifs_pdu == NULL) || (server == NULL))
142142
return -EINVAL;
143143

144+
spin_lock(&cifs_tcp_ses_lock);
144145
if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) ||
145-
server->tcpStatus == CifsNeedNegotiate)
146+
server->tcpStatus == CifsNeedNegotiate) {
147+
spin_unlock(&cifs_tcp_ses_lock);
146148
return rc;
149+
}
150+
spin_unlock(&cifs_tcp_ses_lock);
147151

148152
if (!server->session_estab) {
149153
memcpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8);

fs/cifs/cifsfs.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <linux/random.h>
2727
#include <linux/uuid.h>
2828
#include <linux/xattr.h>
29+
#include <uapi/linux/magic.h>
2930
#include <net/ipv6.h>
3031
#include "cifsfs.h"
3132
#include "cifspdu.h"
@@ -202,7 +203,7 @@ cifs_read_super(struct super_block *sb)
202203
sb->s_time_max = ts.tv_sec;
203204
}
204205

205-
sb->s_magic = CIFS_MAGIC_NUMBER;
206+
sb->s_magic = CIFS_SUPER_MAGIC;
206207
sb->s_op = &cifs_super_ops;
207208
sb->s_xattr = cifs_xattr_handlers;
208209
rc = super_setup_bdi(sb);
@@ -773,7 +774,7 @@ cifs_get_root(struct smb3_fs_context *ctx, struct super_block *sb)
773774

774775
sep = CIFS_DIR_SEP(cifs_sb);
775776
dentry = dget(sb->s_root);
776-
p = s = full_path;
777+
s = full_path;
777778

778779
do {
779780
struct inode *dir = d_inode(dentry);

fs/cifs/cifsglob.h

Lines changed: 36 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
#include "../smbfs_common/smb2pdu.h"
2525
#include "smb2pdu.h"
2626

27-
#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
28-
2927
#define SMB_PATH_MAX 260
3028
#define CIFS_PORT 445
3129
#define RFC1001_PORT 139
@@ -113,7 +111,13 @@ enum statusEnum {
113111
CifsGood,
114112
CifsExiting,
115113
CifsNeedReconnect,
116-
CifsNeedNegotiate
114+
CifsNeedNegotiate,
115+
CifsInNegotiate,
116+
CifsNeedSessSetup,
117+
CifsInSessSetup,
118+
CifsNeedTcon,
119+
CifsInTcon,
120+
CifsInFilesInvalidate
117121
};
118122

119123
enum securityEnum {
@@ -263,13 +267,16 @@ struct smb_version_operations {
263267
/* check if we need to negotiate */
264268
bool (*need_neg)(struct TCP_Server_Info *);
265269
/* negotiate to the server */
266-
int (*negotiate)(const unsigned int, struct cifs_ses *);
270+
int (*negotiate)(const unsigned int xid,
271+
struct cifs_ses *ses,
272+
struct TCP_Server_Info *server);
267273
/* set negotiated write size */
268274
unsigned int (*negotiate_wsize)(struct cifs_tcon *tcon, struct smb3_fs_context *ctx);
269275
/* set negotiated read size */
270276
unsigned int (*negotiate_rsize)(struct cifs_tcon *tcon, struct smb3_fs_context *ctx);
271277
/* setup smb sessionn */
272278
int (*sess_setup)(const unsigned int, struct cifs_ses *,
279+
struct TCP_Server_Info *server,
273280
const struct nls_table *);
274281
/* close smb session */
275282
int (*logoff)(const unsigned int, struct cifs_ses *);
@@ -414,7 +421,8 @@ struct smb_version_operations {
414421
void (*set_lease_key)(struct inode *, struct cifs_fid *);
415422
/* generate new lease key */
416423
void (*new_lease_key)(struct cifs_fid *);
417-
int (*generate_signingkey)(struct cifs_ses *);
424+
int (*generate_signingkey)(struct cifs_ses *ses,
425+
struct TCP_Server_Info *server);
418426
int (*calc_signature)(struct smb_rqst *, struct TCP_Server_Info *,
419427
bool allocate_crypto);
420428
int (*set_integrity)(const unsigned int, struct cifs_tcon *tcon,
@@ -582,7 +590,7 @@ struct TCP_Server_Info {
582590
char server_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL];
583591
struct smb_version_operations *ops;
584592
struct smb_version_values *vals;
585-
/* updates to tcpStatus protected by GlobalMid_Lock */
593+
/* updates to tcpStatus protected by cifs_tcp_ses_lock */
586594
enum statusEnum tcpStatus; /* what we think the status is */
587595
char *hostname; /* hostname portion of UNC string */
588596
struct socket *ssocket;
@@ -920,7 +928,7 @@ struct cifs_ses {
920928
struct mutex session_mutex;
921929
struct TCP_Server_Info *server; /* pointer to server info */
922930
int ses_count; /* reference counter */
923-
enum statusEnum status; /* updates protected by GlobalMid_Lock */
931+
enum statusEnum status; /* updates protected by cifs_tcp_ses_lock */
924932
unsigned overrideSecFlg; /* if non-zero override global sec flags */
925933
char *serverOS; /* name of operating system underlying server */
926934
char *serverNOS; /* name of network operating system of server */
@@ -939,17 +947,13 @@ struct cifs_ses {
939947
struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */
940948
enum securityEnum sectype; /* what security flavor was specified? */
941949
bool sign; /* is signing required? */
942-
bool need_reconnect:1; /* connection reset, uid now invalid */
943950
bool domainAuto:1;
944-
bool binding:1; /* are we binding the session? */
945951
__u16 session_flags;
946952
__u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
947953
__u8 smb3encryptionkey[SMB3_ENC_DEC_KEY_SIZE];
948954
__u8 smb3decryptionkey[SMB3_ENC_DEC_KEY_SIZE];
949955
__u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
950956

951-
__u8 binding_preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
952-
953957
/*
954958
* Network interfaces available on the server this session is
955959
* connected to.
@@ -969,45 +973,34 @@ struct cifs_ses {
969973
spinlock_t chan_lock;
970974
/* ========= begin: protected by chan_lock ======== */
971975
#define CIFS_MAX_CHANNELS 16
976+
#define CIFS_ALL_CHANNELS_SET(ses) \
977+
((1UL << (ses)->chan_count) - 1)
978+
#define CIFS_ALL_CHANS_NEED_RECONNECT(ses) \
979+
((ses)->chans_need_reconnect == CIFS_ALL_CHANNELS_SET(ses))
980+
#define CIFS_SET_ALL_CHANS_NEED_RECONNECT(ses) \
981+
((ses)->chans_need_reconnect = CIFS_ALL_CHANNELS_SET(ses))
982+
#define CIFS_CHAN_NEEDS_RECONNECT(ses, index) \
983+
test_bit((index), &(ses)->chans_need_reconnect)
984+
972985
struct cifs_chan chans[CIFS_MAX_CHANNELS];
973-
struct cifs_chan *binding_chan;
974986
size_t chan_count;
975987
size_t chan_max;
976988
atomic_t chan_seq; /* round robin state */
989+
990+
/*
991+
* chans_need_reconnect is a bitmap indicating which of the channels
992+
* under this smb session needs to be reconnected.
993+
* If not multichannel session, only one bit will be used.
994+
*
995+
* We will ask for sess and tcon reconnection only if all the
996+
* channels are marked for needing reconnection. This will
997+
* enable the sessions on top to continue to live till any
998+
* of the channels below are active.
999+
*/
1000+
unsigned long chans_need_reconnect;
9771001
/* ========= end: protected by chan_lock ======== */
9781002
};
9791003

980-
/*
981-
* When binding a new channel, we need to access the channel which isn't fully
982-
* established yet.
983-
*/
984-
985-
static inline
986-
struct cifs_chan *cifs_ses_binding_channel(struct cifs_ses *ses)
987-
{
988-
if (ses->binding)
989-
return ses->binding_chan;
990-
else
991-
return NULL;
992-
}
993-
994-
/*
995-
* Returns the server pointer of the session. When binding a new
996-
* channel this returns the last channel which isn't fully established
997-
* yet.
998-
*
999-
* This function should be use for negprot/sess.setup codepaths. For
1000-
* the other requests see cifs_pick_channel().
1001-
*/
1002-
static inline
1003-
struct TCP_Server_Info *cifs_ses_server(struct cifs_ses *ses)
1004-
{
1005-
if (ses->binding)
1006-
return ses->binding_chan->server;
1007-
else
1008-
return ses->server;
1009-
}
1010-
10111004
static inline bool
10121005
cap_unix(struct cifs_ses *ses)
10131006
{

fs/cifs/cifspdu.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2560,7 +2560,7 @@ typedef struct {
25602560
__le32 EaSize; /* length of the xattrs */
25612561
__u8 ShortNameLength;
25622562
__u8 Reserved;
2563-
__u8 ShortName[12];
2563+
__u8 ShortName[24];
25642564
char FileName[1];
25652565
} __attribute__((packed)) FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FFrsp data */
25662566

fs/cifs/cifsproto.h

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ extern int SendReceiveBlockingLock(const unsigned int xid,
131131
struct smb_hdr *in_buf ,
132132
struct smb_hdr *out_buf,
133133
int *bytes_returned);
134-
extern int cifs_reconnect(struct TCP_Server_Info *server);
134+
extern int cifs_reconnect(struct TCP_Server_Info *server,
135+
bool mark_smb_session);
135136
extern int checkSMB(char *buf, unsigned int len, struct TCP_Server_Info *srvr);
136137
extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *);
137138
extern bool backup_cred(struct cifs_sb_info *);
@@ -164,6 +165,7 @@ extern int small_smb_init_no_tc(const int smb_cmd, const int wct,
164165
extern enum securityEnum select_sectype(struct TCP_Server_Info *server,
165166
enum securityEnum requested);
166167
extern int CIFS_SessSetup(const unsigned int xid, struct cifs_ses *ses,
168+
struct TCP_Server_Info *server,
167169
const struct nls_table *nls_cp);
168170
extern struct timespec64 cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601);
169171
extern u64 cifs_UnixTimeToNT(struct timespec64);
@@ -293,11 +295,15 @@ extern int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon,
293295
const struct nls_table *nlsc);
294296

295297
extern int cifs_negotiate_protocol(const unsigned int xid,
296-
struct cifs_ses *ses);
298+
struct cifs_ses *ses,
299+
struct TCP_Server_Info *server);
297300
extern int cifs_setup_session(const unsigned int xid, struct cifs_ses *ses,
301+
struct TCP_Server_Info *server,
298302
struct nls_table *nls_info);
299303
extern int cifs_enable_signing(struct TCP_Server_Info *server, bool mnt_sign_required);
300-
extern int CIFSSMBNegotiate(const unsigned int xid, struct cifs_ses *ses);
304+
extern int CIFSSMBNegotiate(const unsigned int xid,
305+
struct cifs_ses *ses,
306+
struct TCP_Server_Info *server);
301307

302308
extern int CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
303309
const char *tree, struct cifs_tcon *tcon,
@@ -504,8 +510,10 @@ extern int cifs_verify_signature(struct smb_rqst *rqst,
504510
extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *);
505511
extern void cifs_crypto_secmech_release(struct TCP_Server_Info *server);
506512
extern int calc_seckey(struct cifs_ses *);
507-
extern int generate_smb30signingkey(struct cifs_ses *);
508-
extern int generate_smb311signingkey(struct cifs_ses *);
513+
extern int generate_smb30signingkey(struct cifs_ses *ses,
514+
struct TCP_Server_Info *server);
515+
extern int generate_smb311signingkey(struct cifs_ses *ses,
516+
struct TCP_Server_Info *server);
509517

510518
extern int CIFSSMBCopy(unsigned int xid,
511519
struct cifs_tcon *source_tcon,
@@ -601,6 +609,19 @@ bool is_server_using_iface(struct TCP_Server_Info *server,
601609
bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface);
602610
void cifs_ses_mark_for_reconnect(struct cifs_ses *ses);
603611

612+
unsigned int
613+
cifs_ses_get_chan_index(struct cifs_ses *ses,
614+
struct TCP_Server_Info *server);
615+
void
616+
cifs_chan_set_need_reconnect(struct cifs_ses *ses,
617+
struct TCP_Server_Info *server);
618+
void
619+
cifs_chan_clear_need_reconnect(struct cifs_ses *ses,
620+
struct TCP_Server_Info *server);
621+
bool
622+
cifs_chan_needs_reconnect(struct cifs_ses *ses,
623+
struct TCP_Server_Info *server);
624+
604625
void extract_unc_hostname(const char *unc, const char **h, size_t *len);
605626
int copy_path_name(char *dst, const char *src);
606627
int smb2_parse_query_directory(struct cifs_tcon *tcon, struct kvec *rsp_iov,

0 commit comments

Comments
 (0)