mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-21 22:21:21 +00:00
reiserfs: locking, release lock around quota operations
Previous commits released the write lock across quota operations but missed several places. In particular, the free operations can also call into the file system code and take the write lock, causing deadlocks. This patch introduces some more helpers and uses them for quota call sites. Without this patch applied, reiserfs + quotas runs into deadlocks under anything more than trivial load. Signed-off-by: Jeff Mahoney <jeffm@suse.com>
This commit is contained in:
parent
278f6679f4
commit
d2d0395fd1
4 changed files with 63 additions and 23 deletions
|
@ -57,8 +57,11 @@ void reiserfs_evict_inode(struct inode *inode)
|
|||
/* Do quota update inside a transaction for journaled quotas. We must do that
|
||||
* after delete_object so that quota updates go into the same transaction as
|
||||
* stat data deletion */
|
||||
if (!err)
|
||||
if (!err) {
|
||||
int depth = reiserfs_write_unlock_nested(inode->i_sb);
|
||||
dquot_free_inode(inode);
|
||||
reiserfs_write_lock_nested(inode->i_sb, depth);
|
||||
}
|
||||
|
||||
if (journal_end(&th, inode->i_sb, jbegin_count))
|
||||
goto out;
|
||||
|
@ -1768,7 +1771,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
|
|||
struct inode *inode,
|
||||
struct reiserfs_security_handle *security)
|
||||
{
|
||||
struct super_block *sb;
|
||||
struct super_block *sb = dir->i_sb;
|
||||
struct reiserfs_iget_args args;
|
||||
INITIALIZE_PATH(path_to_key);
|
||||
struct cpu_key key;
|
||||
|
@ -1780,9 +1783,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
|
|||
|
||||
BUG_ON(!th->t_trans_id);
|
||||
|
||||
reiserfs_write_unlock(inode->i_sb);
|
||||
depth = reiserfs_write_unlock_nested(sb);
|
||||
err = dquot_alloc_inode(inode);
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
reiserfs_write_lock_nested(sb, depth);
|
||||
if (err)
|
||||
goto out_end_trans;
|
||||
if (!dir->i_nlink) {
|
||||
|
@ -1790,8 +1793,6 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
|
|||
goto out_bad_inode;
|
||||
}
|
||||
|
||||
sb = dir->i_sb;
|
||||
|
||||
/* item head of new item */
|
||||
ih.ih_key.k_dir_id = reiserfs_choose_packing(dir);
|
||||
ih.ih_key.k_objectid = cpu_to_le32(reiserfs_get_unused_objectid(th));
|
||||
|
@ -1983,14 +1984,16 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
|
|||
INODE_PKEY(inode)->k_objectid = 0;
|
||||
|
||||
/* Quota change must be inside a transaction for journaling */
|
||||
depth = reiserfs_write_unlock_nested(inode->i_sb);
|
||||
dquot_free_inode(inode);
|
||||
reiserfs_write_lock_nested(inode->i_sb, depth);
|
||||
|
||||
out_end_trans:
|
||||
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 */
|
||||
depth = reiserfs_write_unlock_nested(inode->i_sb);
|
||||
dquot_drop(inode);
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
reiserfs_write_lock_nested(inode->i_sb, depth);
|
||||
inode->i_flags |= S_NOQUOTA;
|
||||
make_bad_inode(inode);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue