diff mbox

[3/4] cifs: move cifs_new_fileinfo call out of cifs_posix_open

Message ID 1274466317-28231-4-git-send-email-jlayton@redhat.com
State New
Headers show

Commit Message

Jeff Layton May 21, 2010, 6:25 p.m. UTC
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(-)

Comments

Suresh Jayaraman May 24, 2010, 6:50 a.m. UTC | #1
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) {
Jeff Layton May 24, 2010, 10:48 a.m. UTC | #2
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 mbox

Patch

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) {