From: Frederic Weisbecker Date: Wed, 30 Dec 2009 04:06:21 +0000 (+0100) Subject: reiserfs: Fix reiserfs lock <-> i_mutex dependency inversion on xattr X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=27026a05bb805866a3b9068dda8153b72cb942f4;p=GitHub%2FLineageOS%2FG12%2Fandroid_kernel_amlogic_linux-4.9.git reiserfs: Fix reiserfs lock <-> i_mutex dependency inversion on xattr While deleting the xattrs of an inode, we hold the reiserfs lock and grab the inode->i_mutex of the targeted inode and the root private xattr directory. Later on, we may relax the reiserfs lock for various reasons, this creates inverted dependencies. We can remove the reiserfs lock -> i_mutex dependency by relaxing the former before calling open_xa_dir(). This is fine because the lookup and creation of xattr private directories done in open_xa_dir() are covered by the targeted inode mutexes. And deeper operations in the tree are still done under the write lock. This fixes the following lockdep report: ======================================================= [ INFO: possible circular locking dependency detected ] 2.6.32-atom #173 ------------------------------------------------------- cp/3204 is trying to acquire lock: (&REISERFS_SB(s)->lock){+.+.+.}, at: [] reiserfs_write_lock_once+0x29/0x50 but task is already holding lock: (&sb->s_type->i_mutex_key#4/3){+.+.+.}, at: [] open_xa_dir+0xd8/0x1b0 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (&sb->s_type->i_mutex_key#4/3){+.+.+.}: [] __lock_acquire+0x11ff/0x19e0 [] lock_acquire+0x68/0x90 [] mutex_lock_nested+0x5b/0x340 [] open_xa_dir+0x43/0x1b0 [] reiserfs_for_each_xattr+0x62/0x260 [] reiserfs_delete_xattrs+0x1a/0x60 [] reiserfs_delete_inode+0x9f/0x150 [] generic_delete_inode+0xa2/0x170 [] generic_drop_inode+0x4f/0x70 [] iput+0x47/0x50 [] do_unlinkat+0xd5/0x160 [] sys_unlink+0x10/0x20 [] sysenter_do_call+0x12/0x32 -> #0 (&REISERFS_SB(s)->lock){+.+.+.}: [] __lock_acquire+0x18f6/0x19e0 [] lock_acquire+0x68/0x90 [] mutex_lock_nested+0x5b/0x340 [] reiserfs_write_lock_once+0x29/0x50 [] reiserfs_lookup+0x62/0x140 [] __lookup_hash+0xef/0x110 [] lookup_one_len+0x8d/0xc0 [] open_xa_dir+0xea/0x1b0 [] xattr_lookup+0x15/0x160 [] reiserfs_xattr_get+0x56/0x2a0 [] reiserfs_get_acl+0xa2/0x360 [] reiserfs_cache_default_acl+0x3a/0x160 [] reiserfs_mkdir+0x6c/0x2c0 [] vfs_mkdir+0xd6/0x180 [] sys_mkdirat+0xc0/0xd0 [] sys_mkdir+0x20/0x30 [] sysenter_do_call+0x12/0x32 other info that might help us debug this: 2 locks held by cp/3204: #0: (&sb->s_type->i_mutex_key#4/1){+.+.+.}, at: [] lookup_create+0x26/0xa0 #1: (&sb->s_type->i_mutex_key#4/3){+.+.+.}, at: [] open_xa_dir+0xd8/0x1b0 stack backtrace: Pid: 3204, comm: cp Not tainted 2.6.32-atom #173 Call Trace: [] ? printk+0x18/0x1a [] print_circular_bug+0xca/0xd0 [] __lock_acquire+0x18f6/0x19e0 [] ? check_usage+0x6a/0x460 [] lock_acquire+0x68/0x90 [] ? reiserfs_write_lock_once+0x29/0x50 [] ? reiserfs_write_lock_once+0x29/0x50 [] mutex_lock_nested+0x5b/0x340 [] ? reiserfs_write_lock_once+0x29/0x50 [] reiserfs_write_lock_once+0x29/0x50 [] reiserfs_lookup+0x62/0x140 [] ? debug_check_no_locks_freed+0x8a/0x140 [] ? trace_hardirqs_on_caller+0x124/0x170 [] __lookup_hash+0xef/0x110 [] lookup_one_len+0x8d/0xc0 [] open_xa_dir+0xea/0x1b0 [] xattr_lookup+0x15/0x160 [] reiserfs_xattr_get+0x56/0x2a0 [] reiserfs_get_acl+0xa2/0x360 [] ? new_inode+0x27/0xa0 [] reiserfs_cache_default_acl+0x3a/0x160 [] ? _spin_unlock+0x27/0x40 [] reiserfs_mkdir+0x6c/0x2c0 [] ? __d_lookup+0x108/0x190 [] ? mark_held_locks+0x62/0x80 [] ? mutex_lock_nested+0x2bd/0x340 [] ? generic_permission+0x1a/0xa0 [] ? security_inode_permission+0x1e/0x20 [] vfs_mkdir+0xd6/0x180 [] sys_mkdirat+0xc0/0xd0 [] ? up_read+0x16/0x30 [] ? restore_all_notrace+0x0/0x18 [] sys_mkdir+0x20/0x30 [] sysenter_do_call+0x12/0x32 v2: Don't drop reiserfs_mutex_lock_nested_safe() as we'll still need it later Signed-off-by: Frederic Weisbecker Tested-by: Christian Kujau Cc: Alexander Beregalov Cc: Chris Mason Cc: Ingo Molnar --- diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index a0e2e7acdc75..c320c7792c75 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -234,17 +234,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; } - reiserfs_mutex_lock_nested_safe(&dir->d_inode->i_mutex, I_MUTEX_XATTR, - inode->i_sb); + 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) {