9p: Fix possible inode leak in v9fs_get_inode.
Abhishek Kulkarni [Sun, 19 Jul 2009 19:41:56 +0000 (13:41 -0600)]
Add a missing iput when cleaning up if v9fs_get_inode
fails after returning a valid inode.

Signed-off-by: Abhishek Kulkarni <adkulkar@umail.iu.edu>
Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>

fs/9p/vfs_inode.c

index 1fa5f15..0c8af1a 100644 (file)
@@ -207,65 +207,72 @@ v9fs_blank_wstat(struct p9_wstat *wstat)
 
 struct inode *v9fs_get_inode(struct super_block *sb, int mode)
 {
+       int err;
        struct inode *inode;
        struct v9fs_session_info *v9ses = sb->s_fs_info;
 
        P9_DPRINTK(P9_DEBUG_VFS, "super block: %p mode: %o\n", sb, mode);
 
        inode = new_inode(sb);
-       if (inode) {
-               inode->i_mode = mode;
-               inode->i_uid = current_fsuid();
-               inode->i_gid = current_fsgid();
-               inode->i_blocks = 0;
-               inode->i_rdev = 0;
-               inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-               inode->i_mapping->a_ops = &v9fs_addr_operations;
-
-               switch (mode & S_IFMT) {
-               case S_IFIFO:
-               case S_IFBLK:
-               case S_IFCHR:
-               case S_IFSOCK:
-                       if (!v9fs_extended(v9ses)) {
-                               P9_DPRINTK(P9_DEBUG_ERROR,
-                                     "special files without extended mode\n");
-                               return ERR_PTR(-EINVAL);
-                       }
-                       init_special_inode(inode, inode->i_mode,
-                                          inode->i_rdev);
-                       break;
-               case S_IFREG:
-                       inode->i_op = &v9fs_file_inode_operations;
-                       inode->i_fop = &v9fs_file_operations;
-                       break;
-               case S_IFLNK:
-                       if (!v9fs_extended(v9ses)) {
-                               P9_DPRINTK(P9_DEBUG_ERROR,
-                                       "extended modes used w/o 9P2000.u\n");
-                               return ERR_PTR(-EINVAL);
-                       }
-                       inode->i_op = &v9fs_symlink_inode_operations;
-                       break;
-               case S_IFDIR:
-                       inc_nlink(inode);
-                       if (v9fs_extended(v9ses))
-                               inode->i_op = &v9fs_dir_inode_operations_ext;
-                       else
-                               inode->i_op = &v9fs_dir_inode_operations;
-                       inode->i_fop = &v9fs_dir_operations;
-                       break;
-               default:
+       if (!inode) {
+               P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
+               return -ENOMEM;
+       }
+
+       inode->i_mode = mode;
+       inode->i_uid = current_fsuid();
+       inode->i_gid = current_fsgid();
+       inode->i_blocks = 0;
+       inode->i_rdev = 0;
+       inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+       inode->i_mapping->a_ops = &v9fs_addr_operations;
+
+       switch (mode & S_IFMT) {
+       case S_IFIFO:
+       case S_IFBLK:
+       case S_IFCHR:
+       case S_IFSOCK:
+               if (!v9fs_extended(v9ses)) {
                        P9_DPRINTK(P9_DEBUG_ERROR,
-                               "BAD mode 0x%x S_IFMT 0x%x\n",
-                               mode, mode & S_IFMT);
-                       return ERR_PTR(-EINVAL);
+                                  "special files without extended mode\n");
+                       err = -EINVAL;
+                       goto error;
                }
-       } else {
-               P9_EPRINTK(KERN_WARNING, "Problem allocating inode\n");
-               return ERR_PTR(-ENOMEM);
+               init_special_inode(inode, inode->i_mode, inode->i_rdev);
+               break;
+       case S_IFREG:
+               inode->i_op = &v9fs_file_inode_operations;
+               inode->i_fop = &v9fs_file_operations;
+               break;
+       case S_IFLNK:
+               if (!v9fs_extended(v9ses)) {
+                       P9_DPRINTK(P9_DEBUG_ERROR,
+                                  "extended modes used w/o 9P2000.u\n");
+                       err = -EINVAL;
+                       goto error;
+               }
+               inode->i_op = &v9fs_symlink_inode_operations;
+               break;
+       case S_IFDIR:
+               inc_nlink(inode);
+               if (v9fs_extended(v9ses))
+                       inode->i_op = &v9fs_dir_inode_operations_ext;
+               else
+                       inode->i_op = &v9fs_dir_inode_operations;
+               inode->i_fop = &v9fs_dir_operations;
+               break;
+       default:
+               P9_DPRINTK(P9_DEBUG_ERROR, "BAD mode 0x%x S_IFMT 0x%x\n",
+                          mode, mode & S_IFMT);
+               err = -EINVAL;
+               goto error;
        }
+
        return inode;
+
+error:
+       iput(inode);
+       return ERR_PTR(err);
 }
 
 /*