--- /dev/null
+From ecdd09597a57251323b0de50e3d45e69298c4a83 Mon Sep 17 00:00:00 2001
+From: Ming Lei <tom.leiming@gmail.com>
+Date: Sat, 11 Feb 2017 11:40:45 +0800
+Subject: block/loop: fix race between I/O and set_status
+
+From: Ming Lei <tom.leiming@gmail.com>
+
+commit ecdd09597a57251323b0de50e3d45e69298c4a83 upstream.
+
+Inside set_status, transfer need to setup again, so
+we have to drain IO before the transition, otherwise
+oops may be triggered like the following:
+
+ divide error: 0000 [#1] SMP KASAN
+ CPU: 0 PID: 2935 Comm: loop7 Not tainted 4.10.0-rc7+ #213
+ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs
+ 01/01/2011
+ task: ffff88006ba1e840 task.stack: ffff880067338000
+ RIP: 0010:transfer_xor+0x1d1/0x440 drivers/block/loop.c:110
+ RSP: 0018:ffff88006733f108 EFLAGS: 00010246
+ RAX: 0000000000000000 RBX: ffff8800688d7000 RCX: 0000000000000059
+ RDX: 0000000000000000 RSI: 1ffff1000d743f43 RDI: ffff880068891c08
+ RBP: ffff88006733f160 R08: ffff8800688d7001 R09: 0000000000000000
+ R10: 0000000000000000 R11: 0000000000000000 R12: ffff8800688d7000
+ R13: ffff880067b7d000 R14: dffffc0000000000 R15: 0000000000000000
+ FS: 0000000000000000(0000) GS:ffff88006d000000(0000)
+ knlGS:0000000000000000
+ CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ CR2: 00000000006c17e0 CR3: 0000000066e3b000 CR4: 00000000001406f0
+ Call Trace:
+ lo_do_transfer drivers/block/loop.c:251 [inline]
+ lo_read_transfer drivers/block/loop.c:392 [inline]
+ do_req_filebacked drivers/block/loop.c:541 [inline]
+ loop_handle_cmd drivers/block/loop.c:1677 [inline]
+ loop_queue_work+0xda0/0x49b0 drivers/block/loop.c:1689
+ kthread_worker_fn+0x4c3/0xa30 kernel/kthread.c:630
+ kthread+0x326/0x3f0 kernel/kthread.c:227
+ ret_from_fork+0x31/0x40 arch/x86/entry/entry_64.S:430
+ Code: 03 83 e2 07 41 29 df 42 0f b6 04 30 4d 8d 44 24 01 38 d0 7f 08
+ 84 c0 0f 85 62 02 00 00 44 89 f8 41 0f b6 48 ff 25 ff 01 00 00 99 <f7>
+ 7d c8 48 63 d2 48 03 55 d0 48 89 d0 48 89 d7 48 c1 e8 03 83
+ RIP: transfer_xor+0x1d1/0x440 drivers/block/loop.c:110 RSP:
+ ffff88006733f108
+ ---[ end trace 0166f7bd3b0c0933 ]---
+
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Ming Lei <tom.leiming@gmail.com>
+Tested-by: Dmitry Vyukov <dvyukov@google.com>
+Signed-off-by: Jens Axboe <axboe@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/loop.c | 17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+--- a/drivers/block/loop.c
++++ b/drivers/block/loop.c
+@@ -1108,9 +1108,12 @@ loop_set_status(struct loop_device *lo,
+ if ((unsigned int) info->lo_encrypt_key_size > LO_KEY_SIZE)
+ return -EINVAL;
+
++ /* I/O need to be drained during transfer transition */
++ blk_mq_freeze_queue(lo->lo_queue);
++
+ err = loop_release_xfer(lo);
+ if (err)
+- return err;
++ goto exit;
+
+ if (info->lo_encrypt_type) {
+ unsigned int type = info->lo_encrypt_type;
+@@ -1125,12 +1128,14 @@ loop_set_status(struct loop_device *lo,
+
+ err = loop_init_xfer(lo, xfer, info);
+ if (err)
+- return err;
++ goto exit;
+
+ if (lo->lo_offset != info->lo_offset ||
+ lo->lo_sizelimit != info->lo_sizelimit)
+- if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit))
+- return -EFBIG;
++ if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit)) {
++ err = -EFBIG;
++ goto exit;
++ }
+
+ loop_config_discard(lo);
+
+@@ -1167,7 +1172,9 @@ loop_set_status(struct loop_device *lo,
+ /* update dio if lo_offset or transfer is changed */
+ __loop_update_dio(lo, lo->use_dio);
+
+- return 0;
++ exit:
++ blk_mq_unfreeze_queue(lo->lo_queue);
++ return err;
+ }
+
+ static int
--- /dev/null
+From 03e916fa8b5577d85471452a3d0c5738aa658dae Mon Sep 17 00:00:00 2001
+From: Roman Pen <roman.penyaev@profitbricks.com>
+Date: Sun, 8 Jan 2017 21:00:35 -0500
+Subject: ext4: do not polute the extents cache while shifting extents
+
+From: Roman Pen <roman.penyaev@profitbricks.com>
+
+commit 03e916fa8b5577d85471452a3d0c5738aa658dae upstream.
+
+Inside ext4_ext_shift_extents() function ext4_find_extent() is called
+without EXT4_EX_NOCACHE flag, which should prevent cache population.
+
+This leads to oudated offsets in the extents tree and wrong blocks
+afterwards.
+
+Patch fixes the problem providing EXT4_EX_NOCACHE flag for each
+ext4_find_extents() call inside ext4_ext_shift_extents function.
+
+Fixes: 331573febb6a2
+Signed-off-by: Roman Pen <roman.penyaev@profitbricks.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: Namjae Jeon <namjae.jeon@samsung.com>
+Cc: Andreas Dilger <adilger.kernel@dilger.ca>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/extents.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -5362,7 +5362,8 @@ ext4_ext_shift_extents(struct inode *ino
+ ext4_lblk_t stop, *iterator, ex_start, ex_end;
+
+ /* Let path point to the last extent */
+- path = ext4_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL, 0);
++ path = ext4_find_extent(inode, EXT_MAX_BLOCKS - 1, NULL,
++ EXT4_EX_NOCACHE);
+ if (IS_ERR(path))
+ return PTR_ERR(path);
+
+@@ -5378,7 +5379,8 @@ ext4_ext_shift_extents(struct inode *ino
+ * sure the hole is big enough to accommodate the shift.
+ */
+ if (SHIFT == SHIFT_LEFT) {
+- path = ext4_find_extent(inode, start - 1, &path, 0);
++ path = ext4_find_extent(inode, start - 1, &path,
++ EXT4_EX_NOCACHE);
+ if (IS_ERR(path))
+ return PTR_ERR(path);
+ depth = path->p_depth;
+@@ -5416,7 +5418,8 @@ ext4_ext_shift_extents(struct inode *ino
+ * becomes NULL to indicate the end of the loop.
+ */
+ while (iterator && start <= stop) {
+- path = ext4_find_extent(inode, *iterator, &path, 0);
++ path = ext4_find_extent(inode, *iterator, &path,
++ EXT4_EX_NOCACHE);
+ if (IS_ERR(path))
+ return PTR_ERR(path);
+ depth = path->p_depth;
--- /dev/null
+From 3b136499e906460919f0d21a49db1aaccf0ae963 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Fri, 27 Jan 2017 14:35:38 -0500
+Subject: ext4: fix data corruption in data=journal mode
+
+From: Jan Kara <jack@suse.cz>
+
+commit 3b136499e906460919f0d21a49db1aaccf0ae963 upstream.
+
+ext4_journalled_write_end() did not propely handle all the cases when
+generic_perform_write() did not copy all the data into the target page
+and could mark buffers with uninitialized contents as uptodate and dirty
+leading to possible data corruption (which would be quickly fixed by
+generic_perform_write() retrying the write but still). Fix the problem
+by carefully handling the case when the page that is written to is not
+uptodate.
+
+Reported-by: Al Viro <viro@ZenIV.linux.org.uk>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/inode.c | 23 +++++++++++++----------
+ 1 file changed, 13 insertions(+), 10 deletions(-)
+
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1220,7 +1220,9 @@ errout:
+ * set the buffer to be dirty, since in data=journalled mode we need
+ * to call ext4_handle_dirty_metadata() instead.
+ */
+-static void zero_new_buffers(struct page *page, unsigned from, unsigned to)
++static void ext4_journalled_zero_new_buffers(handle_t *handle,
++ struct page *page,
++ unsigned from, unsigned to)
+ {
+ unsigned int block_start = 0, block_end;
+ struct buffer_head *head, *bh;
+@@ -1237,7 +1239,7 @@ static void zero_new_buffers(struct page
+ size = min(to, block_end) - start;
+
+ zero_user(page, start, size);
+- set_buffer_uptodate(bh);
++ write_end_fn(handle, bh);
+ }
+ clear_buffer_new(bh);
+ }
+@@ -1269,15 +1271,16 @@ static int ext4_journalled_write_end(str
+ if (ext4_has_inline_data(inode))
+ copied = ext4_write_inline_data_end(inode, pos, len,
+ copied, page);
+- else {
+- if (copied < len) {
+- if (!PageUptodate(page))
+- copied = 0;
+- zero_new_buffers(page, from+copied, to);
+- }
+-
++ else if (unlikely(copied < len) && !PageUptodate(page)) {
++ copied = 0;
++ ext4_journalled_zero_new_buffers(handle, page, from, to);
++ } else {
++ if (unlikely(copied < len))
++ ext4_journalled_zero_new_buffers(handle, page,
++ from + copied, to);
+ ret = ext4_walk_page_buffers(handle, page_buffers(page), from,
+- to, &partial, write_end_fn);
++ from + copied, &partial,
++ write_end_fn);
+ if (!partial)
+ SetPageUptodate(page);
+ }
--- /dev/null
+From eb5efbcb762aee4b454b04f7115f73ccbcf8f0ef Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Sat, 4 Feb 2017 23:04:00 -0500
+Subject: ext4: fix inline data error paths
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit eb5efbcb762aee4b454b04f7115f73ccbcf8f0ef upstream.
+
+The write_end() function must always unlock the page and drop its ref
+count, even on an error.
+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/inline.c | 9 ++++++++-
+ fs/ext4/inode.c | 20 +++++++++++++++-----
+ 2 files changed, 23 insertions(+), 6 deletions(-)
+
+--- a/fs/ext4/inline.c
++++ b/fs/ext4/inline.c
+@@ -933,8 +933,15 @@ int ext4_da_write_inline_data_end(struct
+ struct page *page)
+ {
+ int i_size_changed = 0;
++ int ret;
+
+- copied = ext4_write_inline_data_end(inode, pos, len, copied, page);
++ ret = ext4_write_inline_data_end(inode, pos, len, copied, page);
++ if (ret < 0) {
++ unlock_page(page);
++ put_page(page);
++ return ret;
++ }
++ copied = ret;
+
+ /*
+ * No need to use i_size_read() here, the i_size
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1165,8 +1165,11 @@ static int ext4_write_end(struct file *f
+ if (ext4_has_inline_data(inode)) {
+ ret = ext4_write_inline_data_end(inode, pos, len,
+ copied, page);
+- if (ret < 0)
++ if (ret < 0) {
++ unlock_page(page);
++ put_page(page);
+ goto errout;
++ }
+ copied = ret;
+ } else
+ copied = block_write_end(file, mapping, pos,
+@@ -1268,10 +1271,16 @@ static int ext4_journalled_write_end(str
+
+ BUG_ON(!ext4_handle_valid(handle));
+
+- if (ext4_has_inline_data(inode))
+- copied = ext4_write_inline_data_end(inode, pos, len,
+- copied, page);
+- else if (unlikely(copied < len) && !PageUptodate(page)) {
++ if (ext4_has_inline_data(inode)) {
++ ret = ext4_write_inline_data_end(inode, pos, len,
++ copied, page);
++ if (ret < 0) {
++ unlock_page(page);
++ put_page(page);
++ goto errout;
++ }
++ copied = ret;
++ } else if (unlikely(copied < len) && !PageUptodate(page)) {
+ copied = 0;
+ ext4_journalled_zero_new_buffers(handle, page, from, to);
+ } else {
+@@ -1306,6 +1315,7 @@ static int ext4_journalled_write_end(str
+ */
+ ext4_orphan_add(handle, inode);
+
++errout:
+ ret2 = ext4_journal_stop(handle);
+ if (!ret)
+ ret = ret2;
--- /dev/null
+From 2a9b8cba62c0741109c33a2be700ff3d7703a7c2 Mon Sep 17 00:00:00 2001
+From: Roman Pen <roman.penyaev@profitbricks.com>
+Date: Sun, 8 Jan 2017 20:59:35 -0500
+Subject: ext4: Include forgotten start block on fallocate insert range
+
+From: Roman Pen <roman.penyaev@profitbricks.com>
+
+commit 2a9b8cba62c0741109c33a2be700ff3d7703a7c2 upstream.
+
+While doing 'insert range' start block should be also shifted right.
+The bug can be easily reproduced by the following test:
+
+ ptr = malloc(4096);
+ assert(ptr);
+
+ fd = open("./ext4.file", O_CREAT | O_TRUNC | O_RDWR, 0600);
+ assert(fd >= 0);
+
+ rc = fallocate(fd, 0, 0, 8192);
+ assert(rc == 0);
+ for (i = 0; i < 2048; i++)
+ *((unsigned short *)ptr + i) = 0xbeef;
+ rc = pwrite(fd, ptr, 4096, 0);
+ assert(rc == 4096);
+ rc = pwrite(fd, ptr, 4096, 4096);
+ assert(rc == 4096);
+
+ for (block = 2; block < 1000; block++) {
+ rc = fallocate(fd, FALLOC_FL_INSERT_RANGE, 4096, 4096);
+ assert(rc == 0);
+
+ for (i = 0; i < 2048; i++)
+ *((unsigned short *)ptr + i) = block;
+
+ rc = pwrite(fd, ptr, 4096, 4096);
+ assert(rc == 4096);
+ }
+
+Because start block is not included in the range the hole appears at
+the wrong offset (just after the desired offset) and the following
+pwrite() overwrites already existent block, keeping hole untouched.
+
+Simple way to verify wrong behaviour is to check zeroed blocks after
+the test:
+
+ $ hexdump ./ext4.file | grep '0000 0000'
+
+The root cause of the bug is a wrong range (start, stop], where start
+should be inclusive, i.e. [start, stop].
+
+This patch fixes the problem by including start into the range. But
+not to break left shift (range collapse) stop points to the beginning
+of the a block, not to the end.
+
+The other not obvious change is an iterator check on validness in a
+main loop. Because iterator is unsigned the following corner case
+should be considered with care: insert a block at 0 offset, when stop
+variables overflows and never becomes less than start, which is 0.
+To handle this special case iterator is set to NULL to indicate that
+end of the loop is reached.
+
+Fixes: 331573febb6a2
+Signed-off-by: Roman Pen <roman.penyaev@profitbricks.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Cc: Namjae Jeon <namjae.jeon@samsung.com>
+Cc: Andreas Dilger <adilger.kernel@dilger.ca>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/extents.c | 18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+--- a/fs/ext4/extents.c
++++ b/fs/ext4/extents.c
+@@ -5371,8 +5371,7 @@ ext4_ext_shift_extents(struct inode *ino
+ if (!extent)
+ goto out;
+
+- stop = le32_to_cpu(extent->ee_block) +
+- ext4_ext_get_actual_len(extent);
++ stop = le32_to_cpu(extent->ee_block);
+
+ /*
+ * In case of left shift, Don't start shifting extents until we make
+@@ -5411,8 +5410,12 @@ ext4_ext_shift_extents(struct inode *ino
+ else
+ iterator = &stop;
+
+- /* Its safe to start updating extents */
+- while (start < stop) {
++ /*
++ * Its safe to start updating extents. Start and stop are unsigned, so
++ * in case of right shift if extent with 0 block is reached, iterator
++ * becomes NULL to indicate the end of the loop.
++ */
++ while (iterator && start <= stop) {
+ path = ext4_find_extent(inode, *iterator, &path, 0);
+ if (IS_ERR(path))
+ return PTR_ERR(path);
+@@ -5440,8 +5443,11 @@ ext4_ext_shift_extents(struct inode *ino
+ ext4_ext_get_actual_len(extent);
+ } else {
+ extent = EXT_FIRST_EXTENT(path[depth].p_hdr);
+- *iterator = le32_to_cpu(extent->ee_block) > 0 ?
+- le32_to_cpu(extent->ee_block) - 1 : 0;
++ if (le32_to_cpu(extent->ee_block) > 0)
++ *iterator = le32_to_cpu(extent->ee_block) - 1;
++ else
++ /* Beginning is reached, end of the loop */
++ iterator = NULL;
+ /* Update path extent in case we need to stop */
+ while (le32_to_cpu(extent->ee_block) < start)
+ extent++;
--- /dev/null
+From 97abd7d4b5d9c48ec15c425485f054e1c15e591b Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Sat, 4 Feb 2017 23:38:06 -0500
+Subject: ext4: preserve the needs_recovery flag when the journal is aborted
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit 97abd7d4b5d9c48ec15c425485f054e1c15e591b upstream.
+
+If the journal is aborted, the needs_recovery feature flag should not
+be removed. Otherwise, it's the journal might not get replayed and
+this could lead to more data getting lost.
+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/super.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -793,6 +793,7 @@ static void ext4_put_super(struct super_
+ {
+ struct ext4_sb_info *sbi = EXT4_SB(sb);
+ struct ext4_super_block *es = sbi->s_es;
++ int aborted = 0;
+ int i, err;
+
+ ext4_unregister_li_request(sb);
+@@ -802,9 +803,10 @@ static void ext4_put_super(struct super_
+ destroy_workqueue(sbi->rsv_conversion_wq);
+
+ if (sbi->s_journal) {
++ aborted = is_journal_aborted(sbi->s_journal);
+ err = jbd2_journal_destroy(sbi->s_journal);
+ sbi->s_journal = NULL;
+- if (err < 0)
++ if ((err < 0) && !aborted)
+ ext4_abort(sb, "Couldn't clean up the journal");
+ }
+
+@@ -816,7 +818,7 @@ static void ext4_put_super(struct super_
+ ext4_ext_release(sb);
+ ext4_xattr_put_super(sb);
+
+- if (!(sb->s_flags & MS_RDONLY)) {
++ if (!(sb->s_flags & MS_RDONLY) && !aborted) {
+ ext4_clear_feature_journal_needs_recovery(sb);
+ es->s_state = cpu_to_le16(sbi->s_mount_state);
+ }
--- /dev/null
+From 4753d8a24d4588657bc0a4cd66d4e282dff15c8c Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Sun, 5 Feb 2017 01:26:48 -0500
+Subject: ext4: return EROFS if device is r/o and journal replay is needed
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit 4753d8a24d4588657bc0a4cd66d4e282dff15c8c upstream.
+
+If the file system requires journal recovery, and the device is
+read-ony, return EROFS to the mount system call. This allows xfstests
+generic/050 to pass.
+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/super.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3748,7 +3748,8 @@ static int ext4_fill_super(struct super_
+ * root first: it may be modified in the journal!
+ */
+ if (!test_opt(sb, NOLOAD) && ext4_has_feature_journal(sb)) {
+- if (ext4_load_journal(sb, es, journal_devnum))
++ err = ext4_load_journal(sb, es, journal_devnum);
++ if (err)
+ goto failed_mount3a;
+ } else if (test_opt(sb, NOLOAD) && !(sb->s_flags & MS_RDONLY) &&
+ ext4_has_feature_journal_needs_recovery(sb)) {
--- /dev/null
+From cd648b8a8fd5071d232242d5ee7ee3c0815776af Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Fri, 27 Jan 2017 14:34:30 -0500
+Subject: ext4: trim allocation requests to group size
+
+From: Jan Kara <jack@suse.cz>
+
+commit cd648b8a8fd5071d232242d5ee7ee3c0815776af upstream.
+
+If filesystem groups are artifically small (using parameter -g to
+mkfs.ext4), ext4_mb_normalize_request() can result in a request that is
+larger than a block group. Trim the request size to not confuse
+allocation code.
+
+Reported-by: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/mballoc.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -3120,6 +3120,13 @@ ext4_mb_normalize_request(struct ext4_al
+ if (ar->pright && start + size - 1 >= ar->lright)
+ size -= start + size - ar->lright;
+
++ /*
++ * Trim allocation request for filesystems with artificially small
++ * groups.
++ */
++ if (size > EXT4_BLOCKS_PER_GROUP(ac->ac_sb))
++ size = EXT4_BLOCKS_PER_GROUP(ac->ac_sb);
++
+ end = start + size;
+
+ /* check we don't cross already preallocated blocks */
--- /dev/null
+From e112666b4959b25a8552d63bc564e1059be703e8 Mon Sep 17 00:00:00 2001
+From: Theodore Ts'o <tytso@mit.edu>
+Date: Sat, 4 Feb 2017 23:14:19 -0500
+Subject: jbd2: don't leak modified metadata buffers on an aborted journal
+
+From: Theodore Ts'o <tytso@mit.edu>
+
+commit e112666b4959b25a8552d63bc564e1059be703e8 upstream.
+
+If the journal has been aborted, we shouldn't mark the underlying
+buffer head as dirty, since that will cause the metadata block to get
+modified. And if the journal has been aborted, we shouldn't allow
+this since it will almost certainly lead to a corrupted file system.
+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/jbd2/transaction.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -1876,7 +1876,9 @@ static void __jbd2_journal_temp_unlink_b
+
+ __blist_del_buffer(list, jh);
+ jh->b_jlist = BJ_None;
+- if (test_clear_buffer_jbddirty(bh))
++ if (transaction && is_journal_aborted(transaction->t_journal))
++ clear_buffer_jbddirty(bh);
++ else if (test_clear_buffer_jbddirty(bh))
+ mark_buffer_dirty(bh); /* Expose it to the VM */
+ }
+
--- /dev/null
+From e02898b423802b1f3a3aaa7f16e896da069ba8f7 Mon Sep 17 00:00:00 2001
+From: Omar Sandoval <osandov@fb.com>
+Date: Wed, 1 Mar 2017 10:42:38 -0800
+Subject: loop: fix LO_FLAGS_PARTSCAN hang
+
+From: Omar Sandoval <osandov@fb.com>
+
+commit e02898b423802b1f3a3aaa7f16e896da069ba8f7 upstream.
+
+loop_reread_partitions() needs to do I/O, but we just froze the queue,
+so we end up waiting forever. This can easily be reproduced with losetup
+-P. Fix it by moving the reread to after we unfreeze the queue.
+
+Fixes: ecdd09597a57 ("block/loop: fix race between I/O and set_status")
+Reported-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Omar Sandoval <osandov@fb.com>
+Reviewed-by: Ming Lei <tom.leiming@gmail.com>
+Signed-off-by: Jens Axboe <axboe@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/loop.c | 15 ++++++++-------
+ 1 file changed, 8 insertions(+), 7 deletions(-)
+
+--- a/drivers/block/loop.c
++++ b/drivers/block/loop.c
+@@ -1153,13 +1153,6 @@ loop_set_status(struct loop_device *lo,
+ (info->lo_flags & LO_FLAGS_AUTOCLEAR))
+ lo->lo_flags ^= LO_FLAGS_AUTOCLEAR;
+
+- if ((info->lo_flags & LO_FLAGS_PARTSCAN) &&
+- !(lo->lo_flags & LO_FLAGS_PARTSCAN)) {
+- lo->lo_flags |= LO_FLAGS_PARTSCAN;
+- lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN;
+- loop_reread_partitions(lo, lo->lo_device);
+- }
+-
+ lo->lo_encrypt_key_size = info->lo_encrypt_key_size;
+ lo->lo_init[0] = info->lo_init[0];
+ lo->lo_init[1] = info->lo_init[1];
+@@ -1174,6 +1167,14 @@ loop_set_status(struct loop_device *lo,
+
+ exit:
+ blk_mq_unfreeze_queue(lo->lo_queue);
++
++ if (!err && (info->lo_flags & LO_FLAGS_PARTSCAN) &&
++ !(lo->lo_flags & LO_FLAGS_PARTSCAN)) {
++ lo->lo_flags |= LO_FLAGS_PARTSCAN;
++ lo->lo_disk->flags &= ~GENHD_FL_NO_PART_SCAN;
++ loop_reread_partitions(lo, lo->lo_device);
++ }
++
+ return err;
+ }
+
--- /dev/null
+From 916cafdc95843fb9af5fd5f83ca499d75473d107 Mon Sep 17 00:00:00 2001
+From: Mathias Svensson <idolf@google.com>
+Date: Fri, 6 Jan 2017 13:32:39 -0800
+Subject: samples/seccomp: fix 64-bit comparison macros
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mathias Svensson <idolf@google.com>
+
+commit 916cafdc95843fb9af5fd5f83ca499d75473d107 upstream.
+
+There were some bugs in the JNE64 and JLT64 comparision macros. This fixes
+them, improves comments, and cleans up the file while we are at it.
+
+Reported-by: Stephen Röttger <sroettger@google.com>
+Signed-off-by: Mathias Svensson <idolf@google.com>
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: James Morris <james.l.morris@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ samples/seccomp/bpf-helper.h | 125 ++++++++++++++++++++++++-------------------
+ 1 file changed, 72 insertions(+), 53 deletions(-)
+
+--- a/samples/seccomp/bpf-helper.h
++++ b/samples/seccomp/bpf-helper.h
+@@ -138,7 +138,7 @@ union arg64 {
+ #define ARG_32(idx) \
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx))
+
+-/* Loads hi into A and lo in X */
++/* Loads lo into M[0] and hi into M[1] and A */
+ #define ARG_64(idx) \
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, LO_ARG(idx)), \
+ BPF_STMT(BPF_ST, 0), /* lo -> M[0] */ \
+@@ -153,88 +153,107 @@ union arg64 {
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (value), 1, 0), \
+ jt
+
+-/* Checks the lo, then swaps to check the hi. A=lo,X=hi */
++#define JA32(value, jt) \
++ BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (value), 0, 1), \
++ jt
++
++#define JGE32(value, jt) \
++ BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 0, 1), \
++ jt
++
++#define JGT32(value, jt) \
++ BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 0, 1), \
++ jt
++
++#define JLE32(value, jt) \
++ BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 1, 0), \
++ jt
++
++#define JLT32(value, jt) \
++ BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 1, 0), \
++ jt
++
++/*
++ * All the JXX64 checks assume lo is saved in M[0] and hi is saved in both
++ * A and M[1]. This invariant is kept by restoring A if necessary.
++ */
+ #define JEQ64(lo, hi, jt) \
++ /* if (hi != arg.hi) goto NOMATCH; */ \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
+ BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
++ /* if (lo != arg.lo) goto NOMATCH; */ \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 0, 2), \
+- BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
++ BPF_STMT(BPF_LD+BPF_MEM, 1), \
+ jt, \
+- BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
++ BPF_STMT(BPF_LD+BPF_MEM, 1)
+
+ #define JNE64(lo, hi, jt) \
+- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 5, 0), \
+- BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
++ /* if (hi != arg.hi) goto MATCH; */ \
++ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 3), \
++ BPF_STMT(BPF_LD+BPF_MEM, 0), \
++ /* if (lo != arg.lo) goto MATCH; */ \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (lo), 2, 0), \
+- BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
++ BPF_STMT(BPF_LD+BPF_MEM, 1), \
+ jt, \
+- BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
+-
+-#define JA32(value, jt) \
+- BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (value), 0, 1), \
+- jt
++ BPF_STMT(BPF_LD+BPF_MEM, 1)
+
+ #define JA64(lo, hi, jt) \
++ /* if (hi & arg.hi) goto MATCH; */ \
+ BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (hi), 3, 0), \
+- BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
++ BPF_STMT(BPF_LD+BPF_MEM, 0), \
++ /* if (lo & arg.lo) goto MATCH; */ \
+ BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, (lo), 0, 2), \
+- BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
++ BPF_STMT(BPF_LD+BPF_MEM, 1), \
+ jt, \
+- BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
+-
+-#define JGE32(value, jt) \
+- BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 0, 1), \
+- jt
++ BPF_STMT(BPF_LD+BPF_MEM, 1)
+
+-#define JLT32(value, jt) \
+- BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (value), 1, 0), \
+- jt
+-
+-/* Shortcut checking if hi > arg.hi. */
+ #define JGE64(lo, hi, jt) \
++ /* if (hi > arg.hi) goto MATCH; */ \
+ BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \
++ /* if (hi != arg.hi) goto NOMATCH; */ \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
+- BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
++ BPF_STMT(BPF_LD+BPF_MEM, 0), \
++ /* if (lo >= arg.lo) goto MATCH; */ \
+ BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (lo), 0, 2), \
+- BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
++ BPF_STMT(BPF_LD+BPF_MEM, 1), \
+ jt, \
+- BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
+-
+-#define JLT64(lo, hi, jt) \
+- BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \
+- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
+- BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
+- BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 2, 0), \
+- BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
+- jt, \
+- BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
+-
+-#define JGT32(value, jt) \
+- BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 0, 1), \
+- jt
+-
+-#define JLE32(value, jt) \
+- BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (value), 1, 0), \
+- jt
++ BPF_STMT(BPF_LD+BPF_MEM, 1)
+
+-/* Check hi > args.hi first, then do the GE checking */
+ #define JGT64(lo, hi, jt) \
++ /* if (hi > arg.hi) goto MATCH; */ \
+ BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 4, 0), \
++ /* if (hi != arg.hi) goto NOMATCH; */ \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
+- BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
++ BPF_STMT(BPF_LD+BPF_MEM, 0), \
++ /* if (lo > arg.lo) goto MATCH; */ \
+ BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 0, 2), \
+- BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
++ BPF_STMT(BPF_LD+BPF_MEM, 1), \
+ jt, \
+- BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
++ BPF_STMT(BPF_LD+BPF_MEM, 1)
+
+ #define JLE64(lo, hi, jt) \
+- BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (hi), 6, 0), \
+- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 3), \
+- BPF_STMT(BPF_LD+BPF_MEM, 0), /* swap in lo */ \
++ /* if (hi < arg.hi) goto MATCH; */ \
++ BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \
++ /* if (hi != arg.hi) goto NOMATCH; */ \
++ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
++ BPF_STMT(BPF_LD+BPF_MEM, 0), \
++ /* if (lo <= arg.lo) goto MATCH; */ \
+ BPF_JUMP(BPF_JMP+BPF_JGT+BPF_K, (lo), 2, 0), \
+- BPF_STMT(BPF_LD+BPF_MEM, 1), /* passed: swap hi back in */ \
++ BPF_STMT(BPF_LD+BPF_MEM, 1), \
++ jt, \
++ BPF_STMT(BPF_LD+BPF_MEM, 1)
++
++#define JLT64(lo, hi, jt) \
++ /* if (hi < arg.hi) goto MATCH; */ \
++ BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (hi), 0, 4), \
++ /* if (hi != arg.hi) goto NOMATCH; */ \
++ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (hi), 0, 5), \
++ BPF_STMT(BPF_LD+BPF_MEM, 0), \
++ /* if (lo < arg.lo) goto MATCH; */ \
++ BPF_JUMP(BPF_JMP+BPF_JGE+BPF_K, (lo), 2, 0), \
++ BPF_STMT(BPF_LD+BPF_MEM, 1), \
+ jt, \
+- BPF_STMT(BPF_LD+BPF_MEM, 1) /* failed: swap hi back in */
++ BPF_STMT(BPF_LD+BPF_MEM, 1)
+
+ #define LOAD_SYSCALL_NR \
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \
scsi-use-scsi_device_from_queue-for-scsi_dh.patch
sd-get-disk-reference-in-sd_check_events.patch
fix-disable-sys_membarrier-when-nohz_full-is-enabled.patch
+jbd2-don-t-leak-modified-metadata-buffers-on-an-aborted-journal.patch
+block-loop-fix-race-between-i-o-and-set_status.patch
+loop-fix-lo_flags_partscan-hang.patch
+ext4-include-forgotten-start-block-on-fallocate-insert-range.patch
+ext4-do-not-polute-the-extents-cache-while-shifting-extents.patch
+ext4-trim-allocation-requests-to-group-size.patch
+ext4-fix-data-corruption-in-data-journal-mode.patch
+ext4-fix-inline-data-error-paths.patch
+ext4-preserve-the-needs_recovery-flag-when-the-journal-is-aborted.patch
+ext4-return-erofs-if-device-is-r-o-and-journal-replay-is-needed.patch
+samples-seccomp-fix-64-bit-comparison-macros.patch