Skip to content

Commit

Permalink
Merge tag '5.19-rc-smb3-client-fixes-updated' of git://git.samba.org/…
Browse files Browse the repository at this point in the history
…sfrench/cifs-2.6

Pull cifs client updates from Steve French:

 - multichannel fixes to improve reconnect after network failure

 - improved caching of root directory contents (extending benefit of
   directory leases)

 - two DFS fixes

 - three fixes for improved debugging

 - an NTLMSSP fix for mounts t0 older servers

 - new mount parm to allow disabling creating sparse files

 - various cleanup fixes and minor fixes pointed out by coverity

* tag '5.19-rc-smb3-client-fixes-updated' of git://git.samba.org/sfrench/cifs-2.6: (24 commits)
  smb3: remove unneeded null check in cifs_readdir
  cifs: fix ntlmssp on old servers
  cifs: cache the dirents for entries in a cached directory
  cifs: avoid parallel session setups on same channel
  cifs: use new enum for ses_status
  cifs: do not use tcpStatus after negotiate completes
  smb3: add mount parm nosparse
  smb3: don't set rc when used and unneeded in query_info_compound
  smb3: check for null tcon
  cifs: fix minor compile warning
  Add various fsctl structs
  Add defines for various newer FSCTLs
  smb3: add trace point for oplock not found
  cifs: return the more nuanced writeback error on close()
  smb3: add trace point for lease not found issue
  cifs: smbd: fix typo in comment
  cifs: set the CREATE_NOT_FILE when opening the directory in use_cached_dir()
  cifs: check for smb1 in open_cached_dir()
  cifs: move definition of cifs_fattr earlier in cifsglob.h
  cifs: print TIDs as hex
  ...
  • Loading branch information
torvalds committed May 27, 2022
2 parents aef1ff1 + 44a4808 commit bf27246
Show file tree
Hide file tree
Showing 24 changed files with 559 additions and 189 deletions.
11 changes: 8 additions & 3 deletions fs/cifs/cifs_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon)
tcon->ses->server->ops->dump_share_caps(m, tcon);
if (tcon->use_witness)
seq_puts(m, " Witness");

if (tcon->broken_sparse_sup)
seq_puts(m, " nosparse");
if (tcon->need_reconnect)
seq_puts(m, "\tDISCONNECTED ");
seq_putc(m, '\n');
Expand Down Expand Up @@ -386,7 +387,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
(ses->serverNOS == NULL)) {
seq_printf(m, "\n\t%d) Address: %s Uses: %d Capability: 0x%x\tSession Status: %d ",
i, ses->ip_addr, ses->ses_count,
ses->capabilities, ses->status);
ses->capabilities, ses->ses_status);
if (ses->session_flags & SMB2_SESSION_FLAG_IS_GUEST)
seq_printf(m, "Guest ");
else if (ses->session_flags & SMB2_SESSION_FLAG_IS_NULL)
Expand All @@ -398,7 +399,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
"\n\tSMB session status: %d ",
i, ses->ip_addr, ses->serverDomain,
ses->ses_count, ses->serverOS, ses->serverNOS,
ses->capabilities, ses->status);
ses->capabilities, ses->ses_status);
}

seq_printf(m, "\n\tSecurity type: %s ",
Expand All @@ -418,6 +419,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
spin_lock(&ses->chan_lock);
if (CIFS_CHAN_NEEDS_RECONNECT(ses, 0))
seq_puts(m, "\tPrimary channel: DISCONNECTED ");
if (CIFS_CHAN_IN_RECONNECT(ses, 0))
seq_puts(m, "\t[RECONNECTING] ");

if (ses->chan_count > 1) {
seq_printf(m, "\n\n\tExtra Channels: %zu ",
Expand All @@ -426,6 +429,8 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
cifs_dump_channel(m, j, &ses->chans[j]);
if (CIFS_CHAN_NEEDS_RECONNECT(ses, j))
seq_puts(m, "\tDISCONNECTED ");
if (CIFS_CHAN_IN_RECONNECT(ses, j))
seq_puts(m, "\t[RECONNECTING] ");
}
}
spin_unlock(&ses->chan_lock);
Expand Down
2 changes: 2 additions & 0 deletions fs/cifs/cifsfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
seq_puts(s, ",nocase");
if (tcon->nodelete)
seq_puts(s, ",nodelete");
if (cifs_sb->ctx->no_sparse)
seq_puts(s, ",nosparse");
if (tcon->local_lease)
seq_puts(s, ",locallease");
if (tcon->retry)
Expand Down
124 changes: 88 additions & 36 deletions fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,16 +106,23 @@
* CIFS vfs client Status information (based on what we know.)
*/

/* associated with each tcp and smb session */
/* associated with each connection */
enum statusEnum {
CifsNew = 0,
CifsGood,
CifsExiting,
CifsNeedReconnect,
CifsNeedNegotiate,
CifsInNegotiate,
CifsNeedSessSetup,
CifsInSessSetup,
};

/* associated with each smb session */
enum ses_status_enum {
SES_NEW = 0,
SES_GOOD,
SES_EXITING,
SES_NEED_RECON,
SES_IN_SETUP
};

/* associated with each tree connection to the server */
Expand Down Expand Up @@ -915,6 +922,7 @@ struct cifs_server_iface {
};

struct cifs_chan {
unsigned int in_reconnect : 1; /* if session setup in progress for this channel */
struct TCP_Server_Info *server;
__u8 signkey[SMB3_SIGN_KEY_SIZE];
};
Expand All @@ -930,7 +938,7 @@ struct cifs_ses {
struct mutex session_mutex;
struct TCP_Server_Info *server; /* pointer to server info */
int ses_count; /* reference counter */
enum statusEnum status; /* updates protected by cifs_tcp_ses_lock */
enum ses_status_enum ses_status; /* updates protected by cifs_tcp_ses_lock */
unsigned overrideSecFlg; /* if non-zero override global sec flags */
char *serverOS; /* name of operating system underlying server */
char *serverNOS; /* name of network operating system of server */
Expand All @@ -944,7 +952,7 @@ struct cifs_ses {
and after mount option parsing we fill it */
char *domainName;
char *password;
char *workstation_name;
char workstation_name[CIFS_MAX_WORKSTATION_LEN];
struct session_key auth_key;
struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */
enum securityEnum sectype; /* what security flavor was specified? */
Expand Down Expand Up @@ -977,12 +985,16 @@ struct cifs_ses {
#define CIFS_MAX_CHANNELS 16
#define CIFS_ALL_CHANNELS_SET(ses) \
((1UL << (ses)->chan_count) - 1)
#define CIFS_ALL_CHANS_GOOD(ses) \
(!(ses)->chans_need_reconnect)
#define CIFS_ALL_CHANS_NEED_RECONNECT(ses) \
((ses)->chans_need_reconnect == CIFS_ALL_CHANNELS_SET(ses))
#define CIFS_SET_ALL_CHANS_NEED_RECONNECT(ses) \
((ses)->chans_need_reconnect = CIFS_ALL_CHANNELS_SET(ses))
#define CIFS_CHAN_NEEDS_RECONNECT(ses, index) \
test_bit((index), &(ses)->chans_need_reconnect)
#define CIFS_CHAN_IN_RECONNECT(ses, index) \
((ses)->chans[(index)].in_reconnect)

struct cifs_chan chans[CIFS_MAX_CHANNELS];
size_t chan_count;
Expand All @@ -1009,6 +1021,58 @@ cap_unix(struct cifs_ses *ses)
return ses->server->vals->cap_unix & ses->capabilities;
}

/*
* common struct for holding inode info when searching for or updating an
* inode with new info
*/

#define CIFS_FATTR_DFS_REFERRAL 0x1
#define CIFS_FATTR_DELETE_PENDING 0x2
#define CIFS_FATTR_NEED_REVAL 0x4
#define CIFS_FATTR_INO_COLLISION 0x8
#define CIFS_FATTR_UNKNOWN_NLINK 0x10
#define CIFS_FATTR_FAKE_ROOT_INO 0x20

struct cifs_fattr {
u32 cf_flags;
u32 cf_cifsattrs;
u64 cf_uniqueid;
u64 cf_eof;
u64 cf_bytes;
u64 cf_createtime;
kuid_t cf_uid;
kgid_t cf_gid;
umode_t cf_mode;
dev_t cf_rdev;
unsigned int cf_nlink;
unsigned int cf_dtype;
struct timespec64 cf_atime;
struct timespec64 cf_mtime;
struct timespec64 cf_ctime;
u32 cf_cifstag;
};

struct cached_dirent {
struct list_head entry;
char *name;
int namelen;
loff_t pos;

struct cifs_fattr fattr;
};

struct cached_dirents {
bool is_valid:1;
bool is_failed:1;
struct dir_context *ctx; /*
* Only used to make sure we only take entries
* from a single context. Never dereferenced.
*/
struct mutex de_mutex;
int pos; /* Expected ctx->pos */
struct list_head entries;
};

struct cached_fid {
bool is_valid:1; /* Do we have a useable root fid */
bool file_all_info_is_valid:1;
Expand All @@ -1021,6 +1085,7 @@ struct cached_fid {
struct dentry *dentry;
struct work_struct lease_break;
struct smb2_file_all_info file_all_info;
struct cached_dirents dirents;
};

/*
Expand Down Expand Up @@ -1641,37 +1706,6 @@ struct file_list {
struct cifsFileInfo *cfile;
};

/*
* common struct for holding inode info when searching for or updating an
* inode with new info
*/

#define CIFS_FATTR_DFS_REFERRAL 0x1
#define CIFS_FATTR_DELETE_PENDING 0x2
#define CIFS_FATTR_NEED_REVAL 0x4
#define CIFS_FATTR_INO_COLLISION 0x8
#define CIFS_FATTR_UNKNOWN_NLINK 0x10
#define CIFS_FATTR_FAKE_ROOT_INO 0x20

struct cifs_fattr {
u32 cf_flags;
u32 cf_cifsattrs;
u64 cf_uniqueid;
u64 cf_eof;
u64 cf_bytes;
u64 cf_createtime;
kuid_t cf_uid;
kgid_t cf_gid;
umode_t cf_mode;
dev_t cf_rdev;
unsigned int cf_nlink;
unsigned int cf_dtype;
struct timespec64 cf_atime;
struct timespec64 cf_mtime;
struct timespec64 cf_ctime;
u32 cf_cifstag;
};

static inline void free_dfs_info_param(struct dfs_info3_param *param)
{
if (param) {
Expand Down Expand Up @@ -1979,4 +2013,22 @@ static inline bool cifs_is_referral_server(struct cifs_tcon *tcon,
return is_tcon_dfs(tcon) || (ref && (ref->flags & DFSREF_REFERRAL_SERVER));
}

static inline u64 cifs_flock_len(struct file_lock *fl)
{
return fl->fl_end == OFFSET_MAX ? 0 : fl->fl_end - fl->fl_start + 1;
}

static inline size_t ntlmssp_workstation_name_size(const struct cifs_ses *ses)
{
if (WARN_ON_ONCE(!ses || !ses->server))
return 0;
/*
* Make workstation name no more than 15 chars when using insecure dialects as some legacy
* servers do require it during NTLMSSP.
*/
if (ses->server->dialect <= SMB20_PROT_ID)
return min_t(size_t, sizeof(ses->workstation_name), RFC1001_NAME_LEN_WITH_NULL);
return sizeof(ses->workstation_name);
}

#endif /* _CIFS_GLOB_H */
9 changes: 9 additions & 0 deletions fs/cifs/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,15 @@ unsigned int
cifs_ses_get_chan_index(struct cifs_ses *ses,
struct TCP_Server_Info *server);
void
cifs_chan_set_in_reconnect(struct cifs_ses *ses,
struct TCP_Server_Info *server);
void
cifs_chan_clear_in_reconnect(struct cifs_ses *ses,
struct TCP_Server_Info *server);
bool
cifs_chan_in_reconnect(struct cifs_ses *ses,
struct TCP_Server_Info *server);
void
cifs_chan_set_need_reconnect(struct cifs_ses *ses,
struct TCP_Server_Info *server);
void
Expand Down
5 changes: 3 additions & 2 deletions fs/cifs/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon)

/* only send once per connect */
spin_lock(&cifs_tcp_ses_lock);
if ((tcon->ses->status != CifsGood) || (tcon->status != TID_NEED_RECON)) {
if ((tcon->ses->ses_status != SES_GOOD) || (tcon->status != TID_NEED_RECON)) {
spin_unlock(&cifs_tcp_ses_lock);
return;
}
Expand Down Expand Up @@ -2558,7 +2558,8 @@ CIFSSMBPosixLock(const unsigned int xid, struct cifs_tcon *tcon,

pLockData->fl_start = le64_to_cpu(parm_data->start);
pLockData->fl_end = pLockData->fl_start +
le64_to_cpu(parm_data->length) - 1;
(le64_to_cpu(parm_data->length) ?
le64_to_cpu(parm_data->length) - 1 : 0);
pLockData->fl_pid = -le32_to_cpu(parm_data->pid);
}
}
Expand Down
Loading

0 comments on commit bf27246

Please sign in to comment.