ANDROID: revert fscrypt direct I/O support
Revert the direct I/O support for encrypted files so that we can bring in the latest version of the patches from the mailing list. This is needed because in v5.5 and later, the ext4 support (via fs/iomap/) is broken as-is -- not only is the second call to fscrypt_limit_dio_pages() in the wrong place, but bios can exceed the intended nr_pages limit due to multipage bvecs. In order to fix this we need the v6 patches which make fs/ext4/ handle the limiting instead of fs/iomap/. On android-mainline, this fixes a failure in vts_kernel_encryption_test (specifically, FBEPolicyTest#TestAesEmmcOptimizedPolicy) when run on a device that uses the inlinecrypt mount option on ext4 (e.g. db845c). Bug: 162255927 Bug: 171462575 Change-Id: I0da753dc9e0e7bc8d84bbcadfdfcdb9328cdb8d8 Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Satya Tangirala <satyat@google.com>
This commit is contained in:
committed by
Satya Tangirala
parent
9af429562a
commit
d44ddbf417
@@ -69,14 +69,6 @@ void fscrypt_free_bounce_page(struct page *bounce_page)
|
||||
}
|
||||
EXPORT_SYMBOL(fscrypt_free_bounce_page);
|
||||
|
||||
/*
|
||||
* Generate the IV for the given logical block number within the given file.
|
||||
* For filenames encryption, lblk_num == 0.
|
||||
*
|
||||
* Keep this in sync with fscrypt_limit_dio_pages(). fscrypt_limit_dio_pages()
|
||||
* needs to know about any IV generation methods where the low bits of IV don't
|
||||
* simply contain the lblk_num (e.g., IV_INO_LBLK_32).
|
||||
*/
|
||||
void fscrypt_generate_iv(union fscrypt_iv *iv, u64 lblk_num,
|
||||
const struct fscrypt_info *ci)
|
||||
{
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include <linux/keyslot-manager.h>
|
||||
#include <linux/sched/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uio.h>
|
||||
|
||||
#include "fscrypt_private.h"
|
||||
|
||||
@@ -400,74 +399,3 @@ bool fscrypt_mergeable_bio_bh(struct bio *bio,
|
||||
return fscrypt_mergeable_bio(bio, inode, next_lblk);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio_bh);
|
||||
|
||||
/**
|
||||
* fscrypt_dio_supported() - check whether a direct I/O request is unsupported
|
||||
* due to encryption constraints
|
||||
* @iocb: the file and position the I/O is targeting
|
||||
* @iter: the I/O data segment(s)
|
||||
*
|
||||
* Return: true if direct I/O is supported
|
||||
*/
|
||||
bool fscrypt_dio_supported(struct kiocb *iocb, struct iov_iter *iter)
|
||||
{
|
||||
const struct inode *inode = file_inode(iocb->ki_filp);
|
||||
const unsigned int blocksize = i_blocksize(inode);
|
||||
|
||||
/* If the file is unencrypted, no veto from us. */
|
||||
if (!fscrypt_needs_contents_encryption(inode))
|
||||
return true;
|
||||
|
||||
/* We only support direct I/O with inline crypto, not fs-layer crypto */
|
||||
if (!fscrypt_inode_uses_inline_crypto(inode))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Since the granularity of encryption is filesystem blocks, the I/O
|
||||
* must be block aligned -- not just disk sector aligned.
|
||||
*/
|
||||
if (!IS_ALIGNED(iocb->ki_pos | iov_iter_alignment(iter), blocksize))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fscrypt_dio_supported);
|
||||
|
||||
/**
|
||||
* fscrypt_limit_dio_pages() - limit I/O pages to avoid discontiguous DUNs
|
||||
* @inode: the file on which I/O is being done
|
||||
* @pos: the file position (in bytes) at which the I/O is being done
|
||||
* @nr_pages: the number of pages we want to submit starting at @pos
|
||||
*
|
||||
* For direct I/O: limit the number of pages that will be submitted in the bio
|
||||
* targeting @pos, in order to avoid crossing a data unit number (DUN)
|
||||
* discontinuity. This is only needed for certain IV generation methods.
|
||||
*
|
||||
* This assumes block_size == PAGE_SIZE; see fscrypt_dio_supported().
|
||||
*
|
||||
* Return: the actual number of pages that can be submitted
|
||||
*/
|
||||
int fscrypt_limit_dio_pages(const struct inode *inode, loff_t pos, int nr_pages)
|
||||
{
|
||||
const struct fscrypt_info *ci = inode->i_crypt_info;
|
||||
u32 dun;
|
||||
|
||||
if (!fscrypt_inode_uses_inline_crypto(inode))
|
||||
return nr_pages;
|
||||
|
||||
if (nr_pages <= 1)
|
||||
return nr_pages;
|
||||
|
||||
if (!(fscrypt_policy_flags(&ci->ci_policy) &
|
||||
FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32))
|
||||
return nr_pages;
|
||||
|
||||
if (WARN_ON_ONCE(i_blocksize(inode) != PAGE_SIZE))
|
||||
return 1;
|
||||
|
||||
/* With IV_INO_LBLK_32, the DUN can wrap around from U32_MAX to 0. */
|
||||
|
||||
dun = ci->ci_hashed_ino + (pos >> inode->i_blkbits);
|
||||
|
||||
return min_t(u64, nr_pages, (u64)U32_MAX + 1 - dun);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/fscrypt.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/highmem.h>
|
||||
@@ -393,7 +392,6 @@ 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 allowed to sleep and
|
||||
@@ -401,9 +399,6 @@ 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);
|
||||
@@ -768,17 +763,9 @@ static inline int dio_send_cur_page(struct dio *dio, struct dio_submit *sdio,
|
||||
* current logical offset in the file does not equal what would
|
||||
* be the next logical offset in the bio, submit the bio we
|
||||
* have.
|
||||
*
|
||||
* When fscrypt inline encryption is used, data unit number
|
||||
* (DUN) contiguity is also required. Normally that's implied
|
||||
* by logical contiguity. However, certain IV generation
|
||||
* methods (e.g. IV_INO_LBLK_32) don't guarantee it. So, we
|
||||
* must explicitly check fscrypt_mergeable_bio() too.
|
||||
*/
|
||||
if (sdio->final_block_in_bio != sdio->cur_page_block ||
|
||||
cur_offset != bio_next_offset ||
|
||||
!fscrypt_mergeable_bio(sdio->bio, dio->inode,
|
||||
cur_offset >> dio->inode->i_blkbits))
|
||||
cur_offset != bio_next_offset)
|
||||
dio_bio_submit(dio, sdio);
|
||||
}
|
||||
|
||||
|
||||
@@ -36,11 +36,9 @@
|
||||
#include "acl.h"
|
||||
#include "truncate.h"
|
||||
|
||||
static bool ext4_dio_supported(struct kiocb *iocb, struct iov_iter *iter)
|
||||
static bool ext4_dio_supported(struct inode *inode)
|
||||
{
|
||||
struct inode *inode = file_inode(iocb->ki_filp);
|
||||
|
||||
if (!fscrypt_dio_supported(iocb, iter))
|
||||
if (IS_ENABLED(CONFIG_FS_ENCRYPTION) && IS_ENCRYPTED(inode))
|
||||
return false;
|
||||
if (fsverity_active(inode))
|
||||
return false;
|
||||
@@ -63,7 +61,7 @@ static ssize_t ext4_dio_read_iter(struct kiocb *iocb, struct iov_iter *to)
|
||||
inode_lock_shared(inode);
|
||||
}
|
||||
|
||||
if (!ext4_dio_supported(iocb, to)) {
|
||||
if (!ext4_dio_supported(inode)) {
|
||||
inode_unlock_shared(inode);
|
||||
/*
|
||||
* Fallback to buffered I/O if the operation being performed on
|
||||
@@ -497,7 +495,7 @@ static ssize_t ext4_dio_write_iter(struct kiocb *iocb, struct iov_iter *from)
|
||||
}
|
||||
|
||||
/* Fallback to buffered I/O if the inode does not support direct I/O. */
|
||||
if (!ext4_dio_supported(iocb, from)) {
|
||||
if (!ext4_dio_supported(inode)) {
|
||||
if (ilock_shared)
|
||||
inode_unlock_shared(inode);
|
||||
else
|
||||
|
||||
@@ -4091,11 +4091,7 @@ 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 (!fscrypt_dio_supported(iocb, iter))
|
||||
return true;
|
||||
if (fsverity_active(inode))
|
||||
return true;
|
||||
if (f2fs_compressed_file(inode))
|
||||
if (f2fs_post_read_required(inode))
|
||||
return true;
|
||||
if (f2fs_is_multi_device(sbi))
|
||||
return true;
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/fscrypt.h>
|
||||
#include <linux/iomap.h>
|
||||
#include <linux/backing-dev.h>
|
||||
#include <linux/uio.h>
|
||||
@@ -186,14 +185,11 @@ static void
|
||||
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);
|
||||
int flags = REQ_SYNC | REQ_IDLE;
|
||||
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_sector(iomap, pos);
|
||||
bio->bi_private = dio;
|
||||
@@ -259,7 +255,6 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
|
||||
ret = nr_pages;
|
||||
goto out;
|
||||
}
|
||||
nr_pages = fscrypt_limit_dio_pages(inode, pos, nr_pages);
|
||||
|
||||
if (need_zeroout) {
|
||||
/* zero out from the start of the block to the write offset */
|
||||
@@ -277,8 +272,6 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
|
||||
}
|
||||
|
||||
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_sector(iomap, pos);
|
||||
bio->bi_write_hint = dio->iocb->ki_hint;
|
||||
@@ -316,7 +309,6 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
|
||||
copied += n;
|
||||
|
||||
nr_pages = iov_iter_npages(dio->submit.iter, BIO_MAX_PAGES);
|
||||
nr_pages = fscrypt_limit_dio_pages(inode, pos, nr_pages);
|
||||
iomap_dio_submit_bio(dio, iomap, bio, pos);
|
||||
pos += n;
|
||||
} while (nr_pages);
|
||||
|
||||
@@ -609,11 +609,6 @@ bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode,
|
||||
bool fscrypt_mergeable_bio_bh(struct bio *bio,
|
||||
const struct buffer_head *next_bh);
|
||||
|
||||
bool fscrypt_dio_supported(struct kiocb *iocb, struct iov_iter *iter);
|
||||
|
||||
int fscrypt_limit_dio_pages(const struct inode *inode, loff_t pos,
|
||||
int nr_pages);
|
||||
|
||||
#else /* CONFIG_FS_ENCRYPTION_INLINE_CRYPT */
|
||||
|
||||
static inline bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode)
|
||||
@@ -642,20 +637,6 @@ static inline bool fscrypt_mergeable_bio_bh(struct bio *bio,
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool fscrypt_dio_supported(struct kiocb *iocb,
|
||||
struct iov_iter *iter)
|
||||
{
|
||||
const struct inode *inode = file_inode(iocb->ki_filp);
|
||||
|
||||
return !fscrypt_needs_contents_encryption(inode);
|
||||
}
|
||||
|
||||
static inline int fscrypt_limit_dio_pages(const struct inode *inode, loff_t pos,
|
||||
int nr_pages)
|
||||
{
|
||||
return nr_pages;
|
||||
}
|
||||
#endif /* !CONFIG_FS_ENCRYPTION_INLINE_CRYPT */
|
||||
|
||||
#if IS_ENABLED(CONFIG_FS_ENCRYPTION) && IS_ENABLED(CONFIG_DM_DEFAULT_KEY)
|
||||
|
||||
Reference in New Issue
Block a user