cifs: move cifs_new_fileinfo call out of cifs_posix_open
authorJeff Layton <jlayton@redhat.com>
Wed, 16 Jun 2010 17:40:16 +0000 (13:40 -0400)
committerJeff Layton <jlayton@redhat.com>
Wed, 16 Jun 2010 17:40:16 +0000 (13:40 -0400)
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: Jeff Layton <jlayton@redhat.com>
Reviewed-and-Tested-by: Suresh Jayaraman <sjayaraman@suse.de>
fs/cifs/cifsproto.h
fs/cifs/dir.c
fs/cifs/file.c

index fb1657e0fdb812d204b3a9309e3e245e3032e985..fb6318b81509801a218d8a2248542e427b9516ce 100644 (file)
@@ -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);
index 391816b461ca1872328cec6e9d3ec3abbd7502e0..f49afb9980e7c8b2159dc2d08198f210b7f15f4b 100644 (file)
@@ -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,19 +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;
-       }
-
 posix_open_ret:
        kfree(presp_data);
        return rc;
@@ -298,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
@@ -339,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
@@ -347,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 */
@@ -478,11 +461,7 @@ cifs_create_set_dentry:
        else
                cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
 
-       /* nfsd case - nfs srv does not set nd */
-       if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
-               /* mknod case - do not leave file open */
-               CIFSSMBClose(xid, tcon, fileHandle);
-       } else if (!(posix_create) && (newinode)) {
+       if (newinode && nd && (nd->flags & LOOKUP_OPEN)) {
                struct cifsFileInfo *pfile_info;
                /*
                 * cifs_fill_filedata() takes care of setting cifsFileInfo
@@ -492,7 +471,10 @@ cifs_create_set_dentry:
                                               nd->path.mnt, oflags);
                if (pfile_info == NULL)
                        rc = -ENOMEM;
+       } else {
+               CIFSSMBClose(xid, tcon, fileHandle);
        }
+
 cifs_create_out:
        kfree(buf);
        kfree(full_path);
@@ -636,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;
@@ -703,7 +686,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,
@@ -733,8 +716,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);
+                               rc = -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);
@@ -755,6 +747,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
                is a common return code */
        }
 
+lookup_out:
        kfree(full_path);
        FreeXid(xid);
        return ERR_PTR(rc);
index 75541af4b3db1395ecfab6fd318144b88b959fd8..542e0c874d6458d812409418cca57c95486f99dc 100644 (file)
@@ -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) {