[ANDROID] ext4: Set the bio REQ_NOENCRYPT flag
authorMichael Halcrow <mhalcrow@google.com>
Wed, 11 Oct 2017 23:36:05 +0000 (16:36 -0700)
committerhskang <hs1218.kang@samsung.com>
Fri, 14 Sep 2018 03:02:30 +0000 (12:02 +0900)
Sets the REQ_NOENCRYPT flag for I/O requests that ext4 has already
encrypted.  Lower layers such as dm-crypt can observe that flag to
avoid encrypting again if that's how the user configures the
environment.

Conflicts:
fs/ext4/inode.c
fs/ext4/readpage.c

Change-Id: I62a93e480a9f5788070446bd94694dfb9f83c277
Signed-off-by: Michael Halcrow <mhalcrow@google.com>
Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
fs/crypto/bio.c
fs/ext4/ext4.h
fs/ext4/inode.c
fs/ext4/page-io.c
fs/ext4/readpage.c

index 4c38fc438eeeffe57ed79ee37af397c3e277d778..461dde30df7b10db64996023160f58432330a8be 100644 (file)
@@ -141,7 +141,7 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
                bio_set_dev(bio, inode->i_sb->s_bdev);
                bio->bi_iter.bi_sector =
                        pblk << (inode->i_sb->s_blocksize_bits - 9);
-               bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
+               bio_set_op_attrs(bio, REQ_OP_WRITE, REQ_NOENCRYPT);
                ret = bio_add_page(bio, ciphertext_page,
                                        inode->i_sb->s_blocksize, 0);
                if (ret != inode->i_sb->s_blocksize) {
index 69e83cf4c69936a7668b9662d5093f67965a3f43..af982d472cb1c9856095d6957cbc7ae9f527b9e1 100644 (file)
@@ -205,7 +205,10 @@ typedef struct ext4_io_end {
        ssize_t                 size;           /* size of the extent */
 } ext4_io_end_t;
 
+#define EXT4_IO_ENCRYPTED      1
+
 struct ext4_io_submit {
+       unsigned int            io_flags;
        struct writeback_control *io_wbc;
        struct bio              *io_bio;
        ext4_io_end_t           *io_end;
index fdcb9adc43f7a52ded134f8b30579f807d5feca3..295dab557e588df01f46887bdb49fc077a2b8f29 100644 (file)
@@ -1215,19 +1215,21 @@ static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len,
                if (!buffer_uptodate(bh) && !buffer_delay(bh) &&
                    !buffer_unwritten(bh) &&
                    (block_start < from || block_end > to)) {
-                   int bi_opf = 0;
+                       int bi_opf = 0;
 
-                       if (S_ISREG(inode->i_mode) && ext4_encrypted_inode(inode)
-                                       && fscrypt_has_encryption_key(inode)) {
-                                       bh->b_private = fscrypt_get_diskcipher(inode);
-                                       if (bh->b_private)
-                                               bi_opf = REQ_CRYPT | REQ_AUX_PRIV;
+                       decrypt = ext4_encrypted_inode(inode) &&
+                               S_ISREG(inode->i_mode);
+                       bi_opf = decrypt ? REQ_NOENCRYPT : 0;
+                       if (decrypt && fscrypt_has_encryption_key(inode)) {
+                               bh->b_private = fscrypt_get_diskcipher(inode);
+                               if (bh->b_private) {
+                                       bi_opf |= (REQ_CRYPT | REQ_AUX_PRIV);
+                                       decrypt = 0;
                                }
+                       }
                        ll_rw_block(REQ_OP_READ, bi_opf, 1, &bh);
                        crypto_diskcipher_debug(FS_BLOCK_WRITE, bi_opf);
                        *wait_bh++ = bh;
-                       decrypt = ext4_encrypted_inode(inode) &&
-                               S_ISREG(inode->i_mode) && !bh->b_private;
                }
        }
        /*
@@ -3991,6 +3993,7 @@ static int __ext4_block_zero_page_range(handle_t *handle,
        struct inode *inode = mapping->host;
        struct buffer_head *bh;
        struct page *page;
+       bool decrypt;
        int err = 0;
 
        page = find_or_create_page(mapping, from >> PAGE_SHIFT,
@@ -4033,20 +4036,22 @@ static int __ext4_block_zero_page_range(handle_t *handle,
 
        if (!buffer_uptodate(bh)) {
                err = -EIO;
-               if (S_ISREG(inode->i_mode) && ext4_encrypted_inode(inode)
-                               && fscrypt_has_encryption_key(inode))
+               decrypt = S_ISREG(inode->i_mode) &&
+                   ext4_encrypted_inode(inode);
+               if (decrypt && fscrypt_has_encryption_key(inode))
                        bh->b_private = fscrypt_get_diskcipher(inode);
+               else
+                       bh->b_private = NULL;
                if (bh->b_private)
-                       ll_rw_block(REQ_OP_READ, REQ_CRYPT, 1, &bh);
+                       ll_rw_block(REQ_OP_READ, REQ_CRYPT | REQ_NOENCRYPT, 1, &bh);
                else
-                       ll_rw_block(REQ_OP_READ, 0, 1, &bh);
+                       ll_rw_block(REQ_OP_READ, (decrypt ? REQ_NOENCRYPT : 0), 1, &bh);
 
                wait_on_buffer(bh);
                /* Uhhuh. Read error. Complain and punt. */
                if (!buffer_uptodate(bh))
                        goto unlock;
-               if (S_ISREG(inode->i_mode) &&
-                   ext4_encrypted_inode(inode)) {
+               if (decrypt) {
                        /* We expect the key to be set. */
                        BUG_ON(!fscrypt_has_encryption_key(inode));
                        BUG_ON(blocksize != PAGE_SIZE);
index f3f96aacae0d6fdaddeefdff3740b3f4716a29c9..1661d16f39b0db7ed4b13e29ec23ab1d1779944a 100644 (file)
@@ -352,6 +352,8 @@ void ext4_io_submit(struct ext4_io_submit *io)
                int io_op_flags = io->io_wbc->sync_mode == WB_SYNC_ALL ?
                                  REQ_SYNC : 0;
                io->io_bio->bi_write_hint = io->io_end->inode->i_write_hint;
+               if (io->io_flags & EXT4_IO_ENCRYPTED)
+                       io_op_flags |= REQ_NOENCRYPT;
                bio_set_op_attrs(io->io_bio, REQ_OP_WRITE, io_op_flags);
                if (ext4_encrypted_inode(io->io_end->inode) &&
                                S_ISREG(io->io_end->inode->i_mode)) {
@@ -366,6 +368,7 @@ void ext4_io_submit(struct ext4_io_submit *io)
 void ext4_io_submit_init(struct ext4_io_submit *io,
                         struct writeback_control *wbc)
 {
+       io->io_flags = 0;
        io->io_wbc = wbc;
        io->io_bio = NULL;
        io->io_end = NULL;
@@ -508,6 +511,8 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
        do {
                if (!buffer_async_write(bh))
                        continue;
+               if (data_page)
+                       io->io_flags |= EXT4_IO_ENCRYPTED;
                ret = io_submit_add_bh(io, inode,
                                       data_page ? data_page : page, bh);
                if (ret) {
index a82b3a122d3d5b81c814dfc551c603dd5ae650c9..b3a78ae3205a9dd1ec4915b3637ac54a1b80098f 100644 (file)
@@ -302,7 +302,8 @@ int ext4_mpage_readpages(struct address_space *mapping,
                        bio->bi_iter.bi_sector = blocks[0] << (blkbits - 9);
                        bio->bi_end_io = mpage_end_io;
                        bio->bi_private = ctx;
-                       bio_set_op_attrs(bio, REQ_OP_READ, 0);
+                       bio_set_op_attrs(bio, REQ_OP_READ,
+                               ctx ? REQ_NOENCRYPT : 0);
                        if (ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode)) {
                                fscrypt_set_bio(inode, bio);
                                crypto_diskcipher_debug(FS_READP, bio->bi_opf);