Message ID | 1274466317-28231-4-git-send-email-jlayton@redhat.com |
---|---|
State | New |
Headers | show |
On 05/21/2010 11:55 PM, Jeff Layton wrote: > 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 > fileinfo struct 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. > > Signed-off-by: Jeff Layton <jlayton@redhat.com> > --- > fs/cifs/cifsproto.h | 1 - > fs/cifs/dir.c | 38 +++++++++++++++----------------------- > fs/cifs/file.c | 17 ++++++++++++----- > 3 files changed, 27 insertions(+), 29 deletions(-) > > diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h > index fb1657e..fb6318b 100644 > --- a/fs/cifs/cifsproto.h > +++ b/fs/cifs/cifsproto.h > @@ -106,7 +106,6 @@ extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode, > __u16 fileHandle, struct file *file, > struct vfsmount *mnt, unsigned int oflags); > extern int cifs_posix_open(char *full_path, struct inode **pinode, > - struct vfsmount *mnt, > struct super_block *sb, > int mode, int oflags, > __u32 *poplock, __u16 *pnetfid, int xid); > diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c > index e11ee2e..fc3129b 100644 > --- a/fs/cifs/dir.c > +++ b/fs/cifs/dir.c > @@ -188,8 +188,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, > } > > int cifs_posix_open(char *full_path, struct inode **pinode, > - struct vfsmount *mnt, struct super_block *sb, > - int mode, int oflags, > + struct super_block *sb, int mode, int oflags, > __u32 *poplock, __u16 *pnetfid, int xid) > { > int rc; > @@ -258,21 +257,6 @@ int cifs_posix_open(char *full_path, struct inode **pinode, > 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; > - } else { > - CIFSSMBClose(xid, cifs_sb->tcon, *pnetfid); > - } > - > posix_open_ret: > kfree(presp_data); > return rc; > @@ -300,7 +284,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, > int create_options = CREATE_NOT_DIR; > __u32 oplock = 0; > int oflags; > - bool posix_create = false; > /* > * BB below access is probably too much for mknod to request > * but we have to do query and setpathinfo so requesting > @@ -341,7 +324,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, > (CIFS_UNIX_POSIX_PATH_OPS_CAP & > le64_to_cpu(tcon->fsUnixInfo.Capability))) { > rc = cifs_posix_open(full_path, &newinode, > - nd ? nd->path.mnt : NULL, > inode->i_sb, mode, oflags, &oplock, &fileHandle, xid); > /* EIO could indicate that (posix open) operation is not > supported, despite what server claimed in capability > @@ -349,7 +331,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, > handled in posix open */ > > if (rc == 0) { > - posix_create = true; > if (newinode == NULL) /* query inode info */ > goto cifs_create_get_file_info; > else /* success, no need to query */ > @@ -480,7 +461,7 @@ cifs_create_set_dentry: > else > cFYI(1, "Create worked, get_inode_info failed rc = %d", rc); > > - if (!posix_create && newinode) { > + if (newinode) { > struct cifsFileInfo *pfile_info; > /* > * cifs_fill_filedata() takes care of setting cifsFileInfo > @@ -637,6 +618,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, > bool posix_open = false; > struct cifs_sb_info *cifs_sb; > struct cifsTconInfo *pTcon; > + struct cifsFileInfo *cfile; > struct inode *newInode = NULL; > char *full_path = NULL; > struct file *filp; > @@ -705,7 +687,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, > if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) && > (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && > (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, > nd->intent.open.create_mode, > nd->intent.open.flags, &oplock, > @@ -735,8 +717,17 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, > else > direntry->d_op = &cifs_dentry_ops; > 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); > + res = ERR_PTR(ENOMEM); Should be ERR_PTR(-ENOMEM)? If you are planning to drop patch [1/4], res goes undeclared. > + goto lookup_out; > + } > filp = lookup_instantiate_filp(nd, direntry, NULL); > + } > /* since paths are not looked up by component - the parent > directories are presumed to be good here */ > renew_parental_timestamps(direntry); > @@ -761,6 +752,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, > res = ERR_PTR(rc); > } > > +lookup_out: > kfree(full_path); > FreeXid(xid); > return res; > diff --git a/fs/cifs/file.c b/fs/cifs/file.c > index a83541e..001e916 100644 > --- a/fs/cifs/file.c > +++ b/fs/cifs/file.c > @@ -299,8 +299,7 @@ int cifs_open(struct inode *inode, struct file *file) > int oflags = (int) cifs_posix_convert_flags(file->f_flags); > oflags |= SMB_O_CREAT; > /* can not refresh inode info since size could be stale */ > - rc = cifs_posix_open(full_path, &inode, file->f_path.mnt, > - inode->i_sb, > + rc = cifs_posix_open(full_path, &inode, inode->i_sb, > cifs_sb->mnt_file_mode /* ignored */, > oflags, &oplock, &netfid, xid); > if (rc == 0) { > @@ -308,7 +307,16 @@ 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); > + 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, > oplock, netfid); > goto out; > @@ -513,8 +521,7 @@ reopen_error_exit: > le64_to_cpu(tcon->fsUnixInfo.Capability))) { > int oflags = (int) cifs_posix_convert_flags(file->f_flags); > /* can not refresh inode info since size could be stale */ > - rc = cifs_posix_open(full_path, NULL, file->f_path.mnt, > - inode->i_sb, > + rc = cifs_posix_open(full_path, NULL, inode->i_sb, > cifs_sb->mnt_file_mode /* ignored */, > oflags, &oplock, &netfid, xid); > if (rc == 0) {
On Mon, 24 May 2010 12:20:28 +0530 Suresh Jayaraman <sjayaraman@suse.de> wrote: > On 05/21/2010 11:55 PM, Jeff Layton wrote: > > 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 > > fileinfo struct 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. > > > > Signed-off-by: Jeff Layton <jlayton@redhat.com> > > --- > > fs/cifs/cifsproto.h | 1 - > > fs/cifs/dir.c | 38 +++++++++++++++----------------------- > > fs/cifs/file.c | 17 ++++++++++++----- > > 3 files changed, 27 insertions(+), 29 deletions(-) > > > > diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h > > index fb1657e..fb6318b 100644 > > --- a/fs/cifs/cifsproto.h > > +++ b/fs/cifs/cifsproto.h > > @@ -106,7 +106,6 @@ extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode, > > __u16 fileHandle, struct file *file, > > struct vfsmount *mnt, unsigned int oflags); > > extern int cifs_posix_open(char *full_path, struct inode **pinode, > > - struct vfsmount *mnt, > > struct super_block *sb, > > int mode, int oflags, > > __u32 *poplock, __u16 *pnetfid, int xid); > > diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c > > index e11ee2e..fc3129b 100644 > > --- a/fs/cifs/dir.c > > +++ b/fs/cifs/dir.c > > @@ -188,8 +188,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, > > } > > > > int cifs_posix_open(char *full_path, struct inode **pinode, > > - struct vfsmount *mnt, struct super_block *sb, > > - int mode, int oflags, > > + struct super_block *sb, int mode, int oflags, > > __u32 *poplock, __u16 *pnetfid, int xid) > > { > > int rc; > > @@ -258,21 +257,6 @@ int cifs_posix_open(char *full_path, struct inode **pinode, > > 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; > > - } else { > > - CIFSSMBClose(xid, cifs_sb->tcon, *pnetfid); > > - } > > - > > posix_open_ret: > > kfree(presp_data); > > return rc; > > @@ -300,7 +284,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, > > int create_options = CREATE_NOT_DIR; > > __u32 oplock = 0; > > int oflags; > > - bool posix_create = false; > > /* > > * BB below access is probably too much for mknod to request > > * but we have to do query and setpathinfo so requesting > > @@ -341,7 +324,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, > > (CIFS_UNIX_POSIX_PATH_OPS_CAP & > > le64_to_cpu(tcon->fsUnixInfo.Capability))) { > > rc = cifs_posix_open(full_path, &newinode, > > - nd ? nd->path.mnt : NULL, > > inode->i_sb, mode, oflags, &oplock, &fileHandle, xid); > > /* EIO could indicate that (posix open) operation is not > > supported, despite what server claimed in capability > > @@ -349,7 +331,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, > > handled in posix open */ > > > > if (rc == 0) { > > - posix_create = true; > > if (newinode == NULL) /* query inode info */ > > goto cifs_create_get_file_info; > > else /* success, no need to query */ > > @@ -480,7 +461,7 @@ cifs_create_set_dentry: > > else > > cFYI(1, "Create worked, get_inode_info failed rc = %d", rc); > > > > - if (!posix_create && newinode) { > > + if (newinode) { > > struct cifsFileInfo *pfile_info; > > /* > > * cifs_fill_filedata() takes care of setting cifsFileInfo > > @@ -637,6 +618,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, > > bool posix_open = false; > > struct cifs_sb_info *cifs_sb; > > struct cifsTconInfo *pTcon; > > + struct cifsFileInfo *cfile; > > struct inode *newInode = NULL; > > char *full_path = NULL; > > struct file *filp; > > @@ -705,7 +687,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, > > if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) && > > (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && > > (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, > > nd->intent.open.create_mode, > > nd->intent.open.flags, &oplock, > > @@ -735,8 +717,17 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, > > else > > direntry->d_op = &cifs_dentry_ops; > > 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); > > + res = ERR_PTR(ENOMEM); > > Should be ERR_PTR(-ENOMEM)? > > If you are planning to drop patch [1/4], res goes undeclared. > Good catch, will fix in next set. > > + goto lookup_out; > > + } > > filp = lookup_instantiate_filp(nd, direntry, NULL); > > + } > > /* since paths are not looked up by component - the parent > > directories are presumed to be good here */ > > renew_parental_timestamps(direntry); > > @@ -761,6 +752,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, > > res = ERR_PTR(rc); > > } > > > > +lookup_out: > > kfree(full_path); > > FreeXid(xid); > > return res; > > diff --git a/fs/cifs/file.c b/fs/cifs/file.c > > index a83541e..001e916 100644 > > --- a/fs/cifs/file.c > > +++ b/fs/cifs/file.c > > @@ -299,8 +299,7 @@ int cifs_open(struct inode *inode, struct file *file) > > int oflags = (int) cifs_posix_convert_flags(file->f_flags); > > oflags |= SMB_O_CREAT; > > /* can not refresh inode info since size could be stale */ > > - rc = cifs_posix_open(full_path, &inode, file->f_path.mnt, > > - inode->i_sb, > > + rc = cifs_posix_open(full_path, &inode, inode->i_sb, > > cifs_sb->mnt_file_mode /* ignored */, > > oflags, &oplock, &netfid, xid); > > if (rc == 0) { > > @@ -308,7 +307,16 @@ 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); > > + 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, > > oplock, netfid); > > goto out; > > @@ -513,8 +521,7 @@ reopen_error_exit: > > le64_to_cpu(tcon->fsUnixInfo.Capability))) { > > int oflags = (int) cifs_posix_convert_flags(file->f_flags); > > /* can not refresh inode info since size could be stale */ > > - rc = cifs_posix_open(full_path, NULL, file->f_path.mnt, > > - inode->i_sb, > > + rc = cifs_posix_open(full_path, NULL, inode->i_sb, > > cifs_sb->mnt_file_mode /* ignored */, > > oflags, &oplock, &netfid, xid); > > if (rc == 0) { > >
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index fb1657e..fb6318b 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -106,7 +106,6 @@ extern struct cifsFileInfo *cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, struct file *file, struct vfsmount *mnt, unsigned int oflags); extern int cifs_posix_open(char *full_path, struct inode **pinode, - struct vfsmount *mnt, struct super_block *sb, int mode, int oflags, __u32 *poplock, __u16 *pnetfid, int xid); diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index e11ee2e..fc3129b 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -188,8 +188,7 @@ cifs_new_fileinfo(struct inode *newinode, __u16 fileHandle, } int cifs_posix_open(char *full_path, struct inode **pinode, - struct vfsmount *mnt, struct super_block *sb, - int mode, int oflags, + struct super_block *sb, int mode, int oflags, __u32 *poplock, __u16 *pnetfid, int xid) { int rc; @@ -258,21 +257,6 @@ int cifs_posix_open(char *full_path, struct inode **pinode, 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; - } else { - CIFSSMBClose(xid, cifs_sb->tcon, *pnetfid); - } - posix_open_ret: kfree(presp_data); return rc; @@ -300,7 +284,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, int create_options = CREATE_NOT_DIR; __u32 oplock = 0; int oflags; - bool posix_create = false; /* * BB below access is probably too much for mknod to request * but we have to do query and setpathinfo so requesting @@ -341,7 +324,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, (CIFS_UNIX_POSIX_PATH_OPS_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability))) { rc = cifs_posix_open(full_path, &newinode, - nd ? nd->path.mnt : NULL, inode->i_sb, mode, oflags, &oplock, &fileHandle, xid); /* EIO could indicate that (posix open) operation is not supported, despite what server claimed in capability @@ -349,7 +331,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, handled in posix open */ if (rc == 0) { - posix_create = true; if (newinode == NULL) /* query inode info */ goto cifs_create_get_file_info; else /* success, no need to query */ @@ -480,7 +461,7 @@ cifs_create_set_dentry: else cFYI(1, "Create worked, get_inode_info failed rc = %d", rc); - if (!posix_create && newinode) { + if (newinode) { struct cifsFileInfo *pfile_info; /* * cifs_fill_filedata() takes care of setting cifsFileInfo @@ -637,6 +618,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, bool posix_open = false; struct cifs_sb_info *cifs_sb; struct cifsTconInfo *pTcon; + struct cifsFileInfo *cfile; struct inode *newInode = NULL; char *full_path = NULL; struct file *filp; @@ -705,7 +687,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) && (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && (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, nd->intent.open.create_mode, nd->intent.open.flags, &oplock, @@ -735,8 +717,17 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, else direntry->d_op = &cifs_dentry_ops; 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); + res = ERR_PTR(ENOMEM); + goto lookup_out; + } filp = lookup_instantiate_filp(nd, direntry, NULL); + } /* since paths are not looked up by component - the parent directories are presumed to be good here */ renew_parental_timestamps(direntry); @@ -761,6 +752,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, res = ERR_PTR(rc); } +lookup_out: kfree(full_path); FreeXid(xid); return res; diff --git a/fs/cifs/file.c b/fs/cifs/file.c index a83541e..001e916 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -299,8 +299,7 @@ int cifs_open(struct inode *inode, struct file *file) int oflags = (int) cifs_posix_convert_flags(file->f_flags); oflags |= SMB_O_CREAT; /* can not refresh inode info since size could be stale */ - rc = cifs_posix_open(full_path, &inode, file->f_path.mnt, - inode->i_sb, + rc = cifs_posix_open(full_path, &inode, inode->i_sb, cifs_sb->mnt_file_mode /* ignored */, oflags, &oplock, &netfid, xid); if (rc == 0) { @@ -308,7 +307,16 @@ 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); + 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, oplock, netfid); goto out; @@ -513,8 +521,7 @@ reopen_error_exit: le64_to_cpu(tcon->fsUnixInfo.Capability))) { int oflags = (int) cifs_posix_convert_flags(file->f_flags); /* can not refresh inode info since size could be stale */ - rc = cifs_posix_open(full_path, NULL, file->f_path.mnt, - inode->i_sb, + rc = cifs_posix_open(full_path, NULL, inode->i_sb, cifs_sb->mnt_file_mode /* ignored */, oflags, &oplock, &netfid, xid); if (rc == 0) {
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 fileinfo struct 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. Signed-off-by: Jeff Layton <jlayton@redhat.com> --- fs/cifs/cifsproto.h | 1 - fs/cifs/dir.c | 38 +++++++++++++++----------------------- fs/cifs/file.c | 17 ++++++++++++----- 3 files changed, 27 insertions(+), 29 deletions(-)