Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
Pull reiserfs and ext3 fixes from Jan Kara: "Fixes of reiserfs deadlocks when quotas are enabled (locking there was completely busted by BKL conversion) and also one small ext3 fix in the trim interface." * 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs: ext3: Avoid underflow of in ext3_trim_fs() reiserfs: Move quota calls out of write lock reiserfs: Protect reiserfs_quota_write() with write lock reiserfs: Protect reiserfs_quota_on() with write lock reiserfs: Fix lock ordering during remount
This commit is contained in:
commit
ca6215dfc7
@ -2101,8 +2101,9 @@ int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range)
|
|||||||
end = start + (range->len >> sb->s_blocksize_bits) - 1;
|
end = start + (range->len >> sb->s_blocksize_bits) - 1;
|
||||||
minlen = range->minlen >> sb->s_blocksize_bits;
|
minlen = range->minlen >> sb->s_blocksize_bits;
|
||||||
|
|
||||||
if (unlikely(minlen > EXT3_BLOCKS_PER_GROUP(sb)) ||
|
if (minlen > EXT3_BLOCKS_PER_GROUP(sb) ||
|
||||||
unlikely(start >= max_blks))
|
start >= max_blks ||
|
||||||
|
range->len < sb->s_blocksize)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (end >= max_blks)
|
if (end >= max_blks)
|
||||||
end = max_blks - 1;
|
end = max_blks - 1;
|
||||||
|
@ -1782,8 +1782,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
|
|||||||
|
|
||||||
BUG_ON(!th->t_trans_id);
|
BUG_ON(!th->t_trans_id);
|
||||||
|
|
||||||
dquot_initialize(inode);
|
reiserfs_write_unlock(inode->i_sb);
|
||||||
err = dquot_alloc_inode(inode);
|
err = dquot_alloc_inode(inode);
|
||||||
|
reiserfs_write_lock(inode->i_sb);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_end_trans;
|
goto out_end_trans;
|
||||||
if (!dir->i_nlink) {
|
if (!dir->i_nlink) {
|
||||||
@ -1979,8 +1980,10 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
|
|||||||
|
|
||||||
out_end_trans:
|
out_end_trans:
|
||||||
journal_end(th, th->t_super, th->t_blocks_allocated);
|
journal_end(th, th->t_super, th->t_blocks_allocated);
|
||||||
|
reiserfs_write_unlock(inode->i_sb);
|
||||||
/* Drop can be outside and it needs more credits so it's better to have it outside */
|
/* Drop can be outside and it needs more credits so it's better to have it outside */
|
||||||
dquot_drop(inode);
|
dquot_drop(inode);
|
||||||
|
reiserfs_write_lock(inode->i_sb);
|
||||||
inode->i_flags |= S_NOQUOTA;
|
inode->i_flags |= S_NOQUOTA;
|
||||||
make_bad_inode(inode);
|
make_bad_inode(inode);
|
||||||
|
|
||||||
@ -3103,10 +3106,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
|
|||||||
/* must be turned off for recursive notify_change calls */
|
/* must be turned off for recursive notify_change calls */
|
||||||
ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID);
|
ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID);
|
||||||
|
|
||||||
depth = reiserfs_write_lock_once(inode->i_sb);
|
|
||||||
if (is_quota_modification(inode, attr))
|
if (is_quota_modification(inode, attr))
|
||||||
dquot_initialize(inode);
|
dquot_initialize(inode);
|
||||||
|
depth = reiserfs_write_lock_once(inode->i_sb);
|
||||||
if (attr->ia_valid & ATTR_SIZE) {
|
if (attr->ia_valid & ATTR_SIZE) {
|
||||||
/* version 2 items will be caught by the s_maxbytes check
|
/* version 2 items will be caught by the s_maxbytes check
|
||||||
** done for us in vmtruncate
|
** done for us in vmtruncate
|
||||||
@ -3170,7 +3172,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
|
|||||||
error = journal_begin(&th, inode->i_sb, jbegin_count);
|
error = journal_begin(&th, inode->i_sb, jbegin_count);
|
||||||
if (error)
|
if (error)
|
||||||
goto out;
|
goto out;
|
||||||
|
reiserfs_write_unlock_once(inode->i_sb, depth);
|
||||||
error = dquot_transfer(inode, attr);
|
error = dquot_transfer(inode, attr);
|
||||||
|
depth = reiserfs_write_lock_once(inode->i_sb);
|
||||||
if (error) {
|
if (error) {
|
||||||
journal_end(&th, inode->i_sb, jbegin_count);
|
journal_end(&th, inode->i_sb, jbegin_count);
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1968,7 +1968,9 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree
|
|||||||
key2type(&(key->on_disk_key)));
|
key2type(&(key->on_disk_key)));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
reiserfs_write_unlock(inode->i_sb);
|
||||||
retval = dquot_alloc_space_nodirty(inode, pasted_size);
|
retval = dquot_alloc_space_nodirty(inode, pasted_size);
|
||||||
|
reiserfs_write_lock(inode->i_sb);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
pathrelse(search_path);
|
pathrelse(search_path);
|
||||||
return retval;
|
return retval;
|
||||||
@ -2061,9 +2063,11 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
|
|||||||
"reiserquota insert_item(): allocating %u id=%u type=%c",
|
"reiserquota insert_item(): allocating %u id=%u type=%c",
|
||||||
quota_bytes, inode->i_uid, head2type(ih));
|
quota_bytes, inode->i_uid, head2type(ih));
|
||||||
#endif
|
#endif
|
||||||
|
reiserfs_write_unlock(inode->i_sb);
|
||||||
/* We can't dirty inode here. It would be immediately written but
|
/* We can't dirty inode here. It would be immediately written but
|
||||||
* appropriate stat item isn't inserted yet... */
|
* appropriate stat item isn't inserted yet... */
|
||||||
retval = dquot_alloc_space_nodirty(inode, quota_bytes);
|
retval = dquot_alloc_space_nodirty(inode, quota_bytes);
|
||||||
|
reiserfs_write_lock(inode->i_sb);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
pathrelse(path);
|
pathrelse(path);
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -298,7 +298,9 @@ static int finish_unfinished(struct super_block *s)
|
|||||||
retval = remove_save_link_only(s, &save_link_key, 0);
|
retval = remove_save_link_only(s, &save_link_key, 0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
reiserfs_write_unlock(s);
|
||||||
dquot_initialize(inode);
|
dquot_initialize(inode);
|
||||||
|
reiserfs_write_lock(s);
|
||||||
|
|
||||||
if (truncate && S_ISDIR(inode->i_mode)) {
|
if (truncate && S_ISDIR(inode->i_mode)) {
|
||||||
/* We got a truncate request for a dir which is impossible.
|
/* We got a truncate request for a dir which is impossible.
|
||||||
@ -1335,7 +1337,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
|||||||
kfree(qf_names[i]);
|
kfree(qf_names[i]);
|
||||||
#endif
|
#endif
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto out_err;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_QUOTA
|
#ifdef CONFIG_QUOTA
|
||||||
handle_quota_files(s, qf_names, &qfmt);
|
handle_quota_files(s, qf_names, &qfmt);
|
||||||
@ -1379,7 +1381,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
|||||||
if (blocks) {
|
if (blocks) {
|
||||||
err = reiserfs_resize(s, blocks);
|
err = reiserfs_resize(s, blocks);
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
goto out_err;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*mount_flags & MS_RDONLY) {
|
if (*mount_flags & MS_RDONLY) {
|
||||||
@ -1389,9 +1391,15 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
|||||||
/* it is read-only already */
|
/* it is read-only already */
|
||||||
goto out_ok;
|
goto out_ok;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Drop write lock. Quota will retake it when needed and lock
|
||||||
|
* ordering requires calling dquot_suspend() without it.
|
||||||
|
*/
|
||||||
|
reiserfs_write_unlock(s);
|
||||||
err = dquot_suspend(s, -1);
|
err = dquot_suspend(s, -1);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
reiserfs_write_lock(s);
|
||||||
|
|
||||||
/* try to remount file system with read-only permissions */
|
/* try to remount file system with read-only permissions */
|
||||||
if (sb_umount_state(rs) == REISERFS_VALID_FS
|
if (sb_umount_state(rs) == REISERFS_VALID_FS
|
||||||
@ -1401,7 +1409,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
|||||||
|
|
||||||
err = journal_begin(&th, s, 10);
|
err = journal_begin(&th, s, 10);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_err;
|
goto out_unlock;
|
||||||
|
|
||||||
/* Mounting a rw partition read-only. */
|
/* Mounting a rw partition read-only. */
|
||||||
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
|
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
|
||||||
@ -1416,7 +1424,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
|||||||
|
|
||||||
if (reiserfs_is_journal_aborted(journal)) {
|
if (reiserfs_is_journal_aborted(journal)) {
|
||||||
err = journal->j_errno;
|
err = journal->j_errno;
|
||||||
goto out_err;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_data_mode(s, mount_options);
|
handle_data_mode(s, mount_options);
|
||||||
@ -1425,7 +1433,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
|||||||
s->s_flags &= ~MS_RDONLY; /* now it is safe to call journal_begin */
|
s->s_flags &= ~MS_RDONLY; /* now it is safe to call journal_begin */
|
||||||
err = journal_begin(&th, s, 10);
|
err = journal_begin(&th, s, 10);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_err;
|
goto out_unlock;
|
||||||
|
|
||||||
/* Mount a partition which is read-only, read-write */
|
/* Mount a partition which is read-only, read-write */
|
||||||
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
|
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
|
||||||
@ -1442,10 +1450,16 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
|||||||
SB_JOURNAL(s)->j_must_wait = 1;
|
SB_JOURNAL(s)->j_must_wait = 1;
|
||||||
err = journal_end(&th, s, 10);
|
err = journal_end(&th, s, 10);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_err;
|
goto out_unlock;
|
||||||
|
|
||||||
if (!(*mount_flags & MS_RDONLY)) {
|
if (!(*mount_flags & MS_RDONLY)) {
|
||||||
|
/*
|
||||||
|
* Drop write lock. Quota will retake it when needed and lock
|
||||||
|
* ordering requires calling dquot_resume() without it.
|
||||||
|
*/
|
||||||
|
reiserfs_write_unlock(s);
|
||||||
dquot_resume(s, -1);
|
dquot_resume(s, -1);
|
||||||
|
reiserfs_write_lock(s);
|
||||||
finish_unfinished(s);
|
finish_unfinished(s);
|
||||||
reiserfs_xattr_init(s, *mount_flags);
|
reiserfs_xattr_init(s, *mount_flags);
|
||||||
}
|
}
|
||||||
@ -1455,9 +1469,10 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
|
|||||||
reiserfs_write_unlock(s);
|
reiserfs_write_unlock(s);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out_unlock:
|
||||||
|
reiserfs_write_unlock(s);
|
||||||
out_err:
|
out_err:
|
||||||
kfree(new_opts);
|
kfree(new_opts);
|
||||||
reiserfs_write_unlock(s);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2095,13 +2110,15 @@ static int reiserfs_write_dquot(struct dquot *dquot)
|
|||||||
REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
|
REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
reiserfs_write_unlock(dquot->dq_sb);
|
||||||
ret = dquot_commit(dquot);
|
ret = dquot_commit(dquot);
|
||||||
|
reiserfs_write_lock(dquot->dq_sb);
|
||||||
err =
|
err =
|
||||||
journal_end(&th, dquot->dq_sb,
|
journal_end(&th, dquot->dq_sb,
|
||||||
REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
|
REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
|
||||||
if (!ret && err)
|
if (!ret && err)
|
||||||
ret = err;
|
ret = err;
|
||||||
out:
|
out:
|
||||||
reiserfs_write_unlock(dquot->dq_sb);
|
reiserfs_write_unlock(dquot->dq_sb);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -2117,13 +2134,15 @@ static int reiserfs_acquire_dquot(struct dquot *dquot)
|
|||||||
REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
|
REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
reiserfs_write_unlock(dquot->dq_sb);
|
||||||
ret = dquot_acquire(dquot);
|
ret = dquot_acquire(dquot);
|
||||||
|
reiserfs_write_lock(dquot->dq_sb);
|
||||||
err =
|
err =
|
||||||
journal_end(&th, dquot->dq_sb,
|
journal_end(&th, dquot->dq_sb,
|
||||||
REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
|
REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
|
||||||
if (!ret && err)
|
if (!ret && err)
|
||||||
ret = err;
|
ret = err;
|
||||||
out:
|
out:
|
||||||
reiserfs_write_unlock(dquot->dq_sb);
|
reiserfs_write_unlock(dquot->dq_sb);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -2137,19 +2156,21 @@ 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));
|
||||||
|
reiserfs_write_unlock(dquot->dq_sb);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
/* Release dquot anyway to avoid endless cycle in dqput() */
|
/* Release dquot anyway to avoid endless cycle in dqput() */
|
||||||
dquot_release(dquot);
|
dquot_release(dquot);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
ret = dquot_release(dquot);
|
ret = dquot_release(dquot);
|
||||||
|
reiserfs_write_lock(dquot->dq_sb);
|
||||||
err =
|
err =
|
||||||
journal_end(&th, dquot->dq_sb,
|
journal_end(&th, dquot->dq_sb,
|
||||||
REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
|
REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
|
||||||
if (!ret && err)
|
if (!ret && err)
|
||||||
ret = err;
|
ret = err;
|
||||||
out:
|
|
||||||
reiserfs_write_unlock(dquot->dq_sb);
|
reiserfs_write_unlock(dquot->dq_sb);
|
||||||
|
out:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2174,11 +2195,13 @@ static int reiserfs_write_info(struct super_block *sb, int type)
|
|||||||
ret = journal_begin(&th, sb, 2);
|
ret = journal_begin(&th, sb, 2);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
|
reiserfs_write_unlock(sb);
|
||||||
ret = dquot_commit_info(sb, type);
|
ret = dquot_commit_info(sb, type);
|
||||||
|
reiserfs_write_lock(sb);
|
||||||
err = journal_end(&th, sb, 2);
|
err = journal_end(&th, sb, 2);
|
||||||
if (!ret && err)
|
if (!ret && err)
|
||||||
ret = err;
|
ret = err;
|
||||||
out:
|
out:
|
||||||
reiserfs_write_unlock(sb);
|
reiserfs_write_unlock(sb);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -2203,8 +2226,11 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
|
|||||||
struct reiserfs_transaction_handle th;
|
struct reiserfs_transaction_handle th;
|
||||||
int opt = type == USRQUOTA ? REISERFS_USRQUOTA : REISERFS_GRPQUOTA;
|
int opt = type == USRQUOTA ? REISERFS_USRQUOTA : REISERFS_GRPQUOTA;
|
||||||
|
|
||||||
if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt)))
|
reiserfs_write_lock(sb);
|
||||||
return -EINVAL;
|
if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* Quotafile not on the same filesystem? */
|
/* Quotafile not on the same filesystem? */
|
||||||
if (path->dentry->d_sb != sb) {
|
if (path->dentry->d_sb != sb) {
|
||||||
@ -2246,8 +2272,10 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
|
|||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
err = dquot_quota_on(sb, type, format_id, path);
|
reiserfs_write_unlock(sb);
|
||||||
|
return dquot_quota_on(sb, type, format_id, path);
|
||||||
out:
|
out:
|
||||||
|
reiserfs_write_unlock(sb);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2320,7 +2348,9 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
|
|||||||
tocopy = sb->s_blocksize - offset < towrite ?
|
tocopy = sb->s_blocksize - offset < towrite ?
|
||||||
sb->s_blocksize - offset : towrite;
|
sb->s_blocksize - offset : towrite;
|
||||||
tmp_bh.b_state = 0;
|
tmp_bh.b_state = 0;
|
||||||
|
reiserfs_write_lock(sb);
|
||||||
err = reiserfs_get_block(inode, blk, &tmp_bh, GET_BLOCK_CREATE);
|
err = reiserfs_get_block(inode, blk, &tmp_bh, GET_BLOCK_CREATE);
|
||||||
|
reiserfs_write_unlock(sb);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
if (offset || tocopy != sb->s_blocksize)
|
if (offset || tocopy != sb->s_blocksize)
|
||||||
@ -2336,10 +2366,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
|
|||||||
flush_dcache_page(bh->b_page);
|
flush_dcache_page(bh->b_page);
|
||||||
set_buffer_uptodate(bh);
|
set_buffer_uptodate(bh);
|
||||||
unlock_buffer(bh);
|
unlock_buffer(bh);
|
||||||
|
reiserfs_write_lock(sb);
|
||||||
reiserfs_prepare_for_journal(sb, bh, 1);
|
reiserfs_prepare_for_journal(sb, bh, 1);
|
||||||
journal_mark_dirty(current->journal_info, sb, bh);
|
journal_mark_dirty(current->journal_info, sb, bh);
|
||||||
if (!journal_quota)
|
if (!journal_quota)
|
||||||
reiserfs_add_ordered_list(inode, bh);
|
reiserfs_add_ordered_list(inode, bh);
|
||||||
|
reiserfs_write_unlock(sb);
|
||||||
brelse(bh);
|
brelse(bh);
|
||||||
offset = 0;
|
offset = 0;
|
||||||
towrite -= tocopy;
|
towrite -= tocopy;
|
||||||
|
Loading…
Reference in New Issue
Block a user