[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20220822122527.GA14620@lst.de>
Date: Mon, 22 Aug 2022 14:25:27 +0200
From: Christoph Hellwig <hch@....de>
To: Eric Biggers <ebiggers@...nel.org>
Cc: linux-fscrypt@...r.kernel.org, linux-fsdevel@...r.kernel.org,
linux-block@...r.kernel.org, linux-ext4@...r.kernel.org,
linux-f2fs-devel@...ts.sourceforge.net,
Christoph Hellwig <hch@....de>
Subject: Re: [PATCH v2 0/2] fscrypt: rework filesystem-level keyring
On Sat, Aug 20, 2022 at 12:02:08PM -0700, Eric Biggers wrote:
> This series reworks the filesystem-level keyring to not use the keyrings
> subsystem as part of its internal implementation (except for ->mk_users,
> which remains unchanged for now). This fixes several issues, described
> in the first patch. This is also a prerequisite for removing the direct
> use of struct request_queue from filesystem code, as discussed at
> https://lore.kernel.org/linux-fscrypt/20220721125929.1866403-1-hch@lst.de/T/#u
Nice, this looks great to me. Something like the patch below would be
good to include with this series for the current merge window, I can then
attack the block layer side for the release after that.
---
>From e038171b286e2747cbc54e36a8d0e0d6b8a2071e Mon Sep 17 00:00:00 2001
From: Christoph Hellwig <hch@....de>
Date: Mon, 22 Aug 2022 14:08:52 +0200
Subject: fscrypt: work on block_device instead of request_queues
request_queues are a block layer implementation detail that should not
leak into file systems. Change the fscrypt inline crypto code to
retrieve block devices instead of request_queues from the file system.
As part of that clean up the interaction with multi-device file systems
by returning both the number of devices and the actual device array
in a single method call.
Signed-off-by: Christoph Hellwig <hch@....de>
---
fs/crypto/inline_crypt.c | 73 ++++++++++++++++++++--------------------
fs/f2fs/super.c | 24 ++++++-------
include/linux/fscrypt.h | 21 ++++++------
3 files changed, 58 insertions(+), 60 deletions(-)
diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c
index f75dcb403c365..88ca838fa1b25 100644
--- a/fs/crypto/inline_crypt.c
+++ b/fs/crypto/inline_crypt.c
@@ -21,20 +21,21 @@
#include "fscrypt_private.h"
-static int fscrypt_get_num_devices(struct super_block *sb)
+static struct block_device **fscrypt_get_devices(struct super_block *sb,
+ unsigned int *num_devs)
{
- if (sb->s_cop->get_num_devices)
- return sb->s_cop->get_num_devices(sb);
- return 1;
-}
+ struct block_device **devs;
-static void fscrypt_get_devices(struct super_block *sb, int num_devs,
- struct block_device **devs)
-{
- if (num_devs == 1)
- devs[0] = sb->s_bdev;
- else
- sb->s_cop->get_devices(sb, devs);
+ if (sb->s_cop->get_devices) {
+ devs = sb->s_cop->get_devices(sb, num_devs);
+ if (devs)
+ return devs;
+ }
+ devs = kmalloc(sizeof(*devs), GFP_KERNEL);
+ if (!devs)
+ return ERR_PTR(-ENOMEM);
+ devs[0] = sb->s_bdev;
+ return devs;
}
static unsigned int fscrypt_get_dun_bytes(const struct fscrypt_info *ci)
@@ -76,6 +77,7 @@ static void fscrypt_log_blk_crypto_impl(struct fscrypt_mode *mode,
for (i = 0; i < num_devs; i++) {
struct request_queue *q = bdev_get_queue(devs[i]);
+
if (!IS_ENABLED(CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK) ||
__blk_crypto_cfg_supported(q->crypto_profile, cfg)) {
if (!xchg(&mode->logged_blk_crypto_native, 1))
@@ -94,8 +96,8 @@ int fscrypt_select_encryption_impl(struct fscrypt_info *ci)
const struct inode *inode = ci->ci_inode;
struct super_block *sb = inode->i_sb;
struct blk_crypto_config crypto_cfg;
- int num_devs;
struct block_device **devs;
+ unsigned int num_devs;
int i;
/* The file must need contents encryption, not filenames encryption */
@@ -130,12 +132,10 @@ int fscrypt_select_encryption_impl(struct fscrypt_info *ci)
crypto_cfg.crypto_mode = ci->ci_mode->blk_crypto_mode;
crypto_cfg.data_unit_size = sb->s_blocksize;
crypto_cfg.dun_bytes = fscrypt_get_dun_bytes(ci);
- num_devs = fscrypt_get_num_devices(sb);
- devs = kmalloc_array(num_devs, sizeof(*devs), GFP_KERNEL);
- if (!devs)
- return -ENOMEM;
- fscrypt_get_devices(sb, num_devs, devs);
+ devs = fscrypt_get_devices(sb, &num_devs);
+ if (IS_ERR(devs))
+ return PTR_ERR(devs);
for (i = 0; i < num_devs; i++) {
if (!blk_crypto_config_supported(bdev_get_queue(devs[i]),
&crypto_cfg))
@@ -159,8 +159,8 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
struct super_block *sb = inode->i_sb;
enum blk_crypto_mode_num crypto_mode = ci->ci_mode->blk_crypto_mode;
struct blk_crypto_key *blk_key;
- int num_devs;
struct block_device **devs = NULL;
+ unsigned int num_devs;
int err;
int i;
@@ -176,22 +176,25 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
}
/* Start using blk-crypto on all the filesystem's block devices. */
- num_devs = fscrypt_get_num_devices(sb);
- devs = kmalloc_array(num_devs, sizeof(*devs), GFP_KERNEL);
- if (!devs) {
- err = -ENOMEM;
+ devs = fscrypt_get_devices(sb, &num_devs);
+ if (IS_ERR(devs)) {
+ err = PTR_ERR(devs);
goto out;
}
- fscrypt_get_devices(sb, num_devs, devs);
for (i = 0; i < num_devs; i++) {
err = blk_crypto_start_using_key(blk_key,
bdev_get_queue(devs[i]));
- if (err) {
- fscrypt_err(inode,
- "error %d starting to use blk-crypto", err);
- goto out;
- }
+ if (err)
+ break;
}
+ kfree(devs);
+
+ if (err) {
+ fscrypt_err(inode,
+ "error %d starting to use blk-crypto", err);
+ goto out;
+ }
+
/*
* Pairs with the smp_load_acquire() in fscrypt_is_key_prepared().
* I.e., here we publish ->blk_key with a RELEASE barrier so that
@@ -199,10 +202,8 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
* possible for per-mode keys, not for per-file keys.
*/
smp_store_release(&prep_key->blk_key, blk_key);
- blk_key = NULL;
- err = 0;
+ return 0;
out:
- kfree(devs);
kfree_sensitive(blk_key);
return err;
}
@@ -211,15 +212,13 @@ void fscrypt_destroy_inline_crypt_key(struct super_block *sb,
struct fscrypt_prepared_key *prep_key)
{
struct blk_crypto_key *blk_key = prep_key->blk_key;
- int num_devs;
struct block_device **devs;
+ unsigned int num_devs;
int i;
/* Evict the key from all the filesystem's block devices. */
- num_devs = fscrypt_get_num_devices(sb);
- devs = kmalloc_array(num_devs, sizeof(*devs), GFP_KERNEL);
- if (devs) {
- fscrypt_get_devices(sb, num_devs, devs);
+ devs = fscrypt_get_devices(sb, &num_devs);
+ if (IS_ERR(devs)) {
for (i = 0; i < num_devs; i++)
blk_crypto_evict_key(bdev_get_queue(devs[i]), blk_key);
kfree(devs);
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 7dcac93e00eba..26817b5aeac78 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -3039,23 +3039,24 @@ static void f2fs_get_ino_and_lblk_bits(struct super_block *sb,
*lblk_bits_ret = 8 * sizeof(block_t);
}
-static int f2fs_get_num_devices(struct super_block *sb)
+static struct block_device **f2fs_get_devices(struct super_block *sb,
+ unsigned int *num_devs)
{
struct f2fs_sb_info *sbi = F2FS_SB(sb);
+ struct block_device **devs;
+ int i;
- if (f2fs_is_multi_device(sbi))
- return sbi->s_ndevs;
- return 1;
-}
+ if (!f2fs_is_multi_device(sbi))
+ return NULL;
-static void f2fs_get_devices(struct super_block *sb,
- struct block_device **bdevs)
-{
- struct f2fs_sb_info *sbi = F2FS_SB(sb);
- int i;
+ devs = kmalloc_array(sbi->s_ndevs, sizeof(*devs), GFP_KERNEL);
+ if (!devs)
+ return ERR_PTR(-ENOMEM);
for (i = 0; i < sbi->s_ndevs; i++)
- bdevs[i] = FDEV(i).bdev;
+ devs[i] = FDEV(i).bdev;
+ *num_devs = sbi->s_ndevs;
+ return devs;
}
static const struct fscrypt_operations f2fs_cryptops = {
@@ -3066,7 +3067,6 @@ static const struct fscrypt_operations f2fs_cryptops = {
.empty_dir = f2fs_empty_dir,
.has_stable_inodes = f2fs_has_stable_inodes,
.get_ino_and_lblk_bits = f2fs_get_ino_and_lblk_bits,
- .get_num_devices = f2fs_get_num_devices,
.get_devices = f2fs_get_devices,
};
#endif
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 5097dbd048a4a..ea6485cb0e351 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -161,23 +161,22 @@ struct fscrypt_operations {
int *ino_bits_ret, int *lblk_bits_ret);
/*
- * Return the number of block devices to which the filesystem may write
- * encrypted file contents.
+ * Return an array of pointers to the block devices to which the file
+ * system may write encrypted file contents, NULL if the file system
+ * only has a single device or an ERR_PTR() on error.
+ *
+ * On successful return, *num_devs is set to the number of devices in
+ * the returned array.
*
* If the filesystem can use multiple block devices (other than block
* devices that aren't used for encrypted file contents, such as
* external journal devices), and wants to support inline encryption,
* then it must implement this function. Otherwise it's not needed.
+ *
+ * The returned array must be freed by the caller using kfree().
*/
- int (*get_num_devices)(struct super_block *sb);
-
- /*
- * If ->get_num_devices() returns a value greater than 1, then this
- * function is called to get the array of block devices that the
- * filesystem is using.
- */
- void (*get_devices)(struct super_block *sb,
- struct block_device **bdev);
+ struct block_device **(*get_devices)(struct super_block *sb,
+ unsigned int *num_devs);
};
static inline struct fscrypt_info *fscrypt_get_info(const struct inode *inode)
--
2.30.2
Powered by blists - more mailing lists