Commit 2422f676 authored by Jeff Layton's avatar Jeff Layton

cifs: move cifs_new_fileinfo call out of cifs_posix_open

Having cifs_posix_open call cifs_new_fileinfo is problematic and
inconsistent with how "regular" opens work. It's also buggy as
cifs_reopen_file calls this function on a reconnect, which creates a new
struct cifsFileInfo that just gets leaked.

Push it out into the callers. This also allows us to get rid of the
"mnt" arg to cifs_posix_open.

Finally, in the event that a cifsFileInfo isn't or can't be created, we
always want to close the filehandle out on the server as the client
won't have a record of the filehandle and can't actually use it. Make
sure that CIFSSMBClose is called in those cases.
Signed-off-by: default avatarJeff Layton <jlayton@redhat.com>
Reviewed-and-Tested-by: default avatarSuresh Jayaraman <sjayaraman@suse.de>
parent 0933a95d
...@@ -106,7 +106,6 @@ extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode, ...@@ -106,7 +106,6 @@ extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode,
__u16 fileHandle, struct file *file, __u16 fileHandle, struct file *file,
struct vfsmount *mnt, unsigned int oflags); struct vfsmount *mnt, unsigned int oflags);
extern int cifs_posix_open(char *full_path, struct inode **pinode, extern int cifs_posix_open(char *full_path, struct inode **pinode,
struct vfsmount *mnt,
struct super_block *sb, struct super_block *sb,
int mode, int oflags, int mode, int oflags,
__u32 *poplock, __u16 *pnetfid, int xid); __u32 *poplock, __u16 *pnetfid, int xid);
......
...@@ -188,8 +188,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, ...@@ -188,8 +188,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle,
} }
int cifs_posix_open(char *full_path, struct inode **pinode, int cifs_posix_open(char *full_path, struct inode **pinode,
struct vfsmount *mnt, struct super_block *sb, struct super_block *sb, int mode, int oflags,
int mode, int oflags,
__u32 *poplock, __u16 *pnetfid, int xid) __u32 *poplock, __u16 *pnetfid, int xid)
{ {
int rc; int rc;
...@@ -258,19 +257,6 @@ int cifs_posix_open(char *full_path, struct inode **pinode, ...@@ -258,19 +257,6 @@ int cifs_posix_open(char *full_path, struct inode **pinode,
cifs_fattr_to_inode(*pinode, &fattr); cifs_fattr_to_inode(*pinode, &fattr);
} }
/*
* cifs_fill_filedata() takes care of setting cifsFileInfo pointer to
* file->private_data.
*/
if (mnt) {
struct cifsFileInfo *pfile_info;
pfile_info = cifs_new_fileinfo(*pinode, *pnetfid, NULL, mnt,
oflags);
if (pfile_info == NULL)
rc = -ENOMEM;
}
posix_open_ret: posix_open_ret:
kfree(presp_data); kfree(presp_data);
return rc; return rc;
...@@ -298,7 +284,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -298,7 +284,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
int create_options = CREATE_NOT_DIR; int create_options = CREATE_NOT_DIR;
__u32 oplock = 0; __u32 oplock = 0;
int oflags; int oflags;
bool posix_create = false;
/* /*
* BB below access is probably too much for mknod to request * BB below access is probably too much for mknod to request
* but we have to do query and setpathinfo so requesting * but we have to do query and setpathinfo so requesting
...@@ -339,7 +324,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -339,7 +324,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
(CIFS_UNIX_POSIX_PATH_OPS_CAP & (CIFS_UNIX_POSIX_PATH_OPS_CAP &
le64_to_cpu(tcon->fsUnixInfo.Capability))) { le64_to_cpu(tcon->fsUnixInfo.Capability))) {
rc = cifs_posix_open(full_path, &newinode, rc = cifs_posix_open(full_path, &newinode,
nd ? nd->path.mnt : NULL,
inode->i_sb, mode, oflags, &oplock, &fileHandle, xid); inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
/* EIO could indicate that (posix open) operation is not /* EIO could indicate that (posix open) operation is not
supported, despite what server claimed in capability supported, despite what server claimed in capability
...@@ -347,7 +331,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -347,7 +331,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
handled in posix open */ handled in posix open */
if (rc == 0) { if (rc == 0) {
posix_create = true;
if (newinode == NULL) /* query inode info */ if (newinode == NULL) /* query inode info */
goto cifs_create_get_file_info; goto cifs_create_get_file_info;
else /* success, no need to query */ else /* success, no need to query */
...@@ -478,11 +461,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -478,11 +461,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
else else
cFYI(1, "Create worked, get_inode_info failed rc = %d", rc); cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
/* nfsd case - nfs srv does not set nd */ if (newinode && nd && (nd->flags & LOOKUP_OPEN)) {
if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
/* mknod case - do not leave file open */
CIFSSMBClose(xid, tcon, fileHandle);
} else if (!(posix_create) && (newinode)) {
struct cifsFileInfo *pfile_info; struct cifsFileInfo *pfile_info;
/* /*
* cifs_fill_filedata() takes care of setting cifsFileInfo * cifs_fill_filedata() takes care of setting cifsFileInfo
...@@ -492,7 +471,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -492,7 +471,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
nd->path.mnt, oflags); nd->path.mnt, oflags);
if (pfile_info == NULL) if (pfile_info == NULL)
rc = -ENOMEM; rc = -ENOMEM;
} else {
CIFSSMBClose(xid, tcon, fileHandle);
} }
cifs_create_out: cifs_create_out:
kfree(buf); kfree(buf);
kfree(full_path); kfree(full_path);
...@@ -636,6 +618,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, ...@@ -636,6 +618,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
bool posix_open = false; bool posix_open = false;
struct cifs_sb_info *cifs_sb; struct cifs_sb_info *cifs_sb;
struct cifsTconInfo *pTcon; struct cifsTconInfo *pTcon;
struct cifsFileInfo *cfile;
struct inode *newInode = NULL; struct inode *newInode = NULL;
char *full_path = NULL; char *full_path = NULL;
struct file *filp; struct file *filp;
...@@ -703,7 +686,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, ...@@ -703,7 +686,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) && if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) &&
(nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
(nd->intent.open.flags & O_CREAT)) { (nd->intent.open.flags & O_CREAT)) {
rc = cifs_posix_open(full_path, &newInode, nd->path.mnt, rc = cifs_posix_open(full_path, &newInode,
parent_dir_inode->i_sb, parent_dir_inode->i_sb,
nd->intent.open.create_mode, nd->intent.open.create_mode,
nd->intent.open.flags, &oplock, nd->intent.open.flags, &oplock,
...@@ -733,8 +716,17 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, ...@@ -733,8 +716,17 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
else else
direntry->d_op = &cifs_dentry_ops; direntry->d_op = &cifs_dentry_ops;
d_add(direntry, newInode); d_add(direntry, newInode);
if (posix_open) if (posix_open) {
cfile = cifs_new_fileinfo(newInode, fileHandle, NULL,
nd->path.mnt,
nd->intent.open.flags);
if (cfile == NULL) {
CIFSSMBClose(xid, pTcon, fileHandle);
rc = -ENOMEM;
goto lookup_out;
}
filp = lookup_instantiate_filp(nd, direntry, NULL); filp = lookup_instantiate_filp(nd, direntry, NULL);
}
/* since paths are not looked up by component - the parent /* since paths are not looked up by component - the parent
directories are presumed to be good here */ directories are presumed to be good here */
renew_parental_timestamps(direntry); renew_parental_timestamps(direntry);
...@@ -755,6 +747,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, ...@@ -755,6 +747,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
is a common return code */ is a common return code */
} }
lookup_out:
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
return ERR_PTR(rc); return ERR_PTR(rc);
......
...@@ -299,8 +299,7 @@ int cifs_open(struct inode *inode, struct file *file) ...@@ -299,8 +299,7 @@ int cifs_open(struct inode *inode, struct file *file)
int oflags = (int) cifs_posix_convert_flags(file->f_flags); int oflags = (int) cifs_posix_convert_flags(file->f_flags);
oflags |= SMB_O_CREAT; oflags |= SMB_O_CREAT;
/* can not refresh inode info since size could be stale */ /* can not refresh inode info since size could be stale */
rc = cifs_posix_open(full_path, &inode, file->f_path.mnt, rc = cifs_posix_open(full_path, &inode, inode->i_sb,
inode->i_sb,
cifs_sb->mnt_file_mode /* ignored */, cifs_sb->mnt_file_mode /* ignored */,
oflags, &oplock, &netfid, xid); oflags, &oplock, &netfid, xid);
if (rc == 0) { if (rc == 0) {
...@@ -308,7 +307,16 @@ int cifs_open(struct inode *inode, struct file *file) ...@@ -308,7 +307,16 @@ 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); pCifsFile = cifs_new_fileinfo(inode, netfid, file,
file->f_path.mnt,
oflags);
if (pCifsFile == NULL) {
CIFSSMBClose(xid, tcon, netfid);
rc = -ENOMEM;
goto out;
}
file->private_data = pCifsFile;
cifs_posix_open_inode_helper(inode, file, pCifsInode, cifs_posix_open_inode_helper(inode, file, pCifsInode,
oplock, netfid); oplock, netfid);
goto out; goto out;
...@@ -513,8 +521,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush) ...@@ -513,8 +521,7 @@ static int cifs_reopen_file(struct file *file, bool can_flush)
le64_to_cpu(tcon->fsUnixInfo.Capability))) { le64_to_cpu(tcon->fsUnixInfo.Capability))) {
int oflags = (int) cifs_posix_convert_flags(file->f_flags); int oflags = (int) cifs_posix_convert_flags(file->f_flags);
/* can not refresh inode info since size could be stale */ /* can not refresh inode info since size could be stale */
rc = cifs_posix_open(full_path, NULL, file->f_path.mnt, rc = cifs_posix_open(full_path, NULL, inode->i_sb,
inode->i_sb,
cifs_sb->mnt_file_mode /* ignored */, cifs_sb->mnt_file_mode /* ignored */,
oflags, &oplock, &netfid, xid); oflags, &oplock, &netfid, xid);
if (rc == 0) { if (rc == 0) {
......
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