|
17 | 17 | #include <linux/buffer_head.h> |
18 | 18 | #include <linux/sched/mm.h> |
19 | 19 | #include <linux/slab.h> |
| 20 | +#include <linux/uio.h> |
20 | 21 |
|
21 | 22 | #include "fscrypt_private.h" |
22 | 23 |
|
@@ -315,6 +316,10 @@ EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx_bh); |
315 | 316 | * |
316 | 317 | * fscrypt_set_bio_crypt_ctx() must have already been called on the bio. |
317 | 318 | * |
| 319 | + * This function isn't required in cases where crypto-mergeability is ensured in |
| 320 | + * another way, such as I/O targeting only a single file (and thus a single key) |
| 321 | + * combined with fscrypt_limit_io_blocks() to ensure DUN contiguity. |
| 322 | + * |
318 | 323 | * Return: true iff the I/O is mergeable |
319 | 324 | */ |
320 | 325 | bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode, |
@@ -363,3 +368,91 @@ bool fscrypt_mergeable_bio_bh(struct bio *bio, |
363 | 368 | return fscrypt_mergeable_bio(bio, inode, next_lblk); |
364 | 369 | } |
365 | 370 | EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio_bh); |
| 371 | + |
| 372 | +/** |
| 373 | + * fscrypt_dio_supported() - check whether a DIO (direct I/O) request is |
| 374 | + * supported as far as encryption is concerned |
| 375 | + * @iocb: the file and position the I/O is targeting |
| 376 | + * @iter: the I/O data segment(s) |
| 377 | + * |
| 378 | + * Return: %true if there are no encryption constraints that prevent DIO from |
| 379 | + * being supported; %false if DIO is unsupported. (Note that in the |
| 380 | + * %true case, the filesystem might have other, non-encryption-related |
| 381 | + * constraints that prevent DIO from actually being supported.) |
| 382 | + */ |
| 383 | +bool fscrypt_dio_supported(struct kiocb *iocb, struct iov_iter *iter) |
| 384 | +{ |
| 385 | + const struct inode *inode = file_inode(iocb->ki_filp); |
| 386 | + const unsigned int blocksize = i_blocksize(inode); |
| 387 | + |
| 388 | + /* If the file is unencrypted, no veto from us. */ |
| 389 | + if (!fscrypt_needs_contents_encryption(inode)) |
| 390 | + return true; |
| 391 | + |
| 392 | + /* We only support DIO with inline crypto, not fs-layer crypto. */ |
| 393 | + if (!fscrypt_inode_uses_inline_crypto(inode)) |
| 394 | + return false; |
| 395 | + |
| 396 | + /* |
| 397 | + * Since the granularity of encryption is filesystem blocks, the file |
| 398 | + * position and total I/O length must be aligned to the filesystem block |
| 399 | + * size -- not just to the block device's logical block size as is |
| 400 | + * traditionally the case for DIO on many filesystems. |
| 401 | + * |
| 402 | + * We require that the user-provided memory buffers be filesystem block |
| 403 | + * aligned too. It is simpler to have a single alignment value required |
| 404 | + * for all properties of the I/O, as is normally the case for DIO. |
| 405 | + * Also, allowing less aligned buffers would imply that data units could |
| 406 | + * cross bvecs, which would greatly complicate the I/O stack, which |
| 407 | + * assumes that bios can be split at any bvec boundary. |
| 408 | + */ |
| 409 | + if (!IS_ALIGNED(iocb->ki_pos | iov_iter_alignment(iter), blocksize)) |
| 410 | + return false; |
| 411 | + |
| 412 | + return true; |
| 413 | +} |
| 414 | +EXPORT_SYMBOL_GPL(fscrypt_dio_supported); |
| 415 | + |
| 416 | +/** |
| 417 | + * fscrypt_limit_io_blocks() - limit I/O blocks to avoid discontiguous DUNs |
| 418 | + * @inode: the file on which I/O is being done |
| 419 | + * @lblk: the block at which the I/O is being started from |
| 420 | + * @nr_blocks: the number of blocks we want to submit starting at @lblk |
| 421 | + * |
| 422 | + * Determine the limit to the number of blocks that can be submitted in a bio |
| 423 | + * targeting @lblk without causing a data unit number (DUN) discontiguity. |
| 424 | + * |
| 425 | + * This is normally just @nr_blocks, as normally the DUNs just increment along |
| 426 | + * with the logical blocks. (Or the file is not encrypted.) |
| 427 | + * |
| 428 | + * In rare cases, fscrypt can be using an IV generation method that allows the |
| 429 | + * DUN to wrap around within logically contiguous blocks, and that wraparound |
| 430 | + * will occur. If this happens, a value less than @nr_blocks will be returned |
| 431 | + * so that the wraparound doesn't occur in the middle of a bio, which would |
| 432 | + * cause encryption/decryption to produce wrong results. |
| 433 | + * |
| 434 | + * Return: the actual number of blocks that can be submitted |
| 435 | + */ |
| 436 | +u64 fscrypt_limit_io_blocks(const struct inode *inode, u64 lblk, u64 nr_blocks) |
| 437 | +{ |
| 438 | + const struct fscrypt_info *ci; |
| 439 | + u32 dun; |
| 440 | + |
| 441 | + if (!fscrypt_inode_uses_inline_crypto(inode)) |
| 442 | + return nr_blocks; |
| 443 | + |
| 444 | + if (nr_blocks <= 1) |
| 445 | + return nr_blocks; |
| 446 | + |
| 447 | + ci = inode->i_crypt_info; |
| 448 | + if (!(fscrypt_policy_flags(&ci->ci_policy) & |
| 449 | + FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) |
| 450 | + return nr_blocks; |
| 451 | + |
| 452 | + /* With IV_INO_LBLK_32, the DUN can wrap around from U32_MAX to 0. */ |
| 453 | + |
| 454 | + dun = ci->ci_hashed_ino + lblk; |
| 455 | + |
| 456 | + return min_t(u64, nr_blocks, (u64)U32_MAX + 1 - dun); |
| 457 | +} |
| 458 | +EXPORT_SYMBOL_GPL(fscrypt_limit_io_blocks); |
0 commit comments