cifs: don't call cifs_new_fileinfo unless cifs_open succeeds
authorJeff Layton <jlayton@redhat.com>
Wed, 16 Jun 2010 17:40:17 +0000 (13:40 -0400)
committerJeff Layton <jlayton@redhat.com>
Wed, 16 Jun 2010 17:40:17 +0000 (13:40 -0400)
It's currently possible for cifs_open to fail after it has already
called cifs_new_fileinfo. In that situation, the new fileinfo will be
leaked as the caller doesn't call fput. That in turn leads to a busy
inodes after umount problem since the fileinfo holds an extra inode
reference now. Shuffle cifs_open around a bit so that it only calls
cifs_new_fileinfo if it's going to succeed.

Signed-off-by: Jeff Layton <jlayton@redhat.com>
Reviewed-and-Tested-by: Suresh Jayaraman <sjayaraman@suse.de>
fs/cifs/file.c

index 02a2df9cdd9cf611cec41b4fd9d7c88bac454b11..409e4f523e61e56aae0e1b892c2a9021ebe3728d 100644 (file)
@@ -268,17 +268,20 @@ int cifs_open(struct inode *inode, struct file *file)
                        /* no need for special case handling of setting mode
                           on read only files needed here */
 
+                       rc = cifs_posix_open_inode_helper(inode, file,
+                                       pCifsInode, oplock, netfid);
+                       if (rc != 0) {
+                               CIFSSMBClose(xid, tcon, netfid);
+                               goto out;
+                       }
+
                        pCifsFile = cifs_new_fileinfo(inode, netfid, file,
                                                        file->f_path.mnt,
                                                        oflags);
                        if (pCifsFile == NULL) {
                                CIFSSMBClose(xid, tcon, netfid);
                                rc = -ENOMEM;
-                               goto out;
                        }
-
-                       rc = cifs_posix_open_inode_helper(inode, file,
-                                       pCifsInode, oplock, netfid);
                        goto out;
                } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) {
                        if (tcon->ses->serverNOS)
@@ -359,6 +362,10 @@ int cifs_open(struct inode *inode, struct file *file)
                goto out;
        }
 
+       rc = cifs_open_inode_helper(inode, tcon, &oplock, buf, full_path, xid);
+       if (rc != 0)
+               goto out;
+
        pCifsFile = cifs_new_fileinfo(inode, netfid, file, file->f_path.mnt,
                                        file->f_flags);
        if (pCifsFile == NULL) {
@@ -366,8 +373,6 @@ int cifs_open(struct inode *inode, struct file *file)
                goto out;
        }
 
-       rc = cifs_open_inode_helper(inode, tcon, &oplock, buf, full_path, xid);
-
        if (oplock & CIFS_CREATE_ACTION) {
                /* time to set mode which we can not set earlier due to
                   problems creating new read-only files */