add patch add-get_inode_usage-callback-to-transfer-multi-inode-charges
[ext4-patch-queue.git] / fix-lockdep-warning-about-recursive-inode-locking
blobde3bbe78ede88a53dc1251c05700b06055cac6de
1 ext4: fix lockdep warning about recursive inode locking
3 From: Tahsin Erdogan <tahsin@google.com>
5 Setting a large xattr value may require writing the attribute contents
6 to an external inode. In this case we may need to lock the xattr inode
7 along with the parent inode. This doesn't pose a deadlock risk because
8 xattr inodes are not directly visible to the user and their access is
9 restricted.
11 Assign a lockdep subclass to xattr inode's lock.
13  ============================================
14  WARNING: possible recursive locking detected
15  4.12.0-rc1+ #740 Not tainted
16  --------------------------------------------
17  python/1822 is trying to acquire lock:
18   (&sb->s_type->i_mutex_key#15){+.+...}, at: [<ffffffff804912ca>] ext4_xattr_set_entry+0x65a/0x7b0
20  but task is already holding lock:
21   (&sb->s_type->i_mutex_key#15){+.+...}, at: [<ffffffff803d6687>] vfs_setxattr+0x57/0xb0
23  other info that might help us debug this:
24   Possible unsafe locking scenario:
26         CPU0
27         ----
28    lock(&sb->s_type->i_mutex_key#15);
29    lock(&sb->s_type->i_mutex_key#15);
31   *** DEADLOCK ***
33   May be due to missing lock nesting notation
35  4 locks held by python/1822:
36   #0:  (sb_writers#10){.+.+.+}, at: [<ffffffff803d0eef>] mnt_want_write+0x1f/0x50
37   #1:  (&sb->s_type->i_mutex_key#15){+.+...}, at: [<ffffffff803d6687>] vfs_setxattr+0x57/0xb0
38   #2:  (jbd2_handle){.+.+..}, at: [<ffffffff80493f40>] start_this_handle+0xf0/0x420
39   #3:  (&ei->xattr_sem){++++..}, at: [<ffffffff804920ba>] ext4_xattr_set_handle+0x9a/0x4f0
41  stack backtrace:
42  CPU: 0 PID: 1822 Comm: python Not tainted 4.12.0-rc1+ #740
43  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
44  Call Trace:
45   dump_stack+0x67/0x9e
46   __lock_acquire+0x5f3/0x1750
47   lock_acquire+0xb5/0x1d0
48   down_write+0x2c/0x60
49   ext4_xattr_set_entry+0x65a/0x7b0
50   ext4_xattr_block_set+0x1b2/0x9b0
51   ext4_xattr_set_handle+0x322/0x4f0
52   ext4_xattr_set+0x144/0x1a0
53   ext4_xattr_user_set+0x34/0x40
54   __vfs_setxattr+0x66/0x80
55   __vfs_setxattr_noperm+0x69/0x1c0
56   vfs_setxattr+0xa2/0xb0
57   setxattr+0x12e/0x150
58   path_setxattr+0x87/0xb0
59   SyS_setxattr+0xf/0x20
60   entry_SYSCALL_64_fastpath+0x18/0xad
62 Signed-off-by: Tahsin Erdogan <tahsin@google.com>
63 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
64 ---
65  fs/ext4/inode.c | 2 ++
66  fs/ext4/xattr.c | 8 ++++++++
67  fs/ext4/xattr.h | 6 ++++++
68  3 files changed, 16 insertions(+)
70 diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
71 index e5535e5b3dc5..d095bf7ad390 100644
72 --- a/fs/ext4/inode.c
73 +++ b/fs/ext4/inode.c
74 @@ -4877,6 +4877,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
75         }
76         brelse(iloc.bh);
77         ext4_set_inode_flags(inode);
78 +       if (ei->i_flags & EXT4_EA_INODE_FL)
79 +               ext4_xattr_inode_set_class(inode);
80         unlock_new_inode(inode);
81         return inode;
83 diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
84 index 444be5c7a1d5..26d2705950a5 100644
85 --- a/fs/ext4/xattr.c
86 +++ b/fs/ext4/xattr.c
87 @@ -107,6 +107,13 @@ const struct xattr_handler *ext4_xattr_handlers[] = {
88  #define EXT4_GET_MB_CACHE(inode)       (((struct ext4_sb_info *) \
89                                 inode->i_sb->s_fs_info)->s_mb_cache)
91 +#ifdef CONFIG_LOCKDEP
92 +void ext4_xattr_inode_set_class(struct inode *ea_inode)
94 +       lockdep_set_subclass(&ea_inode->i_rwsem, 1);
96 +#endif
98  static __le32 ext4_xattr_block_csum(struct inode *inode,
99                                     sector_t block_nr,
100                                     struct ext4_xattr_header *hdr)
101 @@ -830,6 +837,7 @@ static struct inode *ext4_xattr_inode_create(handle_t *handle,
102                 ea_inode->i_op = &ext4_file_inode_operations;
103                 ea_inode->i_fop = &ext4_file_operations;
104                 ext4_set_aops(ea_inode);
105 +               ext4_xattr_inode_set_class(ea_inode);
106                 ea_inode->i_generation = inode->i_generation;
107                 EXT4_I(ea_inode)->i_flags |= EXT4_EA_INODE_FL;
109 diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
110 index 6e10ff9393d4..e8bef79bdc38 100644
111 --- a/fs/ext4/xattr.h
112 +++ b/fs/ext4/xattr.h
113 @@ -196,3 +196,9 @@ static inline int ext4_init_security(handle_t *handle, struct inode *inode,
114         return 0;
116  #endif
118 +#ifdef CONFIG_LOCKDEP
119 +extern void ext4_xattr_inode_set_class(struct inode *ea_inode);
120 +#else
121 +static inline void ext4_xattr_inode_set_class(struct inode *ea_inode) { }
122 +#endif
123 -- 
124 2.13.1.611.g7e3b11ae1-goog