From: Josef Bacik <josef@toxicpanda.com>
To: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
Cc: "Theodore Y. Ts'o" <tytso@mit.edu>,
Jaegeuk Kim <jaegeuk@kernel.org>,
Eric Biggers <ebiggers@kernel.org>, Chris Mason <clm@fb.com>,
David Sterba <dsterba@suse.com>,
linux-fscrypt@vger.kernel.org, linux-btrfs@vger.kernel.org,
kernel-team@meta.com
Subject: Re: [PATCH v2 11/14] fscrypt: add creation/usage/freeing of per-extent infos
Date: Mon, 17 Jul 2023 11:21:44 -0400 [thread overview]
Message-ID: <20230717152144.GF691303@perftesting> (raw)
In-Reply-To: <f3a26dde5d1ba50faf3f1db418b1066e859110de.1688927487.git.sweettea-kernel@dorminy.me>
On Sun, Jul 09, 2023 at 02:53:44PM -0400, Sweet Tea Dorminy wrote:
> This change adds the superblock function pointer to get the info
> corresponding to a specific block in an inode for a filesystem using
> per-extent infos. It allows creating a info for a new extent and freeing
> that info, and uses the extent's info if appropriate in encrypting
> blocks of data.
>
> This change does not deal with saving and loading an extent's info, but
> introduces the mechanics necessary therefore.
>
> Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
> ---
> fs/crypto/crypto.c | 2 +
> fs/crypto/fscrypt_private.h | 76 +++++++++++++++++++++----------------
> fs/crypto/keyring.c | 9 +----
> fs/crypto/keysetup.c | 58 +++++++++++++++++++++++++++-
> include/linux/fscrypt.h | 48 ++++++++++++++++++-----
> 5 files changed, 141 insertions(+), 52 deletions(-)
>
> diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
> index d75f1b3f5795..0f0c721e40fe 100644
> --- a/fs/crypto/crypto.c
> +++ b/fs/crypto/crypto.c
> @@ -113,6 +113,8 @@ int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw,
> struct crypto_skcipher *tfm = ci->ci_enc_key->tfm;
> int res = 0;
>
> + if (!ci)
> + return -EINVAL;
> if (WARN_ON_ONCE(len <= 0))
> return -EINVAL;
> if (WARN_ON_ONCE(len % FSCRYPT_CONTENTS_ALIGNMENT != 0))
> diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
> index 926531597e7b..6e6020f7746c 100644
> --- a/fs/crypto/fscrypt_private.h
> +++ b/fs/crypto/fscrypt_private.h
> @@ -286,6 +286,38 @@ typedef enum {
> FS_ENCRYPT,
> } fscrypt_direction_t;
>
> +/**
> + * fscrypt_fs_uses_extent_encryption() -- whether a filesystem uses per-extent
> + * encryption
> + *
> + * @sb: the superblock of the filesystem in question
> + *
> + * Return: true if the fs uses per-extent fscrypt_infos, false otherwise
> + */
> +static inline bool
> +fscrypt_fs_uses_extent_encryption(const struct super_block *sb)
> +{
> + return !!sb->s_cop->get_extent_info;
> +}
> +
> +/**
> + * fscrypt_uses_extent_encryption() -- whether an inode uses per-extent
> + * encryption
> + *
> + * @inode: the inode in question
> + *
> + * Return: true if the inode uses per-extent fscrypt_infos, false otherwise
> + */
> +static inline bool fscrypt_uses_extent_encryption(const struct inode *inode)
> +{
> + // Non-regular files don't have extents
Wrong comment format.
> + if (!S_ISREG(inode->i_mode))
> + return false;
> +
> + return fscrypt_fs_uses_extent_encryption(inode->i_sb);
> +}
> +
> +
> /**
> * fscrypt_get_lblk_info() - get the fscrypt_info to crypt a particular block
> *
> @@ -306,6 +338,17 @@ static inline struct fscrypt_info *
> fscrypt_get_lblk_info(const struct inode *inode, u64 lblk, u64 *offset,
> u64 *extent_len)
> {
> + if (fscrypt_uses_extent_encryption(inode)) {
> + struct fscrypt_info *info;
> + int res;
> +
> + res = inode->i_sb->s_cop->get_extent_info(inode, lblk, &info,
> + offset, extent_len);
> + if (res == 0)
> + return info;
> + return NULL;
> + }
> +
> if (offset)
> *offset = lblk;
> if (extent_len)
> @@ -314,39 +357,6 @@ fscrypt_get_lblk_info(const struct inode *inode, u64 lblk, u64 *offset,
> return inode->i_crypt_info;
> }
>
> -/**
> - * fscrypt_uses_extent_encryption() -- whether an inode uses per-extent
> - * encryption
> - *
> - * @inode: the inode in question
> - *
> - * Return: true if the inode uses per-extent fscrypt_infos, false otherwise
> - */
> -static inline bool fscrypt_uses_extent_encryption(const struct inode *inode)
> -{
> - // Non-regular files don't have extents
> - if (!S_ISREG(inode->i_mode))
> - return false;
> -
> - // No filesystems currently use per-extent infos
> - return false;
> -}
> -
> -/**
> - * fscrypt_fs_uses_extent_encryption() -- whether a filesystem uses per-extent
> - * encryption
> - *
> - * @sb: the superblock of the filesystem in question
> - *
> - * Return: true if the fs uses per-extent fscrypt_infos, false otherwise
> - */
> -static inline bool
> -fscrypt_fs_uses_extent_encryption(const struct super_block *sb)
> -{
> - // No filesystems currently use per-extent infos
> - return false;
> -}
> -
> /**
> * fscrypt_get_info_ino() - get the ino or ino equivalent for an info
> *
> diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c
> index 59748d333b89..8e4065d1e422 100644
> --- a/fs/crypto/keyring.c
> +++ b/fs/crypto/keyring.c
> @@ -880,15 +880,8 @@ static void evict_dentries_for_decrypted_inodes(struct fscrypt_master_key *mk)
>
> list_for_each_entry(ci, &mk->mk_decrypted_inodes, ci_master_key_link) {
> inode = ci->ci_inode;
> - if (!inode) {
> - if (!ci->ci_sb->s_cop->forget_extent_info)
> - continue;
> -
> - spin_unlock(&mk->mk_decrypted_inodes_lock);
> - ci->ci_sb->s_cop->forget_extent_info(ci->ci_info_ptr);
> - spin_lock(&mk->mk_decrypted_inodes_lock);
> + if (ci->ci_info_ptr)
> continue;
> - }
>
> spin_lock(&inode->i_lock);
> if (inode->i_state & (I_FREEING | I_WILL_FREE | I_NEW)) {
> diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
> index 2b4fca6814a7..c8cdcd4fe835 100644
> --- a/fs/crypto/keysetup.c
> +++ b/fs/crypto/keysetup.c
> @@ -676,8 +676,8 @@ fscrypt_setup_encryption_info(struct inode *inode,
>
> if (fscrypt_uses_extent_encryption(inode) && info_for_extent)
> crypt_info->ci_info_ptr = info_ptr;
> - else
> - crypt_info->ci_inode = inode;
> +
> + crypt_info->ci_inode = inode;
You changed this and now you're changing it back, go back to the original patch
and leave this the way it was.
>
> crypt_info->ci_sb = inode->i_sb;
> crypt_info->ci_policy = *policy;
> @@ -917,6 +917,60 @@ int fscrypt_prepare_new_inode(struct inode *dir, struct inode *inode,
> }
> EXPORT_SYMBOL_GPL(fscrypt_prepare_new_inode);
>
> +/**
> + * fscrypt_prepare_new_extent() - set up the fscrypt_info for a new extent
> + * @inode: the inode to which the extent belongs
> + * @info_ptr: a pointer to return the extent's fscrypt_info into. Should be
> + * a pointer to a member of the extent struct, as it will be passed
> + * back to the filesystem if key removal demands removal of the
> + * info from the extent
> + * @encrypt_ret: (output) set to %true if the new inode will be encrypted
> + *
> + * If the extent is part of an encrypted inode, set up its fscrypt_info in
> + * preparation for encrypting data and set *encrypt_ret=true.
> + *
> + * This isn't %GFP_NOFS-safe, and therefore it should be called before starting
> + * any filesystem transaction to create the inode.
> + *
> + * This doesn't persist the new inode's encryption context. That still needs to
> + * be done later by calling fscrypt_set_context().
> + *
> + * Return: 0 on success, -ENOKEY if the encryption key is missing, or another
> + * -errno code
> + */
> +int fscrypt_prepare_new_extent(struct inode *inode,
> + struct fscrypt_info **info_ptr)
> +{
> + const union fscrypt_policy *policy;
> + u8 nonce[FSCRYPT_FILE_NONCE_SIZE];
> +
> + policy = fscrypt_policy_to_inherit(inode);
> + if (policy == NULL)
> + return 0;
> + if (IS_ERR(policy))
> + return PTR_ERR(policy);
> +
> + /* Only regular files can have extents. */
> + if (WARN_ON_ONCE(!S_ISREG(inode->i_mode)))
> + return -EINVAL;
> +
> + get_random_bytes(nonce, FSCRYPT_FILE_NONCE_SIZE);
> + return fscrypt_setup_encryption_info(inode, policy, nonce,
> + false, info_ptr);
> +}
> +EXPORT_SYMBOL_GPL(fscrypt_prepare_new_extent);
> +
> +/**
> + * fscrypt_free_extent_info() - free an extent's fscrypt_info
> + * @info_ptr: a pointer containing the extent's fscrypt_info pointer.
> + */
> +void fscrypt_free_extent_info(struct fscrypt_info **info_ptr)
> +{
> + put_crypt_info(*info_ptr);
> + *info_ptr = NULL;
> +}
> +EXPORT_SYMBOL_GPL(fscrypt_free_extent_info);
> +
> /**
> * fscrypt_put_encryption_info() - free most of an inode's fscrypt data
> * @inode: an inode being evicted
> diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
> index 22affbb15706..e39165fbed41 100644
> --- a/include/linux/fscrypt.h
> +++ b/include/linux/fscrypt.h
> @@ -113,6 +113,29 @@ struct fscrypt_operations {
> int (*set_context)(struct inode *inode, const void *ctx, size_t len,
> void *fs_data);
>
> + /*
> + * Get the fscrypt_info for the given inode at the given block, for
> + * extent-based encryption only.
> + *
> + * @inode: the inode in question
> + * @lblk: the logical block number in question
> + * @ci: a pointer to return the fscrypt_info
> + * @offset: a pointer to return the offset of @lblk into the extent,
> + * in blocks (may be NULL)
> + * @extent_len: a pointer to return the number of blocks in this extent
> + * starting at this point (may be NULL)
> + *
> + * May cause the filesystem to allocate memory, which the filesystem
> + * must do with %GFP_NOFS, including calls into fscrypt to create or
> + * load an fscrypt_info.
> + *
> + * Return: 0 if an extent is found with an info, -ENODATA if the key is
> + * unavailable, or another -errno.
> + */
> + int (*get_extent_info)(const struct inode *inode, u64 lblk,
> + struct fscrypt_info **ci, u64 *offset,
> + u64 *extent_len);
> +
> /*
> * Get the dummy fscrypt policy in use on the filesystem (if any).
> *
> @@ -129,15 +152,6 @@ struct fscrypt_operations {
> */
> bool (*empty_dir)(struct inode *inode);
>
> - /*
> - * Inform the filesystem that a particular extent must forget its
> - * fscrypt_info (for instance, for a key removal).
> - *
> - * @info_ptr: a pointer to the location storing the fscrypt_info pointer
> - * within the opaque extent whose info is to be freed
> - */
> - void (*forget_extent_info)(struct fscrypt_info **info_ptr);
> -
You've done this again, backed out a change you did before. Rework the series
to simply not need this thing in the first place. Thanks,
Josef
next prev parent reply other threads:[~2023-07-17 15:22 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-09 18:53 [PATCH v2 00/14] fscrypt: add extent encryption Sweet Tea Dorminy
2023-07-09 18:53 ` [PATCH v2 01/14] fscrypt: factor helper for locking master key Sweet Tea Dorminy
2023-07-09 18:53 ` [PATCH v2 02/14] fscrypt: factor getting info for a specific block Sweet Tea Dorminy
2023-07-09 18:53 ` [PATCH v2 03/14] fscrypt: adjust effective lblks based on extents Sweet Tea Dorminy
2023-07-14 18:13 ` Josef Bacik
2023-07-09 18:53 ` [PATCH v2 04/14] fscrypt: add a super_block pointer to fscrypt_info Sweet Tea Dorminy
2023-07-09 18:53 ` [PATCH v2 05/14] fscrypt: setup leaf inodes for extent encryption Sweet Tea Dorminy
2023-07-14 18:16 ` Josef Bacik
2023-07-09 18:53 ` [PATCH v2 06/14] fscrypt: allow infos to be owned by extents Sweet Tea Dorminy
2023-07-09 18:53 ` [PATCH v2 07/14] fscrypt: notify per-extent infos if master key vanishes Sweet Tea Dorminy
2023-07-17 14:54 ` Josef Bacik
2023-07-09 18:53 ` [PATCH v2 08/14] fscrypt: use an optional ino equivalent for per-extent infos Sweet Tea Dorminy
2023-07-09 18:53 ` [PATCH v2 09/14] fscrypt: move function call warning of busy inodes Sweet Tea Dorminy
2023-07-17 14:59 ` Josef Bacik
2023-07-09 18:53 ` [PATCH v2 10/14] fscrypt: revamp key removal for extent encryption Sweet Tea Dorminy
2023-07-17 15:18 ` Josef Bacik
2023-07-09 18:53 ` [PATCH v2 11/14] fscrypt: add creation/usage/freeing of per-extent infos Sweet Tea Dorminy
2023-07-17 15:21 ` Josef Bacik [this message]
2023-07-09 18:53 ` [PATCH v2 12/14] fscrypt: allow load/save of extent contexts Sweet Tea Dorminy
2023-07-17 15:23 ` Josef Bacik
2023-07-09 18:53 ` [PATCH v2 13/14] fscrypt: save session key credentials for extent infos Sweet Tea Dorminy
2023-07-17 14:31 ` Josef Bacik
2023-07-09 18:53 ` [PATCH v2 14/14] fscrypt: update documentation for per-extent keys Sweet Tea Dorminy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230717152144.GF691303@perftesting \
--to=josef@toxicpanda.com \
--cc=clm@fb.com \
--cc=dsterba@suse.com \
--cc=ebiggers@kernel.org \
--cc=jaegeuk@kernel.org \
--cc=kernel-team@meta.com \
--cc=linux-btrfs@vger.kernel.org \
--cc=linux-fscrypt@vger.kernel.org \
--cc=sweettea-kernel@dorminy.me \
--cc=tytso@mit.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).