Reserve code points for project quota and adjust codepoints used by
[ext4-patch-queue.git] / fix-bugs-in-ext4_encrypted_zeroout
blob841dbd4483602b17786fc2a8917b2b47d3a3f70c
1 ext4 crypto: fix bugs in ext4_encrypted_zeroout()
3 Fix multiple bugs in ext4_encrypted_zeroout(), including one that
4 could cause us to write an encrypted zero page to the wrong location
5 on disk, potentially causing data and file system corruption.
6 Fortunately, this tends to only show up in stress tests, but even with
7 these fixes, we are seeing some test failures with generic/127 --- but
8 these are now caused by data failures instead of metadata corruption.
10 Since ext4_encrypted_zeroout() is only used for some optimizations to
11 keep the extent tree from being too fragmented, and
12 ext4_encrypted_zeroout() itself isn't all that optimized from a time
13 or IOPS perspective, disable the extent tree optimization for
14 encrypted inodes for now.  This prevents the data corruption issues
15 reported by generic/127 until we can figure out what's going wrong.
17 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
18 Cc: stable@vger.kernel.org
19 ---
20  fs/ext4/crypto.c  | 23 +++++++++++++++++++----
21  fs/ext4/extents.c |  3 +++
22  2 files changed, 22 insertions(+), 4 deletions(-)
24 diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
25 index 3a5a7a2..b4bb1f8 100644
26 --- a/fs/ext4/crypto.c
27 +++ b/fs/ext4/crypto.c
28 @@ -393,7 +393,13 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex)
29         ext4_lblk_t             lblk = ex->ee_block;
30         ext4_fsblk_t            pblk = ext4_ext_pblock(ex);
31         unsigned int            len = ext4_ext_get_actual_len(ex);
32 -       int                     err = 0;
33 +       int                     ret, err = 0;
35 +#if 0
36 +       ext4_msg(inode->i_sb, KERN_CRIT,
37 +                "ext4_encrypted_zeroout ino %lu lblk %u len %u",
38 +                (unsigned long) inode->i_ino, lblk, len);
39 +#endif
41         BUG_ON(inode->i_sb->s_blocksize != PAGE_CACHE_SIZE);
43 @@ -419,17 +425,26 @@ int ext4_encrypted_zeroout(struct inode *inode, struct ext4_extent *ex)
44                         goto errout;
45                 }
46                 bio->bi_bdev = inode->i_sb->s_bdev;
47 -               bio->bi_iter.bi_sector = pblk;
48 -               err = bio_add_page(bio, ciphertext_page,
49 +               bio->bi_iter.bi_sector =
50 +                       pblk << (inode->i_sb->s_blocksize_bits - 9);
51 +               ret = bio_add_page(bio, ciphertext_page,
52                                    inode->i_sb->s_blocksize, 0);
53 -               if (err) {
54 +               if (ret != inode->i_sb->s_blocksize) {
55 +                       /* should never happen! */
56 +                       ext4_msg(inode->i_sb, KERN_ERR,
57 +                                "bio_add_page failed: %d", ret);
58 +                       WARN_ON(1);
59                         bio_put(bio);
60 +                       err = -EIO;
61                         goto errout;
62                 }
63                 err = submit_bio_wait(WRITE, bio);
64 +               if ((err == 0) && bio->bi_error)
65 +                       err = -EIO;
66                 bio_put(bio);
67                 if (err)
68                         goto errout;
69 +               lblk++; pblk++;
70         }
71         err = 0;
72  errout:
73 diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
74 index 2553aa8..7f486e3 100644
75 --- a/fs/ext4/extents.c
76 +++ b/fs/ext4/extents.c
77 @@ -3558,6 +3558,9 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
78                 max_zeroout = sbi->s_extent_max_zeroout_kb >>
79                         (inode->i_sb->s_blocksize_bits - 10);
81 +       if (ext4_encrypted_inode(inode))
82 +               max_zeroout = 0;
84         /* If extent is less than s_max_zeroout_kb, zeroout directly */
85         if (max_zeroout && (ee_len <= max_zeroout)) {
86                 err = ext4_ext_zeroout(inode, ex);