mirror of
https://github.com/S3NEO/android_kernel_samsung_msm8226.git
synced 2024-11-07 03:47:13 +00:00
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>
This commit is contained in:
parent
af7b83f932
commit
9c3013e9b9
3 changed files with 31 additions and 4 deletions
|
@ -2578,8 +2578,11 @@ static int ext3_release_dquot(struct dquot *dquot)
|
||||||
|
|
||||||
handle = ext3_journal_start(dquot_to_inode(dquot),
|
handle = ext3_journal_start(dquot_to_inode(dquot),
|
||||||
EXT3_QUOTA_DEL_BLOCKS(dquot->dq_sb));
|
EXT3_QUOTA_DEL_BLOCKS(dquot->dq_sb));
|
||||||
if (IS_ERR(handle))
|
if (IS_ERR(handle)) {
|
||||||
|
/* Release dquot anyway to avoid endless cycle in dqput() */
|
||||||
|
dquot_release(dquot);
|
||||||
return PTR_ERR(handle);
|
return PTR_ERR(handle);
|
||||||
|
}
|
||||||
ret = dquot_release(dquot);
|
ret = dquot_release(dquot);
|
||||||
err = ext3_journal_stop(handle);
|
err = ext3_journal_stop(handle);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
@ -2712,6 +2715,12 @@ static ssize_t ext3_quota_write(struct super_block *sb, int type,
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
handle_t *handle = journal_current_handle();
|
handle_t *handle = journal_current_handle();
|
||||||
|
|
||||||
|
if (!handle) {
|
||||||
|
printk(KERN_WARNING "EXT3-fs: Quota write (off=%Lu, len=%Lu)"
|
||||||
|
" cancelled because transaction is not started.\n",
|
||||||
|
(unsigned long long)off, (unsigned long long)len);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
|
mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
|
||||||
while (towrite > 0) {
|
while (towrite > 0) {
|
||||||
tocopy = sb->s_blocksize - offset < towrite ?
|
tocopy = sb->s_blocksize - offset < towrite ?
|
||||||
|
|
|
@ -2698,8 +2698,11 @@ static int ext4_release_dquot(struct dquot *dquot)
|
||||||
|
|
||||||
handle = ext4_journal_start(dquot_to_inode(dquot),
|
handle = ext4_journal_start(dquot_to_inode(dquot),
|
||||||
EXT4_QUOTA_DEL_BLOCKS(dquot->dq_sb));
|
EXT4_QUOTA_DEL_BLOCKS(dquot->dq_sb));
|
||||||
if (IS_ERR(handle))
|
if (IS_ERR(handle)) {
|
||||||
|
/* Release dquot anyway to avoid endless cycle in dqput() */
|
||||||
|
dquot_release(dquot);
|
||||||
return PTR_ERR(handle);
|
return PTR_ERR(handle);
|
||||||
|
}
|
||||||
ret = dquot_release(dquot);
|
ret = dquot_release(dquot);
|
||||||
err = ext4_journal_stop(handle);
|
err = ext4_journal_stop(handle);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
@ -2832,6 +2835,12 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,
|
||||||
struct buffer_head *bh;
|
struct buffer_head *bh;
|
||||||
handle_t *handle = journal_current_handle();
|
handle_t *handle = journal_current_handle();
|
||||||
|
|
||||||
|
if (!handle) {
|
||||||
|
printk(KERN_WARNING "EXT4-fs: Quota write (off=%Lu, len=%Lu)"
|
||||||
|
" cancelled because transaction is not started.\n",
|
||||||
|
(unsigned long long)off, (unsigned long long)len);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
|
mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
|
||||||
while (towrite > 0) {
|
while (towrite > 0) {
|
||||||
tocopy = sb->s_blocksize - offset < towrite ?
|
tocopy = sb->s_blocksize - offset < towrite ?
|
||||||
|
|
|
@ -1915,8 +1915,11 @@ static int reiserfs_release_dquot(struct dquot *dquot)
|
||||||
ret =
|
ret =
|
||||||
journal_begin(&th, dquot->dq_sb,
|
journal_begin(&th, dquot->dq_sb,
|
||||||
REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
|
REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
/* Release dquot anyway to avoid endless cycle in dqput() */
|
||||||
|
dquot_release(dquot);
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
ret = dquot_release(dquot);
|
ret = dquot_release(dquot);
|
||||||
err =
|
err =
|
||||||
journal_end(&th, dquot->dq_sb,
|
journal_end(&th, dquot->dq_sb,
|
||||||
|
@ -2067,6 +2070,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
|
||||||
size_t towrite = len;
|
size_t towrite = len;
|
||||||
struct buffer_head tmp_bh, *bh;
|
struct buffer_head tmp_bh, *bh;
|
||||||
|
|
||||||
|
if (!current->journal_info) {
|
||||||
|
printk(KERN_WARNING "reiserfs: Quota write (off=%Lu, len=%Lu)"
|
||||||
|
" cancelled because transaction is not started.\n",
|
||||||
|
(unsigned long long)off, (unsigned long long)len);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
|
mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
|
||||||
while (towrite > 0) {
|
while (towrite > 0) {
|
||||||
tocopy = sb->s_blocksize - offset < towrite ?
|
tocopy = sb->s_blocksize - offset < towrite ?
|
||||||
|
@ -2098,7 +2107,7 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
|
||||||
data += tocopy;
|
data += tocopy;
|
||||||
blk++;
|
blk++;
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
if (len == towrite)
|
if (len == towrite)
|
||||||
return err;
|
return err;
|
||||||
if (inode->i_size < off + len - towrite)
|
if (inode->i_size < off + len - towrite)
|
||||||
|
|
Loading…
Reference in a new issue