forked from Minki/linux
Eighsmall SMB3 fixes, 4 for stable
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAl2gzCMACgkQiiy9cAdy T1F5aAv+M5OLmFX6OOuCQNYWqku8N9K78C3+bvdpDINYceozhPgKX1/+RO3z8rcR v+cK0b+R6tXVmpTbyo1t7QW3UVzHiJLEaGKjafbHNBjOM87wYkW7D9Uc6u6GSYDp 7cgXqmMDM+26FftBwxaxLjbjY6YAN/3V66j5Zt6I+lTb+8YC2DO1ihprwaMmGAm2 hDGYpvrW9KPjTB23+dC5Z9/YfG6EGXOvXl4z20JajCVoKD/70KdpDwVLNo2JuPsL hsgV38xmUd7PtFXeFtStPjN9VpNOf4sp29xmWnjJVGaVx4hnhzcyiKmiW2o5VkKM 14PEUd/N26/+E6VXuY1eP6L8O9EwkZISNZUXWBI/zyyiVedBfSJVeSXTU4NyqB0g B7WMnWYbJ73AeOsq9iVrcribrRPDtAcyK5UKMWEkrYhB/BIylg1vWUhn6B5bPqv0 3Q9TR+pSmEifkAk3ZSu5CjKNEgpNj6lpFoIcmkdp3Gg/qzeWvcFUTJTnxZZbxSqP qtmZ3d8z =mXpP -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
c6ad7c3ce9
@ -169,19 +169,27 @@ 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) {
|
||||
/* 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 = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MAX),
|
||||
cpu_to_le16(SMB_TIME_MAX), 0);
|
||||
sb->s_time_max = ts.tv_sec;
|
||||
} else {
|
||||
/*
|
||||
* 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 = cifs_NTtimeToUnix(cpu_to_le64(S64_MAX));
|
||||
sb->s_time_max = ts.tv_sec;
|
||||
} else {
|
||||
ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MIN), 0, 0);
|
||||
sb->s_time_min = ts.tv_sec;
|
||||
ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MAX), cpu_to_le16(SMB_TIME_MAX), 0);
|
||||
sb->s_time_max = ts.tv_sec;
|
||||
}
|
||||
|
||||
sb->s_magic = CIFS_MAGIC_NUMBER;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -414,6 +414,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
/* if uniqueid is different, return error */
|
||||
if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
|
||||
CIFS_I(*pinode)->uniqueid != fattr.cf_uniqueid)) {
|
||||
CIFS_I(*pinode)->time = 0; /* force reval */
|
||||
rc = -ESTALE;
|
||||
goto cgiiu_exit;
|
||||
}
|
||||
@ -421,6 +422,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
|
||||
/* if filetype is different, return error */
|
||||
if (unlikely(((*pinode)->i_mode & S_IFMT) !=
|
||||
(fattr.cf_mode & S_IFMT))) {
|
||||
CIFS_I(*pinode)->time = 0; /* force reval */
|
||||
rc = -ESTALE;
|
||||
goto cgiiu_exit;
|
||||
}
|
||||
@ -933,6 +935,7 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
|
||||
/* if uniqueid is different, return error */
|
||||
if (unlikely(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM &&
|
||||
CIFS_I(*inode)->uniqueid != fattr.cf_uniqueid)) {
|
||||
CIFS_I(*inode)->time = 0; /* force reval */
|
||||
rc = -ESTALE;
|
||||
goto cgii_exit;
|
||||
}
|
||||
@ -940,6 +943,7 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
|
||||
/* if filetype is different, return error */
|
||||
if (unlikely(((*inode)->i_mode & S_IFMT) !=
|
||||
(fattr.cf_mode & S_IFMT))) {
|
||||
CIFS_I(*inode)->time = 0; /* force reval */
|
||||
rc = -ESTALE;
|
||||
goto cgii_exit;
|
||||
}
|
||||
|
@ -117,10 +117,6 @@ static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
static const struct smb_to_posix_error mapping_table_ERRHRD[] = {
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
/*
|
||||
* Convert a string containing text IPv4 or IPv6 address to binary form.
|
||||
*
|
||||
|
@ -751,8 +751,8 @@ add_posix_context(struct kvec *iov, unsigned int *num_iovec, umode_t mode)
|
||||
unsigned int num = *num_iovec;
|
||||
|
||||
iov[num].iov_base = create_posix_buf(mode);
|
||||
if (mode == -1)
|
||||
cifs_dbg(VFS, "illegal mode\n"); /* BB REMOVEME */
|
||||
if (mode == ACL_NO_MODE)
|
||||
cifs_dbg(FYI, "illegal mode\n");
|
||||
if (iov[num].iov_base == NULL)
|
||||
return -ENOMEM;
|
||||
iov[num].iov_len = sizeof(struct create_posix);
|
||||
@ -2521,11 +2521,8 @@ SMB2_open_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, __u8 *oplock,
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* TODO: add handling for the mode on create */
|
||||
if (oparms->disposition == FILE_CREATE)
|
||||
cifs_dbg(VFS, "mode is 0x%x\n", oparms->mode); /* BB REMOVEME */
|
||||
|
||||
if ((oparms->disposition == FILE_CREATE) && (oparms->mode != -1)) {
|
||||
if ((oparms->disposition == FILE_CREATE) &&
|
||||
(oparms->mode != ACL_NO_MODE)) {
|
||||
if (n_iov > 2) {
|
||||
struct create_context *ccontext =
|
||||
(struct create_context *)iov[n_iov-1].iov_base;
|
||||
@ -3217,7 +3214,8 @@ SMB2_notify_init(const unsigned int xid, struct smb_rqst *rqst,
|
||||
|
||||
req->PersistentFileId = persistent_fid;
|
||||
req->VolatileFileId = volatile_fid;
|
||||
req->OutputBufferLength = SMB2_MAX_BUFFER_SIZE - MAX_SMB2_HDR_SIZE;
|
||||
req->OutputBufferLength =
|
||||
cpu_to_le32(SMB2_MAX_BUFFER_SIZE - MAX_SMB2_HDR_SIZE);
|
||||
req->CompletionFilter = cpu_to_le32(completion_filter);
|
||||
if (watch_tree)
|
||||
req->Flags = cpu_to_le16(SMB2_WATCH_TREE);
|
||||
|
@ -150,6 +150,10 @@ extern int SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst,
|
||||
bool is_fsctl, char *in_data, u32 indatalen,
|
||||
__u32 max_response_size);
|
||||
extern void SMB2_ioctl_free(struct smb_rqst *rqst);
|
||||
extern int SMB2_change_notify(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
u64 persistent_fid, u64 volatile_fid, bool watch_tree,
|
||||
u32 completion_filter);
|
||||
|
||||
extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
u64 persistent_file_id, u64 volatile_file_id);
|
||||
extern int SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
|
Loading…
Reference in New Issue
Block a user