From ccd9ac1a24f3d553f8e29cb7b8dfa4c6f6338d65 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 14 Jan 2013 11:22:02 -0800 Subject: [PATCH] 3.7-stable patches added patches: ext4-avoid-hang-when-mounting-non-journal-filesystems-with-orphan-list.patch ext4-check-dioread_nolock-on-remount.patch ext4-do-not-try-to-write-superblock-on-ro-remount-w-o-journal.patch ext4-fix-extent-tree-corruption-caused-by-hole-punch.patch ext4-lock-i_mutex-when-truncating-orphan-inodes.patch ext4-release-buffer-in-failed-path-in-dx_probe.patch jbd2-fix-assertion-failure-in-jbd2_journal_flush.patch --- ...journal-filesystems-with-orphan-list.patch | 45 +++++++++++ ...ext4-check-dioread_nolock-on-remount.patch | 78 +++++++++++++++++++ ...superblock-on-ro-remount-w-o-journal.patch | 47 +++++++++++ ...tree-corruption-caused-by-hole-punch.patch | 78 +++++++++++++++++++ ..._mutex-when-truncating-orphan-inodes.patch | 37 +++++++++ ...se-buffer-in-failed-path-in-dx_probe.patch | 32 ++++++++ ...ertion-failure-in-jbd2_journal_flush.patch | 58 ++++++++++++++ queue-3.7/series | 7 ++ 8 files changed, 382 insertions(+) create mode 100644 queue-3.7/ext4-avoid-hang-when-mounting-non-journal-filesystems-with-orphan-list.patch create mode 100644 queue-3.7/ext4-check-dioread_nolock-on-remount.patch create mode 100644 queue-3.7/ext4-do-not-try-to-write-superblock-on-ro-remount-w-o-journal.patch create mode 100644 queue-3.7/ext4-fix-extent-tree-corruption-caused-by-hole-punch.patch create mode 100644 queue-3.7/ext4-lock-i_mutex-when-truncating-orphan-inodes.patch create mode 100644 queue-3.7/ext4-release-buffer-in-failed-path-in-dx_probe.patch create mode 100644 queue-3.7/jbd2-fix-assertion-failure-in-jbd2_journal_flush.patch diff --git a/queue-3.7/ext4-avoid-hang-when-mounting-non-journal-filesystems-with-orphan-list.patch b/queue-3.7/ext4-avoid-hang-when-mounting-non-journal-filesystems-with-orphan-list.patch new file mode 100644 index 00000000000..1cb109985a2 --- /dev/null +++ b/queue-3.7/ext4-avoid-hang-when-mounting-non-journal-filesystems-with-orphan-list.patch @@ -0,0 +1,45 @@ +From 0e9a9a1ad619e7e987815d20262d36a2f95717ca Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Thu, 27 Dec 2012 01:42:50 -0500 +Subject: ext4: avoid hang when mounting non-journal filesystems with orphan list + +From: Theodore Ts'o + +commit 0e9a9a1ad619e7e987815d20262d36a2f95717ca upstream. + +When trying to mount a file system which does not contain a journal, +but which does have a orphan list containing an inode which needs to +be truncated, the mount call with hang forever in +ext4_orphan_cleanup() because ext4_orphan_del() will return +immediately without removing the inode from the orphan list, leading +to an uninterruptible loop in kernel code which will busy out one of +the CPU's on the system. + +This can be trivially reproduced by trying to mount the file system +found in tests/f_orphan_extents_inode/image.gz from the e2fsprogs +source tree. If a malicious user were to put this on a USB stick, and +mount it on a Linux desktop which has automatic mounts enabled, this +could be considered a potential denial of service attack. (Not a big +deal in practice, but professional paranoids worry about such things, +and have even been known to allocate CVE numbers for such problems.) + +Signed-off-by: "Theodore Ts'o" +Reviewed-by: Zheng Liu +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/namei.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -2498,7 +2498,8 @@ int ext4_orphan_del(handle_t *handle, st + struct ext4_iloc iloc; + int err = 0; + +- if (!EXT4_SB(inode->i_sb)->s_journal) ++ if ((!EXT4_SB(inode->i_sb)->s_journal) && ++ !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) + return 0; + + mutex_lock(&EXT4_SB(inode->i_sb)->s_orphan_lock); diff --git a/queue-3.7/ext4-check-dioread_nolock-on-remount.patch b/queue-3.7/ext4-check-dioread_nolock-on-remount.patch new file mode 100644 index 00000000000..8d6c6fe1b72 --- /dev/null +++ b/queue-3.7/ext4-check-dioread_nolock-on-remount.patch @@ -0,0 +1,78 @@ +From 261cb20cb2f0737a247aaf08dff7eb065e3e5b66 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Thu, 20 Dec 2012 00:07:18 -0500 +Subject: ext4: check dioread_nolock on remount + +From: Jan Kara + +commit 261cb20cb2f0737a247aaf08dff7eb065e3e5b66 upstream. + +Currently we allow enabling dioread_nolock mount option on remount for +filesystems where blocksize < PAGE_CACHE_SIZE. This isn't really +supported so fix the bug by moving the check for blocksize != +PAGE_CACHE_SIZE into parse_options(). Change the original PAGE_SIZE to +PAGE_CACHE_SIZE along the way because that's what we are really +interested in. + +Signed-off-by: Jan Kara +Signed-off-by: "Theodore Ts'o" +Reviewed-by: Eric Sandeen +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -1650,9 +1650,7 @@ static int parse_options(char *options, + unsigned int *journal_ioprio, + int is_remount) + { +-#ifdef CONFIG_QUOTA + struct ext4_sb_info *sbi = EXT4_SB(sb); +-#endif + char *p; + substring_t args[MAX_OPT_ARGS]; + int token; +@@ -1701,6 +1699,16 @@ static int parse_options(char *options, + } + } + #endif ++ if (test_opt(sb, DIOREAD_NOLOCK)) { ++ int blocksize = ++ BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size); ++ ++ if (blocksize < PAGE_CACHE_SIZE) { ++ ext4_msg(sb, KERN_ERR, "can't mount with " ++ "dioread_nolock if block size != PAGE_SIZE"); ++ return 0; ++ } ++ } + return 1; + } + +@@ -3446,15 +3454,6 @@ static int ext4_fill_super(struct super_ + clear_opt(sb, DELALLOC); + } + +- blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size); +- if (test_opt(sb, DIOREAD_NOLOCK)) { +- if (blocksize < PAGE_SIZE) { +- ext4_msg(sb, KERN_ERR, "can't mount with " +- "dioread_nolock if block size != PAGE_SIZE"); +- goto failed_mount; +- } +- } +- + sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | + (test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0); + +@@ -3496,6 +3495,7 @@ static int ext4_fill_super(struct super_ + if (!ext4_feature_set_ok(sb, (sb->s_flags & MS_RDONLY))) + goto failed_mount; + ++ blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size); + if (blocksize < EXT4_MIN_BLOCK_SIZE || + blocksize > EXT4_MAX_BLOCK_SIZE) { + ext4_msg(sb, KERN_ERR, diff --git a/queue-3.7/ext4-do-not-try-to-write-superblock-on-ro-remount-w-o-journal.patch b/queue-3.7/ext4-do-not-try-to-write-superblock-on-ro-remount-w-o-journal.patch new file mode 100644 index 00000000000..5d3eaf78cda --- /dev/null +++ b/queue-3.7/ext4-do-not-try-to-write-superblock-on-ro-remount-w-o-journal.patch @@ -0,0 +1,47 @@ +From d096ad0f79a782935d2e06ae8fb235e8c5397775 Mon Sep 17 00:00:00 2001 +From: Michael Tokarev +Date: Tue, 25 Dec 2012 14:08:16 -0500 +Subject: ext4: do not try to write superblock on ro remount w/o journal + +From: Michael Tokarev + +commit d096ad0f79a782935d2e06ae8fb235e8c5397775 upstream. + +When a journal-less ext4 filesystem is mounted on a read-only block +device (blockdev --setro will do), each remount (for other, unrelated, +flags, like suid=>nosuid etc) results in a series of scary messages +from kernel telling about I/O errors on the device. + +This is becauese of the following code ext4_remount(): + + if (sbi->s_journal == NULL) + ext4_commit_super(sb, 1); + +at the end of remount procedure, which forces writing (flushing) of +a superblock regardless whenever it is dirty or not, if the filesystem +is readonly or not, and whenever the device itself is readonly or not. + +We only need call ext4_commit_super when the file system had been +previously mounted read/write. + +Thanks to Eric Sandeen for help in diagnosing this issue. + +Signed-off-By: Michael Tokarev +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -4729,7 +4729,7 @@ static int ext4_remount(struct super_blo + } + + ext4_setup_system_zone(sb); +- if (sbi->s_journal == NULL) ++ if (sbi->s_journal == NULL && !(old_sb_flags & MS_RDONLY)) + ext4_commit_super(sb, 1); + + #ifdef CONFIG_QUOTA diff --git a/queue-3.7/ext4-fix-extent-tree-corruption-caused-by-hole-punch.patch b/queue-3.7/ext4-fix-extent-tree-corruption-caused-by-hole-punch.patch new file mode 100644 index 00000000000..a8af3a8b298 --- /dev/null +++ b/queue-3.7/ext4-fix-extent-tree-corruption-caused-by-hole-punch.patch @@ -0,0 +1,78 @@ +From c36575e663e302dbaa4d16b9c72d2c9a913a9aef Mon Sep 17 00:00:00 2001 +From: Forrest Liu +Date: Mon, 17 Dec 2012 09:55:39 -0500 +Subject: ext4: fix extent tree corruption caused by hole punch + +From: Forrest Liu + +commit c36575e663e302dbaa4d16b9c72d2c9a913a9aef upstream. + +When depth of extent tree is greater than 1, logical start value of +interior node is not correctly updated in ext4_ext_rm_idx. + +Signed-off-by: Forrest Liu +Signed-off-by: "Theodore Ts'o" +Reviewed-by: Ashish Sangwan +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/extents.c | 22 ++++++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -2190,13 +2190,14 @@ errout: + * removes index from the index block. + */ + static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, +- struct ext4_ext_path *path) ++ struct ext4_ext_path *path, int depth) + { + int err; + ext4_fsblk_t leaf; + + /* free index block */ +- path--; ++ depth--; ++ path = path + depth; + leaf = ext4_idx_pblock(path->p_idx); + if (unlikely(path->p_hdr->eh_entries == 0)) { + EXT4_ERROR_INODE(inode, "path->p_hdr->eh_entries == 0"); +@@ -2221,6 +2222,19 @@ static int ext4_ext_rm_idx(handle_t *han + + ext4_free_blocks(handle, inode, NULL, leaf, 1, + EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); ++ ++ while (--depth >= 0) { ++ if (path->p_idx != EXT_FIRST_INDEX(path->p_hdr)) ++ break; ++ path--; ++ err = ext4_ext_get_access(handle, inode, path); ++ if (err) ++ break; ++ path->p_idx->ei_block = (path+1)->p_idx->ei_block; ++ err = ext4_ext_dirty(handle, inode, path); ++ if (err) ++ break; ++ } + return err; + } + +@@ -2557,7 +2571,7 @@ ext4_ext_rm_leaf(handle_t *handle, struc + /* if this leaf is free, then we should + * remove it from index block above */ + if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL) +- err = ext4_ext_rm_idx(handle, inode, path + depth); ++ err = ext4_ext_rm_idx(handle, inode, path, depth); + + out: + return err; +@@ -2760,7 +2774,7 @@ again: + /* index is empty, remove it; + * handle must be already prepared by the + * truncatei_leaf() */ +- err = ext4_ext_rm_idx(handle, inode, path + i); ++ err = ext4_ext_rm_idx(handle, inode, path, i); + } + /* root level has p_bh == NULL, brelse() eats this */ + brelse(path[i].p_bh); diff --git a/queue-3.7/ext4-lock-i_mutex-when-truncating-orphan-inodes.patch b/queue-3.7/ext4-lock-i_mutex-when-truncating-orphan-inodes.patch new file mode 100644 index 00000000000..e12babddc99 --- /dev/null +++ b/queue-3.7/ext4-lock-i_mutex-when-truncating-orphan-inodes.patch @@ -0,0 +1,37 @@ +From 721e3eba21e43532e438652dd8f1fcdfce3187e7 Mon Sep 17 00:00:00 2001 +From: Theodore Ts'o +Date: Thu, 27 Dec 2012 01:42:48 -0500 +Subject: ext4: lock i_mutex when truncating orphan inodes + +From: Theodore Ts'o + +commit 721e3eba21e43532e438652dd8f1fcdfce3187e7 upstream. + +Commit c278531d39 added a warning when ext4_flush_unwritten_io() is +called without i_mutex being taken. It had previously not been taken +during orphan cleanup since races weren't possible at that point in +the mount process, but as a result of this c278531d39, we will now see +a kernel WARN_ON in this case. Take the i_mutex in +ext4_orphan_cleanup() to suppress this warning. + +Reported-by: Alexander Beregalov +Signed-off-by: "Theodore Ts'o" +Reviewed-by: Zheng Liu +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/super.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -2225,7 +2225,9 @@ static void ext4_orphan_cleanup(struct s + __func__, inode->i_ino, inode->i_size); + jbd_debug(2, "truncating inode %lu to %lld bytes\n", + inode->i_ino, inode->i_size); ++ mutex_lock(&inode->i_mutex); + ext4_truncate(inode); ++ mutex_unlock(&inode->i_mutex); + nr_truncates++; + } else { + ext4_msg(sb, KERN_DEBUG, diff --git a/queue-3.7/ext4-release-buffer-in-failed-path-in-dx_probe.patch b/queue-3.7/ext4-release-buffer-in-failed-path-in-dx_probe.patch new file mode 100644 index 00000000000..1b7bdddc0e0 --- /dev/null +++ b/queue-3.7/ext4-release-buffer-in-failed-path-in-dx_probe.patch @@ -0,0 +1,32 @@ +From 0ecaef0644973e9006fdbc6974301047aaff9bc6 Mon Sep 17 00:00:00 2001 +From: Guo Chao +Date: Sun, 6 Jan 2013 23:38:47 -0500 +Subject: ext4: release buffer in failed path in dx_probe() + +From: Guo Chao + +commit 0ecaef0644973e9006fdbc6974301047aaff9bc6 upstream. + +If checksum fails, we should also release the buffer +read from previous iteration. + +Signed-off-by: Guo Chao +Signed-off-by: "Theodore Ts'o" +Reviewed-by: Darrick J. Wong - +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ext4/namei.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/ext4/namei.c ++++ b/fs/ext4/namei.c +@@ -725,7 +725,7 @@ dx_probe(const struct qstr *d_name, stru + ext4_warning(dir->i_sb, "Node failed checksum"); + brelse(bh); + *err = ERR_BAD_DX_DIR; +- goto fail; ++ goto fail2; + } + set_buffer_verified(bh); + diff --git a/queue-3.7/jbd2-fix-assertion-failure-in-jbd2_journal_flush.patch b/queue-3.7/jbd2-fix-assertion-failure-in-jbd2_journal_flush.patch new file mode 100644 index 00000000000..b813d2ced4b --- /dev/null +++ b/queue-3.7/jbd2-fix-assertion-failure-in-jbd2_journal_flush.patch @@ -0,0 +1,58 @@ +From d7961c7fa4d2e3c3f12be67e21ba8799b5a7238a Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 21 Dec 2012 00:15:51 -0500 +Subject: jbd2: fix assertion failure in jbd2_journal_flush() + +From: Jan Kara + +commit d7961c7fa4d2e3c3f12be67e21ba8799b5a7238a upstream. + +The following race is possible between start_this_handle() and someone +calling jbd2_journal_flush(). + +Process A Process B +start_this_handle(). + if (journal->j_barrier_count) # false + if (!journal->j_running_transaction) { #true + read_unlock(&journal->j_state_lock); + jbd2_journal_lock_updates() + jbd2_journal_flush() + write_lock(&journal->j_state_lock); + if (journal->j_running_transaction) { + # false + ... wait for committing trans ... + write_unlock(&journal->j_state_lock); + ... + write_lock(&journal->j_state_lock); + if (!journal->j_running_transaction) { # true + jbd2_get_transaction(journal, new_transaction); + write_unlock(&journal->j_state_lock); + goto repeat; # eventually blocks on j_barrier_count > 0 + ... + J_ASSERT(!journal->j_running_transaction); + # fails + +We fix the race by rechecking j_barrier_count after reacquiring j_state_lock +in exclusive mode. + +Reported-by: yjwsignal@empal.com +Signed-off-by: Jan Kara +Signed-off-by: "Theodore Ts'o" +Signed-off-by: Greg Kroah-Hartman + +--- + fs/jbd2/transaction.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -209,7 +209,8 @@ repeat: + if (!new_transaction) + goto alloc_transaction; + write_lock(&journal->j_state_lock); +- if (!journal->j_running_transaction) { ++ if (!journal->j_running_transaction && ++ !journal->j_barrier_count) { + jbd2_get_transaction(journal, new_transaction); + new_transaction = NULL; + } diff --git a/queue-3.7/series b/queue-3.7/series index 297898e7fa7..268d091871b 100644 --- a/queue-3.7/series +++ b/queue-3.7/series @@ -106,3 +106,10 @@ brcmfmac-fix-parsing-rsn-ie-for-ap-mode.patch video-mxsfb-fix-crash-when-unblanking-the-display.patch samsung-laptop-add-quirk-for-broken-acpi_video-backlight-on-n250p.patch pm-move-disabling-enabling-runtime-pm-to-late-suspend-early-resume.patch +ext4-fix-extent-tree-corruption-caused-by-hole-punch.patch +ext4-check-dioread_nolock-on-remount.patch +jbd2-fix-assertion-failure-in-jbd2_journal_flush.patch +ext4-do-not-try-to-write-superblock-on-ro-remount-w-o-journal.patch +ext4-lock-i_mutex-when-truncating-orphan-inodes.patch +ext4-avoid-hang-when-mounting-non-journal-filesystems-with-orphan-list.patch +ext4-release-buffer-in-failed-path-in-dx_probe.patch -- 2.47.3