Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 21 Jan 2011 15:33:37 +0000 (07:33 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 21 Jan 2011 15:33:37 +0000 (07:33 -0800)
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs-2.6:
  quota: Fix deadlock during path resolution

1  2 
fs/ext3/super.c
fs/ext4/super.c
fs/ocfs2/super.c

diff --combined fs/ext3/super.c
@@@ -364,7 -364,7 +364,7 @@@ static struct block_device *ext3_blkdev
        struct block_device *bdev;
        char b[BDEVNAME_SIZE];
  
 -      bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE);
 +      bdev = blkdev_get_by_dev(dev, FMODE_READ|FMODE_WRITE|FMODE_EXCL, sb);
        if (IS_ERR(bdev))
                goto fail;
        return bdev;
@@@ -381,7 -381,8 +381,7 @@@ fail
   */
  static int ext3_blkdev_put(struct block_device *bdev)
  {
 -      bd_release(bdev);
 -      return blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
 +      return blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
  }
  
  static int ext3_blkdev_remove(struct ext3_sb_info *sbi)
@@@ -754,7 -755,7 +754,7 @@@ static int ext3_release_dquot(struct dq
  static int ext3_mark_dquot_dirty(struct dquot *dquot);
  static int ext3_write_info(struct super_block *sb, int type);
  static int ext3_quota_on(struct super_block *sb, int type, int format_id,
-                               char *path);
+                        struct path *path);
  static int ext3_quota_on_mount(struct super_block *sb, int type);
  static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data,
                               size_t len, loff_t off);
@@@ -2161,6 -2162,13 +2161,6 @@@ static journal_t *ext3_get_dev_journal(
        if (bdev == NULL)
                return NULL;
  
 -      if (bd_claim(bdev, sb)) {
 -              ext3_msg(sb, KERN_ERR,
 -                      "error: failed to claim external journal device");
 -              blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
 -              return NULL;
 -      }
 -
        blocksize = sb->s_blocksize;
        hblock = bdev_logical_block_size(bdev);
        if (blocksize < hblock) {
@@@ -2877,27 -2885,20 +2877,20 @@@ static int ext3_quota_on_mount(struct s
   * Standard function to be called on quota_on
   */
  static int ext3_quota_on(struct super_block *sb, int type, int format_id,
-                        char *name)
+                        struct path *path)
  {
        int err;
-       struct path path;
  
        if (!test_opt(sb, QUOTA))
                return -EINVAL;
  
-       err = kern_path(name, LOOKUP_FOLLOW, &path);
-       if (err)
-               return err;
        /* Quotafile not on the same filesystem? */
-       if (path.mnt->mnt_sb != sb) {
-               path_put(&path);
+       if (path->mnt->mnt_sb != sb)
                return -EXDEV;
-       }
        /* Journaling quota? */
        if (EXT3_SB(sb)->s_qf_names[type]) {
                /* Quotafile not of fs root? */
-               if (path.dentry->d_parent != sb->s_root)
+               if (path->dentry->d_parent != sb->s_root)
                        ext3_msg(sb, KERN_WARNING,
                                "warning: Quota file not on filesystem root. "
                                "Journaled quota will not work.");
         * When we journal data on quota file, we have to flush journal to see
         * all updates to the file when we bypass pagecache...
         */
-       if (ext3_should_journal_data(path.dentry->d_inode)) {
+       if (ext3_should_journal_data(path->dentry->d_inode)) {
                /*
                 * We don't need to lock updates but journal_flush() could
                 * otherwise be livelocked...
                journal_lock_updates(EXT3_SB(sb)->s_journal);
                err = journal_flush(EXT3_SB(sb)->s_journal);
                journal_unlock_updates(EXT3_SB(sb)->s_journal);
-               if (err) {
-                       path_put(&path);
+               if (err)
                        return err;
-               }
        }
  
-       err = dquot_quota_on_path(sb, type, format_id, &path);
-       path_put(&path);
-       return err;
+       return dquot_quota_on(sb, type, format_id, path);
  }
  
  /* Read data from quotafile - avoid pagecache and such because we cannot afford
diff --combined fs/ext4/super.c
@@@ -657,7 -657,7 +657,7 @@@ static struct block_device *ext4_blkdev
        struct block_device *bdev;
        char b[BDEVNAME_SIZE];
  
 -      bdev = open_by_devnum(dev, FMODE_READ|FMODE_WRITE);
 +      bdev = blkdev_get_by_dev(dev, FMODE_READ|FMODE_WRITE|FMODE_EXCL, sb);
        if (IS_ERR(bdev))
                goto fail;
        return bdev;
@@@ -673,7 -673,8 +673,7 @@@ fail
   */
  static int ext4_blkdev_put(struct block_device *bdev)
  {
 -      bd_release(bdev);
 -      return blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
 +      return blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
  }
  
  static int ext4_blkdev_remove(struct ext4_sb_info *sbi)
@@@ -1161,7 -1162,7 +1161,7 @@@ static int ext4_release_dquot(struct dq
  static int ext4_mark_dquot_dirty(struct dquot *dquot);
  static int ext4_write_info(struct super_block *sb, int type);
  static int ext4_quota_on(struct super_block *sb, int type, int format_id,
-                               char *path);
+                        struct path *path);
  static int ext4_quota_off(struct super_block *sb, int type);
  static int ext4_quota_on_mount(struct super_block *sb, int type);
  static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
@@@ -3777,6 -3778,13 +3777,6 @@@ static journal_t *ext4_get_dev_journal(
        if (bdev == NULL)
                return NULL;
  
 -      if (bd_claim(bdev, sb)) {
 -              ext4_msg(sb, KERN_ERR,
 -                      "failed to claim external journal device");
 -              blkdev_put(bdev, FMODE_READ|FMODE_WRITE);
 -              return NULL;
 -      }
 -
        blocksize = sb->s_blocksize;
        hblock = bdev_logical_block_size(bdev);
        if (blocksize < hblock) {
@@@ -4558,27 -4566,20 +4558,20 @@@ static int ext4_quota_on_mount(struct s
   * Standard function to be called on quota_on
   */
  static int ext4_quota_on(struct super_block *sb, int type, int format_id,
-                        char *name)
+                        struct path *path)
  {
        int err;
-       struct path path;
  
        if (!test_opt(sb, QUOTA))
                return -EINVAL;
  
-       err = kern_path(name, LOOKUP_FOLLOW, &path);
-       if (err)
-               return err;
        /* Quotafile not on the same filesystem? */
-       if (path.mnt->mnt_sb != sb) {
-               path_put(&path);
+       if (path->mnt->mnt_sb != sb)
                return -EXDEV;
-       }
        /* Journaling quota? */
        if (EXT4_SB(sb)->s_qf_names[type]) {
                /* Quotafile not in fs root? */
-               if (path.dentry->d_parent != sb->s_root)
+               if (path->dentry->d_parent != sb->s_root)
                        ext4_msg(sb, KERN_WARNING,
                                "Quota file not on filesystem root. "
                                "Journaled quota will not work");
         * all updates to the file when we bypass pagecache...
         */
        if (EXT4_SB(sb)->s_journal &&
-           ext4_should_journal_data(path.dentry->d_inode)) {
+           ext4_should_journal_data(path->dentry->d_inode)) {
                /*
                 * We don't need to lock updates but journal_flush() could
                 * otherwise be livelocked...
                jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
                err = jbd2_journal_flush(EXT4_SB(sb)->s_journal);
                jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
-               if (err) {
-                       path_put(&path);
+               if (err)
                        return err;
-               }
        }
  
-       err = dquot_quota_on_path(sb, type, format_id, &path);
-       path_put(&path);
-       return err;
+       return dquot_quota_on(sb, type, format_id, path);
  }
  
  static int ext4_quota_off(struct super_block *sb, int type)
diff --combined fs/ocfs2/super.c
@@@ -993,8 -993,7 +993,7 @@@ static void ocfs2_disable_quotas(struc
  }
  
  /* Handle quota on quotactl */
- static int ocfs2_quota_on(struct super_block *sb, int type, int format_id,
-                         char *path)
+ static int ocfs2_quota_on(struct super_block *sb, int type, int format_id)
  {
        unsigned int feature[MAXQUOTAS] = { OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
                                             OCFS2_FEATURE_RO_COMPAT_GRPQUOTA};
@@@ -1013,7 -1012,7 +1012,7 @@@ static int ocfs2_quota_off(struct super
  }
  
  static const struct quotactl_ops ocfs2_quotactl_ops = {
-       .quota_on       = ocfs2_quota_on,
+       .quota_on_meta  = ocfs2_quota_on,
        .quota_off      = ocfs2_quota_off,
        .quota_sync     = dquot_quota_sync,
        .get_info       = dquot_get_dqinfo,
@@@ -2097,7 -2096,6 +2096,7 @@@ static int ocfs2_initialize_super(struc
  
        sb->s_fs_info = osb;
        sb->s_op = &ocfs2_sops;
 +      sb->s_d_op = &ocfs2_dentry_ops;
        sb->s_export_op = &ocfs2_export_ops;
        sb->s_qcop = &ocfs2_quotactl_ops;
        sb->dq_op = &ocfs2_quota_operations;