ANDROID: fscrypt: handle direct I/O with IV_INO_LBLK_32

With the existing fscrypt IV generation methods, each file's data blocks
have contiguous DUNs.  Therefore the direct I/O code "just worked"
because it only submits logically contiguous bios.  But with
IV_INO_LBLK_32, the direct I/O code breaks because the DUN can wrap from
0xffffffff to 0.  We can't submit bios across such boundaries.

This is especially difficult to handle when block_size != PAGE_SIZE,
since in that case the DUN can wrap in the middle of a page.  Punt on
this case for now and just handle block_size == PAGE_SIZE.

Add and use a new function fscrypt_dio_supported() to check whether a
direct I/O request is unsupported due to encryption constraints.

Then, update fs/direct-io.c (used by f2fs, and by ext4 in kernel v5.4
and earlier) and fs/iomap/direct-io.c (used by ext4 in kernel v5.5 and
later) to avoid submitting I/O across a DUN discontinuity.

(This is needed in ACK now because ACK already supports direct I/O with
inline crypto.  I'll be sending this upstream along with the encrypted
direct I/O support itself once its prerequisites are closer to landing.)

(cherry picked from android-mainline commit
 8d6c90c9d68b985fa809626d12f8c9aff3c9dcb1)

Conflicts:
	fs/ext4/file.c
	fs/iomap/direct-io.c

(Dropped the iomap changes because in kernel v5.4 and earlier,
 ext4 doesn't use iomap for direct I/O)

Test: For now, just manually tested direct I/O on ext4 and f2fs in the
      DUN discontinuity case.
Bug: 144046242
Change-Id: I0c0b0b20a73ade35c3660cc6f9c09d49d3853ba5
Signed-off-by: Eric Biggers <ebiggers@google.com>
This commit is contained in:
Eric Biggers
2020-05-19 16:11:59 -07:00
parent 4286f44bea
commit cfc3461a04
6 changed files with 123 additions and 13 deletions

View File

@@ -814,9 +814,17 @@ 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)
cur_offset != bio_next_offset ||
!fscrypt_mergeable_bio(sdio->bio, dio->inode,
cur_offset >> dio->inode->i_blkbits))
dio_bio_submit(dio, sdio);
}