From 4f27c8b90bd223e967c98dc658961e67b9b864ae Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Tue, 21 Jan 2020 09:25:59 -0800 Subject: [PATCH] ANDROID: ext4, f2fs: enable direct I/O with inline encryption ext4 and f2fs have traditionally not supported direct I/O on encrypted files, since it's difficult to implement with the traditional filesystem-layer encryption. But when inline encryption is used instead, it's straightforward to support direct I/O, as long as the I/O is fully filesystem-block-aligned. Add support for it by: - Making the two generic direct I/O implementations in the kernel, __blockdev_direct_IO() and iomap_dio_rw(), set the encryption context on bios for inline-encrypted files. __blockdev_direct_IO() is used by f2fs, and was used by ext4 in kernel v5.4 and earlier. iomap_dio_rw() is used by ext4 in kernel v5.5 and later. - Making ext4 and f2fs allow direct I/O to encrypted files (rather the current behavior of falling back to buffered I/O) when the file is using inline encryption and the I/O is fully filesystem-block-aligned. Bug: 137270441 Change-Id: I4c8f7497eb8f829d03611d24281113d68c21d4d1 Signed-off-by: Eric Biggers Signed-off-by: Satya Tangirala --- fs/direct-io.c | 5 +++++ fs/ext4/inode.c | 10 ++++++---- fs/f2fs/f2fs.h | 8 +++++++- fs/iomap.c | 6 ++++++ 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/fs/direct-io.c b/fs/direct-io.c index 30bf22c989de..729c59213d2e 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -431,6 +432,7 @@ dio_bio_alloc(struct dio *dio, struct dio_submit *sdio, sector_t first_sector, int nr_vecs) { struct bio *bio; + struct inode *inode = dio->inode; /* * bio_alloc() is guaranteed to return a bio when called with @@ -438,6 +440,9 @@ dio_bio_alloc(struct dio *dio, struct dio_submit *sdio, */ bio = bio_alloc(GFP_KERNEL, nr_vecs); + fscrypt_set_bio_crypt_ctx(bio, inode, + sdio->cur_page_fs_offset >> inode->i_blkbits, + GFP_KERNEL); bio_set_dev(bio, bdev); bio->bi_iter.bi_sector = first_sector; bio_set_op_attrs(bio, dio->op, dio->op_flags); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 0aefed560d91..638151a97bfd 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3850,10 +3850,12 @@ static ssize_t ext4_direct_IO(struct kiocb *iocb, struct iov_iter *iter) ssize_t ret; int rw = iov_iter_rw(iter); -#ifdef CONFIG_FS_ENCRYPTION - if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)) - return 0; -#endif + if (IS_ENABLED(CONFIG_FS_ENCRYPTION) && IS_ENCRYPTED(inode)) { + if (!fscrypt_inode_uses_inline_crypto(inode) || + !IS_ALIGNED(iocb->ki_pos | iov_iter_alignment(iter), + i_blocksize(inode))) + return 0; + } if (fsverity_active(inode)) return 0; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 2c181a4bec9d..7cc17c1640d7 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3733,7 +3733,13 @@ static inline bool f2fs_force_buffered_io(struct inode *inode, struct f2fs_sb_info *sbi = F2FS_I_SB(inode); int rw = iov_iter_rw(iter); - if (f2fs_post_read_required(inode)) + if (IS_ENABLED(CONFIG_FS_ENCRYPTION) && f2fs_encrypted_file(inode)) { + if (!fscrypt_inode_uses_inline_crypto(inode) || + !IS_ALIGNED(iocb->ki_pos | iov_iter_alignment(iter), + F2FS_BLKSIZE)) + return true; + } + if (fsverity_active(inode)) return true; if (f2fs_is_multi_device(sbi)) return true; diff --git a/fs/iomap.c b/fs/iomap.c index 3f5b1655cfce..1e573a59ea71 100644 --- a/fs/iomap.c +++ b/fs/iomap.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -825,10 +826,13 @@ static blk_qc_t iomap_dio_zero(struct iomap_dio *dio, struct iomap *iomap, loff_t pos, unsigned len) { + struct inode *inode = file_inode(dio->iocb->ki_filp); struct page *page = ZERO_PAGE(0); struct bio *bio; bio = bio_alloc(GFP_KERNEL, 1); + fscrypt_set_bio_crypt_ctx(bio, inode, pos >> inode->i_blkbits, + GFP_KERNEL); bio_set_dev(bio, iomap->bdev); bio->bi_iter.bi_sector = iomap->blkno + ((pos - iomap->offset) >> 9); @@ -908,6 +912,8 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length, return 0; bio = bio_alloc(GFP_KERNEL, nr_pages); + fscrypt_set_bio_crypt_ctx(bio, inode, pos >> inode->i_blkbits, + GFP_KERNEL); bio_set_dev(bio, iomap->bdev); bio->bi_iter.bi_sector = iomap->blkno + ((pos - iomap->offset) >> 9);