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

Merge tag '5.4-rc2-smb3' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
 "Eight small SMB3 fixes, four for stable, and important fix for the
  recent regression introduced by filesystem timestamp range patches"

* tag '5.4-rc2-smb3' of git://git.samba.org/sfrench/cifs-2.6:
  CIFS: Force reval dentry if LOOKUP_REVAL flag is set
  CIFS: Force revalidate inode when dentry is stale
  smb3: Fix regression in time handling
  smb3: remove noisy debug message and minor cleanup
  CIFS: Gracefully handle QueryInfo errors during open
  cifs: use cifsInodeInfo->open_file_lock while iterating to avoid a panic
  fs: cifs: mute -Wunused-const-variable message
  smb3: cleanup some recent endian errors spotted by updated sparse
parents c6f6ebd7 0b3d0ef9
Loading
Loading
Loading
Loading
+16 −8
Original line number Diff line number Diff line
@@ -169,18 +169,26 @@ cifs_read_super(struct super_block *sb)
	else
		sb->s_maxbytes = MAX_NON_LFS;

	/* BB FIXME fix time_gran to be larger for LANMAN sessions */
	sb->s_time_gran = 100;

	if (tcon->unix_ext) {
		ts = cifs_NTtimeToUnix(0);
	/* Some very old servers like DOS and OS/2 used 2 second granularity */
	if ((tcon->ses->server->vals->protocol_id == SMB10_PROT_ID) &&
	    ((tcon->ses->capabilities &
	      tcon->ses->server->vals->cap_nt_find) == 0) &&
	    !tcon->unix_ext) {
		sb->s_time_gran = 1000000000; /* 1 second is max allowed gran */
		ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MIN), 0, 0);
		sb->s_time_min = ts.tv_sec;
		ts = cifs_NTtimeToUnix(cpu_to_le64(S64_MAX));
		ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MAX),
				    cpu_to_le16(SMB_TIME_MAX), 0);
		sb->s_time_max = ts.tv_sec;
	} else {
		ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MIN), 0, 0);
		/*
		 * Almost every server, including all SMB2+, uses DCE TIME
		 * ie 100 nanosecond units, since 1601.  See MS-DTYP and MS-FSCC
		 */
		sb->s_time_gran = 100;
		ts = cifs_NTtimeToUnix(0);
		sb->s_time_min = ts.tv_sec;
		ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MAX), cpu_to_le16(SMB_TIME_MAX), 0);
		ts = cifs_NTtimeToUnix(cpu_to_le64(S64_MAX));
		sb->s_time_max = ts.tv_sec;
	}

+1 −1
Original line number Diff line number Diff line
@@ -1210,7 +1210,7 @@ struct cifs_search_info {
	bool smallBuf:1; /* so we know which buf_release function to call */
};

#define ACL_NO_MODE	-1
#define ACL_NO_MODE	((umode_t)(-1))
struct cifs_open_parms {
	struct cifs_tcon *tcon;
	struct cifs_sb_info *cifs_sb;
+2 −2
Original line number Diff line number Diff line
@@ -4264,7 +4264,7 @@ static int mount_get_conns(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
		server->ops->qfs_tcon(*xid, tcon);
		if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) {
			if (tcon->fsDevInfo.DeviceCharacteristics &
			    FILE_READ_ONLY_DEVICE)
			    cpu_to_le32(FILE_READ_ONLY_DEVICE))
				cifs_dbg(VFS, "mounted to read only share\n");
			else if ((cifs_sb->mnt_cifs_flags &
				  CIFS_MOUNT_RW_CACHE) == 0)
@@ -4445,7 +4445,7 @@ static int setup_dfs_tgt_conn(const char *path,
	int rc;
	struct dfs_info3_param ref = {0};
	char *mdata = NULL, *fake_devname = NULL;
	struct smb_vol fake_vol = {0};
	struct smb_vol fake_vol = {NULL};

	cifs_dbg(FYI, "%s: dfs path: %s\n", __func__, path);

+7 −1
Original line number Diff line number Diff line
@@ -738,10 +738,16 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
static int
cifs_d_revalidate(struct dentry *direntry, unsigned int flags)
{
	struct inode *inode;

	if (flags & LOOKUP_RCU)
		return -ECHILD;

	if (d_really_is_positive(direntry)) {
		inode = d_inode(direntry);
		if ((flags & LOOKUP_REVAL) && !CIFS_CACHE_READ(CIFS_I(inode)))
			CIFS_I(inode)->time = 0; /* force reval */

		if (cifs_revalidate_dentry(direntry))
			return 0;
		else {
@@ -752,7 +758,7 @@ cifs_d_revalidate(struct dentry *direntry, unsigned int flags)
			 * attributes will have been updated by
			 * cifs_revalidate_dentry().
			 */
			if (IS_AUTOMOUNT(d_inode(direntry)) &&
			if (IS_AUTOMOUNT(inode) &&
			   !(direntry->d_flags & DCACHE_NEED_AUTOMOUNT)) {
				spin_lock(&direntry->d_lock);
				direntry->d_flags |= DCACHE_NEED_AUTOMOUNT;
+17 −16
Original line number Diff line number Diff line
@@ -253,6 +253,12 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
		rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb,
					 xid, fid);

	if (rc) {
		server->ops->close(xid, tcon, fid);
		if (rc == -ESTALE)
			rc = -EOPENSTALE;
	}

out:
	kfree(buf);
	return rc;
@@ -1840,13 +1846,12 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
{
	struct cifsFileInfo *open_file = NULL;
	struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);

	/* only filter by fsuid on multiuser mounts */
	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
		fsuid_only = false;

	spin_lock(&tcon->open_file_lock);
	spin_lock(&cifs_inode->open_file_lock);
	/* we could simply get the first_list_entry since write-only entries
	   are always at the end of the list but since the first entry might
	   have a close pending, we go through the whole list */
@@ -1858,7 +1863,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
				/* found a good file */
				/* lock it so it will not be closed on us */
				cifsFileInfo_get(open_file);
				spin_unlock(&tcon->open_file_lock);
				spin_unlock(&cifs_inode->open_file_lock);
				return open_file;
			} /* else might as well continue, and look for
			     another, or simply have the caller reopen it
@@ -1866,7 +1871,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
		} else /* write only file */
			break; /* write only files are last so must be done */
	}
	spin_unlock(&tcon->open_file_lock);
	spin_unlock(&cifs_inode->open_file_lock);
	return NULL;
}

@@ -1877,7 +1882,6 @@ cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only,
{
	struct cifsFileInfo *open_file, *inv_file = NULL;
	struct cifs_sb_info *cifs_sb;
	struct cifs_tcon *tcon;
	bool any_available = false;
	int rc = -EBADF;
	unsigned int refind = 0;
@@ -1897,16 +1901,15 @@ cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only,
	}

	cifs_sb = CIFS_SB(cifs_inode->vfs_inode.i_sb);
	tcon = cifs_sb_master_tcon(cifs_sb);

	/* only filter by fsuid on multiuser mounts */
	if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER))
		fsuid_only = false;

	spin_lock(&tcon->open_file_lock);
	spin_lock(&cifs_inode->open_file_lock);
refind_writable:
	if (refind > MAX_REOPEN_ATT) {
		spin_unlock(&tcon->open_file_lock);
		spin_unlock(&cifs_inode->open_file_lock);
		return rc;
	}
	list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
@@ -1918,7 +1921,7 @@ refind_writable:
			if (!open_file->invalidHandle) {
				/* found a good writable file */
				cifsFileInfo_get(open_file);
				spin_unlock(&tcon->open_file_lock);
				spin_unlock(&cifs_inode->open_file_lock);
				*ret_file = open_file;
				return 0;
			} else {
@@ -1938,7 +1941,7 @@ refind_writable:
		cifsFileInfo_get(inv_file);
	}

	spin_unlock(&tcon->open_file_lock);
	spin_unlock(&cifs_inode->open_file_lock);

	if (inv_file) {
		rc = cifs_reopen_file(inv_file, false);
@@ -1953,7 +1956,7 @@ refind_writable:
		cifsFileInfo_put(inv_file);
		++refind;
		inv_file = NULL;
		spin_lock(&tcon->open_file_lock);
		spin_lock(&cifs_inode->open_file_lock);
		goto refind_writable;
	}

@@ -4461,17 +4464,15 @@ static int cifs_readpage(struct file *file, struct page *page)
static int is_inode_writable(struct cifsInodeInfo *cifs_inode)
{
	struct cifsFileInfo *open_file;
	struct cifs_tcon *tcon =
		cifs_sb_master_tcon(CIFS_SB(cifs_inode->vfs_inode.i_sb));

	spin_lock(&tcon->open_file_lock);
	spin_lock(&cifs_inode->open_file_lock);
	list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
		if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) {
			spin_unlock(&tcon->open_file_lock);
			spin_unlock(&cifs_inode->open_file_lock);
			return 1;
		}
	}
	spin_unlock(&tcon->open_file_lock);
	spin_unlock(&cifs_inode->open_file_lock);
	return 0;
}

Loading