From bb02f8abcc1c688613e279c75c323fc827de34a2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 17 Apr 2016 03:38:19 -0700 Subject: [PATCH] 3.14-stable patches added patches: ext4-add-lockdep-annotations-for-i_data_sem.patch --- ...d-lockdep-annotations-for-i_data_sem.patch | 148 ++++++++++++++++++ queue-3.14/series | 1 + 2 files changed, 149 insertions(+) create mode 100644 queue-3.14/ext4-add-lockdep-annotations-for-i_data_sem.patch diff --git a/queue-3.14/ext4-add-lockdep-annotations-for-i_data_sem.patch b/queue-3.14/ext4-add-lockdep-annotations-for-i_data_sem.patch new file mode 100644 index 00000000000..7312258c499 --- /dev/null +++ b/queue-3.14/ext4-add-lockdep-annotations-for-i_data_sem.patch @@ -0,0 +1,148 @@ +From daf647d2dd58cec59570d7698a45b98e580f2076 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Fri, 1 Apr 2016 01:31:28 -0400 +Subject: ext4: add lockdep annotations for i_data_sem + +From: Theodore Ts'o + +commit daf647d2dd58cec59570d7698a45b98e580f2076 upstream. + +With the internal Quota feature, mke2fs creates empty quota inodes and +quota usage tracking is enabled as soon as the file system is mounted. +Since quotacheck is no longer preallocating all of the blocks in the +quota inode that are likely needed to be written to, we are now seeing +a lockdep false positive caused by needing to allocate a quota block +from inside ext4_map_blocks(), while holding i_data_sem for a data +inode. This results in this complaint: + + Possible unsafe locking scenario: + + CPU0 CPU1 + ---- ---- + lock(&ei->i_data_sem); + lock(&s->s_dquot.dqio_mutex); + lock(&ei->i_data_sem); + lock(&s->s_dquot.dqio_mutex); + +Google-Bug-Id: 27907753 + +Signed-off-by: Theodore Ts'o +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/ext4.h | 23 +++++++++++++++++++++++ + fs/ext4/move_extent.c | 11 +++++++++-- + fs/ext4/super.c | 25 +++++++++++++++++++++++-- + 3 files changed, 55 insertions(+), 4 deletions(-) + +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -847,6 +847,29 @@ do { \ + #include "extents_status.h" + + /* ++ * Lock subclasses for i_data_sem in the ext4_inode_info structure. ++ * ++ * These are needed to avoid lockdep false positives when we need to ++ * allocate blocks to the quota inode during ext4_map_blocks(), while ++ * holding i_data_sem for a normal (non-quota) inode. Since we don't ++ * do quota tracking for the quota inode, this avoids deadlock (as ++ * well as infinite recursion, since it isn't turtles all the way ++ * down...) ++ * ++ * I_DATA_SEM_NORMAL - Used for most inodes ++ * I_DATA_SEM_OTHER - Used by move_inode.c for the second normal inode ++ * where the second inode has larger inode number ++ * than the first ++ * I_DATA_SEM_QUOTA - Used for quota inodes only ++ */ ++enum { ++ I_DATA_SEM_NORMAL = 0, ++ I_DATA_SEM_OTHER, ++ I_DATA_SEM_QUOTA, ++}; ++ ++ ++/* + * fourth extended file system inode data in memory + */ + struct ext4_inode_info { +--- a/fs/ext4/move_extent.c ++++ b/fs/ext4/move_extent.c +@@ -154,10 +154,10 @@ ext4_double_down_write_data_sem(struct i + { + if (first < second) { + down_write(&EXT4_I(first)->i_data_sem); +- down_write_nested(&EXT4_I(second)->i_data_sem, SINGLE_DEPTH_NESTING); ++ down_write_nested(&EXT4_I(second)->i_data_sem, I_DATA_SEM_OTHER); + } else { + down_write(&EXT4_I(second)->i_data_sem); +- down_write_nested(&EXT4_I(first)->i_data_sem, SINGLE_DEPTH_NESTING); ++ down_write_nested(&EXT4_I(first)->i_data_sem, I_DATA_SEM_OTHER); + + } + } +@@ -1114,6 +1114,13 @@ mext_check_arguments(struct inode *orig_ + return -EINVAL; + } + ++ if (IS_NOQUOTA(orig_inode) || IS_NOQUOTA(donor_inode)) { ++ ext4_debug("ext4 move extent: The argument files should " ++ "not be quota files [ino:orig %lu, donor %lu]\n", ++ orig_inode->i_ino, donor_inode->i_ino); ++ return -EBUSY; ++ } ++ + /* Ext4 move extent supports only extent based file */ + if (!(ext4_test_inode_flag(orig_inode, EXT4_INODE_EXTENTS))) { + ext4_debug("ext4 move extent: orig file is not extents " +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -5123,6 +5123,20 @@ static int ext4_quota_on_mount(struct su + EXT4_SB(sb)->s_jquota_fmt, type); + } + ++static void lockdep_set_quota_inode(struct inode *inode, int subclass) ++{ ++ struct ext4_inode_info *ei = EXT4_I(inode); ++ ++ /* The first argument of lockdep_set_subclass has to be ++ * *exactly* the same as the argument to init_rwsem() --- in ++ * this case, in init_once() --- or lockdep gets unhappy ++ * because the name of the lock is set using the ++ * stringification of the argument to init_rwsem(). ++ */ ++ (void) ei; /* shut up clang warning if !CONFIG_LOCKDEP */ ++ lockdep_set_subclass(&ei->i_data_sem, subclass); ++} ++ + /* + * Standard function to be called on quota_on + */ +@@ -5162,8 +5176,12 @@ static int ext4_quota_on(struct super_bl + if (err) + return err; + } +- +- return dquot_quota_on(sb, type, format_id, path); ++ lockdep_set_quota_inode(path->dentry->d_inode, I_DATA_SEM_QUOTA); ++ err = dquot_quota_on(sb, type, format_id, path); ++ if (err) ++ lockdep_set_quota_inode(path->dentry->d_inode, ++ I_DATA_SEM_NORMAL); ++ return err; + } + + static int ext4_quota_enable(struct super_block *sb, int type, int format_id, +@@ -5189,8 +5207,11 @@ static int ext4_quota_enable(struct supe + + /* Don't account quota for quota files to avoid recursion */ + qf_inode->i_flags |= S_NOQUOTA; ++ lockdep_set_quota_inode(qf_inode, I_DATA_SEM_QUOTA); + err = dquot_enable(qf_inode, type, format_id, flags); + iput(qf_inode); ++ if (err) ++ lockdep_set_quota_inode(qf_inode, I_DATA_SEM_NORMAL); + + return err; + } diff --git a/queue-3.14/series b/queue-3.14/series index 2c269afd82b..b4538b4ed5e 100644 --- a/queue-3.14/series +++ b/queue-3.14/series @@ -26,3 +26,4 @@ ip6_tunnel-set-rtnl_link_ops-before-calling-register_netdevice.patch mac80211-fix-unnecessary-frame-drops-in-mesh-fwding.patch usb-renesas_usbhs-avoid-null-pointer-derefernce-in-usbhsf_pkt_handler.patch usb-renesas_usbhs-disable-tx-irq-before-starting-tx-dmac-transfer.patch +ext4-add-lockdep-annotations-for-i_data_sem.patch -- 2.47.2