Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 91962d0f authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag '5.3-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
 "Two fixes for stable, one that had dependency on earlier patch in this
  merge window and can now go in, and a perf improvement in SMB3 open"

* tag '5.3-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  cifs: update internal module number
  cifs: flush before set-info if we have writeable handles
  smb3: optimize open to not send query file internal info
  cifs: copy_file_range needs to strip setuid bits and update timestamps
  CIFS: fix deadlock in cached root handling
parents 8cf66504 2a957ace
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -1104,6 +1104,10 @@ ssize_t cifs_file_copychunk_range(unsigned int xid,
		goto out;
	}

	rc = -EOPNOTSUPP;
	if (!target_tcon->ses->server->ops->copychunk_range)
		goto out;

	/*
	 * Note: cifs case is easier than btrfs since server responsible for
	 * checks for proper open modes and file type and if it wants
@@ -1115,11 +1119,12 @@ ssize_t cifs_file_copychunk_range(unsigned int xid,
	/* should we flush first and last page first */
	truncate_inode_pages(&target_inode->i_data, 0);

	if (target_tcon->ses->server->ops->copychunk_range)
	rc = file_modified(dst_file);
	if (!rc)
		rc = target_tcon->ses->server->ops->copychunk_range(xid,
			smb_file_src, smb_file_target, off, len, destoff);
	else
		rc = -EOPNOTSUPP;

	file_accessed(src_file);

	/* force revalidate of size and timestamps of target file now
	 * that target is updated on the server
+1 −1
Original line number Diff line number Diff line
@@ -152,5 +152,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
extern const struct export_operations cifs_export_ops;
#endif /* CONFIG_CIFS_NFSD_EXPORT */

#define CIFS_VERSION   "2.20"
#define CIFS_VERSION   "2.21"
#endif				/* _CIFSFS_H */
+16 −0
Original line number Diff line number Diff line
@@ -2406,6 +2406,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
	struct inode *inode = d_inode(direntry);
	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
	struct cifsInodeInfo *cifsInode = CIFS_I(inode);
	struct cifsFileInfo *wfile;
	struct cifs_tcon *tcon;
	char *full_path = NULL;
	int rc = -EACCES;
	__u32 dosattr = 0;
@@ -2452,6 +2454,20 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
	mapping_set_error(inode->i_mapping, rc);
	rc = 0;

	if (attrs->ia_valid & ATTR_MTIME) {
		rc = cifs_get_writable_file(cifsInode, false, &wfile);
		if (!rc) {
			tcon = tlink_tcon(wfile->tlink);
			rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid);
			cifsFileInfo_put(wfile);
			if (rc)
				return rc;
		} else if (rc != -EBADF)
			return rc;
		else
			rc = 0;
	}

	if (attrs->ia_valid & ATTR_SIZE) {
		rc = cifs_set_file_size(inode, attrs, xid, full_path);
		if (rc != 0)
+12 −6
Original line number Diff line number Diff line
@@ -88,15 +88,21 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
	}

	if (buf) {
		/* open response does not have IndexNumber field - get it */
		rc = SMB2_get_srv_num(xid, oparms->tcon, fid->persistent_fid,
		/* if open response does not have IndexNumber field - get it */
		if (smb2_data->IndexNumber == 0) {
			rc = SMB2_get_srv_num(xid, oparms->tcon,
				      fid->persistent_fid,
				      fid->volatile_fid,
				      &smb2_data->IndexNumber);
			if (rc) {
			/* let get_inode_info disable server inode numbers */
				/*
				 * let get_inode_info disable server inode
				 * numbers
				 */
				smb2_data->IndexNumber = 0;
				rc = 0;
			}
		}
		move_smb2_info_to_cifs(buf, smb2_data);
	}

+49 −4
Original line number Diff line number Diff line
@@ -694,8 +694,51 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid)

	smb2_set_related(&rqst[1]);

	/*
	 * We do not hold the lock for the open because in case
	 * SMB2_open needs to reconnect, it will end up calling
	 * cifs_mark_open_files_invalid() which takes the lock again
	 * thus causing a deadlock
	 */

	mutex_unlock(&tcon->crfid.fid_mutex);
	rc = compound_send_recv(xid, ses, flags, 2, rqst,
				resp_buftype, rsp_iov);
	mutex_lock(&tcon->crfid.fid_mutex);

	/*
	 * Now we need to check again as the cached root might have
	 * been successfully re-opened from a concurrent process
	 */

	if (tcon->crfid.is_valid) {
		/* work was already done */

		/* stash fids for close() later */
		struct cifs_fid fid = {
			.persistent_fid = pfid->persistent_fid,
			.volatile_fid = pfid->volatile_fid,
		};

		/*
		 * caller expects this func to set pfid to a valid
		 * cached root, so we copy the existing one and get a
		 * reference.
		 */
		memcpy(pfid, tcon->crfid.fid, sizeof(*pfid));
		kref_get(&tcon->crfid.refcount);

		mutex_unlock(&tcon->crfid.fid_mutex);

		if (rc == 0) {
			/* close extra handle outside of crit sec */
			SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
		}
		goto oshr_free;
	}

	/* Cached root is still invalid, continue normaly */

	if (rc)
		goto oshr_exit;

@@ -711,11 +754,12 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid)
	tcon->crfid.is_valid = true;
	kref_init(&tcon->crfid.refcount);

	/* BB TBD check to see if oplock level check can be removed below */
	if (o_rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) {
		kref_get(&tcon->crfid.refcount);
		oplock = smb2_parse_lease_state(server, o_rsp,
		smb2_parse_contexts(server, o_rsp,
				&oparms.fid->epoch,
						oparms.fid->lease_key);
				oparms.fid->lease_key, &oplock, NULL);
	} else
		goto oshr_exit;

@@ -731,6 +775,7 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid)

oshr_exit:
	mutex_unlock(&tcon->crfid.fid_mutex);
oshr_free:
	SMB2_open_free(&rqst[0]);
	SMB2_query_info_free(&rqst[1]);
	free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
Loading