Commit 84e9a2d5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'v6.8-rc-part1-smb-client' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:
 "Various smb client fixes, most related to better handling special file
  types:

   - Improve handling of special file types:
      - performance improvement (better compounding and better caching
        of readdir entries that are reparse points)
      - extend support for creating special files (sockets, fifos,
        block/char devices)
      - fix renaming and hardlinking of reparse points
      - extend support for creating symlinks with IO_REPARSE_TAG_SYMLINK

   - Multichannel logging improvement

   - Exception handling fix

   - Minor cleanups"

* tag 'v6.8-rc-part1-smb-client' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: update internal module version number for cifs.ko
  cifs: remove unneeded return statement
  cifs: make cifs_chan_update_iface() a void function
  cifs: delete unnecessary NULL checks in cifs_chan_update_iface()
  cifs: get rid of dup length check in parse_reparse_point()
  smb: client: stop revalidating reparse points unnecessarily
  cifs: Pass unbyteswapped eof value into SMB2_set_eof()
  smb3: Improve exception handling in allocate_mr_list()
  cifs: fix in logging in cifs_chan_update_iface
  smb: client: handle special files and symlinks in SMB3 POSIX
  smb: client: cleanup smb2_query_reparse_point()
  smb: client: allow creating symlinks via reparse points
  smb: client: fix hardlinking of reparse points
  smb: client: fix renaming of reparse points
  smb: client: optimise reparse point querying
  smb: client: allow creating special files via reparse points
  smb: client: extend smb2_compound_op() to accept more commands
  smb: client: Fix minor whitespace errors and warnings
parents 587217f9 26ba1bf3
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -152,6 +152,6 @@ extern const struct export_operations cifs_export_ops;
#endif /* CONFIG_CIFS_NFSD_EXPORT */

/* when changing internal version - update following two lines at same time */
#define SMB3_PRODUCT_BUILD 46
#define CIFS_VERSION   "2.46"
#define SMB3_PRODUCT_BUILD 47
#define CIFS_VERSION   "2.47"
#endif				/* _CIFSFS_H */
+34 −13
Original line number Diff line number Diff line
@@ -192,6 +192,11 @@ struct cifs_open_info_data {
		bool symlink;
	};
	struct {
		/* ioctl response buffer */
		struct {
			int buftype;
			struct kvec iov;
		} io;
		__u32 tag;
		union {
			struct reparse_data_buffer *buf;
@@ -205,13 +210,17 @@ struct cifs_open_info_data {
	};
};

#define cifs_open_data_reparse(d) \
	((d)->reparse_point || \
	 (le32_to_cpu((d)->fi.Attributes) & ATTR_REPARSE))

static inline void cifs_free_open_info(struct cifs_open_info_data *data)
static inline bool cifs_open_data_reparse(struct cifs_open_info_data *data)
{
	kfree(data->symlink_target);
	struct smb2_file_all_info *fi = &data->fi;
	u32 attrs = le32_to_cpu(fi->Attributes);
	bool ret;

	ret = data->reparse_point || (attrs & ATTR_REPARSE);
	if (ret)
		attrs |= ATTR_REPARSE;
	fi->Attributes = cpu_to_le32(attrs);
	return ret;
}

/*
@@ -390,12 +399,17 @@ struct smb_version_operations {
	int (*rename_pending_delete)(const char *, struct dentry *,
				     const unsigned int);
	/* send rename request */
	int (*rename)(const unsigned int, struct cifs_tcon *, const char *,
		      const char *, struct cifs_sb_info *);
	int (*rename)(const unsigned int xid,
		      struct cifs_tcon *tcon,
		      struct dentry *source_dentry,
		      const char *from_name, const char *to_name,
		      struct cifs_sb_info *cifs_sb);
	/* send create hardlink request */
	int (*create_hardlink)(const unsigned int, struct cifs_tcon *,
			       const char *, const char *,
			       struct cifs_sb_info *);
	int (*create_hardlink)(const unsigned int xid,
			       struct cifs_tcon *tcon,
			       struct dentry *source_dentry,
			       const char *from_name, const char *to_name,
			       struct cifs_sb_info *cifs_sb);
	/* query symlink target */
	int (*query_symlink)(const unsigned int xid,
			     struct cifs_tcon *tcon,
@@ -560,6 +574,12 @@ struct smb_version_operations {
	int (*parse_reparse_point)(struct cifs_sb_info *cifs_sb,
				   struct kvec *rsp_iov,
				   struct cifs_open_info_data *data);
	int (*create_reparse_symlink)(const unsigned int xid,
				      struct inode *inode,
				      struct dentry *dentry,
				      struct cifs_tcon *tcon,
				      const char *full_path,
				      const char *symname);
};

struct smb_version_values {
@@ -1545,6 +1565,7 @@ struct cifsInodeInfo {
	spinlock_t deferred_lock; /* protection on deferred list */
	bool lease_granted; /* Flag to indicate whether lease or oplock is granted. */
	char *symlink_target;
	__u32 reparse_tag;
};

static inline struct cifsInodeInfo *
@@ -2238,8 +2259,8 @@ static inline void cifs_sg_set_buf(struct sg_table *sgtable,

struct smb2_compound_vars {
	struct cifs_open_parms oparms;
	struct kvec rsp_iov[3];
	struct smb_rqst rqst[3];
	struct kvec rsp_iov[MAX_COMPOUND];
	struct smb_rqst rqst[MAX_COMPOUND];
	struct kvec open_iov[SMB2_CREATE_IOV_SIZE];
	struct kvec qi_iov;
	struct kvec io_iov[SMB2_IOCTL_IOV_SIZE];
+23 −9
Original line number Diff line number Diff line
@@ -211,8 +211,12 @@ int cifs_get_inode_info(struct inode **inode, const char *full_path,
bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
				 struct cifs_fattr *fattr,
				 struct cifs_open_info_data *data);
extern int smb311_posix_get_inode_info(struct inode **pinode, const char *search_path,
			struct super_block *sb, unsigned int xid);

extern int smb311_posix_get_inode_info(struct inode **inode,
				       const char *full_path,
				       struct cifs_open_info_data *data,
				       struct super_block *sb,
				       const unsigned int xid);
extern int cifs_get_inode_info_unix(struct inode **pinode,
			const unsigned char *search_path,
			struct super_block *sb, unsigned int xid);
@@ -435,14 +439,17 @@ extern int CIFSPOSIXDelFile(const unsigned int xid, struct cifs_tcon *tcon,
			int remap_special_chars);
extern int CIFSSMBDelFile(const unsigned int xid, struct cifs_tcon *tcon,
			  const char *name, struct cifs_sb_info *cifs_sb);
extern int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
		  struct dentry *source_dentry,
		  const char *from_name, const char *to_name,
		  struct cifs_sb_info *cifs_sb);
extern int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *tcon,
				 int netfid, const char *target_name,
				 const struct nls_table *nls_codepage,
				 int remap_special_chars);
extern int CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
int CIFSCreateHardLink(const unsigned int xid,
		       struct cifs_tcon *tcon,
		       struct dentry *source_dentry,
		       const char *from_name, const char *to_name,
		       struct cifs_sb_info *cifs_sb);
extern int CIFSUnixCreateHardLink(const unsigned int xid,
@@ -649,7 +656,7 @@ cifs_chan_is_iface_active(struct cifs_ses *ses,
			  struct TCP_Server_Info *server);
void
cifs_disable_secondary_channels(struct cifs_ses *ses);
int
void
cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server);
int
SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon, bool in_mount);
@@ -760,4 +767,11 @@ static inline void release_mid(struct mid_q_entry *mid)
	kref_put(&mid->refcount, __release_mid);
}

static inline void cifs_free_open_info(struct cifs_open_info_data *data)
{
	kfree(data->symlink_target);
	free_rsp_buf(data->reparse.io.buftype, data->reparse.io.iov.iov_base);
	memset(data, 0, sizeof(*data));
}

#endif			/* _CIFSPROTO_H */
+21 −10
Original line number Diff line number Diff line
@@ -2149,8 +2149,8 @@ CIFSSMBFlush(const unsigned int xid, struct cifs_tcon *tcon, int smb_file_id)
	return rc;
}

int
CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
int CIFSSMBRename(const unsigned int xid, struct cifs_tcon *tcon,
		  struct dentry *source_dentry,
		  const char *from_name, const char *to_name,
		  struct cifs_sb_info *cifs_sb)
{
@@ -2530,8 +2530,9 @@ CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
	return rc;
}

int
CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
int CIFSCreateHardLink(const unsigned int xid,
		       struct cifs_tcon *tcon,
		       struct dentry *source_dentry,
		       const char *from_name, const char *to_name,
		       struct cifs_sb_info *cifs_sb)
{
@@ -2699,11 +2700,12 @@ int cifs_query_reparse_point(const unsigned int xid,
			     u32 *tag, struct kvec *rsp,
			     int *rsp_buftype)
{
	struct reparse_data_buffer *buf;
	struct cifs_open_parms oparms;
	TRANSACT_IOCTL_REQ *io_req = NULL;
	TRANSACT_IOCTL_RSP *io_rsp = NULL;
	struct cifs_fid fid;
	__u32 data_offset, data_count;
	__u32 data_offset, data_count, len;
	__u8 *start, *end;
	int io_rsp_len;
	int oplock = 0;
@@ -2773,7 +2775,16 @@ int cifs_query_reparse_point(const unsigned int xid,
		goto error;
	}

	*tag = le32_to_cpu(((struct reparse_data_buffer *)start)->ReparseTag);
	data_count = le16_to_cpu(io_rsp->ByteCount);
	buf = (struct reparse_data_buffer *)start;
	len = sizeof(*buf);
	if (data_count < len ||
	    data_count < le16_to_cpu(buf->ReparseDataLength) + len) {
		rc = -EIO;
		goto error;
	}

	*tag = le32_to_cpu(buf->ReparseTag);
	rsp->iov_base = io_rsp;
	rsp->iov_len = io_rsp_len;
	*rsp_buftype = CIFS_LARGE_BUFFER;
+17 −8
Original line number Diff line number Diff line
@@ -483,6 +483,7 @@ static int reconnect_target_unlocked(struct TCP_Server_Info *server, struct dfs_
static int reconnect_dfs_server(struct TCP_Server_Info *server)
{
	struct dfs_cache_tgt_iterator *target_hint = NULL;

	DFS_CACHE_TGT_LIST(tl);
	int num_targets = 0;
	int rc = 0;
@@ -745,6 +746,7 @@ cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
{
	struct msghdr smb_msg = {};
	struct kvec iov = {.iov_base = buf, .iov_len = to_read};

	iov_iter_kvec(&smb_msg.msg_iter, ITER_DEST, &iov, 1, to_read);

	return cifs_readv_from_socket(server, &smb_msg);
@@ -1400,11 +1402,13 @@ cifs_match_ipaddr(struct sockaddr *srcaddr, struct sockaddr *rhs)
	case AF_INET: {
		struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
		struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;

		return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
	}
	case AF_INET6: {
		struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
		struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;

		return (ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr)
			&& saddr6->sin6_scope_id == vaddr6->sin6_scope_id);
	}
@@ -2599,8 +2603,8 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
			rc = -EOPNOTSUPP;
			goto out_fail;
		} else {
			cifs_dbg(VFS, "Check vers= mount option. SMB3.11 "
				"disabled but required for POSIX extensions\n");
			cifs_dbg(VFS,
				"Check vers= mount option. SMB3.11 disabled but required for POSIX extensions\n");
			rc = -EOPNOTSUPP;
			goto out_fail;
		}
@@ -2743,7 +2747,6 @@ cifs_put_tlink(struct tcon_link *tlink)
	if (!IS_ERR(tlink_tcon(tlink)))
		cifs_put_tcon(tlink_tcon(tlink));
	kfree(tlink);
	return;
}

static int
@@ -2884,6 +2887,7 @@ static inline void
cifs_reclassify_socket4(struct socket *sock)
{
	struct sock *sk = sock->sk;

	BUG_ON(!sock_allow_reclassification(sk));
	sock_lock_init_class_and_name(sk, "slock-AF_INET-CIFS",
		&cifs_slock_key[0], "sk_lock-AF_INET-CIFS", &cifs_key[0]);
@@ -2893,6 +2897,7 @@ static inline void
cifs_reclassify_socket6(struct socket *sock)
{
	struct sock *sk = sock->sk;

	BUG_ON(!sock_allow_reclassification(sk));
	sock_lock_init_class_and_name(sk, "slock-AF_INET6-CIFS",
		&cifs_slock_key[1], "sk_lock-AF_INET6-CIFS", &cifs_key[1]);
@@ -2927,15 +2932,18 @@ static int
bind_socket(struct TCP_Server_Info *server)
{
	int rc = 0;

	if (server->srcaddr.ss_family != AF_UNSPEC) {
		/* Bind to the specified local IP address */
		struct socket *socket = server->ssocket;

		rc = kernel_bind(socket,
				 (struct sockaddr *) &server->srcaddr,
				 sizeof(server->srcaddr));
		if (rc < 0) {
			struct sockaddr_in *saddr4;
			struct sockaddr_in6 *saddr6;

			saddr4 = (struct sockaddr_in *)&server->srcaddr;
			saddr6 = (struct sockaddr_in6 *)&server->srcaddr;
			if (saddr6->sin6_family == AF_INET6)
@@ -3165,6 +3173,7 @@ void reset_cifs_unix_caps(unsigned int xid, struct cifs_tcon *tcon,

	if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
		__u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);

		cifs_dbg(FYI, "unix caps which server supports %lld\n", cap);
		/*
		 * check for reconnect case in which we do not
@@ -3687,12 +3696,12 @@ CIFSTCon(const unsigned int xid, struct cifs_ses *ses,
	if (ses->server->sign)
		smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;

	if (ses->capabilities & CAP_STATUS32) {
	if (ses->capabilities & CAP_STATUS32)
		smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
	}
	if (ses->capabilities & CAP_DFS) {

	if (ses->capabilities & CAP_DFS)
		smb_buffer->Flags2 |= SMBFLG2_DFS;
	}

	if (ses->capabilities & CAP_UNICODE) {
		smb_buffer->Flags2 |= SMBFLG2_UNICODE;
		length =
Loading