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
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:
28 lock(&sb->s_type->i_mutex_key#15);
29 lock(&sb->s_type->i_mutex_key#15);
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
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
46 __lock_acquire+0x5f3/0x1750
47 lock_acquire+0xb5/0x1d0
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
58 path_setxattr+0x87/0xb0
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>
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
74 @@ -4877,6 +4877,8 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
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);
83 diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
84 index 444be5c7a1d5..26d2705950a5 100644
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);
98 static __le32 ext4_xattr_block_csum(struct inode *inode,
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,
118 +#ifdef CONFIG_LOCKDEP
119 +extern void ext4_xattr_inode_set_class(struct inode *ea_inode);
121 +static inline void ext4_xattr_inode_set_class(struct inode *ea_inode) { }
124 2.13.1.611.g7e3b11ae1-goog