Merge branch 'reiserfs/kill-bkl' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic/random-tracing
* 'reiserfs/kill-bkl' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic/random-tracing: reiserfs: Safely acquire i_mutex from xattr_rmdir reiserfs: Safely acquire i_mutex from reiserfs_for_each_xattr reiserfs: Fix journal mutex <-> inode mutex lock inversion reiserfs: Fix unwanted recursive reiserfs lock in reiserfs_unlink() reiserfs: Relax lock before open xattr dir in reiserfs_xattr_set_handle() reiserfs: Relax reiserfs lock while freeing the journal reiserfs: Fix reiserfs lock <-> i_mutex dependency inversion on xattr reiserfs: Warn on lock relax if taken recursively reiserfs: Fix reiserfs lock <-> i_xattr_sem dependency inversion reiserfs: Fix remaining in-reclaim-fs <-> reclaim-fs-on locking inversion reiserfs: Fix reiserfs lock <-> inode mutex dependency inversion reiserfs: Fix reiserfs lock and journal lock inversion dependency reiserfs: Fix possible recursive lock
This commit is contained in:
commit
45d28b0972
|
@ -1277,7 +1277,10 @@ int reiserfs_init_bitmap_cache(struct super_block *sb)
|
|||
struct reiserfs_bitmap_info *bitmap;
|
||||
unsigned int bmap_nr = reiserfs_bmap_count(sb);
|
||||
|
||||
/* Avoid lock recursion in fault case */
|
||||
reiserfs_write_unlock(sb);
|
||||
bitmap = vmalloc(sizeof(*bitmap) * bmap_nr);
|
||||
reiserfs_write_lock(sb);
|
||||
if (bitmap == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
@ -31,11 +31,12 @@ void reiserfs_delete_inode(struct inode *inode)
|
|||
JOURNAL_PER_BALANCE_CNT * 2 +
|
||||
2 * REISERFS_QUOTA_INIT_BLOCKS(inode->i_sb);
|
||||
struct reiserfs_transaction_handle th;
|
||||
int depth;
|
||||
int err;
|
||||
|
||||
truncate_inode_pages(&inode->i_data, 0);
|
||||
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
depth = reiserfs_write_lock_once(inode->i_sb);
|
||||
|
||||
/* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */
|
||||
if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */
|
||||
|
@ -74,7 +75,7 @@ void reiserfs_delete_inode(struct inode *inode)
|
|||
out:
|
||||
clear_inode(inode); /* note this must go after the journal_end to prevent deadlock */
|
||||
inode->i_blocks = 0;
|
||||
reiserfs_write_unlock(inode->i_sb);
|
||||
reiserfs_write_unlock_once(inode->i_sb, depth);
|
||||
}
|
||||
|
||||
static void _make_cpu_key(struct cpu_key *key, int version, __u32 dirid,
|
||||
|
|
|
@ -2009,10 +2009,11 @@ static int do_journal_release(struct reiserfs_transaction_handle *th,
|
|||
destroy_workqueue(commit_wq);
|
||||
commit_wq = NULL;
|
||||
}
|
||||
reiserfs_write_lock(sb);
|
||||
|
||||
free_journal_ram(sb);
|
||||
|
||||
reiserfs_write_lock(sb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2758,11 +2759,18 @@ int journal_init(struct super_block *sb, const char *j_dev_name,
|
|||
struct reiserfs_journal *journal;
|
||||
struct reiserfs_journal_list *jl;
|
||||
char b[BDEVNAME_SIZE];
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Unlock here to avoid various RECLAIM-FS-ON <-> IN-RECLAIM-FS
|
||||
* dependency inversion warnings.
|
||||
*/
|
||||
reiserfs_write_unlock(sb);
|
||||
journal = SB_JOURNAL(sb) = vmalloc(sizeof(struct reiserfs_journal));
|
||||
if (!journal) {
|
||||
reiserfs_warning(sb, "journal-1256",
|
||||
"unable to get memory for journal structure");
|
||||
reiserfs_write_lock(sb);
|
||||
return 1;
|
||||
}
|
||||
memset(journal, 0, sizeof(struct reiserfs_journal));
|
||||
|
@ -2771,10 +2779,12 @@ int journal_init(struct super_block *sb, const char *j_dev_name,
|
|||
INIT_LIST_HEAD(&journal->j_working_list);
|
||||
INIT_LIST_HEAD(&journal->j_journal_list);
|
||||
journal->j_persistent_trans = 0;
|
||||
if (reiserfs_allocate_list_bitmaps(sb,
|
||||
journal->j_list_bitmap,
|
||||
reiserfs_bmap_count(sb)))
|
||||
ret = reiserfs_allocate_list_bitmaps(sb, journal->j_list_bitmap,
|
||||
reiserfs_bmap_count(sb));
|
||||
reiserfs_write_lock(sb);
|
||||
if (ret)
|
||||
goto free_and_return;
|
||||
|
||||
allocate_bitmap_nodes(sb);
|
||||
|
||||
/* reserved for journal area support */
|
||||
|
|
|
@ -86,3 +86,12 @@ void reiserfs_check_lock_depth(struct super_block *sb, char *caller)
|
|||
reiserfs_panic(sb, "%s called without kernel lock held %d",
|
||||
caller);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_REISERFS_CHECK
|
||||
void reiserfs_lock_check_recursive(struct super_block *sb)
|
||||
{
|
||||
struct reiserfs_sb_info *sb_i = REISERFS_SB(sb);
|
||||
|
||||
WARN_ONCE((sb_i->lock_depth > 0), "Unwanted recursive reiserfs lock!\n");
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -921,6 +921,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
|
|||
struct reiserfs_transaction_handle th;
|
||||
int jbegin_count;
|
||||
unsigned long savelink;
|
||||
int depth;
|
||||
|
||||
inode = dentry->d_inode;
|
||||
|
||||
|
@ -932,7 +933,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
|
|||
JOURNAL_PER_BALANCE_CNT * 2 + 2 +
|
||||
4 * REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb);
|
||||
|
||||
reiserfs_write_lock(dir->i_sb);
|
||||
depth = reiserfs_write_lock_once(dir->i_sb);
|
||||
retval = journal_begin(&th, dir->i_sb, jbegin_count);
|
||||
if (retval)
|
||||
goto out_unlink;
|
||||
|
@ -993,7 +994,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
|
|||
|
||||
retval = journal_end(&th, dir->i_sb, jbegin_count);
|
||||
reiserfs_check_path(&path);
|
||||
reiserfs_write_unlock(dir->i_sb);
|
||||
reiserfs_write_unlock_once(dir->i_sb, depth);
|
||||
return retval;
|
||||
|
||||
end_unlink:
|
||||
|
@ -1003,7 +1004,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry)
|
|||
if (err)
|
||||
retval = err;
|
||||
out_unlink:
|
||||
reiserfs_write_unlock(dir->i_sb);
|
||||
reiserfs_write_unlock_once(dir->i_sb, depth);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
|
@ -83,7 +83,8 @@ static int xattr_unlink(struct inode *dir, struct dentry *dentry)
|
|||
BUG_ON(!mutex_is_locked(&dir->i_mutex));
|
||||
vfs_dq_init(dir);
|
||||
|
||||
mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
|
||||
reiserfs_mutex_lock_nested_safe(&dentry->d_inode->i_mutex,
|
||||
I_MUTEX_CHILD, dir->i_sb);
|
||||
error = dir->i_op->unlink(dir, dentry);
|
||||
mutex_unlock(&dentry->d_inode->i_mutex);
|
||||
|
||||
|
@ -98,7 +99,8 @@ static int xattr_rmdir(struct inode *dir, struct dentry *dentry)
|
|||
BUG_ON(!mutex_is_locked(&dir->i_mutex));
|
||||
vfs_dq_init(dir);
|
||||
|
||||
mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD);
|
||||
reiserfs_mutex_lock_nested_safe(&dentry->d_inode->i_mutex,
|
||||
I_MUTEX_CHILD, dir->i_sb);
|
||||
dentry_unhash(dentry);
|
||||
error = dir->i_op->rmdir(dir, dentry);
|
||||
if (!error)
|
||||
|
@ -235,16 +237,22 @@ static int reiserfs_for_each_xattr(struct inode *inode,
|
|||
if (IS_PRIVATE(inode) || get_inode_sd_version(inode) == STAT_DATA_V1)
|
||||
return 0;
|
||||
|
||||
reiserfs_write_unlock(inode->i_sb);
|
||||
dir = open_xa_dir(inode, XATTR_REPLACE);
|
||||
if (IS_ERR(dir)) {
|
||||
err = PTR_ERR(dir);
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
goto out;
|
||||
} else if (!dir->d_inode) {
|
||||
err = 0;
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
goto out_dir;
|
||||
}
|
||||
|
||||
mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_XATTR);
|
||||
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
|
||||
buf.xadir = dir;
|
||||
err = reiserfs_readdir_dentry(dir, &buf, fill_with_dentries, &pos);
|
||||
while ((err == 0 || err == -ENOSPC) && buf.count) {
|
||||
|
@ -283,8 +291,9 @@ static int reiserfs_for_each_xattr(struct inode *inode,
|
|||
err = journal_begin(&th, inode->i_sb, blocks);
|
||||
if (!err) {
|
||||
int jerror;
|
||||
mutex_lock_nested(&dir->d_parent->d_inode->i_mutex,
|
||||
I_MUTEX_XATTR);
|
||||
reiserfs_mutex_lock_nested_safe(
|
||||
&dir->d_parent->d_inode->i_mutex,
|
||||
I_MUTEX_XATTR, inode->i_sb);
|
||||
err = action(dir, data);
|
||||
jerror = journal_end(&th, inode->i_sb, blocks);
|
||||
mutex_unlock(&dir->d_parent->d_inode->i_mutex);
|
||||
|
@ -480,11 +489,16 @@ reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *th,
|
|||
if (!buffer)
|
||||
return lookup_and_delete_xattr(inode, name);
|
||||
|
||||
reiserfs_write_unlock(inode->i_sb);
|
||||
dentry = xattr_lookup(inode, name, flags);
|
||||
if (IS_ERR(dentry))
|
||||
if (IS_ERR(dentry)) {
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
return PTR_ERR(dentry);
|
||||
}
|
||||
|
||||
down_write(&REISERFS_I(inode)->i_xattr_sem);
|
||||
down_read(&REISERFS_I(inode)->i_xattr_sem);
|
||||
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
|
||||
xahash = xattr_hash(buffer, buffer_size);
|
||||
while (buffer_pos < buffer_size || buffer_pos == 0) {
|
||||
|
|
|
@ -62,6 +62,12 @@ void reiserfs_write_unlock(struct super_block *s);
|
|||
int reiserfs_write_lock_once(struct super_block *s);
|
||||
void reiserfs_write_unlock_once(struct super_block *s, int lock_depth);
|
||||
|
||||
#ifdef CONFIG_REISERFS_CHECK
|
||||
void reiserfs_lock_check_recursive(struct super_block *s);
|
||||
#else
|
||||
static inline void reiserfs_lock_check_recursive(struct super_block *s) { }
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Several mutexes depend on the write lock.
|
||||
* However sometimes we want to relax the write lock while we hold
|
||||
|
@ -92,11 +98,31 @@ void reiserfs_write_unlock_once(struct super_block *s, int lock_depth);
|
|||
static inline void reiserfs_mutex_lock_safe(struct mutex *m,
|
||||
struct super_block *s)
|
||||
{
|
||||
reiserfs_lock_check_recursive(s);
|
||||
reiserfs_write_unlock(s);
|
||||
mutex_lock(m);
|
||||
reiserfs_write_lock(s);
|
||||
}
|
||||
|
||||
static inline void
|
||||
reiserfs_mutex_lock_nested_safe(struct mutex *m, unsigned int subclass,
|
||||
struct super_block *s)
|
||||
{
|
||||
reiserfs_lock_check_recursive(s);
|
||||
reiserfs_write_unlock(s);
|
||||
mutex_lock_nested(m, subclass);
|
||||
reiserfs_write_lock(s);
|
||||
}
|
||||
|
||||
static inline void
|
||||
reiserfs_down_read_safe(struct rw_semaphore *sem, struct super_block *s)
|
||||
{
|
||||
reiserfs_lock_check_recursive(s);
|
||||
reiserfs_write_unlock(s);
|
||||
down_read(sem);
|
||||
reiserfs_write_lock(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* When we schedule, we usually want to also release the write lock,
|
||||
* according to the previous bkl based locking scheme of reiserfs.
|
||||
|
|
Loading…
Reference in New Issue