Skip to content

Commit 93c1fe1

Browse files
Christoph Hellwigkawasaki
authored andcommitted
blk-crypto: handle the fallback above the block layer
Add a blk_crypto_submit_bio helper that either submits the bio when it is not encrypted or inline encryption is provided, but otherwise handles the encryption before going down into the low-level driver. This reduces the risk from bio reordering and keeps memory allocation as high up in the stack as possible. Note that if the submitter knows that inline enctryption is known to be supported by the underyling driver, it can still use plain submit_bio. Signed-off-by: Christoph Hellwig <[email protected]> Reviewed-by: Eric Biggers <[email protected]>
1 parent e073a83 commit 93c1fe1

File tree

12 files changed

+68
-39
lines changed

12 files changed

+68
-39
lines changed

Documentation/block/inline-encryption.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,12 @@ it to a bio, given the blk_crypto_key and the data unit number that will be used
206206
for en/decryption. Users don't need to worry about freeing the bio_crypt_ctx
207207
later, as that happens automatically when the bio is freed or reset.
208208

209+
To submit a bio that uses inline encryption, users must call
210+
``blk_crypto_submit_bio()`` instead of the usual ``submit_bio()``. This will
211+
submit the bio to the underlying driver if it supports inline crypto, or else
212+
call the blk-crypto fallback routines before submitting normal bios to the
213+
underlying drivers.
214+
209215
Finally, when done using inline encryption with a blk_crypto_key on a
210216
block_device, users must call ``blk_crypto_evict_key()``. This ensures that
211217
the key is evicted from all keyslots it may be programmed into and unlinked from

block/blk-core.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -628,9 +628,6 @@ static void __submit_bio(struct bio *bio)
628628
/* If plug is not used, add new plug here to cache nsecs time. */
629629
struct blk_plug plug;
630630

631-
if (unlikely(!blk_crypto_bio_prep(bio)))
632-
return;
633-
634631
blk_start_plug(&plug);
635632

636633
if (!bdev_test_flag(bio->bi_bdev, BD_HAS_SUBMIT_BIO)) {
@@ -794,6 +791,13 @@ void submit_bio_noacct(struct bio *bio)
794791
if ((bio->bi_opf & REQ_NOWAIT) && !bdev_nowait(bdev))
795792
goto not_supported;
796793

794+
if (bio_has_crypt_ctx(bio)) {
795+
if (WARN_ON_ONCE(!bio_has_data(bio)))
796+
goto end_io;
797+
if (!blk_crypto_supported(bio))
798+
goto not_supported;
799+
}
800+
797801
if (should_fail_bio(bio))
798802
goto end_io;
799803
bio_check_ro(bio);

block/blk-crypto-internal.h

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ bool __blk_crypto_cfg_supported(struct blk_crypto_profile *profile,
8686
int blk_crypto_ioctl(struct block_device *bdev, unsigned int cmd,
8787
void __user *argp);
8888

89+
static inline bool blk_crypto_supported(struct bio *bio)
90+
{
91+
return blk_crypto_config_supported_natively(bio->bi_bdev,
92+
&bio->bi_crypt_context->bc_key->crypto_cfg);
93+
}
94+
8995
#else /* CONFIG_BLK_INLINE_ENCRYPTION */
9096

9197
static inline int blk_crypto_sysfs_register(struct gendisk *disk)
@@ -139,6 +145,11 @@ static inline int blk_crypto_ioctl(struct block_device *bdev, unsigned int cmd,
139145
return -ENOTTY;
140146
}
141147

148+
static inline bool blk_crypto_supported(struct bio *bio)
149+
{
150+
return false;
151+
}
152+
142153
#endif /* CONFIG_BLK_INLINE_ENCRYPTION */
143154

144155
void __bio_crypt_advance(struct bio *bio, unsigned int bytes);
@@ -165,14 +176,6 @@ static inline void bio_crypt_do_front_merge(struct request *rq,
165176
#endif
166177
}
167178

168-
bool __blk_crypto_bio_prep(struct bio *bio);
169-
static inline bool blk_crypto_bio_prep(struct bio *bio)
170-
{
171-
if (bio_has_crypt_ctx(bio))
172-
return __blk_crypto_bio_prep(bio);
173-
return true;
174-
}
175-
176179
blk_status_t __blk_crypto_rq_get_keyslot(struct request *rq);
177180
static inline blk_status_t blk_crypto_rq_get_keyslot(struct request *rq)
178181
{

block/blk-crypto.c

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -242,25 +242,13 @@ void __blk_crypto_free_request(struct request *rq)
242242
rq->crypt_ctx = NULL;
243243
}
244244

245-
/**
246-
* __blk_crypto_bio_prep - Prepare bio for inline encryption
247-
* @bio: bio to prepare
248-
*
249-
* If the bio crypt context provided for the bio is supported by the underlying
250-
* device's inline encryption hardware, do nothing.
251-
*
252-
* Otherwise, try to perform en/decryption for this bio by falling back to the
253-
* kernel crypto API. For encryption this means submitting newly allocated
254-
* bios for the encrypted payload while keeping back the source bio until they
255-
* complete, while for reads the decryption happens in-place by a hooked in
256-
* completion handler.
257-
*
258-
* Caller must ensure bio has bio_crypt_ctx.
245+
/*
246+
* Process a bio with a crypto context. Returns true if the caller should
247+
* submit the passed in bio, false if the bio is consumed.
259248
*
260-
* Return: true if @bio should be submitted to the driver by the caller, else
261-
* false. Sets bio->bi_status, calls bio_endio and returns false on error.
249+
* See the kerneldoc comment for blk_crypto_submit_bio for further details.
262250
*/
263-
bool __blk_crypto_bio_prep(struct bio *bio)
251+
bool __blk_crypto_submit_bio(struct bio *bio)
264252
{
265253
const struct blk_crypto_key *bc_key = bio->bi_crypt_context->bc_key;
266254
struct block_device *bdev = bio->bi_bdev;
@@ -288,6 +276,7 @@ bool __blk_crypto_bio_prep(struct bio *bio)
288276

289277
return true;
290278
}
279+
EXPORT_SYMBOL_GPL(__blk_crypto_submit_bio);
291280

292281
int __blk_crypto_rq_bio_prep(struct request *rq, struct bio *bio,
293282
gfp_t gfp_mask)

fs/buffer.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <linux/slab.h>
3030
#include <linux/capability.h>
3131
#include <linux/blkdev.h>
32+
#include <linux/blk-crypto.h>
3233
#include <linux/file.h>
3334
#include <linux/quotaops.h>
3435
#include <linux/highmem.h>
@@ -2821,7 +2822,7 @@ static void submit_bh_wbc(blk_opf_t opf, struct buffer_head *bh,
28212822
wbc_account_cgroup_owner(wbc, bh->b_folio, bh->b_size);
28222823
}
28232824

2824-
submit_bio(bio);
2825+
blk_crypto_submit_bio(bio);
28252826
}
28262827

28272828
void submit_bh(blk_opf_t opf, struct buffer_head *bh)

fs/crypto/bio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
105105
}
106106

107107
atomic_inc(&done.pending);
108-
submit_bio(bio);
108+
blk_crypto_submit_bio(bio);
109109
}
110110

111111
fscrypt_zeroout_range_done(&done);

fs/ext4/page-io.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* Written by Theodore Ts'o, 2010.
88
*/
99

10+
#include <linux/blk-crypto.h>
1011
#include <linux/fs.h>
1112
#include <linux/time.h>
1213
#include <linux/highuid.h>
@@ -401,7 +402,7 @@ void ext4_io_submit(struct ext4_io_submit *io)
401402
if (bio) {
402403
if (io->io_wbc->sync_mode == WB_SYNC_ALL)
403404
io->io_bio->bi_opf |= REQ_SYNC;
404-
submit_bio(io->io_bio);
405+
blk_crypto_submit_bio(io->io_bio);
405406
}
406407
io->io_bio = NULL;
407408
}

fs/ext4/readpage.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <linux/bio.h>
3737
#include <linux/fs.h>
3838
#include <linux/buffer_head.h>
39+
#include <linux/blk-crypto.h>
3940
#include <linux/blkdev.h>
4041
#include <linux/highmem.h>
4142
#include <linux/prefetch.h>
@@ -345,7 +346,7 @@ int ext4_mpage_readpages(struct inode *inode,
345346
if (bio && (last_block_in_bio != first_block - 1 ||
346347
!fscrypt_mergeable_bio(bio, inode, next_block))) {
347348
submit_and_realloc:
348-
submit_bio(bio);
349+
blk_crypto_submit_bio(bio);
349350
bio = NULL;
350351
}
351352
if (bio == NULL) {
@@ -371,14 +372,14 @@ int ext4_mpage_readpages(struct inode *inode,
371372
if (((map.m_flags & EXT4_MAP_BOUNDARY) &&
372373
(relative_block == map.m_len)) ||
373374
(first_hole != blocks_per_folio)) {
374-
submit_bio(bio);
375+
blk_crypto_submit_bio(bio);
375376
bio = NULL;
376377
} else
377378
last_block_in_bio = first_block + blocks_per_folio - 1;
378379
continue;
379380
confused:
380381
if (bio) {
381-
submit_bio(bio);
382+
blk_crypto_submit_bio(bio);
382383
bio = NULL;
383384
}
384385
if (!folio_test_uptodate(folio))
@@ -389,7 +390,7 @@ int ext4_mpage_readpages(struct inode *inode,
389390
; /* A label shall be followed by a statement until C23 */
390391
}
391392
if (bio)
392-
submit_bio(bio);
393+
blk_crypto_submit_bio(bio);
393394
return 0;
394395
}
395396

fs/f2fs/data.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ void f2fs_submit_read_bio(struct f2fs_sb_info *sbi, struct bio *bio,
513513
trace_f2fs_submit_read_bio(sbi->sb, type, bio);
514514

515515
iostat_update_submit_ctx(bio, type);
516-
submit_bio(bio);
516+
blk_crypto_submit_bio(bio);
517517
}
518518

519519
static void f2fs_submit_write_bio(struct f2fs_sb_info *sbi, struct bio *bio,
@@ -522,7 +522,7 @@ static void f2fs_submit_write_bio(struct f2fs_sb_info *sbi, struct bio *bio,
522522
WARN_ON_ONCE(is_read_io(bio_op(bio)));
523523
trace_f2fs_submit_write_bio(sbi->sb, type, bio);
524524
iostat_update_submit_ctx(bio, type);
525-
submit_bio(bio);
525+
blk_crypto_submit_bio(bio);
526526
}
527527

528528
static void __submit_merged_bio(struct f2fs_bio_info *io)

fs/f2fs/file.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
66
* http://www.samsung.com/
77
*/
8+
#include <linux/blk-crypto.h>
89
#include <linux/fs.h>
910
#include <linux/f2fs_fs.h>
1011
#include <linux/stat.h>
@@ -5046,7 +5047,7 @@ static void f2fs_dio_write_submit_io(const struct iomap_iter *iter,
50465047
enum temp_type temp = f2fs_get_segment_temp(sbi, type);
50475048

50485049
bio->bi_write_hint = f2fs_io_type_to_rw_hint(sbi, DATA, temp);
5049-
submit_bio(bio);
5050+
blk_crypto_submit_bio(bio);
50505051
}
50515052

50525053
static const struct iomap_dio_ops f2fs_iomap_dio_write_ops = {

0 commit comments

Comments
 (0)