From: Greg Kroah-Hartman Date: Wed, 28 Mar 2012 22:31:56 +0000 (-0700) Subject: 3.2-stable patches X-Git-Tag: v3.0.27~29 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0978aa1135530d321306452188aaa0431dd46ee0;p=thirdparty%2Fkernel%2Fstable-queue.git 3.2-stable patches 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 --- diff --git a/queue-3.2/arm-tegra-select-required-cpu-and-l2-errata-options.patch b/queue-3.2/arm-tegra-select-required-cpu-and-l2-errata-options.patch new file mode 100644 index 00000000000..38f2c734555 --- /dev/null +++ b/queue-3.2/arm-tegra-select-required-cpu-and-l2-errata-options.patch @@ -0,0 +1,53 @@ +From f35b431dde39fb40944d1024f08d88fbf04a3193 Mon Sep 17 00:00:00 2001 +From: Stephen Warren +Date: Tue, 14 Feb 2012 13:39:39 -0700 +Subject: ARM: tegra: select required CPU and L2 errata options + +From: Stephen Warren + +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 +Signed-off-by: Olof Johansson +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/mach-tegra/Kconfig | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/arch/arm/mach-tegra/Kconfig ++++ b/arch/arm/mach-tegra/Kconfig +@@ -13,6 +13,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 +@@ -54,6 +61,11 @@ config MACH_SEABOARD + config MACH_TEGRA_DT + bool "Generic Tegra board (FDT 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 generic nVidia Tegra boards using Flattened Device Tree + diff --git a/queue-3.2/ext4-check-for-zero-length-extent.patch b/queue-3.2/ext4-check-for-zero-length-extent.patch new file mode 100644 index 00000000000..efa1c6077a1 --- /dev/null +++ b/queue-3.2/ext4-check-for-zero-length-extent.patch @@ -0,0 +1,39 @@ +From 31d4f3a2f3c73f279ff96a7135d7202ef6833f12 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Sun, 11 Mar 2012 23:30:16 -0400 +Subject: ext4: check for zero length extent + +From: Theodore Ts'o + +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" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/extents.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -301,6 +301,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.2/ext4-fix-race-between-sync-and-completed-io-work.patch b/queue-3.2/ext4-fix-race-between-sync-and-completed-io-work.patch new file mode 100644 index 00000000000..980898267cd --- /dev/null +++ b/queue-3.2/ext4-fix-race-between-sync-and-completed-io-work.patch @@ -0,0 +1,113 @@ +From 491caa43639abcffaa645fbab372a7ef4ce2975c Mon Sep 17 00:00:00 2001 +From: Jeff Moyer +Date: Mon, 5 Mar 2012 10:29:52 -0500 +Subject: ext4: fix race between sync and completed io work + +From: Jeff Moyer + +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 +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -130,12 +130,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 +@@ -148,9 +154,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.2/ext4-fix-race-between-unwritten-extent-conversion-and-truncate.patch b/queue-3.2/ext4-fix-race-between-unwritten-extent-conversion-and-truncate.patch new file mode 100644 index 00000000000..883a9b77e2c --- /dev/null +++ b/queue-3.2/ext4-fix-race-between-unwritten-extent-conversion-and-truncate.patch @@ -0,0 +1,83 @@ +From 266991b13890049ee1a6bb95b9817f06339ee3d7 Mon Sep 17 00:00:00 2001 +From: Jeff Moyer +Date: Mon, 20 Feb 2012 17:59:24 -0500 +Subject: ext4: fix race between unwritten extent conversion and truncate + +From: Jeff Moyer + +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 +Signed-off-by: Jeff Moyer +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -2794,9 +2794,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) +@@ -2920,9 +2917,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 +@@ -111,6 +111,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.2/ext4-ignore-ext4_inode_journal_data-flag-with-delalloc.patch b/queue-3.2/ext4-ignore-ext4_inode_journal_data-flag-with-delalloc.patch new file mode 100644 index 00000000000..e54e22ccf12 --- /dev/null +++ b/queue-3.2/ext4-ignore-ext4_inode_journal_data-flag-with-delalloc.patch @@ -0,0 +1,189 @@ +From 3d2b158262826e8b75bbbfb7b97010838dd92ac7 Mon Sep 17 00:00:00 2001 +From: Lukas Czerner +Date: Mon, 20 Feb 2012 17:53:00 -0500 +Subject: ext4: ignore EXT4_INODE_JOURNAL_DATA flag with delalloc + +From: Lukas Czerner + +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 +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -2480,13 +2480,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(); + } + } +@@ -3084,18 +3085,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.2/jbd2-clear-bh_delay-bh_unwritten-in-journal_unmap_buffer.patch b/queue-3.2/jbd2-clear-bh_delay-bh_unwritten-in-journal_unmap_buffer.patch new file mode 100644 index 00000000000..1215481222d --- /dev/null +++ b/queue-3.2/jbd2-clear-bh_delay-bh_unwritten-in-journal_unmap_buffer.patch @@ -0,0 +1,46 @@ +From 15291164b22a357cb211b618adfef4fa82fc0de3 Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Mon, 20 Feb 2012 17:53:01 -0500 +Subject: jbd2: clear BH_Delay & BH_Unwritten in journal_unmap_buffer + +From: Eric Sandeen + +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 +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/jbd2/transaction.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -1948,6 +1948,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; + } diff --git a/queue-3.2/series b/queue-3.2/series index df27a87b312..fb4a7997be4 100644 --- a/queue-3.2/series +++ b/queue-3.2/series @@ -108,3 +108,10 @@ pvrusb2-fix-7mhz-8mhz-dvb-t-tuner-support-for-hvr1900-rev-d1f5.patch mxl111sf-fix-error-on-stream-stop-in-mxl111sf_ep6_streaming_ctrl.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.2/vfs-fix-d_ancestor-case-in-d_materialize_unique.patch b/queue-3.2/vfs-fix-d_ancestor-case-in-d_materialize_unique.patch new file mode 100644 index 00000000000..04a286b6253 --- /dev/null +++ b/queue-3.2/vfs-fix-d_ancestor-case-in-d_materialize_unique.patch @@ -0,0 +1,52 @@ +From b18dafc86bb879d2f38a1743985d7ceb283c2f4d Mon Sep 17 00:00:00 2001 +From: Michel Lespinasse +Date: Mon, 26 Mar 2012 17:32:44 -0700 +Subject: vfs: fix d_ancestor() case in d_materialize_unique + +From: Michel Lespinasse + +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 +[ 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 +Signed-off-by: Greg Kroah-Hartman + +--- + fs/dcache.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/dcache.c ++++ b/fs/dcache.c +@@ -2357,6 +2357,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? */ +@@ -2366,7 +2367,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);