[RAMEN9610-8702][COMMON] f2fs: support fmp encryption
authorBoojin Kim <boojin.kim@samsung.com>
Thu, 25 Oct 2018 03:20:58 +0000 (12:20 +0900)
committerhskang <hs1218.kang@samsung.com>
Thu, 22 Nov 2018 11:27:00 +0000 (20:27 +0900)
Change-Id: I9ce6fdb2367c031a0b776cb77fb54fac3944a43a
Signed-off-by: Boojin Kim <boojin.kim@samsung.com>
fs/f2fs/data.c
fs/f2fs/f2fs.h

index 0f42c7ae35e6a152bd678dee4673f27ef37e7127..5f86acecfc8195a59f4bc25eecc80bd1f52b7eb3 100644 (file)
@@ -67,6 +67,37 @@ struct bio_post_read_ctx {
        unsigned int enabled_steps;
 };
 
+static inline bool f2fs_may_encrypt_bio(struct inode *inode,
+               struct f2fs_io_info *fio)
+{
+       if (fio && (fio->type != DATA || fio->encrypted_page))
+               return false;
+
+       return (f2fs_encrypted_file(inode) &&
+                       fscrypt_disk_encrypted(inode));
+}
+
+static inline bool f2fs_bio_disk_encrypted(unsigned int bi_opf)
+{
+       if (bi_opf & REQ_CRYPT)
+               return true;
+       else
+               return false;
+}
+
+static bool f2fs_mergeable_bio(struct bio *bio, void *ci, bool bio_encrypted)
+{
+       if (!bio)
+               return true;
+
+       /* if both of them are not encrypted, no further check is needed */
+       if (!f2fs_bio_disk_encrypted(bio->bi_opf) && !bio_encrypted)
+               return true;
+
+       /* ICE allows only consecutive iv_key stream. */
+       return bio->bi_aux_private == ci;
+}
+
 static void __read_end_io(struct bio *bio)
 {
        struct page *page;
@@ -132,6 +163,9 @@ static void f2fs_read_end_io(struct bio *bio)
        }
 #endif
 
+       if(f2fs_bio_disk_encrypted(bio->bi_opf))
+               goto end_io;
+
        if (f2fs_bio_post_read_required(bio)) {
                struct bio_post_read_ctx *ctx = bio->bi_private;
 
@@ -140,6 +174,7 @@ static void f2fs_read_end_io(struct bio *bio)
                return;
        }
 
+end_io:
        __read_end_io(bio);
 }
 
@@ -307,7 +342,10 @@ static void __submit_merged_bio(struct f2fs_bio_info *io)
        if (!io->bio)
                return;
 
-       bio_set_op_attrs(io->bio, fio->op, fio->op_flags);
+       if (f2fs_bio_disk_encrypted(io->bio->bi_opf))
+               bio_set_op_attrs(io->bio, fio->op, fio->op_flags | REQ_CRYPT);
+       else
+               bio_set_op_attrs(io->bio, fio->op, fio->op_flags);
 
        if (is_read_io(fio->op))
                trace_f2fs_prepare_read_bio(io->sbi->sb, fio->type, io->bio);
@@ -439,6 +477,7 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
        struct bio *bio;
        struct page *page = fio->encrypted_page ?
                        fio->encrypted_page : fio->page;
+       struct inode *inode = fio->page->mapping->host;
 
        verify_block_addr(fio, fio->new_blkaddr);
        trace_f2fs_submit_page_bio(page, fio);
@@ -455,6 +494,9 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
        fio->op_flags |= fio->encrypted_page ? REQ_NOENCRYPT : 0;
        bio_set_op_attrs(bio, fio->op, fio->op_flags);
 
+       if (f2fs_may_encrypt_bio(inode, fio))
+               fscrypt_set_bio(inode, bio);
+
        __submit_bio(fio->sbi, bio, fio->type);
 
        if (!is_read_io(fio->op))
@@ -469,6 +511,8 @@ int f2fs_submit_page_write(struct f2fs_io_info *fio)
        struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp;
        struct page *bio_page;
        int err = 0;
+       struct inode *inode;
+       bool bio_encrypted;
 
        f2fs_bug_on(sbi, is_read_io(fio->op));
 
@@ -491,6 +535,8 @@ next:
        verify_block_addr(fio, fio->new_blkaddr);
 
        bio_page = fio->encrypted_page ? fio->encrypted_page : fio->page;
+       inode = fio->page->mapping->host;
+       bio_encrypted = f2fs_may_encrypt_bio(inode, fio);
        fio->op_flags |= fio->encrypted_page ? REQ_NOENCRYPT : 0;
 
        /* set submitted = true as a return value */
@@ -502,6 +548,10 @@ next:
            (io->fio.op != fio->op || io->fio.op_flags != fio->op_flags) ||
                        !__same_bdev(sbi, fio->new_blkaddr, io->bio)))
                __submit_merged_bio(io);
+
+       if (!f2fs_mergeable_bio(io->bio, fscrypt_get_diskcipher(inode), bio_encrypted))
+               __submit_merged_bio(io);
+
 alloc_new:
        if (io->bio == NULL) {
                if ((fio->type == DATA || fio->type == NODE) &&
@@ -513,6 +563,9 @@ alloc_new:
                io->bio = __bio_alloc(sbi, fio->new_blkaddr, fio->io_wbc,
                                                BIO_MAX_PAGES, false,
                                                fio->type, fio->temp);
+               if (bio_encrypted)
+                       fscrypt_set_bio(inode, io->bio);
+
                io->fio = *fio;
        }
 
@@ -551,7 +604,7 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr,
        bio->bi_end_io = f2fs_read_end_io;
        bio_set_op_attrs(bio, REQ_OP_READ, 0);
 
-       if (f2fs_encrypted_file(inode))
+       if (f2fs_encrypted_file(inode) && !fscrypt_disk_encrypted(inode))
                post_read_steps |= 1 << STEP_DECRYPT;
        if (post_read_steps) {
                ctx = mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS);
@@ -587,6 +640,10 @@ static int f2fs_submit_page_read(struct inode *inode, struct page *page,
                bio_put(bio);
                return -EFAULT;
        }
+
+       if (f2fs_may_encrypt_bio(inode, NULL))
+               fscrypt_set_bio(inode, bio);
+
        __submit_bio(F2FS_I_SB(inode), bio, DATA);
        return 0;
 }
@@ -1442,6 +1499,7 @@ static int f2fs_mpage_readpages(struct address_space *mapping,
        sector_t last_block_in_file;
        sector_t block_nr;
        struct f2fs_map_blocks map;
+       bool bio_encrypted;
 
        map.m_pblk = 0;
        map.m_lblk = 0;
@@ -1519,12 +1577,21 @@ submit_and_realloc:
                        __submit_bio(F2FS_I_SB(inode), bio, DATA);
                        bio = NULL;
                }
+
+               bio_encrypted = f2fs_may_encrypt_bio(inode, NULL);
+               if (!f2fs_mergeable_bio(bio, fscrypt_get_diskcipher(inode), bio_encrypted)) {
+                       __submit_bio(F2FS_I_SB(inode), bio, DATA);
+                       bio = NULL;
+               }
+
                if (bio == NULL) {
                        bio = f2fs_grab_read_bio(inode, block_nr, nr_pages);
                        if (IS_ERR(bio)) {
                                bio = NULL;
                                goto set_error_page;
                        }
+                       if (f2fs_may_encrypt_bio(inode, NULL))
+                               fscrypt_set_bio(inode, bio);
                }
 
                if (bio_add_page(bio, page, blocksize, 0) < blocksize)
@@ -1596,6 +1663,9 @@ static int encrypt_one_page(struct f2fs_io_info *fio)
        f2fs_wait_on_block_writeback(fio->sbi, fio->old_blkaddr);
 
 retry_encrypt:
+       if (fscrypt_disk_encrypted(inode))
+               return 0;
+
        fio->encrypted_page = fscrypt_encrypt_page(inode, fio->page,
                        PAGE_SIZE, 0, fio->page->index, gfp_flags);
        if (!IS_ERR(fio->encrypted_page))
index bc633925d7b7ffccd63f678ae399040911202aeb..5be16660cd74160dacd6491d06b53d626b2e761e 100644 (file)
@@ -3279,7 +3279,8 @@ static inline bool f2fs_may_encrypt(struct inode *inode)
 
 static inline bool f2fs_force_buffered_io(struct inode *inode, int rw)
 {
-       return (f2fs_post_read_required(inode) ||
+       return ((f2fs_post_read_required(inode) &&
+                       !fscrypt_disk_encrypted(inode)) ||
                        (rw == WRITE && test_opt(F2FS_I_SB(inode), LFS)) ||
                        F2FS_I_SB(inode)->s_ndevs);
 }