Commit 703a3b8e authored by Steve French's avatar Steve French

[CIFS] fix posix open regression

Posix open code was not properly adding the file to the
list of open files.  Fix  allocating cifsFileInfo
more than once, and adding twice to flist and tlist.
Also fix mode setting to be done in one place in these
paths.
Signed-off-by: default avatarSteve French <sfrench@us.ibm.com>
Reviewed-by: default avatarShirish Pargaonkar <shirishp@us.ibm.com>
Tested-by: default avatarJeff Layton <jlayton@redhat.com>
Tested-by: default avatarLuca Tettamanti <kronos.it@gmail.com>
parent 5805977e
......@@ -225,6 +225,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
if (!(oflags & FMODE_READ))
write_only = true;
mode &= ~current_umask();
rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
pnetfid, presp_data, &oplock, full_path,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
......@@ -310,7 +311,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
return -ENOMEM;
}
mode &= ~current_umask();
if (oplockEnabled)
oplock = REQ_OPLOCK;
......@@ -336,7 +336,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
else /* success, no need to query */
goto cifs_create_set_dentry;
} else if ((rc != -EIO) && (rc != -EREMOTE) &&
(rc != -EOPNOTSUPP)) /* path not found or net err */
(rc != -EOPNOTSUPP) && (rc != -EINVAL))
goto cifs_create_out;
/* else fallthrough to retry, using older open call, this is
case where server does not support this SMB level, and
......@@ -609,7 +609,6 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
int xid;
int rc = 0; /* to get around spurious gcc warning, set to zero here */
int oplock = 0;
int mode;
__u16 fileHandle = 0;
bool posix_open = false;
struct cifs_sb_info *cifs_sb;
......@@ -660,13 +659,12 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
if (pTcon->unix_ext) {
if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
(nd->flags & LOOKUP_OPEN)) {
(nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open) {
if (!((nd->intent.open.flags & O_CREAT) &&
(nd->intent.open.flags & O_EXCL))) {
mode = nd->intent.open.create_mode &
~current_umask();
rc = cifs_posix_open(full_path, &newInode,
parent_dir_inode->i_sb, mode,
parent_dir_inode->i_sb,
nd->intent.open.create_mode,
nd->intent.open.flags, &oplock,
&fileHandle, xid);
/*
......@@ -681,6 +679,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
*/
if ((rc != -EINVAL) && (rc != -EOPNOTSUPP))
posix_open = true;
else
pTcon->broken_posix_open = true;
}
}
if (!posix_open)
......
......@@ -130,10 +130,6 @@ static inline int cifs_posix_open_inode_helper(struct inode *inode,
struct cifsFileInfo *pCifsFile, int oplock, u16 netfid)
{
file->private_data = kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
if (file->private_data == NULL)
return -ENOMEM;
pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
write_lock(&GlobalSMBSeslock);
pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
......@@ -184,6 +180,38 @@ static inline int cifs_posix_open_inode_helper(struct inode *inode,
return 0;
}
static struct cifsFileInfo *
cifs_fill_filedata(struct file *file)
{
struct list_head *tmp;
struct cifsFileInfo *pCifsFile = NULL;
struct cifsInodeInfo *pCifsInode = NULL;
/* search inode for this file and fill in file->private_data */
pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &pCifsInode->openFileList) {
pCifsFile = list_entry(tmp, struct cifsFileInfo, flist);
if ((pCifsFile->pfile == NULL) &&
(pCifsFile->pid == current->tgid)) {
/* mode set in cifs_create */
/* needed for writepage */
pCifsFile->pfile = file;
file->private_data = pCifsFile;
break;
}
}
read_unlock(&GlobalSMBSeslock);
if (file->private_data != NULL) {
return pCifsFile;
} else if ((file->f_flags & O_CREAT) && (file->f_flags & O_EXCL))
cERROR(1, ("could not find file instance for "
"new file %p", file));
return NULL;
}
/* all arguments to this function must be checked for validity in caller */
static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile,
......@@ -258,7 +286,6 @@ int cifs_open(struct inode *inode, struct file *file)
struct cifsTconInfo *tcon;
struct cifsFileInfo *pCifsFile;
struct cifsInodeInfo *pCifsInode;
struct list_head *tmp;
char *full_path = NULL;
int desiredAccess;
int disposition;
......@@ -270,32 +297,12 @@ int cifs_open(struct inode *inode, struct file *file)
cifs_sb = CIFS_SB(inode->i_sb);
tcon = cifs_sb->tcon;
/* search inode for this file and fill in file->private_data */
pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
read_lock(&GlobalSMBSeslock);
list_for_each(tmp, &pCifsInode->openFileList) {
pCifsFile = list_entry(tmp, struct cifsFileInfo,
flist);
if ((pCifsFile->pfile == NULL) &&
(pCifsFile->pid == current->tgid)) {
/* mode set in cifs_create */
/* needed for writepage */
pCifsFile->pfile = file;
file->private_data = pCifsFile;
break;
}
}
read_unlock(&GlobalSMBSeslock);
if (file->private_data != NULL) {
rc = 0;
pCifsFile = cifs_fill_filedata(file);
if (pCifsFile) {
FreeXid(xid);
return rc;
} else if ((file->f_flags & O_CREAT) && (file->f_flags & O_EXCL))
cERROR(1, ("could not find file instance for "
"new file %p", file));
return 0;
}
full_path = build_path_from_dentry(file->f_path.dentry);
if (full_path == NULL) {
......@@ -325,6 +332,7 @@ int cifs_open(struct inode *inode, struct file *file)
/* no need for special case handling of setting mode
on read only files needed here */
pCifsFile = cifs_fill_filedata(file);
cifs_posix_open_inode_helper(inode, file, pCifsInode,
pCifsFile, oplock, netfid);
goto out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment