]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.3-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 28 Mar 2012 22:32:02 +0000 (15:32 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 28 Mar 2012 22:32:02 +0000 (15:32 -0700)
added patches:
arm-tegra-select-required-cpu-and-l2-errata-options.patch
ext4-check-for-zero-length-extent.patch
ext4-fix-race-between-sync-and-completed-io-work.patch
ext4-fix-race-between-unwritten-extent-conversion-and-truncate.patch
ext4-ignore-ext4_inode_journal_data-flag-with-delalloc.patch
jbd2-clear-bh_delay-bh_unwritten-in-journal_unmap_buffer.patch
vfs-fix-d_ancestor-case-in-d_materialize_unique.patch

queue-3.3/arm-tegra-select-required-cpu-and-l2-errata-options.patch [new file with mode: 0644]
queue-3.3/ext4-check-for-zero-length-extent.patch [new file with mode: 0644]
queue-3.3/ext4-fix-race-between-sync-and-completed-io-work.patch [new file with mode: 0644]
queue-3.3/ext4-fix-race-between-unwritten-extent-conversion-and-truncate.patch [new file with mode: 0644]
queue-3.3/ext4-ignore-ext4_inode_journal_data-flag-with-delalloc.patch [new file with mode: 0644]
queue-3.3/jbd2-clear-bh_delay-bh_unwritten-in-journal_unmap_buffer.patch [new file with mode: 0644]
queue-3.3/series
queue-3.3/vfs-fix-d_ancestor-case-in-d_materialize_unique.patch [new file with mode: 0644]

diff --git a/queue-3.3/arm-tegra-select-required-cpu-and-l2-errata-options.patch b/queue-3.3/arm-tegra-select-required-cpu-and-l2-errata-options.patch
new file mode 100644 (file)
index 0000000..6e29234
--- /dev/null
@@ -0,0 +1,53 @@
+From f35b431dde39fb40944d1024f08d88fbf04a3193 Mon Sep 17 00:00:00 2001
+From: Stephen Warren <swarren@nvidia.com>
+Date: Tue, 14 Feb 2012 13:39:39 -0700
+Subject: ARM: tegra: select required CPU and L2 errata options
+
+From: Stephen Warren <swarren@nvidia.com>
+
+commit f35b431dde39fb40944d1024f08d88fbf04a3193 upstream.
+
+The ARM IP revisions in Tegra are:
+Tegra20: CPU r1p1, PL310 r2p0
+Tegra30: CPU A01=r2p7/>=A02=r2p9, NEON r2p3-50, PL310 r3p1-50
+
+Based on work by Olof Johansson, although the actual list of errata is
+somewhat different here, since I added a bunch more and removed one PL310
+erratum that doesn't seem applicable.
+
+Signed-off-by: Stephen Warren <swarren@nvidia.com>
+Signed-off-by: Olof Johansson <olof@lixom.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm/mach-tegra/Kconfig |   12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+--- a/arch/arm/mach-tegra/Kconfig
++++ b/arch/arm/mach-tegra/Kconfig
+@@ -10,6 +10,13 @@ config ARCH_TEGRA_2x_SOC
+       select USB_ARCH_HAS_EHCI if USB_SUPPORT
+       select USB_ULPI if USB_SUPPORT
+       select USB_ULPI_VIEWPORT if USB_SUPPORT
++      select ARM_ERRATA_720789
++      select ARM_ERRATA_742230
++      select ARM_ERRATA_751472
++      select ARM_ERRATA_754327
++      select ARM_ERRATA_764369
++      select PL310_ERRATA_727915 if CACHE_L2X0
++      select PL310_ERRATA_769419 if CACHE_L2X0
+       help
+         Support for NVIDIA Tegra AP20 and T20 processors, based on the
+         ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
+@@ -23,6 +30,11 @@ config ARCH_TEGRA_3x_SOC
+       select USB_ULPI if USB_SUPPORT
+       select USB_ULPI_VIEWPORT if USB_SUPPORT
+       select USE_OF
++      select ARM_ERRATA_743622
++      select ARM_ERRATA_751472
++      select ARM_ERRATA_754322
++      select ARM_ERRATA_764369
++      select PL310_ERRATA_769419 if CACHE_L2X0
+       help
+         Support for NVIDIA Tegra T30 processor family, based on the
+         ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
diff --git a/queue-3.3/ext4-check-for-zero-length-extent.patch b/queue-3.3/ext4-check-for-zero-length-extent.patch
new file mode 100644 (file)
index 0000000..5224352
--- /dev/null
@@ -0,0 +1,39 @@
+From 31d4f3a2f3c73f279ff96a7135d7202ef6833f12 Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Sun, 11 Mar 2012 23:30:16 -0400
+Subject: ext4: check for zero length extent
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit 31d4f3a2f3c73f279ff96a7135d7202ef6833f12 upstream.
+
+Explicitly test for an extent whose length is zero, and flag that as a
+corrupted extent.
+
+This avoids a kernel BUG_ON assertion failure.
+
+Tested: Without this patch, the file system image found in
+tests/f_ext_zero_len/image.gz in the latest e2fsprogs sources causes a
+kernel panic.  With this patch, an ext4 file system error is noted
+instead, and the file system is marked as being corrupted.
+
+https://bugzilla.kernel.org/show_bug.cgi?id=42859
+
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/extents.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -300,6 +300,8 @@ static int ext4_valid_extent(struct inod
+       ext4_fsblk_t block = ext4_ext_pblock(ext);
+       int len = ext4_ext_get_actual_len(ext);
++      if (len == 0)
++              return 0;
+       return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len);
+ }
diff --git a/queue-3.3/ext4-fix-race-between-sync-and-completed-io-work.patch b/queue-3.3/ext4-fix-race-between-sync-and-completed-io-work.patch
new file mode 100644 (file)
index 0000000..31fd610
--- /dev/null
@@ -0,0 +1,113 @@
+From 491caa43639abcffaa645fbab372a7ef4ce2975c Mon Sep 17 00:00:00 2001
+From: Jeff Moyer <jmoyer@redhat.com>
+Date: Mon, 5 Mar 2012 10:29:52 -0500
+Subject: ext4: fix race between sync and completed io work
+
+From: Jeff Moyer <jmoyer@redhat.com>
+
+commit 491caa43639abcffaa645fbab372a7ef4ce2975c upstream.
+
+The following command line will leave the aio-stress process unkillable
+on an ext4 file system (in my case, mounted on /mnt/test):
+
+aio-stress -t 20 -s 10 -O -S -o 2 -I 1000 /mnt/test/aiostress.3561.4 /mnt/test/aiostress.3561.4.20 /mnt/test/aiostress.3561.4.19 /mnt/test/aiostress.3561.4.18 /mnt/test/aiostress.3561.4.17 /mnt/test/aiostress.3561.4.16 /mnt/test/aiostress.3561.4.15 /mnt/test/aiostress.3561.4.14 /mnt/test/aiostress.3561.4.13 /mnt/test/aiostress.3561.4.12 /mnt/test/aiostress.3561.4.11 /mnt/test/aiostress.3561.4.10 /mnt/test/aiostress.3561.4.9 /mnt/test/aiostress.3561.4.8 /mnt/test/aiostress.3561.4.7 /mnt/test/aiostress.3561.4.6 /mnt/test/aiostress.3561.4.5 /mnt/test/aiostress.3561.4.4 /mnt/test/aiostress.3561.4.3 /mnt/test/aiostress.3561.4.2
+
+This is using the aio-stress program from the xfstests test suite.
+That particular command line tells aio-stress to do random writes to
+20 files from 20 threads (one thread per file).  The files are NOT
+preallocated, so you will get writes to random offsets within the
+file, thus creating holes and extending i_size.  It also opens the
+file with O_DIRECT and O_SYNC.
+
+On to the problem.  When an I/O requires unwritten extent conversion,
+it is queued onto the completed_io_list for the ext4 inode.  Two code
+paths will pull work items from this list.  The first is the
+ext4_end_io_work routine, and the second is ext4_flush_completed_IO,
+which is called via the fsync path (and O_SYNC handling, as well).
+There are two issues I've found in these code paths.  First, if the
+fsync path beats the work routine to a particular I/O, the work
+routine will free the io_end structure!  It does not take into account
+the fact that the io_end may still be in use by the fsync path.  I've
+fixed this issue by adding yet another IO_END flag, indicating that
+the io_end is being processed by the fsync path.
+
+The second problem is that the work routine will make an assignment to
+io->flag outside of the lock.  I have witnessed this result in a hang
+at umount.  Moving the flag setting inside the lock resolved that
+problem.
+
+The problem was introduced by commit b82e384c7b ("ext4: optimize
+locking for end_io extent conversion"), which first appeared in 3.2.
+As such, the fix should be backported to that release (probably along
+with the unwritten extent conversion race fix).
+
+Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/ext4.h    |    1 +
+ fs/ext4/fsync.c   |    2 ++
+ fs/ext4/page-io.c |    9 +++++++--
+ 3 files changed, 10 insertions(+), 2 deletions(-)
+
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -185,6 +185,7 @@ struct mpage_da_data {
+ #define EXT4_IO_END_ERROR     0x0002
+ #define EXT4_IO_END_QUEUED    0x0004
+ #define EXT4_IO_END_DIRECT    0x0008
++#define EXT4_IO_END_IN_FSYNC  0x0010
+ struct ext4_io_page {
+       struct page     *p_page;
+--- a/fs/ext4/fsync.c
++++ b/fs/ext4/fsync.c
+@@ -89,6 +89,7 @@ int ext4_flush_completed_IO(struct inode
+               io = list_entry(ei->i_completed_io_list.next,
+                               ext4_io_end_t, list);
+               list_del_init(&io->list);
++              io->flag |= EXT4_IO_END_IN_FSYNC;
+               /*
+                * Calling ext4_end_io_nolock() to convert completed
+                * IO to written.
+@@ -108,6 +109,7 @@ int ext4_flush_completed_IO(struct inode
+               if (ret < 0)
+                       ret2 = ret;
+               spin_lock_irqsave(&ei->i_completed_io_lock, flags);
++              io->flag &= ~EXT4_IO_END_IN_FSYNC;
+       }
+       spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
+       return (ret2 < 0) ? ret2 : 0;
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -129,12 +129,18 @@ static void ext4_end_io_work(struct work
+       unsigned long           flags;
+       spin_lock_irqsave(&ei->i_completed_io_lock, flags);
++      if (io->flag & EXT4_IO_END_IN_FSYNC)
++              goto requeue;
+       if (list_empty(&io->list)) {
+               spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
+               goto free;
+       }
+       if (!mutex_trylock(&inode->i_mutex)) {
++              bool was_queued;
++requeue:
++              was_queued = !!(io->flag & EXT4_IO_END_QUEUED);
++              io->flag |= EXT4_IO_END_QUEUED;
+               spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
+               /*
+                * Requeue the work instead of waiting so that the work
+@@ -147,9 +153,8 @@ static void ext4_end_io_work(struct work
+                * yield the cpu if it sees an end_io request that has already
+                * been requeued.
+                */
+-              if (io->flag & EXT4_IO_END_QUEUED)
++              if (was_queued)
+                       yield();
+-              io->flag |= EXT4_IO_END_QUEUED;
+               return;
+       }
+       list_del_init(&io->list);
diff --git a/queue-3.3/ext4-fix-race-between-unwritten-extent-conversion-and-truncate.patch b/queue-3.3/ext4-fix-race-between-unwritten-extent-conversion-and-truncate.patch
new file mode 100644 (file)
index 0000000..daa08ed
--- /dev/null
@@ -0,0 +1,83 @@
+From 266991b13890049ee1a6bb95b9817f06339ee3d7 Mon Sep 17 00:00:00 2001
+From: Jeff Moyer <jmoyer@redhat.com>
+Date: Mon, 20 Feb 2012 17:59:24 -0500
+Subject: ext4: fix race between unwritten extent conversion and truncate
+
+From: Jeff Moyer <jmoyer@redhat.com>
+
+commit 266991b13890049ee1a6bb95b9817f06339ee3d7 upstream.
+
+The following comment in ext4_end_io_dio caught my attention:
+
+       /* XXX: probably should move into the real I/O completion handler */
+        inode_dio_done(inode);
+
+The truncate code takes i_mutex, then calls inode_dio_wait.  Because the
+ext4 code path above will end up dropping the mutex before it is
+reacquired by the worker thread that does the extent conversion, it
+seems to me that the truncate can happen out of order.  Jan Kara
+mentioned that this might result in error messages in the system logs,
+but that should be the extent of the "damage."
+
+The fix is pretty straight-forward: don't call inode_dio_done until the
+extent conversion is complete.
+
+Reviewed-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/ext4.h    |    1 +
+ fs/ext4/inode.c   |   10 +++++-----
+ fs/ext4/page-io.c |    2 ++
+ 3 files changed, 8 insertions(+), 5 deletions(-)
+
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -184,6 +184,7 @@ struct mpage_da_data {
+ #define       EXT4_IO_END_UNWRITTEN   0x0001
+ #define EXT4_IO_END_ERROR     0x0002
+ #define EXT4_IO_END_QUEUED    0x0004
++#define EXT4_IO_END_DIRECT    0x0008
+ struct ext4_io_page {
+       struct page     *p_page;
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2796,9 +2796,6 @@ out:
+       /* queue the work to convert unwritten extents to written */
+       queue_work(wq, &io_end->work);
+-
+-      /* XXX: probably should move into the real I/O completion handler */
+-      inode_dio_done(inode);
+ }
+ static void ext4_end_io_buffer_write(struct buffer_head *bh, int uptodate)
+@@ -2922,9 +2919,12 @@ static ssize_t ext4_ext_direct_IO(int rw
+               iocb->private = NULL;
+               EXT4_I(inode)->cur_aio_dio = NULL;
+               if (!is_sync_kiocb(iocb)) {
+-                      iocb->private = ext4_init_io_end(inode, GFP_NOFS);
+-                      if (!iocb->private)
++                      ext4_io_end_t *io_end =
++                              ext4_init_io_end(inode, GFP_NOFS);
++                      if (!io_end)
+                               return -ENOMEM;
++                      io_end->flag |= EXT4_IO_END_DIRECT;
++                      iocb->private = io_end;
+                       /*
+                        * we save the io structure for current async
+                        * direct IO, so that later ext4_map_blocks()
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -110,6 +110,8 @@ int ext4_end_io_nolock(ext4_io_end_t *io
+       if (io->iocb)
+               aio_complete(io->iocb, io->result, 0);
++      if (io->flag & EXT4_IO_END_DIRECT)
++              inode_dio_done(inode);
+       /* Wake up anyone waiting on unwritten extent conversion */
+       if (atomic_dec_and_test(&EXT4_I(inode)->i_aiodio_unwritten))
+               wake_up_all(ext4_ioend_wq(io->inode));
diff --git a/queue-3.3/ext4-ignore-ext4_inode_journal_data-flag-with-delalloc.patch b/queue-3.3/ext4-ignore-ext4_inode_journal_data-flag-with-delalloc.patch
new file mode 100644 (file)
index 0000000..8633e05
--- /dev/null
@@ -0,0 +1,189 @@
+From 3d2b158262826e8b75bbbfb7b97010838dd92ac7 Mon Sep 17 00:00:00 2001
+From: Lukas Czerner <lczerner@redhat.com>
+Date: Mon, 20 Feb 2012 17:53:00 -0500
+Subject: ext4: ignore EXT4_INODE_JOURNAL_DATA flag with delalloc
+
+From: Lukas Czerner <lczerner@redhat.com>
+
+commit 3d2b158262826e8b75bbbfb7b97010838dd92ac7 upstream.
+
+Ext4 does not support data journalling with delayed allocation enabled.
+We even do not allow to mount the file system with delayed allocation
+and data journalling enabled, however it can be set via FS_IOC_SETFLAGS
+so we can hit the inode with EXT4_INODE_JOURNAL_DATA set even on file
+system mounted with delayed allocation (default) and that's where
+problem arises. The easies way to reproduce this problem is with the
+following set of commands:
+
+ mkfs.ext4 /dev/sdd
+ mount /dev/sdd /mnt/test1
+ dd if=/dev/zero of=/mnt/test1/file bs=1M count=4
+ chattr +j /mnt/test1/file
+ dd if=/dev/zero of=/mnt/test1/file bs=1M count=4 conv=notrunc
+ chattr -j /mnt/test1/file
+
+Additionally it can be reproduced quite reliably with xfstests 272 and
+269. In fact the above reproducer is a part of test 272.
+
+To fix this we should ignore the EXT4_INODE_JOURNAL_DATA inode flag if
+the file system is mounted with delayed allocation. This can be easily
+done by fixing ext4_should_*_data() functions do ignore data journal
+flag when delalloc is set (suggested by Ted). We also have to set the
+appropriate address space operations for the inode (again, ignoring data
+journal flag if delalloc enabled).
+
+Additionally this commit introduces ext4_inode_journal_mode() function
+because ext4_should_*_data() has already had a lot of common code and
+this change is putting it all into one function so it is easier to
+read.
+
+Successfully tested with xfstests in following configurations:
+
+delalloc + data=ordered
+delalloc + data=writeback
+data=journal
+nodelalloc + data=ordered
+nodelalloc + data=writeback
+nodelalloc + data=journal
+
+Signed-off-by: Lukas Czerner <lczerner@redhat.com>
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/ext4_jbd2.h |   56 ++++++++++++++++++++++++++--------------------------
+ fs/ext4/inode.c     |   36 ++++++++++++++++++++-------------
+ 2 files changed, 51 insertions(+), 41 deletions(-)
+
+--- a/fs/ext4/ext4_jbd2.h
++++ b/fs/ext4/ext4_jbd2.h
+@@ -261,43 +261,45 @@ static inline void ext4_update_inode_fsy
+ /* super.c */
+ int ext4_force_commit(struct super_block *sb);
+-static inline int ext4_should_journal_data(struct inode *inode)
++/*
++ * Ext4 inode journal modes
++ */
++#define EXT4_INODE_JOURNAL_DATA_MODE  0x01 /* journal data mode */
++#define EXT4_INODE_ORDERED_DATA_MODE  0x02 /* ordered data mode */
++#define EXT4_INODE_WRITEBACK_DATA_MODE        0x04 /* writeback data mode */
++
++static inline int ext4_inode_journal_mode(struct inode *inode)
+ {
+       if (EXT4_JOURNAL(inode) == NULL)
+-              return 0;
+-      if (!S_ISREG(inode->i_mode))
+-              return 1;
+-      if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
+-              return 1;
+-      if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
+-              return 1;
+-      return 0;
++              return EXT4_INODE_WRITEBACK_DATA_MODE;  /* writeback */
++      /* We do not support data journalling with delayed allocation */
++      if (!S_ISREG(inode->i_mode) ||
++          test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA)
++              return EXT4_INODE_JOURNAL_DATA_MODE;    /* journal data */
++      if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA) &&
++          !test_opt(inode->i_sb, DELALLOC))
++              return EXT4_INODE_JOURNAL_DATA_MODE;    /* journal data */
++      if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
++              return EXT4_INODE_ORDERED_DATA_MODE;    /* ordered */
++      if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
++              return EXT4_INODE_WRITEBACK_DATA_MODE;  /* writeback */
++      else
++              BUG();
++}
++
++static inline int ext4_should_journal_data(struct inode *inode)
++{
++      return ext4_inode_journal_mode(inode) & EXT4_INODE_JOURNAL_DATA_MODE;
+ }
+ static inline int ext4_should_order_data(struct inode *inode)
+ {
+-      if (EXT4_JOURNAL(inode) == NULL)
+-              return 0;
+-      if (!S_ISREG(inode->i_mode))
+-              return 0;
+-      if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
+-              return 0;
+-      if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA)
+-              return 1;
+-      return 0;
++      return ext4_inode_journal_mode(inode) & EXT4_INODE_ORDERED_DATA_MODE;
+ }
+ static inline int ext4_should_writeback_data(struct inode *inode)
+ {
+-      if (EXT4_JOURNAL(inode) == NULL)
+-              return 1;
+-      if (!S_ISREG(inode->i_mode))
+-              return 0;
+-      if (ext4_test_inode_flag(inode, EXT4_INODE_JOURNAL_DATA))
+-              return 0;
+-      if (test_opt(inode->i_sb, DATA_FLAGS) == EXT4_MOUNT_WRITEBACK_DATA)
+-              return 1;
+-      return 0;
++      return ext4_inode_journal_mode(inode) & EXT4_INODE_WRITEBACK_DATA_MODE;
+ }
+ /*
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -2482,13 +2482,14 @@ static int ext4_da_write_end(struct file
+       int write_mode = (int)(unsigned long)fsdata;
+       if (write_mode == FALL_BACK_TO_NONDELALLOC) {
+-              if (ext4_should_order_data(inode)) {
++              switch (ext4_inode_journal_mode(inode)) {
++              case EXT4_INODE_ORDERED_DATA_MODE:
+                       return ext4_ordered_write_end(file, mapping, pos,
+                                       len, copied, page, fsdata);
+-              } else if (ext4_should_writeback_data(inode)) {
++              case EXT4_INODE_WRITEBACK_DATA_MODE:
+                       return ext4_writeback_write_end(file, mapping, pos,
+                                       len, copied, page, fsdata);
+-              } else {
++              default:
+                       BUG();
+               }
+       }
+@@ -3086,18 +3087,25 @@ static const struct address_space_operat
+ void ext4_set_aops(struct inode *inode)
+ {
+-      if (ext4_should_order_data(inode) &&
+-              test_opt(inode->i_sb, DELALLOC))
+-              inode->i_mapping->a_ops = &ext4_da_aops;
+-      else if (ext4_should_order_data(inode))
+-              inode->i_mapping->a_ops = &ext4_ordered_aops;
+-      else if (ext4_should_writeback_data(inode) &&
+-               test_opt(inode->i_sb, DELALLOC))
+-              inode->i_mapping->a_ops = &ext4_da_aops;
+-      else if (ext4_should_writeback_data(inode))
+-              inode->i_mapping->a_ops = &ext4_writeback_aops;
+-      else
++      switch (ext4_inode_journal_mode(inode)) {
++      case EXT4_INODE_ORDERED_DATA_MODE:
++              if (test_opt(inode->i_sb, DELALLOC))
++                      inode->i_mapping->a_ops = &ext4_da_aops;
++              else
++                      inode->i_mapping->a_ops = &ext4_ordered_aops;
++              break;
++      case EXT4_INODE_WRITEBACK_DATA_MODE:
++              if (test_opt(inode->i_sb, DELALLOC))
++                      inode->i_mapping->a_ops = &ext4_da_aops;
++              else
++                      inode->i_mapping->a_ops = &ext4_writeback_aops;
++              break;
++      case EXT4_INODE_JOURNAL_DATA_MODE:
+               inode->i_mapping->a_ops = &ext4_journalled_aops;
++              break;
++      default:
++              BUG();
++      }
+ }
diff --git a/queue-3.3/jbd2-clear-bh_delay-bh_unwritten-in-journal_unmap_buffer.patch b/queue-3.3/jbd2-clear-bh_delay-bh_unwritten-in-journal_unmap_buffer.patch
new file mode 100644 (file)
index 0000000..e7f1192
--- /dev/null
@@ -0,0 +1,46 @@
+From 15291164b22a357cb211b618adfef4fa82fc0de3 Mon Sep 17 00:00:00 2001
+From: Eric Sandeen <sandeen@redhat.com>
+Date: Mon, 20 Feb 2012 17:53:01 -0500
+Subject: jbd2: clear BH_Delay & BH_Unwritten in journal_unmap_buffer
+
+From: Eric Sandeen <sandeen@redhat.com>
+
+commit 15291164b22a357cb211b618adfef4fa82fc0de3 upstream.
+
+journal_unmap_buffer()'s zap_buffer: code clears a lot of buffer head
+state ala discard_buffer(), but does not touch _Delay or _Unwritten as
+discard_buffer() does.
+
+This can be problematic in some areas of the ext4 code which assume
+that if they have found a buffer marked unwritten or delay, then it's
+a live one.  Perhaps those spots should check whether it is mapped
+as well, but if jbd2 is going to tear down a buffer, let's really
+tear it down completely.
+
+Without this I get some fsx failures on sub-page-block filesystems
+up until v3.2, at which point 4e96b2dbbf1d7e81f22047a50f862555a6cb87cb
+and 189e868fa8fdca702eb9db9d8afc46b5cb9144c9 make the failures go
+away, because buried within that large change is some more flag
+clearing.  I still think it's worth doing in jbd2, since
+->invalidatepage leads here directly, and it's the right place
+to clear away these flags.
+
+Signed-off-by: Eric Sandeen <sandeen@redhat.com>
+Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/jbd2/transaction.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -1949,6 +1949,8 @@ zap_buffer_unlocked:
+       clear_buffer_mapped(bh);
+       clear_buffer_req(bh);
+       clear_buffer_new(bh);
++      clear_buffer_delay(bh);
++      clear_buffer_unwritten(bh);
+       bh->b_bdev = NULL;
+       return may_free;
+ }
index aad6f5019f40b38c1281cdf09d103232a62cc29f..c069f3dd4ddc4db69c03c04a90583012773e25fb 100644 (file)
@@ -133,3 +133,10 @@ rtlwifi-convert-to-asynchronous-firmware-load.patch
 staging-r8712u-add-missing-initialization-and-remove-configuration-parameter-config_r8712_ap.patch
 nfsv4-rate-limit-the-state-manager-warning-messages.patch
 pm-hibernate-enable-usermodehelpers-in-hibernate-error-path.patch
+jbd2-clear-bh_delay-bh_unwritten-in-journal_unmap_buffer.patch
+ext4-ignore-ext4_inode_journal_data-flag-with-delalloc.patch
+ext4-fix-race-between-unwritten-extent-conversion-and-truncate.patch
+ext4-fix-race-between-sync-and-completed-io-work.patch
+ext4-check-for-zero-length-extent.patch
+vfs-fix-d_ancestor-case-in-d_materialize_unique.patch
+arm-tegra-select-required-cpu-and-l2-errata-options.patch
diff --git a/queue-3.3/vfs-fix-d_ancestor-case-in-d_materialize_unique.patch b/queue-3.3/vfs-fix-d_ancestor-case-in-d_materialize_unique.patch
new file mode 100644 (file)
index 0000000..c0de4c9
--- /dev/null
@@ -0,0 +1,52 @@
+From b18dafc86bb879d2f38a1743985d7ceb283c2f4d Mon Sep 17 00:00:00 2001
+From: Michel Lespinasse <walken@google.com>
+Date: Mon, 26 Mar 2012 17:32:44 -0700
+Subject: vfs: fix d_ancestor() case in d_materialize_unique
+
+From: Michel Lespinasse <walken@google.com>
+
+commit b18dafc86bb879d2f38a1743985d7ceb283c2f4d upstream.
+
+In d_materialise_unique() there are 3 subcases to the 'aliased dentry'
+case; in two subcases the inode i_lock is properly released but this
+does not occur in the -ELOOP subcase.
+
+This seems to have been introduced by commit 1836750115f2 ("fix loop
+checks in d_materialise_unique()").
+
+Signed-off-by: Michel Lespinasse <walken@google.com>
+[ Added a comment, and moved the unlock to where we generate the -ELOOP,
+  which seems to be more natural.
+
+  You probably can't actually trigger this without a buggy network file
+  server - d_materialize_unique() is for finding aliases on non-local
+  filesystems, and the d_ancestor() case is for a hardlinked directory
+  loop.
+
+  But we should be robust in the case of such buggy servers anyway. ]
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/dcache.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/dcache.c
++++ b/fs/dcache.c
+@@ -2405,6 +2405,7 @@ struct dentry *d_materialise_unique(stru
+                       if (d_ancestor(alias, dentry)) {
+                               /* Check for loops */
+                               actual = ERR_PTR(-ELOOP);
++                              spin_unlock(&inode->i_lock);
+                       } else if (IS_ROOT(alias)) {
+                               /* Is this an anonymous mountpoint that we
+                                * could splice into our tree? */
+@@ -2414,7 +2415,7 @@ struct dentry *d_materialise_unique(stru
+                               goto found;
+                       } else {
+                               /* Nope, but we must(!) avoid directory
+-                               * aliasing */
++                               * aliasing. This drops inode->i_lock */
+                               actual = __d_unalias(inode, dentry, alias);
+                       }
+                       write_sequnlock(&rename_lock);