Message ID | 20201117140708.1068688-7-satyat@google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v7,1/8] block: ensure bios are not split in middle of crypto data unit | expand |
On Tue, Nov 17, 2020 at 02:07:06PM +0000, Satya Tangirala wrote: > From: Eric Biggers <ebiggers@google.com> > > Wire up ext4 with fscrypt direct I/O support. Direct I/O with fscrypt is > only supported through blk-crypto (i.e. CONFIG_BLK_INLINE_ENCRYPTION must > have been enabled, the 'inlinecrypt' mount option must have been specified, > and either hardware inline encryption support must be present or > CONFIG_BLK_INLINE_ENCYRPTION_FALLBACK must have been enabled). Further, > direct I/O on encrypted files is only supported when the *length* of the > I/O is aligned to the filesystem block size (which is *not* necessarily the > same as the block device's block size). > > fscrypt_limit_io_blocks() is called before setting up the iomap to ensure > that the blocks of each bio that iomap will submit will have contiguous > DUNs. Note that fscrypt_limit_io_blocks() is normally a no-op, as normally > the DUNs simply increment along with the logical blocks. But it's needed > to handle an edge case in one of the fscrypt IV generation methods. > > Signed-off-by: Eric Biggers <ebiggers@google.com> > Co-developed-by: Satya Tangirala <satyat@google.com> > Signed-off-by: Satya Tangirala <satyat@google.com> > Reviewed-by: Jaegeuk Kim <jaegeuk@kernel.org> Acked-by: Theodore Ts'o <tytso@mit.edu>
diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 3ed8c048fb12..be77b7732c8e 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -36,9 +36,11 @@ #include "acl.h" #include "truncate.h" -static bool ext4_dio_supported(struct inode *inode) +static bool ext4_dio_supported(struct kiocb *iocb, struct iov_iter *iter) { - if (IS_ENABLED(CONFIG_FS_ENCRYPTION) && IS_ENCRYPTED(inode)) + struct inode *inode = file_inode(iocb->ki_filp); + + if (!fscrypt_dio_supported(iocb, iter)) return false; if (fsverity_active(inode)) return false; @@ -61,7 +63,7 @@ static ssize_t ext4_dio_read_iter(struct kiocb *iocb, struct iov_iter *to) inode_lock_shared(inode); } - if (!ext4_dio_supported(inode)) { + if (!ext4_dio_supported(iocb, to)) { inode_unlock_shared(inode); /* * Fallback to buffered I/O if the operation being performed on @@ -495,7 +497,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(inode)) { + if (!ext4_dio_supported(iocb, from)) { if (ilock_shared) inode_unlock_shared(inode); else diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 0d8385aea898..0ef3d805bb8c 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3473,6 +3473,13 @@ static int ext4_iomap_begin(struct inode *inode, loff_t offset, loff_t length, if (ret < 0) return ret; out: + /* + * When inline encryption is enabled, sometimes I/O to an encrypted file + * has to be broken up to guarantee DUN contiguity. Handle this by + * limiting the length of the mapping returned. + */ + map.m_len = fscrypt_limit_io_blocks(inode, map.m_lblk, map.m_len); + ext4_set_iomap(inode, iomap, &map, offset, length); return 0;