aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2007-09-11 18:23:29 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-09-11 20:21:19 -0400
commit9c3013e9b91ad23ecae88e45405e98208cce455d (patch)
tree2f18bb2d539727e2d9228a3d02a2e8810aa2ac3d
parentaf7b83f9324a77ef9a9080044bf0461f444ca651 (diff)
quota: fix infinite loop
If we fail to start a transaction when releasing dquot, we have to call dquot_release() anyway to mark dquot structure as inactive. Otherwise we end in an infinite loop inside dqput(). Signed-off-by: Jan Kara <jack@suse.cz> Cc: xb <xavier.bru@bull.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/ext3/super.c11
-rw-r--r--fs/ext4/super.c11
-rw-r--r--fs/reiserfs/super.c13
3 files changed, 31 insertions, 4 deletions
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 22cfdd61c060..9537316a0714 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -2578,8 +2578,11 @@ static int ext3_release_dquot(struct dquot *dquot)
2578 2578
2579 handle = ext3_journal_start(dquot_to_inode(dquot), 2579 handle = ext3_journal_start(dquot_to_inode(dquot),
2580 EXT3_QUOTA_DEL_BLOCKS(dquot->dq_sb)); 2580 EXT3_QUOTA_DEL_BLOCKS(dquot->dq_sb));
2581 if (IS_ERR(handle)) 2581 if (IS_ERR(handle)) {
2582 /* Release dquot anyway to avoid endless cycle in dqput() */
2583 dquot_release(dquot);
2582 return PTR_ERR(handle); 2584 return PTR_ERR(handle);
2585 }
2583 ret = dquot_release(dquot); 2586 ret = dquot_release(dquot);
2584 err = ext3_journal_stop(handle); 2587 err = ext3_journal_stop(handle);
2585 if (!ret) 2588 if (!ret)
@@ -2712,6 +2715,12 @@ static ssize_t ext3_quota_write(struct super_block *sb, int type,
2712 struct buffer_head *bh; 2715 struct buffer_head *bh;
2713 handle_t *handle = journal_current_handle(); 2716 handle_t *handle = journal_current_handle();
2714 2717
2718 if (!handle) {
2719 printk(KERN_WARNING "EXT3-fs: Quota write (off=%Lu, len=%Lu)"
2720 " cancelled because transaction is not started.\n",
2721 (unsigned long long)off, (unsigned long long)len);
2722 return -EIO;
2723 }
2715 mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); 2724 mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
2716 while (towrite > 0) { 2725 while (towrite > 0) {
2717 tocopy = sb->s_blocksize - offset < towrite ? 2726 tocopy = sb->s_blocksize - offset < towrite ?
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 4550b83ab1c9..3c1397fa83df 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -2698,8 +2698,11 @@ static int ext4_release_dquot(struct dquot *dquot)
2698 2698
2699 handle = ext4_journal_start(dquot_to_inode(dquot), 2699 handle = ext4_journal_start(dquot_to_inode(dquot),
2700 EXT4_QUOTA_DEL_BLOCKS(dquot->dq_sb)); 2700 EXT4_QUOTA_DEL_BLOCKS(dquot->dq_sb));
2701 if (IS_ERR(handle)) 2701 if (IS_ERR(handle)) {
2702 /* Release dquot anyway to avoid endless cycle in dqput() */
2703 dquot_release(dquot);
2702 return PTR_ERR(handle); 2704 return PTR_ERR(handle);
2705 }
2703 ret = dquot_release(dquot); 2706 ret = dquot_release(dquot);
2704 err = ext4_journal_stop(handle); 2707 err = ext4_journal_stop(handle);
2705 if (!ret) 2708 if (!ret)
@@ -2832,6 +2835,12 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
2832 struct buffer_head *bh; 2835 struct buffer_head *bh;
2833 handle_t *handle = journal_current_handle(); 2836 handle_t *handle = journal_current_handle();
2834 2837
2838 if (!handle) {
2839 printk(KERN_WARNING "EXT4-fs: Quota write (off=%Lu, len=%Lu)"
2840 " cancelled because transaction is not started.\n",
2841 (unsigned long long)off, (unsigned long long)len);
2842 return -EIO;
2843 }
2835 mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); 2844 mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
2836 while (towrite > 0) { 2845 while (towrite > 0) {
2837 tocopy = sb->s_blocksize - offset < towrite ? 2846 tocopy = sb->s_blocksize - offset < towrite ?
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c
index 5b68dd3f191a..a005451930b7 100644
--- a/fs/reiserfs/super.c
+++ b/fs/reiserfs/super.c
@@ -1915,8 +1915,11 @@ static int reiserfs_release_dquot(struct dquot *dquot)
1915 ret = 1915 ret =
1916 journal_begin(&th, dquot->dq_sb, 1916 journal_begin(&th, dquot->dq_sb,
1917 REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb)); 1917 REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
1918 if (ret) 1918 if (ret) {
1919 /* Release dquot anyway to avoid endless cycle in dqput() */
1920 dquot_release(dquot);
1919 goto out; 1921 goto out;
1922 }
1920 ret = dquot_release(dquot); 1923 ret = dquot_release(dquot);
1921 err = 1924 err =
1922 journal_end(&th, dquot->dq_sb, 1925 journal_end(&th, dquot->dq_sb,
@@ -2067,6 +2070,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
2067 size_t towrite = len; 2070 size_t towrite = len;
2068 struct buffer_head tmp_bh, *bh; 2071 struct buffer_head tmp_bh, *bh;
2069 2072
2073 if (!current->journal_info) {
2074 printk(KERN_WARNING "reiserfs: Quota write (off=%Lu, len=%Lu)"
2075 " cancelled because transaction is not started.\n",
2076 (unsigned long long)off, (unsigned long long)len);
2077 return -EIO;
2078 }
2070 mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA); 2079 mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
2071 while (towrite > 0) { 2080 while (towrite > 0) {
2072 tocopy = sb->s_blocksize - offset < towrite ? 2081 tocopy = sb->s_blocksize - offset < towrite ?
@@ -2098,7 +2107,7 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
2098 data += tocopy; 2107 data += tocopy;
2099 blk++; 2108 blk++;
2100 } 2109 }
2101 out: 2110out:
2102 if (len == towrite) 2111 if (len == towrite)
2103 return err; 2112 return err;
2104 if (inode->i_size < off + len - towrite) 2113 if (inode->i_size < off + len - towrite)