Skip to content

Commit 27aacd2

Browse files
Satya Tangiralaebiggers
authored andcommitted
f2fs: add inline encryption support
Wire up f2fs to support inline encryption via the helper functions which fs/crypto/ now provides. This includes: - Adding a mount option 'inlinecrypt' which enables inline encryption on encrypted files where it can be used. - Setting the bio_crypt_ctx on bios that will be submitted to an inline-encrypted file. - Not adding logically discontiguous data to bios that will be submitted to an inline-encrypted file. - Not doing filesystem-layer crypto on inline-encrypted files. This patch includes a fix for a race during IPU by Sahitya Tummala <[email protected]> Signed-off-by: Satya Tangirala <[email protected]> Acked-by: Jaegeuk Kim <[email protected]> Reviewed-by: Eric Biggers <[email protected]> Reviewed-by: Chao Yu <[email protected]> Link: https://lore.kernel.org/r/[email protected] Co-developed-by: Eric Biggers <[email protected]> Signed-off-by: Eric Biggers <[email protected]>
1 parent 5fee360 commit 27aacd2

File tree

4 files changed

+109
-14
lines changed

4 files changed

+109
-14
lines changed

Documentation/filesystems/f2fs.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,13 @@ compress_extension=%s Support adding specified extension, so that f2fs can enab
258258
on compression extension list and enable compression on
259259
these file by default rather than to enable it via ioctl.
260260
For other files, we can still enable compression via ioctl.
261+
inlinecrypt
262+
When possible, encrypt/decrypt the contents of encrypted
263+
files using the blk-crypto framework rather than
264+
filesystem-layer encryption. This allows the use of
265+
inline encryption hardware. The on-disk format is
266+
unaffected. For more details, see
267+
Documentation/block/inline-encryption.rst.
261268
====================== ============================================================
262269

263270
Debugfs Entries

fs/f2fs/compress.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1086,7 +1086,7 @@ static int f2fs_write_compressed_pages(struct compress_ctx *cc,
10861086
.submitted = false,
10871087
.io_type = io_type,
10881088
.io_wbc = wbc,
1089-
.encrypted = f2fs_encrypted_file(cc->inode),
1089+
.encrypted = fscrypt_inode_uses_fs_layer_crypto(cc->inode),
10901090
};
10911091
struct dnode_of_data dn;
10921092
struct node_info ni;

fs/f2fs/data.c

Lines changed: 66 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/pagevec.h>
1515
#include <linux/blkdev.h>
1616
#include <linux/bio.h>
17+
#include <linux/blk-crypto.h>
1718
#include <linux/swap.h>
1819
#include <linux/prefetch.h>
1920
#include <linux/uio.h>
@@ -459,6 +460,33 @@ static struct bio *__bio_alloc(struct f2fs_io_info *fio, int npages)
459460
return bio;
460461
}
461462

463+
static void f2fs_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode,
464+
pgoff_t first_idx,
465+
const struct f2fs_io_info *fio,
466+
gfp_t gfp_mask)
467+
{
468+
/*
469+
* The f2fs garbage collector sets ->encrypted_page when it wants to
470+
* read/write raw data without encryption.
471+
*/
472+
if (!fio || !fio->encrypted_page)
473+
fscrypt_set_bio_crypt_ctx(bio, inode, first_idx, gfp_mask);
474+
}
475+
476+
static bool f2fs_crypt_mergeable_bio(struct bio *bio, const struct inode *inode,
477+
pgoff_t next_idx,
478+
const struct f2fs_io_info *fio)
479+
{
480+
/*
481+
* The f2fs garbage collector sets ->encrypted_page when it wants to
482+
* read/write raw data without encryption.
483+
*/
484+
if (fio && fio->encrypted_page)
485+
return !bio_has_crypt_ctx(bio);
486+
487+
return fscrypt_mergeable_bio(bio, inode, next_idx);
488+
}
489+
462490
static inline void __submit_bio(struct f2fs_sb_info *sbi,
463491
struct bio *bio, enum page_type type)
464492
{
@@ -684,6 +712,9 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
684712
/* Allocate a new bio */
685713
bio = __bio_alloc(fio, 1);
686714

715+
f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host,
716+
fio->page->index, fio, GFP_NOIO);
717+
687718
if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) {
688719
bio_put(bio);
689720
return -EFAULT;
@@ -763,9 +794,10 @@ static void del_bio_entry(struct bio_entry *be)
763794
kmem_cache_free(bio_entry_slab, be);
764795
}
765796

766-
static int add_ipu_page(struct f2fs_sb_info *sbi, struct bio **bio,
797+
static int add_ipu_page(struct f2fs_io_info *fio, struct bio **bio,
767798
struct page *page)
768799
{
800+
struct f2fs_sb_info *sbi = fio->sbi;
769801
enum temp_type temp;
770802
bool found = false;
771803
int ret = -EAGAIN;
@@ -782,13 +814,19 @@ static int add_ipu_page(struct f2fs_sb_info *sbi, struct bio **bio,
782814

783815
found = true;
784816

785-
if (bio_add_page(*bio, page, PAGE_SIZE, 0) ==
786-
PAGE_SIZE) {
817+
f2fs_bug_on(sbi, !page_is_mergeable(sbi, *bio,
818+
*fio->last_block,
819+
fio->new_blkaddr));
820+
if (f2fs_crypt_mergeable_bio(*bio,
821+
fio->page->mapping->host,
822+
fio->page->index, fio) &&
823+
bio_add_page(*bio, page, PAGE_SIZE, 0) ==
824+
PAGE_SIZE) {
787825
ret = 0;
788826
break;
789827
}
790828

791-
/* bio is full */
829+
/* page can't be merged into bio; submit the bio */
792830
del_bio_entry(be);
793831
__submit_bio(sbi, *bio, DATA);
794832
break;
@@ -880,11 +918,13 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio)
880918
if (!bio) {
881919
bio = __bio_alloc(fio, BIO_MAX_PAGES);
882920
__attach_io_flag(fio);
921+
f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host,
922+
fio->page->index, fio, GFP_NOIO);
883923
bio_set_op_attrs(bio, fio->op, fio->op_flags);
884924

885925
add_bio_entry(fio->sbi, bio, page, fio->temp);
886926
} else {
887-
if (add_ipu_page(fio->sbi, &bio, page))
927+
if (add_ipu_page(fio, &bio, page))
888928
goto alloc_new;
889929
}
890930

@@ -936,8 +976,11 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
936976

937977
inc_page_count(sbi, WB_DATA_TYPE(bio_page));
938978

939-
if (io->bio && !io_is_mergeable(sbi, io->bio, io, fio,
940-
io->last_block_in_bio, fio->new_blkaddr))
979+
if (io->bio &&
980+
(!io_is_mergeable(sbi, io->bio, io, fio, io->last_block_in_bio,
981+
fio->new_blkaddr) ||
982+
!f2fs_crypt_mergeable_bio(io->bio, fio->page->mapping->host,
983+
bio_page->index, fio)))
941984
__submit_merged_bio(io);
942985
alloc_new:
943986
if (io->bio == NULL) {
@@ -949,6 +992,8 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
949992
goto skip;
950993
}
951994
io->bio = __bio_alloc(fio, BIO_MAX_PAGES);
995+
f2fs_set_bio_crypt_ctx(io->bio, fio->page->mapping->host,
996+
bio_page->index, fio, GFP_NOIO);
952997
io->fio = *fio;
953998
}
954999

@@ -993,11 +1038,14 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr,
9931038
for_write);
9941039
if (!bio)
9951040
return ERR_PTR(-ENOMEM);
1041+
1042+
f2fs_set_bio_crypt_ctx(bio, inode, first_idx, NULL, GFP_NOFS);
1043+
9961044
f2fs_target_device(sbi, blkaddr, bio);
9971045
bio->bi_end_io = f2fs_read_end_io;
9981046
bio_set_op_attrs(bio, REQ_OP_READ, op_flag);
9991047

1000-
if (f2fs_encrypted_file(inode))
1048+
if (fscrypt_inode_uses_fs_layer_crypto(inode))
10011049
post_read_steps |= 1 << STEP_DECRYPT;
10021050
if (f2fs_compressed_file(inode))
10031051
post_read_steps |= 1 << STEP_DECOMPRESS_NOWQ;
@@ -2073,8 +2121,9 @@ static int f2fs_read_single_page(struct inode *inode, struct page *page,
20732121
* This page will go to BIO. Do we need to send this
20742122
* BIO off first?
20752123
*/
2076-
if (bio && !page_is_mergeable(F2FS_I_SB(inode), bio,
2077-
*last_block_in_bio, block_nr)) {
2124+
if (bio && (!page_is_mergeable(F2FS_I_SB(inode), bio,
2125+
*last_block_in_bio, block_nr) ||
2126+
!f2fs_crypt_mergeable_bio(bio, inode, page->index, NULL))) {
20782127
submit_and_realloc:
20792128
__submit_bio(F2FS_I_SB(inode), bio, DATA);
20802129
bio = NULL;
@@ -2204,8 +2253,9 @@ int f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret,
22042253
blkaddr = data_blkaddr(dn.inode, dn.node_page,
22052254
dn.ofs_in_node + i + 1);
22062255

2207-
if (bio && !page_is_mergeable(sbi, bio,
2208-
*last_block_in_bio, blkaddr)) {
2256+
if (bio && (!page_is_mergeable(sbi, bio,
2257+
*last_block_in_bio, blkaddr) ||
2258+
!f2fs_crypt_mergeable_bio(bio, inode, page->index, NULL))) {
22092259
submit_and_realloc:
22102260
__submit_bio(sbi, bio, DATA);
22112261
bio = NULL;
@@ -2421,6 +2471,9 @@ int f2fs_encrypt_one_page(struct f2fs_io_info *fio)
24212471
/* wait for GCed page writeback via META_MAPPING */
24222472
f2fs_wait_on_block_writeback(inode, fio->old_blkaddr);
24232473

2474+
if (fscrypt_inode_uses_inline_crypto(inode))
2475+
return 0;
2476+
24242477
retry_encrypt:
24252478
fio->encrypted_page = fscrypt_encrypt_pagecache_blocks(page,
24262479
PAGE_SIZE, 0, gfp_flags);
@@ -2594,7 +2647,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio)
25942647
f2fs_unlock_op(fio->sbi);
25952648
err = f2fs_inplace_write_data(fio);
25962649
if (err) {
2597-
if (f2fs_encrypted_file(inode))
2650+
if (fscrypt_inode_uses_fs_layer_crypto(inode))
25982651
fscrypt_finalize_bounce_page(&fio->encrypted_page);
25992652
if (PageWriteback(page))
26002653
end_page_writeback(page);

fs/f2fs/super.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ enum {
138138
Opt_alloc,
139139
Opt_fsync,
140140
Opt_test_dummy_encryption,
141+
Opt_inlinecrypt,
141142
Opt_checkpoint_disable,
142143
Opt_checkpoint_disable_cap,
143144
Opt_checkpoint_disable_cap_perc,
@@ -204,6 +205,7 @@ static match_table_t f2fs_tokens = {
204205
{Opt_fsync, "fsync_mode=%s"},
205206
{Opt_test_dummy_encryption, "test_dummy_encryption=%s"},
206207
{Opt_test_dummy_encryption, "test_dummy_encryption"},
208+
{Opt_inlinecrypt, "inlinecrypt"},
207209
{Opt_checkpoint_disable, "checkpoint=disable"},
208210
{Opt_checkpoint_disable_cap, "checkpoint=disable:%u"},
209211
{Opt_checkpoint_disable_cap_perc, "checkpoint=disable:%u%%"},
@@ -833,6 +835,13 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
833835
if (ret)
834836
return ret;
835837
break;
838+
case Opt_inlinecrypt:
839+
#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT
840+
sb->s_flags |= SB_INLINECRYPT;
841+
#else
842+
f2fs_info(sbi, "inline encryption not supported");
843+
#endif
844+
break;
836845
case Opt_checkpoint_disable_cap_perc:
837846
if (args->from && match_int(args, &arg))
838847
return -EINVAL;
@@ -1590,6 +1599,9 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
15901599

15911600
fscrypt_show_test_dummy_encryption(seq, ',', sbi->sb);
15921601

1602+
if (sbi->sb->s_flags & SB_INLINECRYPT)
1603+
seq_puts(seq, ",inlinecrypt");
1604+
15931605
if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_DEFAULT)
15941606
seq_printf(seq, ",alloc_mode=%s", "default");
15951607
else if (F2FS_OPTION(sbi).alloc_mode == ALLOC_MODE_REUSE)
@@ -1624,6 +1636,8 @@ static void default_options(struct f2fs_sb_info *sbi)
16241636
F2FS_OPTION(sbi).compress_ext_cnt = 0;
16251637
F2FS_OPTION(sbi).bggc_mode = BGGC_MODE_ON;
16261638

1639+
sbi->sb->s_flags &= ~SB_INLINECRYPT;
1640+
16271641
set_opt(sbi, INLINE_XATTR);
16281642
set_opt(sbi, INLINE_DATA);
16291643
set_opt(sbi, INLINE_DENTRY);
@@ -2470,6 +2484,25 @@ static void f2fs_get_ino_and_lblk_bits(struct super_block *sb,
24702484
*lblk_bits_ret = 8 * sizeof(block_t);
24712485
}
24722486

2487+
static int f2fs_get_num_devices(struct super_block *sb)
2488+
{
2489+
struct f2fs_sb_info *sbi = F2FS_SB(sb);
2490+
2491+
if (f2fs_is_multi_device(sbi))
2492+
return sbi->s_ndevs;
2493+
return 1;
2494+
}
2495+
2496+
static void f2fs_get_devices(struct super_block *sb,
2497+
struct request_queue **devs)
2498+
{
2499+
struct f2fs_sb_info *sbi = F2FS_SB(sb);
2500+
int i;
2501+
2502+
for (i = 0; i < sbi->s_ndevs; i++)
2503+
devs[i] = bdev_get_queue(FDEV(i).bdev);
2504+
}
2505+
24732506
static const struct fscrypt_operations f2fs_cryptops = {
24742507
.key_prefix = "f2fs:",
24752508
.get_context = f2fs_get_context,
@@ -2479,6 +2512,8 @@ static const struct fscrypt_operations f2fs_cryptops = {
24792512
.max_namelen = F2FS_NAME_LEN,
24802513
.has_stable_inodes = f2fs_has_stable_inodes,
24812514
.get_ino_and_lblk_bits = f2fs_get_ino_and_lblk_bits,
2515+
.get_num_devices = f2fs_get_num_devices,
2516+
.get_devices = f2fs_get_devices,
24822517
};
24832518
#endif
24842519

0 commit comments

Comments
 (0)