--- /dev/null
+From 03a8bb0e53d9562276045bdfcf2b5de2e4cff5a1 Mon Sep 17 00:00:00 2001
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+Date: Tue, 12 Apr 2016 16:05:36 -0700
+Subject: ext4/fscrypto: avoid RCU lookup in d_revalidate
+
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+
+commit 03a8bb0e53d9562276045bdfcf2b5de2e4cff5a1 upstream.
+
+As Al pointed, d_revalidate should return RCU lookup before using d_inode.
+This was originally introduced by:
+commit 34286d666230 ("fs: rcu-walk aware d_revalidate method").
+
+Reported-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Cc: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/crypto.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/fs/ext4/crypto.c
++++ b/fs/ext4/crypto.c
+@@ -34,6 +34,7 @@
+ #include <linux/random.h>
+ #include <linux/scatterlist.h>
+ #include <linux/spinlock_types.h>
++#include <linux/namei.h>
+
+ #include "ext4_extents.h"
+ #include "xattr.h"
+@@ -479,6 +480,9 @@ static int ext4_d_revalidate(struct dent
+ struct ext4_crypt_info *ci;
+ int dir_has_key, cached_with_key;
+
++ if (flags & LOOKUP_RCU)
++ return -ECHILD;
++
+ dir = dget_parent(dentry);
+ if (!ext4_encrypted_inode(d_inode(dir))) {
+ dput(dir);
--- /dev/null
+From fd694733d523df1e0a583cf5c4c08e41d7bf9fa3 Mon Sep 17 00:00:00 2001
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+Date: Sun, 20 Mar 2016 15:33:20 -0700
+Subject: f2fs: cover large section in sanity check of super
+
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+
+commit fd694733d523df1e0a583cf5c4c08e41d7bf9fa3 upstream.
+
+This patch fixes the bug which does not cover a large section case when checking
+the sanity of superblock.
+If f2fs detects misalignment, it will fix the superblock during the mount time,
+so it doesn't need to trigger fsck.f2fs further.
+
+Reported-by: Matthias Prager <linux@matthiasprager.de>
+Reported-by: David Gnedt <david.gnedt@davizone.at>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/f2fs/super.c | 102 +++++++++++++++++++++++++++++++++++---------------------
+ 1 file changed, 65 insertions(+), 37 deletions(-)
+
+--- a/fs/f2fs/super.c
++++ b/fs/f2fs/super.c
+@@ -926,9 +926,25 @@ static loff_t max_file_blocks(void)
+ return result;
+ }
+
++static int __f2fs_commit_super(struct buffer_head *bh,
++ struct f2fs_super_block *super)
++{
++ lock_buffer(bh);
++ if (super)
++ memcpy(bh->b_data + F2FS_SUPER_OFFSET, super, sizeof(*super));
++ set_buffer_uptodate(bh);
++ set_buffer_dirty(bh);
++ unlock_buffer(bh);
++
++ /* it's rare case, we can do fua all the time */
++ return __sync_dirty_buffer(bh, WRITE_FLUSH_FUA);
++}
++
+ static inline bool sanity_check_area_boundary(struct super_block *sb,
+- struct f2fs_super_block *raw_super)
++ struct buffer_head *bh)
+ {
++ struct f2fs_super_block *raw_super = (struct f2fs_super_block *)
++ (bh->b_data + F2FS_SUPER_OFFSET);
+ u32 segment0_blkaddr = le32_to_cpu(raw_super->segment0_blkaddr);
+ u32 cp_blkaddr = le32_to_cpu(raw_super->cp_blkaddr);
+ u32 sit_blkaddr = le32_to_cpu(raw_super->sit_blkaddr);
+@@ -942,6 +958,10 @@ static inline bool sanity_check_area_bou
+ u32 segment_count_main = le32_to_cpu(raw_super->segment_count_main);
+ u32 segment_count = le32_to_cpu(raw_super->segment_count);
+ u32 log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
++ u64 main_end_blkaddr = main_blkaddr +
++ (segment_count_main << log_blocks_per_seg);
++ u64 seg_end_blkaddr = segment0_blkaddr +
++ (segment_count << log_blocks_per_seg);
+
+ if (segment0_blkaddr != cp_blkaddr) {
+ f2fs_msg(sb, KERN_INFO,
+@@ -986,22 +1006,45 @@ static inline bool sanity_check_area_bou
+ return true;
+ }
+
+- if (main_blkaddr + (segment_count_main << log_blocks_per_seg) !=
+- segment0_blkaddr + (segment_count << log_blocks_per_seg)) {
++ if (main_end_blkaddr > seg_end_blkaddr) {
+ f2fs_msg(sb, KERN_INFO,
+- "Wrong MAIN_AREA boundary, start(%u) end(%u) blocks(%u)",
++ "Wrong MAIN_AREA boundary, start(%u) end(%u) block(%u)",
+ main_blkaddr,
+- segment0_blkaddr + (segment_count << log_blocks_per_seg),
++ segment0_blkaddr +
++ (segment_count << log_blocks_per_seg),
+ segment_count_main << log_blocks_per_seg);
+ return true;
++ } else if (main_end_blkaddr < seg_end_blkaddr) {
++ int err = 0;
++ char *res;
++
++ /* fix in-memory information all the time */
++ raw_super->segment_count = cpu_to_le32((main_end_blkaddr -
++ segment0_blkaddr) >> log_blocks_per_seg);
++
++ if (f2fs_readonly(sb) || bdev_read_only(sb->s_bdev)) {
++ res = "internally";
++ } else {
++ err = __f2fs_commit_super(bh, NULL);
++ res = err ? "failed" : "done";
++ }
++ f2fs_msg(sb, KERN_INFO,
++ "Fix alignment : %s, start(%u) end(%u) block(%u)",
++ res, main_blkaddr,
++ segment0_blkaddr +
++ (segment_count << log_blocks_per_seg),
++ segment_count_main << log_blocks_per_seg);
++ if (err)
++ return true;
+ }
+-
+ return false;
+ }
+
+ static int sanity_check_raw_super(struct super_block *sb,
+- struct f2fs_super_block *raw_super)
++ struct buffer_head *bh)
+ {
++ struct f2fs_super_block *raw_super = (struct f2fs_super_block *)
++ (bh->b_data + F2FS_SUPER_OFFSET);
+ unsigned int blocksize;
+
+ if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) {
+@@ -1068,7 +1111,7 @@ static int sanity_check_raw_super(struct
+ }
+
+ /* check CP/SIT/NAT/SSA/MAIN_AREA area boundary */
+- if (sanity_check_area_boundary(sb, raw_super))
++ if (sanity_check_area_boundary(sb, bh))
+ return 1;
+
+ return 0;
+@@ -1144,7 +1187,7 @@ static int read_raw_super_block(struct s
+ {
+ int block;
+ struct buffer_head *bh;
+- struct f2fs_super_block *super, *buf;
++ struct f2fs_super_block *super;
+ int err = 0;
+
+ super = kzalloc(sizeof(struct f2fs_super_block), GFP_KERNEL);
+@@ -1160,11 +1203,8 @@ static int read_raw_super_block(struct s
+ continue;
+ }
+
+- buf = (struct f2fs_super_block *)
+- (bh->b_data + F2FS_SUPER_OFFSET);
+-
+ /* sanity checking of raw super */
+- if (sanity_check_raw_super(sb, buf)) {
++ if (sanity_check_raw_super(sb, bh)) {
+ f2fs_msg(sb, KERN_ERR,
+ "Can't find valid F2FS filesystem in %dth superblock",
+ block + 1);
+@@ -1174,7 +1214,8 @@ static int read_raw_super_block(struct s
+ }
+
+ if (!*raw_super) {
+- memcpy(super, buf, sizeof(*super));
++ memcpy(super, bh->b_data + F2FS_SUPER_OFFSET,
++ sizeof(*super));
+ *valid_super_block = block;
+ *raw_super = super;
+ }
+@@ -1194,42 +1235,29 @@ static int read_raw_super_block(struct s
+ return err;
+ }
+
+-static int __f2fs_commit_super(struct f2fs_sb_info *sbi, int block)
++int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover)
+ {
+- struct f2fs_super_block *super = F2FS_RAW_SUPER(sbi);
+ struct buffer_head *bh;
+ int err;
+
+- bh = sb_getblk(sbi->sb, block);
++ /* write back-up superblock first */
++ bh = sb_getblk(sbi->sb, sbi->valid_super_block ? 0: 1);
+ if (!bh)
+ return -EIO;
+-
+- lock_buffer(bh);
+- memcpy(bh->b_data + F2FS_SUPER_OFFSET, super, sizeof(*super));
+- set_buffer_uptodate(bh);
+- set_buffer_dirty(bh);
+- unlock_buffer(bh);
+-
+- /* it's rare case, we can do fua all the time */
+- err = __sync_dirty_buffer(bh, WRITE_FLUSH_FUA);
++ err = __f2fs_commit_super(bh, F2FS_RAW_SUPER(sbi));
+ brelse(bh);
+
+- return err;
+-}
+-
+-int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover)
+-{
+- int err;
+-
+- /* write back-up superblock first */
+- err = __f2fs_commit_super(sbi, sbi->valid_super_block ? 0 : 1);
+-
+ /* if we are in recovery path, skip writing valid superblock */
+ if (recover || err)
+ return err;
+
+ /* write current valid superblock */
+- return __f2fs_commit_super(sbi, sbi->valid_super_block);
++ bh = sb_getblk(sbi->sb, sbi->valid_super_block);
++ if (!bh)
++ return -EIO;
++ err = __f2fs_commit_super(bh, F2FS_RAW_SUPER(sbi));
++ brelse(bh);
++ return err;
+ }
+
+ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
--- /dev/null
+From ae1086686487f13130937918ca91d920c1daafcb Mon Sep 17 00:00:00 2001
+From: Chao Yu <chao2.yu@samsung.com>
+Date: Sun, 14 Feb 2016 18:58:35 +0800
+Subject: f2fs crypto: handle unexpected lack of encryption keys
+
+From: Chao Yu <chao2.yu@samsung.com>
+
+commit ae1086686487f13130937918ca91d920c1daafcb upstream.
+
+This patch syncs f2fs with commit abdd438b26b4 ("ext4 crypto: handle
+unexpected lack of encryption keys") from ext4.
+
+Fix up attempts by users to try to write to a file when they don't
+have access to the encryption key.
+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Chao Yu <chao2.yu@samsung.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/f2fs/crypto_policy.c | 3 ++-
+ fs/f2fs/file.c | 6 +++++-
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+--- a/fs/f2fs/crypto_policy.c
++++ b/fs/f2fs/crypto_policy.c
+@@ -192,7 +192,8 @@ int f2fs_inherit_context(struct inode *p
+ return res;
+
+ ci = F2FS_I(parent)->i_crypt_info;
+- BUG_ON(ci == NULL);
++ if (ci == NULL)
++ return -ENOKEY;
+
+ ctx.format = F2FS_ENCRYPTION_CONTEXT_FORMAT_V1;
+
+--- a/fs/f2fs/file.c
++++ b/fs/f2fs/file.c
+@@ -425,6 +425,8 @@ static int f2fs_file_mmap(struct file *f
+ err = f2fs_get_encryption_info(inode);
+ if (err)
+ return 0;
++ if (!f2fs_encrypted_inode(inode))
++ return -ENOKEY;
+ }
+
+ /* we don't need to use inline_data strictly */
+@@ -444,7 +446,9 @@ static int f2fs_file_open(struct inode *
+ if (!ret && f2fs_encrypted_inode(inode)) {
+ ret = f2fs_get_encryption_info(inode);
+ if (ret)
+- ret = -EACCES;
++ return -EACCES;
++ if (!f2fs_encrypted_inode(inode))
++ return -ENOKEY;
+ }
+ return ret;
+ }
--- /dev/null
+From ed3360abbc0412f32c398e1c58887d74f3d04225 Mon Sep 17 00:00:00 2001
+From: Chao Yu <chao2.yu@samsung.com>
+Date: Sun, 14 Feb 2016 18:56:55 +0800
+Subject: f2fs crypto: make sure the encryption info is initialized on opendir(2)
+
+From: Chao Yu <chao2.yu@samsung.com>
+
+commit ed3360abbc0412f32c398e1c58887d74f3d04225 upstream.
+
+This patch syncs f2fs with commit 6bc445e0ff44 ("ext4 crypto: make
+sure the encryption info is initialized on opendir(2)") from ext4.
+
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Chao Yu <chao2.yu@samsung.com>
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/f2fs/dir.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/fs/f2fs/dir.c
++++ b/fs/f2fs/dir.c
+@@ -892,11 +892,19 @@ out:
+ return err;
+ }
+
++static int f2fs_dir_open(struct inode *inode, struct file *filp)
++{
++ if (f2fs_encrypted_inode(inode))
++ return f2fs_get_encryption_info(inode) ? -EACCES : 0;
++ return 0;
++}
++
+ const struct file_operations f2fs_dir_operations = {
+ .llseek = generic_file_llseek,
+ .read = generic_read_dir,
+ .iterate = f2fs_readdir,
+ .fsync = f2fs_sync_file,
++ .open = f2fs_dir_open,
+ .unlocked_ioctl = f2fs_ioctl,
+ #ifdef CONFIG_COMPAT
+ .compat_ioctl = f2fs_compat_ioctl,
--- /dev/null
+From 3c082b7b5b28be606ed9ef11e4741df7c722c92e Mon Sep 17 00:00:00 2001
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+Date: Sat, 23 Jan 2016 13:35:18 -0800
+Subject: f2fs: do f2fs_balance_fs when block is allocated
+
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+
+commit 3c082b7b5b28be606ed9ef11e4741df7c722c92e upstream.
+
+We should consider data block allocation to trigger f2fs_balance_fs.
+
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/f2fs/data.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -504,7 +504,7 @@ static int __allocate_data_blocks(struct
+ struct dnode_of_data dn;
+ u64 start = F2FS_BYTES_TO_BLK(offset);
+ u64 len = F2FS_BYTES_TO_BLK(count);
+- bool allocated;
++ bool allocated = false;
+ u64 end_offset;
+ int err = 0;
+
+@@ -546,7 +546,7 @@ static int __allocate_data_blocks(struct
+ f2fs_put_dnode(&dn);
+ f2fs_unlock_op(sbi);
+
+- f2fs_balance_fs(sbi, dn.node_changed);
++ f2fs_balance_fs(sbi, allocated);
+ }
+ return err;
+
+@@ -556,7 +556,7 @@ sync_out:
+ f2fs_put_dnode(&dn);
+ out:
+ f2fs_unlock_op(sbi);
+- f2fs_balance_fs(sbi, dn.node_changed);
++ f2fs_balance_fs(sbi, allocated);
+ return err;
+ }
+
+@@ -650,14 +650,14 @@ get_next:
+ if (dn.ofs_in_node >= end_offset) {
+ if (allocated)
+ sync_inode_page(&dn);
+- allocated = false;
+ f2fs_put_dnode(&dn);
+
+ if (create) {
+ f2fs_unlock_op(sbi);
+- f2fs_balance_fs(sbi, dn.node_changed);
++ f2fs_balance_fs(sbi, allocated);
+ f2fs_lock_op(sbi);
+ }
++ allocated = false;
+
+ set_new_dnode(&dn, inode, NULL, NULL, 0);
+ err = get_dnode_of_data(&dn, pgofs, mode);
+@@ -715,7 +715,7 @@ put_out:
+ unlock_out:
+ if (create) {
+ f2fs_unlock_op(sbi);
+- f2fs_balance_fs(sbi, dn.node_changed);
++ f2fs_balance_fs(sbi, allocated);
+ }
+ out:
+ trace_f2fs_map_blocks(inode, map, err);
--- /dev/null
+From e3ef18762f5757d3fb86f75ca59315db6d17d719 Mon Sep 17 00:00:00 2001
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+Date: Mon, 25 Jan 2016 14:31:58 -0800
+Subject: f2fs: don't need to call set_page_dirty for io error
+
+From: Jaegeuk Kim <jaegeuk@kernel.org>
+
+commit e3ef18762f5757d3fb86f75ca59315db6d17d719 upstream.
+
+If end_io gets an error, we don't need to set the page as dirty, since we
+already set f2fs_stop_checkpoint which will not flush any data.
+
+This will resolve the following warning.
+
+======================================================
+[ INFO: HARDIRQ-safe -> HARDIRQ-unsafe lock order detected ]
+4.4.0+ #9 Tainted: G O
+------------------------------------------------------
+xfs_io/26773 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire:
+ (&(&sbi->inode_lock[i])->rlock){+.+...}, at: [<ffffffffc025483f>] update_dirty_page+0x6f/0xd0 [f2fs]
+
+and this task is already holding:
+ (&(&q->__queue_lock)->rlock){-.-.-.}, at: [<ffffffff81396ea2>] blk_queue_bio+0x422/0x490
+which would create a new lock dependency:
+ (&(&q->__queue_lock)->rlock){-.-.-.} -> (&(&sbi->inode_lock[i])->rlock){+.+...}
+
+Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/f2fs/data.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/fs/f2fs/data.c
++++ b/fs/f2fs/data.c
+@@ -67,7 +67,6 @@ static void f2fs_write_end_io(struct bio
+ f2fs_restore_and_release_control_page(&page);
+
+ if (unlikely(bio->bi_error)) {
+- set_page_dirty(page);
+ set_bit(AS_EIO, &page->mapping->flags);
+ f2fs_stop_checkpoint(sbi);
+ }
ext4-fix-null-pointer-dereference-in-ext4_mark_inode_dirty.patch
f2fs-crypto-fix-corrupted-symlink-in-encrypted-case.patch
f2fs-slightly-reorganize-read_raw_super_block.patch
+f2fs-cover-large-section-in-sanity-check-of-super.patch
+ext4-fscrypto-avoid-rcu-lookup-in-d_revalidate.patch
+f2fs-do-f2fs_balance_fs-when-block-is-allocated.patch
+f2fs-don-t-need-to-call-set_page_dirty-for-io-error.patch
+f2fs-crypto-handle-unexpected-lack-of-encryption-keys.patch
+f2fs-crypto-make-sure-the-encryption-info-is-initialized-on-opendir-2.patch