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

Merge tag 'v6.14-rc3-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:

 - Fix for chmod regression

 - Two reparse point related fixes

 - One minor cleanup (for GCC 14 compiles)

 - Fix for SMB3.1.1 POSIX Extensions reporting incorrect file type

* tag 'v6.14-rc3-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: Treat unhandled directory name surrogate reparse points as mount directory nodes
  cifs: Throw -EOPNOTSUPP error on unsupported reparse point type from parse_reparse_point()
  smb311: failure to open files of length 1040 when mounting with SMB3.1.1 POSIX extensions
  smb: client, common: Avoid multiple -Wflex-array-member-not-at-end warnings
  smb: client: fix chmod(2) regression with ATTR_READONLY
parents bf0e5ed0 b587fd12
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -253,6 +253,7 @@ struct cifs_cred {
struct cifs_open_info_data {
	bool adjust_tz;
	bool reparse_point;
	bool contains_posix_file_info;
	struct {
		/* ioctl response buffer */
		struct {
@@ -2324,8 +2325,8 @@ struct smb2_compound_vars {
	struct kvec io_iov[SMB2_IOCTL_IOV_SIZE];
	struct kvec si_iov[SMB2_SET_INFO_IOV_SIZE];
	struct kvec close_iov;
	struct smb2_file_rename_info rename_info;
	struct smb2_file_link_info link_info;
	struct smb2_file_rename_info_hdr rename_info;
	struct smb2_file_link_info_hdr link_info;
	struct kvec ea_iov;
};

+15 −2
Original line number Diff line number Diff line
@@ -1215,6 +1215,19 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
			rc = server->ops->parse_reparse_point(cifs_sb,
							      full_path,
							      iov, data);
			/*
			 * If the reparse point was not handled but it is the
			 * name surrogate which points to directory, then treat
			 * is as a new mount point. Name surrogate reparse point
			 * represents another named entity in the system.
			 */
			if (rc == -EOPNOTSUPP &&
			    IS_REPARSE_TAG_NAME_SURROGATE(data->reparse.tag) &&
			    (le32_to_cpu(data->fi.Attributes) & ATTR_DIRECTORY)) {
				rc = 0;
				cifs_create_junction_fattr(fattr, sb);
				goto out;
			}
		}

		if (data->reparse.tag == IO_REPARSE_TAG_SYMLINK && !rc) {
@@ -1408,7 +1421,7 @@ int cifs_get_inode_info(struct inode **inode,
	struct cifs_fattr fattr = {};
	int rc;

	if (is_inode_cache_good(*inode)) {
	if (!data && is_inode_cache_good(*inode)) {
		cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
		return 0;
	}
@@ -1507,7 +1520,7 @@ int smb311_posix_get_inode_info(struct inode **inode,
	struct cifs_fattr fattr = {};
	int rc;

	if (is_inode_cache_good(*inode)) {
	if (!data && is_inode_cache_good(*inode)) {
		cifs_dbg(FYI, "No need to revalidate cached inode sizes\n");
		return 0;
	}
+2 −3
Original line number Diff line number Diff line
@@ -1088,13 +1088,12 @@ int parse_reparse_point(struct reparse_data_buffer *buf,
				 le32_to_cpu(buf->ReparseTag));
			return -EIO;
		}
		break;
		return 0;
	default:
		cifs_tcon_dbg(VFS | ONCE, "unhandled reparse tag: 0x%08x\n",
			      le32_to_cpu(buf->ReparseTag));
		break;
		return -EOPNOTSUPP;
	}
	return 0;
}

int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb,
+22 −6
Original line number Diff line number Diff line
@@ -99,14 +99,30 @@ static inline bool reparse_inode_match(struct inode *inode,

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

	ret = data->reparse_point || (attrs & ATTR_REPARSE);
	if (ret)
	if (data->contains_posix_file_info) {
		struct smb311_posix_qinfo *fi = &data->posix_fi;

		attrs = le32_to_cpu(fi->DosAttributes);
		if (data->reparse_point) {
			attrs |= ATTR_REPARSE;
			fi->DosAttributes = cpu_to_le32(attrs);
		}

	} else {
		struct smb2_file_all_info *fi = &data->fi;

		attrs = le32_to_cpu(fi->Attributes);
		if (data->reparse_point) {
			attrs |= ATTR_REPARSE;
			fi->Attributes = cpu_to_le32(attrs);
		}
	}

	ret = attrs & ATTR_REPARSE;

	return ret;
}

+4 −0
Original line number Diff line number Diff line
@@ -650,6 +650,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
		switch (cmds[i]) {
		case SMB2_OP_QUERY_INFO:
			idata = in_iov[i].iov_base;
			idata->contains_posix_file_info = false;
			if (rc == 0 && cfile && cfile->symlink_target) {
				idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
				if (!idata->symlink_target)
@@ -673,6 +674,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
			break;
		case SMB2_OP_POSIX_QUERY_INFO:
			idata = in_iov[i].iov_base;
			idata->contains_posix_file_info = true;
			if (rc == 0 && cfile && cfile->symlink_target) {
				idata->symlink_target = kstrdup(cfile->symlink_target, GFP_KERNEL);
				if (!idata->symlink_target)
@@ -770,6 +772,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
				idata = in_iov[i].iov_base;
				idata->reparse.io.iov = *iov;
				idata->reparse.io.buftype = resp_buftype[i + 1];
				idata->contains_posix_file_info = false; /* BB VERIFY */
				rbuf = reparse_buf_ptr(iov);
				if (IS_ERR(rbuf)) {
					rc = PTR_ERR(rbuf);
@@ -791,6 +794,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
		case SMB2_OP_QUERY_WSL_EA:
			if (!rc) {
				idata = in_iov[i].iov_base;
				idata->contains_posix_file_info = false;
				qi_rsp = rsp_iov[i + 1].iov_base;
				data[0] = (u8 *)qi_rsp + le16_to_cpu(qi_rsp->OutputBufferOffset);
				size[0] = le32_to_cpu(qi_rsp->OutputBufferLength);
Loading