[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: Steve French <sfrench@us.ibm.com>
Reviewed-by: Shirish Pargaonkar <shirishp@us.ibm.com>
Tested-by: Jeff Layton <jlayton@redhat.com>
Tested-by: Luca Tettamanti <kronos.it@gmail.com>
This commit is contained in:
Steve French 2009-05-21 22:21:53 +00:00
Родитель 5805977e63
Коммит 703a3b8e5c
2 изменённых файлов: 44 добавлений и 36 удалений

Просмотреть файл

@ -225,6 +225,7 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
if (!(oflags & FMODE_READ)) if (!(oflags & FMODE_READ))
write_only = true; write_only = true;
mode &= ~current_umask();
rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode, rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
pnetfid, presp_data, &oplock, full_path, pnetfid, presp_data, &oplock, full_path,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & 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; return -ENOMEM;
} }
mode &= ~current_umask();
if (oplockEnabled) if (oplockEnabled)
oplock = REQ_OPLOCK; oplock = REQ_OPLOCK;
@ -336,7 +336,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
else /* success, no need to query */ else /* success, no need to query */
goto cifs_create_set_dentry; goto cifs_create_set_dentry;
} else if ((rc != -EIO) && (rc != -EREMOTE) && } else if ((rc != -EIO) && (rc != -EREMOTE) &&
(rc != -EOPNOTSUPP)) /* path not found or net err */ (rc != -EOPNOTSUPP) && (rc != -EINVAL))
goto cifs_create_out; goto cifs_create_out;
/* else fallthrough to retry, using older open call, this is /* else fallthrough to retry, using older open call, this is
case where server does not support this SMB level, and 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 xid;
int rc = 0; /* to get around spurious gcc warning, set to zero here */ int rc = 0; /* to get around spurious gcc warning, set to zero here */
int oplock = 0; int oplock = 0;
int mode;
__u16 fileHandle = 0; __u16 fileHandle = 0;
bool posix_open = false; bool posix_open = false;
struct cifs_sb_info *cifs_sb; 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 (pTcon->unix_ext) {
if (!(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) && 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) && if (!((nd->intent.open.flags & O_CREAT) &&
(nd->intent.open.flags & O_EXCL))) { (nd->intent.open.flags & O_EXCL))) {
mode = nd->intent.open.create_mode &
~current_umask();
rc = cifs_posix_open(full_path, &newInode, 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, nd->intent.open.flags, &oplock,
&fileHandle, xid); &fileHandle, xid);
/* /*
@ -681,6 +679,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
*/ */
if ((rc != -EINVAL) && (rc != -EOPNOTSUPP)) if ((rc != -EINVAL) && (rc != -EOPNOTSUPP))
posix_open = true; posix_open = true;
else
pTcon->broken_posix_open = true;
} }
} }
if (!posix_open) 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) 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); write_lock(&GlobalSMBSeslock);
pCifsInode = CIFS_I(file->f_path.dentry->d_inode); pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
@ -184,6 +180,38 @@ psx_client_can_cache:
return 0; 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 */ /* 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, static inline int cifs_open_inode_helper(struct inode *inode, struct file *file,
struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile, struct cifsInodeInfo *pCifsInode, struct cifsFileInfo *pCifsFile,
@ -258,7 +286,6 @@ int cifs_open(struct inode *inode, struct file *file)
struct cifsTconInfo *tcon; struct cifsTconInfo *tcon;
struct cifsFileInfo *pCifsFile; struct cifsFileInfo *pCifsFile;
struct cifsInodeInfo *pCifsInode; struct cifsInodeInfo *pCifsInode;
struct list_head *tmp;
char *full_path = NULL; char *full_path = NULL;
int desiredAccess; int desiredAccess;
int disposition; int disposition;
@ -270,32 +297,12 @@ int cifs_open(struct inode *inode, struct file *file)
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
tcon = cifs_sb->tcon; tcon = cifs_sb->tcon;
/* search inode for this file and fill in file->private_data */
pCifsInode = CIFS_I(file->f_path.dentry->d_inode); pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
read_lock(&GlobalSMBSeslock); pCifsFile = cifs_fill_filedata(file);
list_for_each(tmp, &pCifsInode->openFileList) { if (pCifsFile) {
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;
FreeXid(xid); FreeXid(xid);
return rc; return 0;
} else if ((file->f_flags & O_CREAT) && (file->f_flags & O_EXCL)) }
cERROR(1, ("could not find file instance for "
"new file %p", file));
full_path = build_path_from_dentry(file->f_path.dentry); full_path = build_path_from_dentry(file->f_path.dentry);
if (full_path == NULL) { 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 /* no need for special case handling of setting mode
on read only files needed here */ on read only files needed here */
pCifsFile = cifs_fill_filedata(file);
cifs_posix_open_inode_helper(inode, file, pCifsInode, cifs_posix_open_inode_helper(inode, file, pCifsInode,
pCifsFile, oplock, netfid); pCifsFile, oplock, netfid);
goto out; goto out;