]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 17 Apr 2016 10:38:19 +0000 (03:38 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 17 Apr 2016 10:38:19 +0000 (03:38 -0700)
added patches:
ext4-add-lockdep-annotations-for-i_data_sem.patch

queue-3.14/ext4-add-lockdep-annotations-for-i_data_sem.patch [new file with mode: 0644]
queue-3.14/series

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 (file)
index 0000000..7312258
--- /dev/null
@@ -0,0 +1,148 @@
+From daf647d2dd58cec59570d7698a45b98e580f2076 Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Fri, 1 Apr 2016 01:31:28 -0400
+Subject: ext4: add lockdep annotations for i_data_sem
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+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 <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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;
+ }
index 2c269afd82b5dc37d271a62154d5a81d4f08ed65..b4538b4ed5eb3e8e080ff44dd908525c37a161d3 100644 (file)
@@ -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