Commit bf272460 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag '5.19-rc-smb3-client-fixes-updated' of git://git.samba.org/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
  ...
parents aef1ff15 44a48081
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -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');
@@ -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)
@@ -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 ",
@@ -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 ",
@@ -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);
+2 −0
Original line number Diff line number Diff line
@@ -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)
+88 −36
Original line number Diff line number Diff line
@@ -106,7 +106,7 @@
 * 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,
@@ -114,8 +114,15 @@ enum statusEnum {
	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 */
@@ -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];
};
@@ -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 */
@@ -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? */
@@ -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;
@@ -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;
@@ -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;
};

/*
@@ -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) {
@@ -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 −0
Original line number Diff line number Diff line
@@ -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
+3 −2
Original line number Diff line number Diff line
@@ -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;
	}
@@ -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);
		}
	}
Loading