fsverity.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode
       [not found] <fhppu2rnsykr5obrib3btw7wemislq36wufnbl67salvoguaof@kkxaosrv3oho>
@ 2025-07-22 12:57 ` Christian Brauner
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 01/13] fs: add fscrypt offset Christian Brauner
                     ` (14 more replies)
  0 siblings, 15 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 12:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Hey,

This is a POC. We're still discussing alternatives and I want to provide
some useful data on what I learned about using offsets to drop fscrypt
and fsverity from struct inode.

As discussed, this moves the fscrypt and fsverity pointers out of struct
inode shrinking it by 16 bytes. The pointers move into the individual
filesystems that actually do make use of them.

In order to find the fscrypt and fsverity data pointers offsets from the
embedded struct inode in the filesystem's private inode data are
stored in struct inode_operations. This means we get fast access to the
data pointers without having to rely on indirect calls.

Bugs & Issues
=============

* For fscrypt specifically the biggest issue is
  fscrypt_prepare_new_inode() is called in filesystem's inode allocation
  functions before inode->i_op is set. That means the offset isn't
  available at the time when we would need it. To fix this we can set
  dummy encrypted inode operations for the respective filesystem with an
  initialized offset.

* For both fscrypt & fsverity the biggest issue is that every codepath
  that currently calls make_bad_inode() after having initialized fscrypt
  or fsverity data will override inode->i_op with bad_inode_ops. At
  which point we're back to the previous problem: The offset isn't
  available anymore. So when inode->i_sb->s_op->evict_inode() is called
  fscrypt_put_encryption_info() doesn't have the offset available
  anymore and would corrupt the hell out of everything and also leak
  memory.

  Obviously we could use a flag to detect a bad inodes instead of i_op
  and let the filesystem assign it's own bad inode operations including
  the correct offset. Is it worth it?

  The other way I see we can fix this if we require fixed offsets in the
  filesystems inode so fscrypt and fsverity always now what offset to
  calculate. We could use two consecutive pointers at the beginning of
  the filesystem's inode. Does that always work and is it worth it?

Thanks!
Christian

Test results:

+ sudo ./check -g encrypt,verity
FSTYP         -- ext4
PLATFORM      -- Linux/x86_64 localhost 6.16.0-rc1-g15c8eb9cdbd3 #267 SMP PREEMPT_DYNAMIC Fri Jun  5 15:58:00 CEST 2015
MKFS_OPTIONS  -- -F /dev/nvme3n1p6
MOUNT_OPTIONS -- -o acl,user_xattr /dev/nvme3n1p6 /mnt/scratch

ext4/024 3s ...  3s
generic/395 4s ...  4s
generic/396 3s ...  3s
generic/397 4s ...  3s
generic/398 4s ...  4s
generic/399 39s ...  35s
generic/419 3s ...  4s
generic/421 4s ...  4s
generic/429 14s ...  14s
generic/435 23s ...  22s
generic/440 3s ...  4s
generic/548 10s ...  9s
generic/549 9s ...  9s
generic/550       [not run] encryption policy '-c 9 -n 9 -f 0' is unusable; probably missing kernel crypto API support
generic/572        6s
generic/573        4s
generic/574        28s
generic/575        9s
generic/576 5s ...  4s
generic/577        4s
generic/579        24s
generic/580 4s ...  4s
generic/581 10s ...  11s
generic/582 10s ...  9s
generic/583 9s ...  9s
generic/584       [not run] encryption policy '-c 9 -n 9 -v 2 -f 0' is unusable; probably missing kernel crypto API support
generic/592 10s ...  10s
generic/593 4s ...  4s
generic/595 7s ...  7s
generic/602 9s ...  10s
generic/613 20s ...  20s
generic/621 9s ...  9s
generic/624        3s
generic/625        3s
generic/692        5s
generic/693       [not run] encryption policy '-c 1 -n 10 -v 2 -f 0' is unusable; probably missing kernel crypto API support
generic/739 17s ...  18s
Ran: ext4/024 generic/395 generic/396 generic/397 generic/398 generic/399 generic/419 generic/421 generic/429 generic/435 generic/440 generic/548 generic/549 generic/550 generic/572 generic/573 generic/574 generic/575 generic/576 generic/577 generic/579 generic/580 generic/581 generic/582 generic/583 generic/584 generic/592 generic/593 generic/595 generic/602 generic/613 generic/621 generic/624 generic/625 generic/692 generic/693 generic/739
Not run: generic/550 generic/584 generic/693
Passed all 37 tests

---
Changes in v2:
- First full implementation.
- Link to v1: https://lore.kernel.org/20250715-work-inode-fscrypt-v1-1-aa3ef6f44b6b@kernel.org

---
Christian Brauner (13):
      fs: add fscrypt offset
      fs/crypto: use accessors
      ext4: move fscrypt to filesystem inode
      ubifs: move fscrypt to filesystem inode
      f2fs: move fscrypt to filesystem inode
      ceph: move fscrypt to filesystem inode
      fs: drop i_crypt_info from struct inode
      fs: add fsverity offset
      fs/verity: use accessors
      btrfs: move fsverity to filesystem inode
      ext4: move fsverity to filesystem inode
      f2fs: move fsverity to filesystem inode
      fs: drop i_verity_info from struct inode

 fs/btrfs/btrfs_inode.h       |  3 +++
 fs/btrfs/inode.c             | 20 ++++++++++++++++-
 fs/ceph/dir.c                |  8 +++++++
 fs/ceph/inode.c              | 21 ++++++++++++++++++
 fs/crypto/bio.c              |  2 +-
 fs/crypto/crypto.c           |  8 +++----
 fs/crypto/fname.c            |  8 +++----
 fs/crypto/fscrypt_private.h  |  2 +-
 fs/crypto/hooks.c            |  2 +-
 fs/crypto/inline_crypt.c     | 10 ++++-----
 fs/crypto/keysetup.c         | 27 +++++++++++++----------
 fs/crypto/policy.c           |  6 ++---
 fs/ext4/ext4.h               |  9 ++++++++
 fs/ext4/file.c               |  8 +++++++
 fs/ext4/ialloc.c             |  2 ++
 fs/ext4/inode.c              |  1 +
 fs/ext4/mballoc.c            |  3 +++
 fs/ext4/namei.c              | 23 ++++++++++++++++++++
 fs/ext4/super.c              |  6 +++++
 fs/ext4/symlink.c            | 24 ++++++++++++++++++++
 fs/f2fs/f2fs.h               |  7 ++++++
 fs/f2fs/file.c               |  8 +++++++
 fs/f2fs/inode.c              |  1 +
 fs/f2fs/namei.c              | 41 ++++++++++++++++++++++++++++++++++
 fs/f2fs/super.c              |  6 +++++
 fs/ubifs/dir.c               | 52 ++++++++++++++++++++++++--------------------
 fs/ubifs/file.c              |  8 +++++++
 fs/ubifs/super.c             |  8 +++++++
 fs/ubifs/ubifs.h             |  3 +++
 fs/verity/enable.c           |  2 +-
 fs/verity/fsverity_private.h |  2 +-
 fs/verity/open.c             | 18 +++++++++------
 fs/verity/verify.c           |  2 +-
 include/linux/fs.h           | 10 ++-------
 include/linux/fscrypt.h      | 31 ++++++++++++++++++++++++--
 include/linux/fsverity.h     | 21 ++++++++++++------
 include/linux/netfs.h        |  6 +++++
 37 files changed, 337 insertions(+), 82 deletions(-)
---
base-commit: 19272b37aa4f83ca52bdf9c16d5d81bdd1354494
change-id: 20250715-work-inode-fscrypt-2b63b276e793


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH RFC DRAFT v2 01/13] fs: add fscrypt offset
  2025-07-22 12:57 ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode Christian Brauner
@ 2025-07-22 12:57   ` Christian Brauner
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 02/13] fs/crypto: use accessors Christian Brauner
                     ` (13 subsequent siblings)
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 12:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Store the offset of the fscrypt data pointer from struct inode in struct
inode_operations. Both are embedded in the filesystem's private inode.

This will allow us to drop the fscrypt data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 include/linux/fs.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index 96c7925a6551..82678b523720 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2217,6 +2217,7 @@ int wrap_directory_iterator(struct file *, struct dir_context *,
 	{ return wrap_directory_iterator(file, ctx, x); }
 
 struct inode_operations {
+	ptrdiff_t i_fscrypt;
 	struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
 	const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *);
 	int (*permission) (struct mnt_idmap *, struct inode *, int);

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH RFC DRAFT v2 02/13] fs/crypto: use accessors
  2025-07-22 12:57 ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode Christian Brauner
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 01/13] fs: add fscrypt offset Christian Brauner
@ 2025-07-22 12:57   ` Christian Brauner
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 03/13] ext4: move fscrypt to filesystem inode Christian Brauner
                     ` (12 subsequent siblings)
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 12:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Use accessor to get and set the fscrypt info from the filesystem.
They can be removed once all filesystems have been converted to make
room for fscrypt info in their own inodes.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/crypto/bio.c          |  2 +-
 fs/crypto/crypto.c       |  8 ++++----
 fs/crypto/fname.c        |  8 ++++----
 fs/crypto/hooks.c        |  2 +-
 fs/crypto/inline_crypt.c | 10 +++++-----
 fs/crypto/keysetup.c     | 12 +++++++++---
 fs/crypto/policy.c       |  6 +++---
 include/linux/fscrypt.h  | 36 ++++++++++++++++++++++++++++++++++++
 8 files changed, 63 insertions(+), 21 deletions(-)

diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index 0ad8c30b8fa5..73e46d2af511 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -111,7 +111,7 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
 int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
 			  sector_t pblk, unsigned int len)
 {
-	const struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 	const unsigned int du_bits = ci->ci_data_unit_bits;
 	const unsigned int du_size = 1U << du_bits;
 	const unsigned int du_per_page_bits = PAGE_SHIFT - du_bits;
diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
index b74b5937e695..c27ea8baaf52 100644
--- a/fs/crypto/crypto.c
+++ b/fs/crypto/crypto.c
@@ -181,7 +181,7 @@ struct page *fscrypt_encrypt_pagecache_blocks(struct folio *folio,
 		size_t len, size_t offs, gfp_t gfp_flags)
 {
 	const struct inode *inode = folio->mapping->host;
-	const struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 	const unsigned int du_bits = ci->ci_data_unit_bits;
 	const unsigned int du_size = 1U << du_bits;
 	struct page *ciphertext_page;
@@ -241,7 +241,7 @@ int fscrypt_encrypt_block_inplace(const struct inode *inode, struct page *page,
 {
 	if (WARN_ON_ONCE(inode->i_sb->s_cop->supports_subblock_data_units))
 		return -EOPNOTSUPP;
-	return fscrypt_crypt_data_unit(inode->i_crypt_info, FS_ENCRYPT,
+	return fscrypt_crypt_data_unit(fscrypt_get_inode_info_raw(inode), FS_ENCRYPT,
 				       lblk_num, page, page, len, offs,
 				       gfp_flags);
 }
@@ -265,7 +265,7 @@ int fscrypt_decrypt_pagecache_blocks(struct folio *folio, size_t len,
 				     size_t offs)
 {
 	const struct inode *inode = folio->mapping->host;
-	const struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 	const unsigned int du_bits = ci->ci_data_unit_bits;
 	const unsigned int du_size = 1U << du_bits;
 	u64 index = ((u64)folio->index << (PAGE_SHIFT - du_bits)) +
@@ -316,7 +316,7 @@ int fscrypt_decrypt_block_inplace(const struct inode *inode, struct page *page,
 {
 	if (WARN_ON_ONCE(inode->i_sb->s_cop->supports_subblock_data_units))
 		return -EOPNOTSUPP;
-	return fscrypt_crypt_data_unit(inode->i_crypt_info, FS_DECRYPT,
+	return fscrypt_crypt_data_unit(fscrypt_get_inode_info_raw(inode), FS_DECRYPT,
 				       lblk_num, page, page, len, offs,
 				       GFP_NOFS);
 }
diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c
index 010f9c0a4c2f..674b5fb11ac1 100644
--- a/fs/crypto/fname.c
+++ b/fs/crypto/fname.c
@@ -94,7 +94,7 @@ int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
 {
 	struct skcipher_request *req = NULL;
 	DECLARE_CRYPTO_WAIT(wait);
-	const struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 	struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;
 	union fscrypt_iv iv;
 	struct scatterlist sg;
@@ -151,7 +151,7 @@ static int fname_decrypt(const struct inode *inode,
 	struct skcipher_request *req = NULL;
 	DECLARE_CRYPTO_WAIT(wait);
 	struct scatterlist src_sg, dst_sg;
-	const struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 	struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;
 	union fscrypt_iv iv;
 	int res;
@@ -293,7 +293,7 @@ bool __fscrypt_fname_encrypted_size(const union fscrypt_policy *policy,
 bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len,
 				  u32 max_len, u32 *encrypted_len_ret)
 {
-	return __fscrypt_fname_encrypted_size(&inode->i_crypt_info->ci_policy,
+	return __fscrypt_fname_encrypted_size(&fscrypt_get_inode_info_raw(inode)->ci_policy,
 					      orig_len, max_len,
 					      encrypted_len_ret);
 }
@@ -562,7 +562,7 @@ EXPORT_SYMBOL_GPL(fscrypt_match_name);
  */
 u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name)
 {
-	const struct fscrypt_inode_info *ci = dir->i_crypt_info;
+	const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(dir);
 
 	WARN_ON_ONCE(!ci->ci_dirhash_key_initialized);
 
diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c
index d8d5049b8fe1..61bbe7d46df4 100644
--- a/fs/crypto/hooks.c
+++ b/fs/crypto/hooks.c
@@ -197,7 +197,7 @@ int fscrypt_prepare_setflags(struct inode *inode,
 		err = fscrypt_require_key(inode);
 		if (err)
 			return err;
-		ci = inode->i_crypt_info;
+		ci = fscrypt_get_inode_info_raw(inode);
 		if (ci->ci_policy.version != FSCRYPT_POLICY_V2)
 			return -EINVAL;
 		mk = ci->ci_master_key;
diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c
index 1d008c440cb6..6c2784b8e67a 100644
--- a/fs/crypto/inline_crypt.c
+++ b/fs/crypto/inline_crypt.c
@@ -262,7 +262,7 @@ int fscrypt_derive_sw_secret(struct super_block *sb,
 
 bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode)
 {
-	return inode->i_crypt_info->ci_inlinecrypt;
+	return fscrypt_get_inode_info_raw(inode)->ci_inlinecrypt;
 }
 EXPORT_SYMBOL_GPL(__fscrypt_inode_uses_inline_crypto);
 
@@ -306,7 +306,7 @@ void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode,
 
 	if (!fscrypt_inode_uses_inline_crypto(inode))
 		return;
-	ci = inode->i_crypt_info;
+	ci = fscrypt_get_inode_info_raw(inode);
 
 	fscrypt_generate_dun(ci, first_lblk, dun);
 	bio_crypt_set_ctx(bio, ci->ci_enc_key.blk_key, dun, gfp_mask);
@@ -396,10 +396,10 @@ bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode,
 	 * uses the same pointer.  I.e., there's currently no need to support
 	 * merging requests where the keys are the same but the pointers differ.
 	 */
-	if (bc->bc_key != inode->i_crypt_info->ci_enc_key.blk_key)
+	if (bc->bc_key != fscrypt_get_inode_info_raw(inode)->ci_enc_key.blk_key)
 		return false;
 
-	fscrypt_generate_dun(inode->i_crypt_info, next_lblk, next_dun);
+	fscrypt_generate_dun(fscrypt_get_inode_info_raw(inode), next_lblk, next_dun);
 	return bio_crypt_dun_is_contiguous(bc, bio->bi_iter.bi_size, next_dun);
 }
 EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio);
@@ -501,7 +501,7 @@ u64 fscrypt_limit_io_blocks(const struct inode *inode, u64 lblk, u64 nr_blocks)
 	if (nr_blocks <= 1)
 		return nr_blocks;
 
-	ci = inode->i_crypt_info;
+	ci = fscrypt_get_inode_info_raw(inode);
 	if (!(fscrypt_policy_flags(&ci->ci_policy) &
 	      FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32))
 		return nr_blocks;
diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
index 0d71843af946..76a5c7aafd89 100644
--- a/fs/crypto/keysetup.c
+++ b/fs/crypto/keysetup.c
@@ -644,7 +644,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
 	 * fscrypt_get_inode_info().  I.e., here we publish ->i_crypt_info with
 	 * a RELEASE barrier so that other tasks can ACQUIRE it.
 	 */
-	if (cmpxchg_release(&inode->i_crypt_info, NULL, crypt_info) == NULL) {
+	if (fscrypt_set_inode_info(inode, crypt_info)) {
 		/*
 		 * We won the race and set ->i_crypt_info to our crypt_info.
 		 * Now link it into the master key's inode list.
@@ -797,8 +797,14 @@ EXPORT_SYMBOL_GPL(fscrypt_prepare_new_inode);
  */
 void fscrypt_put_encryption_info(struct inode *inode)
 {
-	put_crypt_info(inode->i_crypt_info);
-	inode->i_crypt_info = NULL;
+	struct fscrypt_inode_info **crypt_info;
+
+	if (inode->i_op->i_fscrypt)
+		crypt_info = fscrypt_addr(inode);
+	else
+		crypt_info = &inode->i_crypt_info;
+	put_crypt_info(*crypt_info);
+	*crypt_info = NULL;
 }
 EXPORT_SYMBOL(fscrypt_put_encryption_info);
 
diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c
index 701259991277..d9fb2898a14a 100644
--- a/fs/crypto/policy.c
+++ b/fs/crypto/policy.c
@@ -725,7 +725,7 @@ const union fscrypt_policy *fscrypt_policy_to_inherit(struct inode *dir)
 		err = fscrypt_require_key(dir);
 		if (err)
 			return ERR_PTR(err);
-		return &dir->i_crypt_info->ci_policy;
+		return &fscrypt_get_inode_info_raw(dir)->ci_policy;
 	}
 
 	return fscrypt_get_dummy_policy(dir->i_sb);
@@ -744,7 +744,7 @@ const union fscrypt_policy *fscrypt_policy_to_inherit(struct inode *dir)
  */
 int fscrypt_context_for_new_inode(void *ctx, struct inode *inode)
 {
-	struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 
 	BUILD_BUG_ON(sizeof(union fscrypt_context) !=
 			FSCRYPT_SET_CONTEXT_MAX_SIZE);
@@ -769,7 +769,7 @@ EXPORT_SYMBOL_GPL(fscrypt_context_for_new_inode);
  */
 int fscrypt_set_context(struct inode *inode, void *fs_data)
 {
-	struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 	union fscrypt_context ctx;
 	int ctxsize;
 
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 56fad33043d5..fe48dfe171e4 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -195,6 +195,38 @@ struct fscrypt_operations {
 int fscrypt_d_revalidate(struct inode *dir, const struct qstr *name,
 			 struct dentry *dentry, unsigned int flags);
 
+static inline struct fscrypt_inode_info **fscrypt_addr(const struct inode *inode)
+{
+	return ((void *)inode + inode->i_op->i_fscrypt);
+}
+
+static inline bool fscrypt_set_inode_info(struct inode *inode,
+					  struct fscrypt_inode_info *crypt_info)
+{
+	void *p;
+
+	/*
+	 * For existing inodes, multiple tasks may race to set ->i_crypt_info.
+	 * So use cmpxchg_release().  This pairs with the smp_load_acquire() in
+	 * fscrypt_get_inode_info().  I.e., here we publish ->i_crypt_info with
+	 * a RELEASE barrier so that other tasks can ACQUIRE it.
+	 */
+
+	if (inode->i_op->i_fscrypt)
+		p = cmpxchg_release(fscrypt_addr(inode), NULL, crypt_info);
+	else
+		p = cmpxchg_release(&inode->i_crypt_info, NULL, crypt_info);
+	return p == NULL;
+}
+
+static inline struct fscrypt_inode_info *
+fscrypt_get_inode_info_raw(const struct inode *inode)
+{
+	if (inode->i_op->i_fscrypt)
+		return *fscrypt_addr(inode);
+	return inode->i_crypt_info;
+}
+
 static inline struct fscrypt_inode_info *
 fscrypt_get_inode_info(const struct inode *inode)
 {
@@ -204,6 +236,10 @@ fscrypt_get_inode_info(const struct inode *inode)
 	 * a RELEASE barrier.  We need to use smp_load_acquire() here to safely
 	 * ACQUIRE the memory the other task published.
 	 */
+
+	if (inode->i_op->i_fscrypt)
+		return smp_load_acquire(fscrypt_addr(inode));
+
 	return smp_load_acquire(&inode->i_crypt_info);
 }
 

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH RFC DRAFT v2 03/13] ext4: move fscrypt to filesystem inode
  2025-07-22 12:57 ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode Christian Brauner
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 01/13] fs: add fscrypt offset Christian Brauner
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 02/13] fs/crypto: use accessors Christian Brauner
@ 2025-07-22 12:57   ` Christian Brauner
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 04/13] ubifs: " Christian Brauner
                     ` (11 subsequent siblings)
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 12:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fscrypt data pointer into the filesystem's private inode and record
the offset from the embedded struct inode.

This will allow us to drop the fscrypt data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/ext4/ext4.h    |  5 +++++
 fs/ext4/file.c    |  4 ++++
 fs/ext4/ialloc.c  |  2 ++
 fs/ext4/inode.c   |  1 +
 fs/ext4/mballoc.c |  3 +++
 fs/ext4/namei.c   | 15 +++++++++++++++
 fs/ext4/super.c   |  3 +++
 fs/ext4/symlink.c | 12 ++++++++++++
 8 files changed, 45 insertions(+)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 18373de980f2..e9710366d87a 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1197,6 +1197,10 @@ struct ext4_inode_info {
 	__u32 i_csum_seed;
 
 	kprojid_t i_projid;
+
+#ifdef CONFIG_FS_ENCRYPTION
+	struct fscrypt_inode_info	*i_fscrypt_info;
+#endif
 };
 
 /*
@@ -3604,6 +3608,7 @@ int ext4_enable_quotas(struct super_block *sb);
 extern const struct file_operations ext4_dir_operations;
 
 /* file.c */
+extern const struct inode_operations ext4_encrypted_nop_operations;
 extern const struct inode_operations ext4_file_inode_operations;
 extern const struct file_operations ext4_file_operations;
 extern loff_t ext4_llseek(struct file *file, loff_t offset, int origin);
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 21df81347147..9bdee2757bdf 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -981,6 +981,10 @@ const struct file_operations ext4_file_operations = {
 };
 
 const struct inode_operations ext4_file_inode_operations = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt	= offsetof(struct ext4_inode_info, i_fscrypt_info) -
+			  offsetof(struct ext4_inode_info, vfs_inode),
+#endif
 	.setattr	= ext4_setattr,
 	.getattr	= ext4_file_getattr,
 	.listxattr	= ext4_listxattr,
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 79aa3df8d019..cf1f9c307b9c 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -979,6 +979,8 @@ struct inode *__ext4_new_inode(struct mnt_idmap *idmap,
 	} else
 		inode_init_owner(idmap, inode, dir, mode);
 
+	inode->i_op = &ext4_encrypted_nop_operations;
+
 	if (ext4_has_feature_project(sb) &&
 	    ext4_test_inode_flag(dir, EXT4_INODE_PROJINHERIT))
 		ei->i_projid = EXT4_I(dir)->i_projid;
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index be9a4cba35fd..ce385d9c1683 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -5163,6 +5163,7 @@ struct inode *__ext4_iget(struct super_block *sb, unsigned long ino,
 		return inode;
 	}
 
+	inode->i_op = &ext4_encrypted_nop_operations;
 	ei = EXT4_I(inode);
 	iloc.bh = NULL;
 
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 1e98c5be4e0a..9b93ee2bfd6a 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -3417,6 +3417,9 @@ static int ext4_mb_init_backend(struct super_block *sb)
 		ext4_msg(sb, KERN_ERR, "can't get new inode");
 		goto err_freesgi;
 	}
+
+	sbi->s_buddy_cache->i_op = &ext4_encrypted_nop_operations;
+
 	/* To avoid potentially colliding with an valid on-disk inode number,
 	 * use EXT4_BAD_INO for the buddy cache inode number.  This inode is
 	 * not in the inode hash, so it should never be found by iget(), but
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index a178ac229489..fb953834265c 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -4206,7 +4206,18 @@ static int ext4_rename2(struct mnt_idmap *idmap,
 /*
  * directories can handle most operations...
  */
+const struct inode_operations ext4_encrypted_nop_operations = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt	= offsetof(struct ext4_inode_info, i_fscrypt_info) -
+			  offsetof(struct ext4_inode_info, vfs_inode),
+#endif
+};
+
 const struct inode_operations ext4_dir_inode_operations = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt	= offsetof(struct ext4_inode_info, i_fscrypt_info) -
+			  offsetof(struct ext4_inode_info, vfs_inode),
+#endif
 	.create		= ext4_create,
 	.lookup		= ext4_lookup,
 	.link		= ext4_link,
@@ -4228,6 +4239,10 @@ const struct inode_operations ext4_dir_inode_operations = {
 };
 
 const struct inode_operations ext4_special_inode_operations = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt	= offsetof(struct ext4_inode_info, i_fscrypt_info) -
+			  offsetof(struct ext4_inode_info, vfs_inode),
+#endif
 	.setattr	= ext4_setattr,
 	.getattr	= ext4_getattr,
 	.listxattr	= ext4_listxattr,
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index c7d39da7e733..6085d6c9169b 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1412,6 +1412,9 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
 	INIT_WORK(&ei->i_rsv_conversion_work, ext4_end_io_rsv_work);
 	ext4_fc_init_inode(&ei->vfs_inode);
 	spin_lock_init(&ei->i_fc_lock);
+#ifdef CONFIG_FS_ENCRYPTION
+	ei->i_fscrypt_info = NULL;
+#endif
 	return &ei->vfs_inode;
 }
 
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
index 645240cc0229..6b67a9a5c02c 100644
--- a/fs/ext4/symlink.c
+++ b/fs/ext4/symlink.c
@@ -115,6 +115,10 @@ static const char *ext4_get_link(struct dentry *dentry, struct inode *inode,
 }
 
 const struct inode_operations ext4_encrypted_symlink_inode_operations = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt	= offsetof(struct ext4_inode_info, i_fscrypt_info) -
+			  offsetof(struct ext4_inode_info, vfs_inode),
+#endif
 	.get_link	= ext4_encrypted_get_link,
 	.setattr	= ext4_setattr,
 	.getattr	= ext4_encrypted_symlink_getattr,
@@ -122,6 +126,10 @@ const struct inode_operations ext4_encrypted_symlink_inode_operations = {
 };
 
 const struct inode_operations ext4_symlink_inode_operations = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt	= offsetof(struct ext4_inode_info, i_fscrypt_info) -
+			  offsetof(struct ext4_inode_info, vfs_inode),
+#endif
 	.get_link	= ext4_get_link,
 	.setattr	= ext4_setattr,
 	.getattr	= ext4_getattr,
@@ -129,6 +137,10 @@ const struct inode_operations ext4_symlink_inode_operations = {
 };
 
 const struct inode_operations ext4_fast_symlink_inode_operations = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt	= offsetof(struct ext4_inode_info, i_fscrypt_info) -
+			  offsetof(struct ext4_inode_info, vfs_inode),
+#endif
 	.get_link	= simple_get_link,
 	.setattr	= ext4_setattr,
 	.getattr	= ext4_getattr,

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH RFC DRAFT v2 04/13] ubifs: move fscrypt to filesystem inode
  2025-07-22 12:57 ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode Christian Brauner
                     ` (2 preceding siblings ...)
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 03/13] ext4: move fscrypt to filesystem inode Christian Brauner
@ 2025-07-22 12:57   ` Christian Brauner
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 05/13] f2fs: " Christian Brauner
                     ` (10 subsequent siblings)
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 12:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fscrypt data pointer into the filesystem's private inode and record
the offset from the embedded struct inode.

This will allow us to drop the fscrypt data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/ubifs/dir.c   | 52 ++++++++++++++++++++++++++++------------------------
 fs/ubifs/file.c  |  8 ++++++++
 fs/ubifs/super.c |  8 ++++++++
 fs/ubifs/ubifs.h |  3 +++
 4 files changed, 47 insertions(+), 24 deletions(-)

diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 3c3d3ad4fa6c..7d3c70c057c2 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -104,14 +104,6 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
 	simple_inode_init_ts(inode);
 	inode->i_mapping->nrpages = 0;
 
-	if (!is_xattr) {
-		err = fscrypt_prepare_new_inode(dir, inode, &encrypted);
-		if (err) {
-			ubifs_err(c, "fscrypt_prepare_new_inode failed: %i", err);
-			goto out_iput;
-		}
-	}
-
 	switch (mode & S_IFMT) {
 	case S_IFREG:
 		inode->i_mapping->a_ops = &ubifs_file_address_operations;
@@ -136,6 +128,14 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
 		BUG();
 	}
 
+	if (!is_xattr) {
+		err = fscrypt_prepare_new_inode(dir, inode, &encrypted);
+		if (err) {
+			ubifs_err(c, "fscrypt_prepare_new_inode failed: %i", err);
+			goto out_iput;
+		}
+	}
+
 	ui->flags = inherit_flags(dir, mode);
 	ubifs_set_inode_flags(inode);
 	if (S_ISREG(mode))
@@ -1740,22 +1740,26 @@ static loff_t ubifs_dir_llseek(struct file *file, loff_t offset, int whence)
 }
 
 const struct inode_operations ubifs_dir_inode_operations = {
-	.lookup      = ubifs_lookup,
-	.create      = ubifs_create,
-	.link        = ubifs_link,
-	.symlink     = ubifs_symlink,
-	.unlink      = ubifs_unlink,
-	.mkdir       = ubifs_mkdir,
-	.rmdir       = ubifs_rmdir,
-	.mknod       = ubifs_mknod,
-	.rename      = ubifs_rename,
-	.setattr     = ubifs_setattr,
-	.getattr     = ubifs_getattr,
-	.listxattr   = ubifs_listxattr,
-	.update_time = ubifs_update_time,
-	.tmpfile     = ubifs_tmpfile,
-	.fileattr_get = ubifs_fileattr_get,
-	.fileattr_set = ubifs_fileattr_set,
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt	= offsetof(struct ubifs_inode, i_fscrypt_info) -
+			  offsetof(struct ubifs_inode, vfs_inode),
+#endif
+	.lookup		= ubifs_lookup,
+	.create      	= ubifs_create,
+	.link        	= ubifs_link,
+	.symlink     	= ubifs_symlink,
+	.unlink      	= ubifs_unlink,
+	.mkdir       	= ubifs_mkdir,
+	.rmdir       	= ubifs_rmdir,
+	.mknod       	= ubifs_mknod,
+	.rename      	= ubifs_rename,
+	.setattr     	= ubifs_setattr,
+	.getattr     	= ubifs_getattr,
+	.listxattr   	= ubifs_listxattr,
+	.update_time 	= ubifs_update_time,
+	.tmpfile     	= ubifs_tmpfile,
+	.fileattr_get	= ubifs_fileattr_get,
+	.fileattr_set 	= ubifs_fileattr_set,
 };
 
 const struct file_operations ubifs_dir_operations = {
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index bf311c38d9a8..93ab562f7107 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1632,6 +1632,10 @@ const struct address_space_operations ubifs_file_address_operations = {
 };
 
 const struct inode_operations ubifs_file_inode_operations = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt	= offsetof(struct ubifs_inode, i_fscrypt_info) -
+			  offsetof(struct ubifs_inode, vfs_inode),
+#endif
 	.setattr     = ubifs_setattr,
 	.getattr     = ubifs_getattr,
 	.listxattr   = ubifs_listxattr,
@@ -1641,6 +1645,10 @@ const struct inode_operations ubifs_file_inode_operations = {
 };
 
 const struct inode_operations ubifs_symlink_inode_operations = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt	= offsetof(struct ubifs_inode, i_fscrypt_info) -
+			  offsetof(struct ubifs_inode, vfs_inode),
+#endif
 	.get_link    = ubifs_get_link,
 	.setattr     = ubifs_setattr,
 	.getattr     = ubifs_symlink_getattr,
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index f3e3b2068608..f18b38ee5c0c 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -100,6 +100,13 @@ static int validate_inode(struct ubifs_info *c, const struct inode *inode)
 	return err;
 }
 
+static const struct inode_operations ubifs_encrypted_nop_inode_operations = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt	= offsetof(struct ubifs_inode, i_fscrypt_info) -
+			  offsetof(struct ubifs_inode, vfs_inode),
+#endif
+};
+
 struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
 {
 	int err;
@@ -118,6 +125,7 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum)
 		return inode;
 	ui = ubifs_inode(inode);
 
+	inode->i_op = &ubifs_encrypted_nop_inode_operations;
 	ino = kmalloc(UBIFS_MAX_INO_NODE_SZ, GFP_NOFS);
 	if (!ino) {
 		err = -ENOMEM;
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 256dbaeeb0de..0442782a54ab 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -416,6 +416,9 @@ struct ubifs_inode {
 	pgoff_t read_in_a_row;
 	int data_len;
 	void *data;
+#ifdef CONFIG_FS_ENCRYPTION
+	struct fscrypt_inode_info *i_fscrypt_info;
+#endif
 };
 
 /**

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH RFC DRAFT v2 05/13] f2fs: move fscrypt to filesystem inode
  2025-07-22 12:57 ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode Christian Brauner
                     ` (3 preceding siblings ...)
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 04/13] ubifs: " Christian Brauner
@ 2025-07-22 12:57   ` Christian Brauner
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 06/13] ceph: " Christian Brauner
                     ` (9 subsequent siblings)
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 12:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fscrypt data pointer into the filesystem's private inode and record
the offset from the embedded struct inode.

This will allow us to drop the fscrypt data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/f2fs/f2fs.h  |  4 ++++
 fs/f2fs/file.c  |  4 ++++
 fs/f2fs/inode.c |  1 +
 fs/f2fs/namei.c | 25 +++++++++++++++++++++++++
 fs/f2fs/super.c |  3 +++
 5 files changed, 37 insertions(+)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 9333a22b9a01..152990273c68 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -905,6 +905,9 @@ struct f2fs_inode_info {
 
 	unsigned int atomic_write_cnt;
 	loff_t original_i_size;		/* original i_size before atomic write */
+#ifdef CONFIG_FS_ENCRYPTION
+	struct fscrypt_inode_info *i_fscrypt_info; /* filesystem encryption info */
+#endif
 };
 
 static inline void get_read_extent_info(struct extent_info *ext,
@@ -4297,6 +4300,7 @@ extern const struct inode_operations f2fs_dir_inode_operations;
 extern const struct inode_operations f2fs_symlink_inode_operations;
 extern const struct inode_operations f2fs_encrypted_symlink_inode_operations;
 extern const struct inode_operations f2fs_special_inode_operations;
+extern const struct inode_operations f2fs_encrypted_nop_inode_operations;
 extern struct kmem_cache *f2fs_inode_entry_slab;
 
 /*
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 6bd3de64f2a8..f0003672a42c 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -1150,6 +1150,10 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
 }
 
 const struct inode_operations f2fs_file_inode_operations = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt	= offsetof(struct f2fs_inode_info, i_fscrypt_info) -
+			  offsetof(struct f2fs_inode_info, vfs_inode),
+#endif
 	.getattr	= f2fs_getattr,
 	.setattr	= f2fs_setattr,
 	.get_inode_acl	= f2fs_get_acl,
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index 083d52a42bfb..73bfb9853c25 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -583,6 +583,7 @@ struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
 		return inode;
 	}
 
+	inode->i_op = &f2fs_encrypted_nop_inode_operations;
 	if (is_meta_ino(sbi, ino))
 		goto make_now;
 
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 07e333ee21b7..998b0c31f728 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -216,6 +216,13 @@ static void set_file_temperature(struct f2fs_sb_info *sbi, struct inode *inode,
 		file_set_hot(inode);
 }
 
+const struct inode_operations f2fs_encrypted_nop_inode_operations = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt = offsetof(struct f2fs_inode_info, i_fscrypt_info) -
+		     offsetof(struct f2fs_inode_info, vfs_inode),
+#endif
+};
+
 static struct inode *f2fs_new_inode(struct mnt_idmap *idmap,
 						struct inode *dir, umode_t mode,
 						const char *name)
@@ -249,6 +256,8 @@ static struct inode *f2fs_new_inode(struct mnt_idmap *idmap,
 	fi->i_crtime = inode_get_mtime(inode);
 	inode->i_generation = get_random_u32();
 
+	inode->i_op = &f2fs_encrypted_nop_inode_operations;
+
 	if (S_ISDIR(inode->i_mode))
 		fi->i_current_depth = 1;
 
@@ -1325,6 +1334,10 @@ static int f2fs_encrypted_symlink_getattr(struct mnt_idmap *idmap,
 }
 
 const struct inode_operations f2fs_encrypted_symlink_inode_operations = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt	= offsetof(struct f2fs_inode_info, i_fscrypt_info) -
+			  offsetof(struct f2fs_inode_info, vfs_inode),
+#endif
 	.get_link	= f2fs_encrypted_get_link,
 	.getattr	= f2fs_encrypted_symlink_getattr,
 	.setattr	= f2fs_setattr,
@@ -1332,6 +1345,10 @@ const struct inode_operations f2fs_encrypted_symlink_inode_operations = {
 };
 
 const struct inode_operations f2fs_dir_inode_operations = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt	= offsetof(struct f2fs_inode_info, i_fscrypt_info) -
+			  offsetof(struct f2fs_inode_info, vfs_inode),
+#endif
 	.create		= f2fs_create,
 	.lookup		= f2fs_lookup,
 	.link		= f2fs_link,
@@ -1353,6 +1370,10 @@ const struct inode_operations f2fs_dir_inode_operations = {
 };
 
 const struct inode_operations f2fs_symlink_inode_operations = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt	= offsetof(struct f2fs_inode_info, i_fscrypt_info) -
+			  offsetof(struct f2fs_inode_info, vfs_inode),
+#endif
 	.get_link	= f2fs_get_link,
 	.getattr	= f2fs_getattr,
 	.setattr	= f2fs_setattr,
@@ -1360,6 +1381,10 @@ const struct inode_operations f2fs_symlink_inode_operations = {
 };
 
 const struct inode_operations f2fs_special_inode_operations = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt	= offsetof(struct f2fs_inode_info, i_fscrypt_info) -
+			  offsetof(struct f2fs_inode_info, vfs_inode),
+#endif
 	.getattr	= f2fs_getattr,
 	.setattr	= f2fs_setattr,
 	.get_inode_acl	= f2fs_get_acl,
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index bbf1dad6843f..9f8e5ae13dc9 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1453,6 +1453,9 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
 
 	/* Will be used by directory only */
 	fi->i_dir_level = F2FS_SB(sb)->dir_level;
+#ifdef CONFIG_FS_ENCRYPTION
+	fi->i_fscrypt_info = NULL;
+#endif
 
 	return &fi->vfs_inode;
 }

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH RFC DRAFT v2 06/13] ceph: move fscrypt to filesystem inode
  2025-07-22 12:57 ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode Christian Brauner
                     ` (4 preceding siblings ...)
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 05/13] f2fs: " Christian Brauner
@ 2025-07-22 12:57   ` Christian Brauner
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 07/13] fs: drop i_crypt_info from struct inode Christian Brauner
                     ` (8 subsequent siblings)
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 12:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fscrypt data pointer into the filesystem's private inode and record
the offset from the embedded struct inode.

This will allow us to drop the fscrypt data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/ceph/dir.c         |  8 ++++++++
 fs/ceph/inode.c       | 21 +++++++++++++++++++++
 include/linux/netfs.h |  6 ++++++
 3 files changed, 35 insertions(+)

diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index a321aa6d0ed2..2db146fadddb 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -2229,6 +2229,10 @@ const struct file_operations ceph_snapdir_fops = {
 };
 
 const struct inode_operations ceph_dir_iops = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt = offsetof(struct ceph_inode_info, netfs.i_fscrypt_info) -
+		     offsetof(struct ceph_inode_info, netfs.inode),
+#endif
 	.lookup = ceph_lookup,
 	.permission = ceph_permission,
 	.getattr = ceph_getattr,
@@ -2248,6 +2252,10 @@ const struct inode_operations ceph_dir_iops = {
 };
 
 const struct inode_operations ceph_snapdir_iops = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt = offsetof(struct ceph_inode_info, netfs.i_fscrypt_info) -
+		     offsetof(struct ceph_inode_info, netfs.inode),
+#endif
 	.lookup = ceph_lookup,
 	.permission = ceph_permission,
 	.getattr = ceph_getattr,
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 06cd2963e41e..3f8f779f3dcd 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -36,6 +36,12 @@
 
 static const struct inode_operations ceph_symlink_iops;
 static const struct inode_operations ceph_encrypted_symlink_iops;
+static const struct inode_operations ceph_encrypted_nop_iops = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt = offsetof(struct ceph_inode_info, netfs.i_fscrypt_info) -
+		     offsetof(struct ceph_inode_info, netfs.inode),
+#endif
+};
 
 static void ceph_inode_work(struct work_struct *work);
 
@@ -49,6 +55,7 @@ static int ceph_set_ino_cb(struct inode *inode, void *data)
 
 	ci->i_vino = *(struct ceph_vino *)data;
 	inode->i_ino = ceph_vino_to_ino_t(ci->i_vino);
+	inode->i_op = &ceph_encrypted_nop_iops;
 	inode_set_iversion_raw(inode, 0);
 	percpu_counter_inc(&mdsc->metric.total_inodes);
 
@@ -89,6 +96,8 @@ struct inode *ceph_new_inode(struct inode *dir, struct dentry *dentry,
 	inode->i_state = 0;
 	inode->i_mode = *mode;
 
+	inode->i_op = &ceph_encrypted_nop_iops;
+
 	err = ceph_security_init_secctx(dentry, *mode, as_ctx);
 	if (err < 0)
 		goto out_err;
@@ -232,6 +241,10 @@ struct inode *ceph_get_snapdir(struct inode *parent)
 }
 
 const struct inode_operations ceph_file_iops = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt = offsetof(struct ceph_inode_info, netfs.i_fscrypt_info) -
+		     offsetof(struct ceph_inode_info, netfs.inode),
+#endif
 	.permission = ceph_permission,
 	.setattr = ceph_setattr,
 	.getattr = ceph_getattr,
@@ -2314,6 +2327,10 @@ static int ceph_encrypted_symlink_getattr(struct mnt_idmap *idmap,
  * symlinks
  */
 static const struct inode_operations ceph_symlink_iops = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt = offsetof(struct ceph_inode_info, netfs.i_fscrypt_info) -
+		     offsetof(struct ceph_inode_info, netfs.inode),
+#endif
 	.get_link = simple_get_link,
 	.setattr = ceph_setattr,
 	.getattr = ceph_getattr,
@@ -2321,6 +2338,10 @@ static const struct inode_operations ceph_symlink_iops = {
 };
 
 static const struct inode_operations ceph_encrypted_symlink_iops = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt = offsetof(struct ceph_inode_info, netfs.i_fscrypt_info) -
+		     offsetof(struct ceph_inode_info, netfs.inode),
+#endif
 	.get_link = ceph_encrypted_get_link,
 	.setattr = ceph_setattr,
 	.getattr = ceph_encrypted_symlink_getattr,
diff --git a/include/linux/netfs.h b/include/linux/netfs.h
index 065c17385e53..fda1321da861 100644
--- a/include/linux/netfs.h
+++ b/include/linux/netfs.h
@@ -57,6 +57,9 @@ typedef void (*netfs_io_terminated_t)(void *priv, ssize_t transferred_or_error);
  */
 struct netfs_inode {
 	struct inode		inode;		/* The VFS inode */
+#ifdef CONFIG_FS_ENCRYPTION
+	struct fscrypt_inode_info *i_fscrypt_info;
+#endif
 	const struct netfs_request_ops *ops;
 #if IS_ENABLED(CONFIG_FSCACHE)
 	struct fscache_cookie	*cache;
@@ -503,6 +506,9 @@ static inline void netfs_inode_init(struct netfs_inode *ctx,
 		ctx->zero_point = ctx->remote_i_size;
 		mapping_set_release_always(ctx->inode.i_mapping);
 	}
+#ifdef CONFIG_FS_ENCRYPTION
+	ctx->i_fscrypt_info = NULL;
+#endif
 }
 
 /**

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH RFC DRAFT v2 07/13] fs: drop i_crypt_info from struct inode
  2025-07-22 12:57 ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode Christian Brauner
                     ` (5 preceding siblings ...)
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 06/13] ceph: " Christian Brauner
@ 2025-07-22 12:57   ` Christian Brauner
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 08/13] fs: add fsverity offset Christian Brauner
                     ` (7 subsequent siblings)
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 12:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Now that all filesystems store the fscrypt data pointer in their private
inode, drop the data pointer from struct inode itself freeing up 8
bytes.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/crypto/fscrypt_private.h |  2 +-
 fs/crypto/keysetup.c        | 25 ++++++++++++-------------
 include/linux/fs.h          |  4 ----
 include/linux/fscrypt.h     | 21 ++++++---------------
 4 files changed, 19 insertions(+), 33 deletions(-)

diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
index c1d92074b65c..53a72dc909d9 100644
--- a/fs/crypto/fscrypt_private.h
+++ b/fs/crypto/fscrypt_private.h
@@ -231,7 +231,7 @@ struct fscrypt_prepared_key {
  * fscrypt_inode_info - the "encryption key" for an inode
  *
  * When an encrypted file's key is made available, an instance of this struct is
- * allocated and stored in ->i_crypt_info.  Once created, it remains until the
+ * allocated and stored in ->i_fscrypt_info.  Once created, it remains until the
  * inode is evicted.
  */
 struct fscrypt_inode_info {
diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
index 76a5c7aafd89..e520712431f6 100644
--- a/fs/crypto/keysetup.c
+++ b/fs/crypto/keysetup.c
@@ -639,14 +639,14 @@ fscrypt_setup_encryption_info(struct inode *inode,
 		goto out;
 
 	/*
-	 * For existing inodes, multiple tasks may race to set ->i_crypt_info.
+	 * For existing inodes, multiple tasks may race to set ->i_fscrypt_info.
 	 * So use cmpxchg_release().  This pairs with the smp_load_acquire() in
-	 * fscrypt_get_inode_info().  I.e., here we publish ->i_crypt_info with
+	 * fscrypt_get_inode_info().  I.e., here we publish ->i_fscrypt_info with
 	 * a RELEASE barrier so that other tasks can ACQUIRE it.
 	 */
 	if (fscrypt_set_inode_info(inode, crypt_info)) {
 		/*
-		 * We won the race and set ->i_crypt_info to our crypt_info.
+		 * We won the race and set ->i_fscrypt_info to our crypt_info.
 		 * Now link it into the master key's inode list.
 		 */
 		if (mk) {
@@ -678,12 +678,12 @@ fscrypt_setup_encryption_info(struct inode *inode,
  *		       %false unless the operation being performed is needed in
  *		       order for files (or directories) to be deleted.
  *
- * Set up ->i_crypt_info, if it hasn't already been done.
+ * Set up ->i_fscrypt_info, if it hasn't already been done.
  *
- * Note: unless ->i_crypt_info is already set, this isn't %GFP_NOFS-safe.  So
+ * Note: unless ->i_fscrypt_info is already set, this isn't %GFP_NOFS-safe.  So
  * generally this shouldn't be called from within a filesystem transaction.
  *
- * Return: 0 if ->i_crypt_info was set or was already set, *or* if the
+ * Return: 0 if ->i_fscrypt_info was set or was already set, *or* if the
  *	   encryption key is unavailable.  (Use fscrypt_has_encryption_key() to
  *	   distinguish these cases.)  Also can return another -errno code.
  */
@@ -738,9 +738,9 @@ int fscrypt_get_encryption_info(struct inode *inode, bool allow_unsupported)
  *	   ->i_ino doesn't need to be set yet.
  * @encrypt_ret: (output) set to %true if the new inode will be encrypted
  *
- * If the directory is encrypted, set up its ->i_crypt_info in preparation for
+ * If the directory is encrypted, set up its ->i_fscrypt_info in preparation for
  * encrypting the name of the new file.  Also, if the new inode will be
- * encrypted, set up its ->i_crypt_info and set *encrypt_ret=true.
+ * encrypted, set up its ->i_fscrypt_info 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.  For this reason, ->i_ino
@@ -799,12 +799,11 @@ void fscrypt_put_encryption_info(struct inode *inode)
 {
 	struct fscrypt_inode_info **crypt_info;
 
-	if (inode->i_op->i_fscrypt)
+	if (inode->i_op->i_fscrypt) {
 		crypt_info = fscrypt_addr(inode);
-	else
-		crypt_info = &inode->i_crypt_info;
-	put_crypt_info(*crypt_info);
-	*crypt_info = NULL;
+		put_crypt_info(*crypt_info);
+		*crypt_info = NULL;
+	}
 }
 EXPORT_SYMBOL(fscrypt_put_encryption_info);
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 82678b523720..ea5d3d3356c9 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -778,10 +778,6 @@ struct inode {
 	struct fsnotify_mark_connector __rcu	*i_fsnotify_marks;
 #endif
 
-#ifdef CONFIG_FS_ENCRYPTION
-	struct fscrypt_inode_info	*i_crypt_info;
-#endif
-
 #ifdef CONFIG_FS_VERITY
 	struct fsverity_info	*i_verity_info;
 #endif
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index fe48dfe171e4..fb9c8da4420f 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -203,28 +203,20 @@ static inline struct fscrypt_inode_info **fscrypt_addr(const struct inode *inode
 static inline bool fscrypt_set_inode_info(struct inode *inode,
 					  struct fscrypt_inode_info *crypt_info)
 {
-	void *p;
-
 	/*
-	 * For existing inodes, multiple tasks may race to set ->i_crypt_info.
+	 * For existing inodes, multiple tasks may race to set ->i_fscrypt_info.
 	 * So use cmpxchg_release().  This pairs with the smp_load_acquire() in
-	 * fscrypt_get_inode_info().  I.e., here we publish ->i_crypt_info with
+	 * fscrypt_get_inode_info().  I.e., here we publish ->i_fscrypt_info with
 	 * a RELEASE barrier so that other tasks can ACQUIRE it.
 	 */
 
-	if (inode->i_op->i_fscrypt)
-		p = cmpxchg_release(fscrypt_addr(inode), NULL, crypt_info);
-	else
-		p = cmpxchg_release(&inode->i_crypt_info, NULL, crypt_info);
-	return p == NULL;
+	return cmpxchg_release(fscrypt_addr(inode), NULL, crypt_info) == NULL;
 }
 
 static inline struct fscrypt_inode_info *
 fscrypt_get_inode_info_raw(const struct inode *inode)
 {
-	if (inode->i_op->i_fscrypt)
-		return *fscrypt_addr(inode);
-	return inode->i_crypt_info;
+	return *fscrypt_addr(inode);
 }
 
 static inline struct fscrypt_inode_info *
@@ -232,15 +224,14 @@ fscrypt_get_inode_info(const struct inode *inode)
 {
 	/*
 	 * Pairs with the cmpxchg_release() in fscrypt_setup_encryption_info().
-	 * I.e., another task may publish ->i_crypt_info concurrently, executing
+	 * I.e., another task may publish ->i_fscrypt_info concurrently, executing
 	 * a RELEASE barrier.  We need to use smp_load_acquire() here to safely
 	 * ACQUIRE the memory the other task published.
 	 */
 
 	if (inode->i_op->i_fscrypt)
 		return smp_load_acquire(fscrypt_addr(inode));
-
-	return smp_load_acquire(&inode->i_crypt_info);
+	return NULL;
 }
 
 /**

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH RFC DRAFT v2 08/13] fs: add fsverity offset
  2025-07-22 12:57 ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode Christian Brauner
                     ` (6 preceding siblings ...)
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 07/13] fs: drop i_crypt_info from struct inode Christian Brauner
@ 2025-07-22 12:57   ` Christian Brauner
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 09/13] fs/verity: use accessors Christian Brauner
                     ` (6 subsequent siblings)
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 12:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Store the offset of the fsverity data pointer from struct inode in
struct inode_operations. Both are embedded in the filesystem's private
inode.

This will allow us to drop the fsverity data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 include/linux/fs.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index ea5d3d3356c9..b933b8d75f50 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2214,6 +2214,7 @@ int wrap_directory_iterator(struct file *, struct dir_context *,
 
 struct inode_operations {
 	ptrdiff_t i_fscrypt;
+	ptrdiff_t i_fsverity;
 	struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
 	const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *);
 	int (*permission) (struct mnt_idmap *, struct inode *, int);

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH RFC DRAFT v2 09/13] fs/verity: use accessors
  2025-07-22 12:57 ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode Christian Brauner
                     ` (7 preceding siblings ...)
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 08/13] fs: add fsverity offset Christian Brauner
@ 2025-07-22 12:57   ` Christian Brauner
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 10/13] btrfs: move fsverity to filesystem inode Christian Brauner
                     ` (5 subsequent siblings)
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 12:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Use accessor to get and set the verity info from the filesystem.
They can be removed once all filesystems have been converted to make
room for verity info in their own inodes.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/verity/open.c         | 18 +++++++++++++++---
 fs/verity/verify.c       |  2 +-
 include/linux/fsverity.h |  9 ++++++++-
 3 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/fs/verity/open.c b/fs/verity/open.c
index fdeb95eca3af..2b9da08754f3 100644
--- a/fs/verity/open.c
+++ b/fs/verity/open.c
@@ -250,13 +250,20 @@ struct fsverity_info *fsverity_create_info(const struct inode *inode,
 
 void fsverity_set_info(struct inode *inode, struct fsverity_info *vi)
 {
+	void *p;
+
 	/*
 	 * Multiple tasks may race to set ->i_verity_info, so use
 	 * cmpxchg_release().  This pairs with the smp_load_acquire() in
 	 * fsverity_get_info().  I.e., here we publish ->i_verity_info with a
 	 * RELEASE barrier so that other tasks can ACQUIRE it.
 	 */
-	if (cmpxchg_release(&inode->i_verity_info, NULL, vi) != NULL) {
+
+	if (inode->i_op->i_fsverity)
+		p = cmpxchg_release(fsverity_addr(inode), NULL, vi);
+	else
+		p = cmpxchg_release(&inode->i_verity_info, NULL, vi);
+	if (p != NULL) {
 		/* Lost the race, so free the fsverity_info we allocated. */
 		fsverity_free_info(vi);
 		/*
@@ -402,8 +409,13 @@ EXPORT_SYMBOL_GPL(__fsverity_prepare_setattr);
 
 void __fsverity_cleanup_inode(struct inode *inode)
 {
-	fsverity_free_info(inode->i_verity_info);
-	inode->i_verity_info = NULL;
+	struct fsverity_info **vi;
+
+	vi = fsverity_addr(inode);
+	if (!*vi)
+		vi = &inode->i_verity_info;
+	fsverity_free_info(*vi);
+	*vi = NULL;
 }
 EXPORT_SYMBOL_GPL(__fsverity_cleanup_inode);
 
diff --git a/fs/verity/verify.c b/fs/verity/verify.c
index 4fcad0825a12..a9c2f5c86991 100644
--- a/fs/verity/verify.c
+++ b/fs/verity/verify.c
@@ -247,7 +247,7 @@ verify_data_blocks(struct folio *data_folio, size_t len, size_t offset,
 		   unsigned long max_ra_pages)
 {
 	struct inode *inode = data_folio->mapping->host;
-	struct fsverity_info *vi = inode->i_verity_info;
+	struct fsverity_info *vi = fsverity_get_info(inode);
 	const unsigned int block_size = vi->tree_params.block_size;
 	u64 pos = (u64)data_folio->index << PAGE_SHIFT;
 
diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h
index 1eb7eae580be..3f15d22c03d6 100644
--- a/include/linux/fsverity.h
+++ b/include/linux/fsverity.h
@@ -124,6 +124,11 @@ struct fsverity_operations {
 
 #ifdef CONFIG_FS_VERITY
 
+static inline struct fsverity_info **fsverity_addr(const struct inode *inode)
+{
+	return ((void *)inode + inode->i_op->i_fsverity);
+}
+
 static inline struct fsverity_info *fsverity_get_info(const struct inode *inode)
 {
 	/*
@@ -132,6 +137,8 @@ static inline struct fsverity_info *fsverity_get_info(const struct inode *inode)
 	 * executing a RELEASE barrier.  We need to use smp_load_acquire() here
 	 * to safely ACQUIRE the memory the other task published.
 	 */
+	if (inode->i_op->i_fsverity)
+		return smp_load_acquire(fsverity_addr(inode));
 	return smp_load_acquire(&inode->i_verity_info);
 }
 
@@ -160,7 +167,7 @@ void __fsverity_cleanup_inode(struct inode *inode);
  */
 static inline void fsverity_cleanup_inode(struct inode *inode)
 {
-	if (inode->i_verity_info)
+	if (inode->i_verity_info || inode->i_op->i_fsverity)
 		__fsverity_cleanup_inode(inode);
 }
 

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH RFC DRAFT v2 10/13] btrfs: move fsverity to filesystem inode
  2025-07-22 12:57 ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode Christian Brauner
                     ` (8 preceding siblings ...)
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 09/13] fs/verity: use accessors Christian Brauner
@ 2025-07-22 12:57   ` Christian Brauner
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 11/13] ext4: " Christian Brauner
                     ` (4 subsequent siblings)
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 12:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fsverity data pointer into the filesystem's private inode and
record the offset from the embedded struct inode.

This will allow us to drop the fsverity data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/btrfs/btrfs_inode.h |  3 +++
 fs/btrfs/inode.c       | 20 +++++++++++++++++++-
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
index a79fa0726f1d..10852d13fa00 100644
--- a/fs/btrfs/btrfs_inode.h
+++ b/fs/btrfs/btrfs_inode.h
@@ -339,6 +339,9 @@ struct btrfs_inode {
 
 	struct rw_semaphore i_mmap_lock;
 	struct inode vfs_inode;
+#ifdef CONFIG_FS_VERITY
+	struct fsverity_info *i_fsverity_info;
+#endif
 };
 
 static inline u64 btrfs_get_first_dir_index_to_log(const struct btrfs_inode *inode)
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index c0c778243bf1..634be0e32759 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -7873,7 +7873,9 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
 	INIT_LIST_HEAD(&ei->delalloc_inodes);
 	INIT_LIST_HEAD(&ei->delayed_iput);
 	init_rwsem(&ei->i_mmap_lock);
-
+#ifdef CONFIG_FS_VERITY
+	ei->i_fsverity_info = NULL;
+#endif
 	return inode;
 }
 
@@ -10410,6 +10412,10 @@ struct btrfs_inode *btrfs_find_first_inode(struct btrfs_root *root, u64 min_ino)
 }
 
 static const struct inode_operations btrfs_dir_inode_operations = {
+#ifdef CONFIG_FS_VERITY
+	.i_fsverity	= offsetof(struct btrfs_inode, i_fsverity_info) -
+			  offsetof(struct btrfs_inode, vfs_inode),
+#endif
 	.getattr	= btrfs_getattr,
 	.lookup		= btrfs_lookup,
 	.create		= btrfs_create,
@@ -10471,6 +10477,10 @@ static const struct address_space_operations btrfs_aops = {
 };
 
 static const struct inode_operations btrfs_file_inode_operations = {
+#ifdef CONFIG_FS_VERITY
+	.i_fsverity	= offsetof(struct btrfs_inode, i_fsverity_info) -
+			  offsetof(struct btrfs_inode, vfs_inode),
+#endif
 	.getattr	= btrfs_getattr,
 	.setattr	= btrfs_setattr,
 	.listxattr      = btrfs_listxattr,
@@ -10483,6 +10493,10 @@ static const struct inode_operations btrfs_file_inode_operations = {
 	.fileattr_set	= btrfs_fileattr_set,
 };
 static const struct inode_operations btrfs_special_inode_operations = {
+#ifdef CONFIG_FS_VERITY
+	.i_fsverity	= offsetof(struct btrfs_inode, i_fsverity_info) -
+			  offsetof(struct btrfs_inode, vfs_inode),
+#endif
 	.getattr	= btrfs_getattr,
 	.setattr	= btrfs_setattr,
 	.permission	= btrfs_permission,
@@ -10492,6 +10506,10 @@ static const struct inode_operations btrfs_special_inode_operations = {
 	.update_time	= btrfs_update_time,
 };
 static const struct inode_operations btrfs_symlink_inode_operations = {
+#ifdef CONFIG_FS_VERITY
+	.i_fsverity	= offsetof(struct btrfs_inode, i_fsverity_info) -
+			  offsetof(struct btrfs_inode, vfs_inode),
+#endif
 	.get_link	= page_get_link,
 	.getattr	= btrfs_getattr,
 	.setattr	= btrfs_setattr,

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH RFC DRAFT v2 11/13] ext4: move fsverity to filesystem inode
  2025-07-22 12:57 ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode Christian Brauner
                     ` (9 preceding siblings ...)
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 10/13] btrfs: move fsverity to filesystem inode Christian Brauner
@ 2025-07-22 12:57   ` Christian Brauner
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 12/13] f2fs: " Christian Brauner
                     ` (3 subsequent siblings)
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 12:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fsverity data pointer into the filesystem's private inode and
record the offset from the embedded struct inode.

This will allow us to drop the fsverity data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/ext4/ext4.h    |  4 ++++
 fs/ext4/file.c    |  4 ++++
 fs/ext4/namei.c   |  8 ++++++++
 fs/ext4/super.c   |  3 +++
 fs/ext4/symlink.c | 12 ++++++++++++
 5 files changed, 31 insertions(+)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index e9710366d87a..d388a7fb1a87 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1201,6 +1201,10 @@ struct ext4_inode_info {
 #ifdef CONFIG_FS_ENCRYPTION
 	struct fscrypt_inode_info	*i_fscrypt_info;
 #endif
+
+#ifdef CONFIG_FS_VERITY
+	struct fsverity_info	*i_fsverity_info;
+#endif
 };
 
 /*
diff --git a/fs/ext4/file.c b/fs/ext4/file.c
index 9bdee2757bdf..06347086b87e 100644
--- a/fs/ext4/file.c
+++ b/fs/ext4/file.c
@@ -984,6 +984,10 @@ const struct inode_operations ext4_file_inode_operations = {
 #ifdef CONFIG_FS_ENCRYPTION
 	.i_fscrypt	= offsetof(struct ext4_inode_info, i_fscrypt_info) -
 			  offsetof(struct ext4_inode_info, vfs_inode),
+#endif
+#ifdef CONFIG_FS_VERITY
+	.i_fsverity	= offsetof(struct ext4_inode_info, i_fsverity_info) -
+			  offsetof(struct ext4_inode_info, vfs_inode),
 #endif
 	.setattr	= ext4_setattr,
 	.getattr	= ext4_file_getattr,
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index fb953834265c..c80ac16d9ca8 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -4217,6 +4217,10 @@ const struct inode_operations ext4_dir_inode_operations = {
 #ifdef CONFIG_FS_ENCRYPTION
 	.i_fscrypt	= offsetof(struct ext4_inode_info, i_fscrypt_info) -
 			  offsetof(struct ext4_inode_info, vfs_inode),
+#endif
+#ifdef CONFIG_FS_VERITY
+	.i_fsverity	= offsetof(struct ext4_inode_info, i_fsverity_info) -
+			  offsetof(struct ext4_inode_info, vfs_inode),
 #endif
 	.create		= ext4_create,
 	.lookup		= ext4_lookup,
@@ -4242,6 +4246,10 @@ const struct inode_operations ext4_special_inode_operations = {
 #ifdef CONFIG_FS_ENCRYPTION
 	.i_fscrypt	= offsetof(struct ext4_inode_info, i_fscrypt_info) -
 			  offsetof(struct ext4_inode_info, vfs_inode),
+#endif
+#ifdef CONFIG_FS_VERITY
+	.i_fsverity	= offsetof(struct ext4_inode_info, i_fsverity_info) -
+			  offsetof(struct ext4_inode_info, vfs_inode),
 #endif
 	.setattr	= ext4_setattr,
 	.getattr	= ext4_getattr,
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 6085d6c9169b..f003b23a62e7 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1414,6 +1414,9 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
 	spin_lock_init(&ei->i_fc_lock);
 #ifdef CONFIG_FS_ENCRYPTION
 	ei->i_fscrypt_info = NULL;
+#endif
+#ifdef CONFIG_FS_VERITY
+	ei->i_fsverity_info = NULL;
 #endif
 	return &ei->vfs_inode;
 }
diff --git a/fs/ext4/symlink.c b/fs/ext4/symlink.c
index 6b67a9a5c02c..4cb96956a17e 100644
--- a/fs/ext4/symlink.c
+++ b/fs/ext4/symlink.c
@@ -118,6 +118,10 @@ const struct inode_operations ext4_encrypted_symlink_inode_operations = {
 #ifdef CONFIG_FS_ENCRYPTION
 	.i_fscrypt	= offsetof(struct ext4_inode_info, i_fscrypt_info) -
 			  offsetof(struct ext4_inode_info, vfs_inode),
+#endif
+#ifdef CONFIG_FS_VERITY
+	.i_fsverity	= offsetof(struct ext4_inode_info, i_fsverity_info) -
+			  offsetof(struct ext4_inode_info, vfs_inode),
 #endif
 	.get_link	= ext4_encrypted_get_link,
 	.setattr	= ext4_setattr,
@@ -129,6 +133,10 @@ const struct inode_operations ext4_symlink_inode_operations = {
 #ifdef CONFIG_FS_ENCRYPTION
 	.i_fscrypt	= offsetof(struct ext4_inode_info, i_fscrypt_info) -
 			  offsetof(struct ext4_inode_info, vfs_inode),
+#endif
+#ifdef CONFIG_FS_VERITY
+	.i_fsverity	= offsetof(struct ext4_inode_info, i_fsverity_info) -
+			  offsetof(struct ext4_inode_info, vfs_inode),
 #endif
 	.get_link	= ext4_get_link,
 	.setattr	= ext4_setattr,
@@ -140,6 +148,10 @@ const struct inode_operations ext4_fast_symlink_inode_operations = {
 #ifdef CONFIG_FS_ENCRYPTION
 	.i_fscrypt	= offsetof(struct ext4_inode_info, i_fscrypt_info) -
 			  offsetof(struct ext4_inode_info, vfs_inode),
+#endif
+#ifdef CONFIG_FS_VERITY
+	.i_fsverity	= offsetof(struct ext4_inode_info, i_fsverity_info) -
+			  offsetof(struct ext4_inode_info, vfs_inode),
 #endif
 	.get_link	= simple_get_link,
 	.setattr	= ext4_setattr,

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH RFC DRAFT v2 12/13] f2fs: move fsverity to filesystem inode
  2025-07-22 12:57 ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode Christian Brauner
                     ` (10 preceding siblings ...)
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 11/13] ext4: " Christian Brauner
@ 2025-07-22 12:57   ` Christian Brauner
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 13/13] fs: drop i_verity_info from struct inode Christian Brauner
                     ` (2 subsequent siblings)
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 12:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fsverity data pointer into the filesystem's private inode and
record the offset from the embedded struct inode.

This will allow us to drop the fsverity data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/f2fs/f2fs.h  |  3 +++
 fs/f2fs/file.c  |  4 ++++
 fs/f2fs/namei.c | 16 ++++++++++++++++
 fs/f2fs/super.c |  3 +++
 4 files changed, 26 insertions(+)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 152990273c68..c43f8be39cef 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -908,6 +908,9 @@ struct f2fs_inode_info {
 #ifdef CONFIG_FS_ENCRYPTION
 	struct fscrypt_inode_info *i_fscrypt_info; /* filesystem encryption info */
 #endif
+#ifdef CONFIG_FS_VERITY
+	struct fsverity_info	*i_fsverity_info;
+#endif
 };
 
 static inline void get_read_extent_info(struct extent_info *ext,
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index f0003672a42c..dee7ac9e27bb 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -1153,6 +1153,10 @@ const struct inode_operations f2fs_file_inode_operations = {
 #ifdef CONFIG_FS_ENCRYPTION
 	.i_fscrypt	= offsetof(struct f2fs_inode_info, i_fscrypt_info) -
 			  offsetof(struct f2fs_inode_info, vfs_inode),
+#endif
+#ifdef CONFIG_FS_VERITY
+	.i_fsverity	= offsetof(struct f2fs_inode_info, i_fsverity_info) -
+			  offsetof(struct f2fs_inode_info, vfs_inode),
 #endif
 	.getattr	= f2fs_getattr,
 	.setattr	= f2fs_setattr,
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 998b0c31f728..e30a55fb71bb 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -1337,6 +1337,10 @@ const struct inode_operations f2fs_encrypted_symlink_inode_operations = {
 #ifdef CONFIG_FS_ENCRYPTION
 	.i_fscrypt	= offsetof(struct f2fs_inode_info, i_fscrypt_info) -
 			  offsetof(struct f2fs_inode_info, vfs_inode),
+#endif
+#ifdef CONFIG_FS_VERITY
+	.i_fsverity	= offsetof(struct f2fs_inode_info, i_fsverity_info) -
+			  offsetof(struct f2fs_inode_info, vfs_inode),
 #endif
 	.get_link	= f2fs_encrypted_get_link,
 	.getattr	= f2fs_encrypted_symlink_getattr,
@@ -1348,6 +1352,10 @@ const struct inode_operations f2fs_dir_inode_operations = {
 #ifdef CONFIG_FS_ENCRYPTION
 	.i_fscrypt	= offsetof(struct f2fs_inode_info, i_fscrypt_info) -
 			  offsetof(struct f2fs_inode_info, vfs_inode),
+#endif
+#ifdef CONFIG_FS_VERITY
+	.i_fsverity	= offsetof(struct f2fs_inode_info, i_fsverity_info) -
+			  offsetof(struct f2fs_inode_info, vfs_inode),
 #endif
 	.create		= f2fs_create,
 	.lookup		= f2fs_lookup,
@@ -1373,6 +1381,10 @@ const struct inode_operations f2fs_symlink_inode_operations = {
 #ifdef CONFIG_FS_ENCRYPTION
 	.i_fscrypt	= offsetof(struct f2fs_inode_info, i_fscrypt_info) -
 			  offsetof(struct f2fs_inode_info, vfs_inode),
+#endif
+#ifdef CONFIG_FS_VERITY
+	.i_fsverity	= offsetof(struct f2fs_inode_info, i_fsverity_info) -
+			  offsetof(struct f2fs_inode_info, vfs_inode),
 #endif
 	.get_link	= f2fs_get_link,
 	.getattr	= f2fs_getattr,
@@ -1384,6 +1396,10 @@ const struct inode_operations f2fs_special_inode_operations = {
 #ifdef CONFIG_FS_ENCRYPTION
 	.i_fscrypt	= offsetof(struct f2fs_inode_info, i_fscrypt_info) -
 			  offsetof(struct f2fs_inode_info, vfs_inode),
+#endif
+#ifdef CONFIG_FS_VERITY
+	.i_fsverity	= offsetof(struct f2fs_inode_info, i_fsverity_info) -
+			  offsetof(struct f2fs_inode_info, vfs_inode),
 #endif
 	.getattr	= f2fs_getattr,
 	.setattr	= f2fs_setattr,
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 9f8e5ae13dc9..b88d446b3970 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1456,6 +1456,9 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
 #ifdef CONFIG_FS_ENCRYPTION
 	fi->i_fscrypt_info = NULL;
 #endif
+#ifdef CONFIG_FS_VERITY
+	fi->i_fsverity_info = NULL;
+#endif
 
 	return &fi->vfs_inode;
 }

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH RFC DRAFT v2 13/13] fs: drop i_verity_info from struct inode
  2025-07-22 12:57 ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode Christian Brauner
                     ` (11 preceding siblings ...)
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 12/13] f2fs: " Christian Brauner
@ 2025-07-22 12:57   ` Christian Brauner
  2025-07-22 13:09   ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of " Christian Brauner
  2025-07-22 13:50   ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode Jeff Layton
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 12:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Now that all filesystems store the fsverity data pointer in their
private inode, drop the data pointer from struct inode itself freeing up
8 bytes.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/verity/enable.c           |  2 +-
 fs/verity/fsverity_private.h |  2 +-
 fs/verity/open.c             | 18 +++++-------------
 include/linux/fs.h           |  4 ----
 include/linux/fsverity.h     | 14 +++++++-------
 5 files changed, 14 insertions(+), 26 deletions(-)

diff --git a/fs/verity/enable.c b/fs/verity/enable.c
index c284f46d1b53..255cf73f6c03 100644
--- a/fs/verity/enable.c
+++ b/fs/verity/enable.c
@@ -287,7 +287,7 @@ static int enable_verity(struct file *filp,
 		/* Successfully enabled verity */
 
 		/*
-		 * Readers can start using ->i_verity_info immediately, so it
+		 * Readers can start using ->i_fsverity_info immediately, so it
 		 * can't be rolled back once set.  So don't set it until just
 		 * after the filesystem has successfully enabled verity.
 		 */
diff --git a/fs/verity/fsverity_private.h b/fs/verity/fsverity_private.h
index b3506f56e180..358cbc3aa7ea 100644
--- a/fs/verity/fsverity_private.h
+++ b/fs/verity/fsverity_private.h
@@ -58,7 +58,7 @@ struct merkle_tree_params {
  * fsverity_info - cached verity metadata for an inode
  *
  * When a verity file is first opened, an instance of this struct is allocated
- * and stored in ->i_verity_info; it remains until the inode is evicted.  It
+ * and stored in ->i_fsverity_info; it remains until the inode is evicted.  It
  * caches information about the Merkle tree that's needed to efficiently verify
  * data read from the file.  It also caches the file digest.  The Merkle tree
  * pages themselves are not cached here, but the filesystem may cache them.
diff --git a/fs/verity/open.c b/fs/verity/open.c
index 2b9da08754f3..e7b6d658b0dc 100644
--- a/fs/verity/open.c
+++ b/fs/verity/open.c
@@ -250,24 +250,18 @@ struct fsverity_info *fsverity_create_info(const struct inode *inode,
 
 void fsverity_set_info(struct inode *inode, struct fsverity_info *vi)
 {
-	void *p;
-
 	/*
-	 * Multiple tasks may race to set ->i_verity_info, so use
+	 * Multiple tasks may race to set ->i_fsverity_info, so use
 	 * cmpxchg_release().  This pairs with the smp_load_acquire() in
-	 * fsverity_get_info().  I.e., here we publish ->i_verity_info with a
+	 * fsverity_get_info().  I.e., here we publish ->i_fsverity_info with a
 	 * RELEASE barrier so that other tasks can ACQUIRE it.
 	 */
 
-	if (inode->i_op->i_fsverity)
-		p = cmpxchg_release(fsverity_addr(inode), NULL, vi);
-	else
-		p = cmpxchg_release(&inode->i_verity_info, NULL, vi);
-	if (p != NULL) {
+	if (cmpxchg_release(fsverity_addr(inode), NULL, vi) != NULL) {
 		/* Lost the race, so free the fsverity_info we allocated. */
 		fsverity_free_info(vi);
 		/*
-		 * Afterwards, the caller may access ->i_verity_info directly,
+		 * Afterwards, the caller may access ->i_fsverity_info directly,
 		 * so make sure to ACQUIRE the winning fsverity_info.
 		 */
 		(void)fsverity_get_info(inode);
@@ -364,7 +358,7 @@ int fsverity_get_descriptor(struct inode *inode,
 	return 0;
 }
 
-/* Ensure the inode has an ->i_verity_info */
+/* Ensure the inode has an ->i_fsverity_info */
 static int ensure_verity_info(struct inode *inode)
 {
 	struct fsverity_info *vi = fsverity_get_info(inode);
@@ -412,8 +406,6 @@ void __fsverity_cleanup_inode(struct inode *inode)
 	struct fsverity_info **vi;
 
 	vi = fsverity_addr(inode);
-	if (!*vi)
-		vi = &inode->i_verity_info;
 	fsverity_free_info(*vi);
 	*vi = NULL;
 }
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b933b8d75f50..027f760f306a 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -778,10 +778,6 @@ struct inode {
 	struct fsnotify_mark_connector __rcu	*i_fsnotify_marks;
 #endif
 
-#ifdef CONFIG_FS_VERITY
-	struct fsverity_info	*i_verity_info;
-#endif
-
 	void			*i_private; /* fs or device private pointer */
 } __randomize_layout;
 
diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h
index 3f15d22c03d6..9815158517dc 100644
--- a/include/linux/fsverity.h
+++ b/include/linux/fsverity.h
@@ -133,13 +133,13 @@ static inline struct fsverity_info *fsverity_get_info(const struct inode *inode)
 {
 	/*
 	 * Pairs with the cmpxchg_release() in fsverity_set_info().
-	 * I.e., another task may publish ->i_verity_info concurrently,
+	 * I.e., another task may publish ->i_fsverity_info concurrently,
 	 * executing a RELEASE barrier.  We need to use smp_load_acquire() here
 	 * to safely ACQUIRE the memory the other task published.
 	 */
 	if (inode->i_op->i_fsverity)
 		return smp_load_acquire(fsverity_addr(inode));
-	return smp_load_acquire(&inode->i_verity_info);
+	return NULL;
 }
 
 /* enable.c */
@@ -163,11 +163,11 @@ void __fsverity_cleanup_inode(struct inode *inode);
  * fsverity_cleanup_inode() - free the inode's verity info, if present
  * @inode: an inode being evicted
  *
- * Filesystems must call this on inode eviction to free ->i_verity_info.
+ * Filesystems must call this on inode eviction to free ->i_fsverity_info.
  */
 static inline void fsverity_cleanup_inode(struct inode *inode)
 {
-	if (inode->i_verity_info || inode->i_op->i_fsverity)
+	if (inode->i_op->i_fsverity)
 		__fsverity_cleanup_inode(inode);
 }
 
@@ -274,12 +274,12 @@ static inline bool fsverity_verify_page(struct page *page)
  * fsverity_active() - do reads from the inode need to go through fs-verity?
  * @inode: inode to check
  *
- * This checks whether ->i_verity_info has been set.
+ * This checks whether ->i_fsverity_info has been set.
  *
  * Filesystems call this from ->readahead() to check whether the pages need to
  * be verified or not.  Don't use IS_VERITY() for this purpose; it's subject to
  * a race condition where the file is being read concurrently with
- * FS_IOC_ENABLE_VERITY completing.  (S_VERITY is set before ->i_verity_info.)
+ * FS_IOC_ENABLE_VERITY completing.  (S_VERITY is set before ->i_fsverity_info.)
  *
  * Return: true if reads need to go through fs-verity, otherwise false
  */
@@ -294,7 +294,7 @@ static inline bool fsverity_active(const struct inode *inode)
  * @filp: the struct file being set up
  *
  * When opening a verity file, deny the open if it is for writing.  Otherwise,
- * set up the inode's ->i_verity_info if not already done.
+ * set up the inode's ->i_fsverity_info if not already done.
  *
  * When combined with fscrypt, this must be called after fscrypt_file_open().
  * Otherwise, we won't have the key set up to decrypt the verity metadata.

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* Re: [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode
  2025-07-22 12:57 ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode Christian Brauner
                     ` (12 preceding siblings ...)
  2025-07-22 12:57   ` [PATCH RFC DRAFT v2 13/13] fs: drop i_verity_info from struct inode Christian Brauner
@ 2025-07-22 13:09   ` Christian Brauner
  2025-07-22 19:27     ` [PATCH v3 " Christian Brauner
  2025-07-22 13:50   ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode Jeff Layton
  14 siblings, 1 reply; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 13:09 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Eric Biggers, Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt,
	fsverity

On Tue, Jul 22, 2025 at 02:57:06PM +0200, Christian Brauner wrote:
> Hey,
> 
> This is a POC. We're still discussing alternatives and I want to provide
> some useful data on what I learned about using offsets to drop fscrypt
> and fsverity from struct inode.
> 
> As discussed, this moves the fscrypt and fsverity pointers out of struct
> inode shrinking it by 16 bytes. The pointers move into the individual
> filesystems that actually do make use of them.
> 
> In order to find the fscrypt and fsverity data pointers offsets from the
> embedded struct inode in the filesystem's private inode data are
> stored in struct inode_operations. This means we get fast access to the
> data pointers without having to rely on indirect calls.
> 
> Bugs & Issues
> =============
> 
> * For fscrypt specifically the biggest issue is
>   fscrypt_prepare_new_inode() is called in filesystem's inode allocation
>   functions before inode->i_op is set. That means the offset isn't
>   available at the time when we would need it. To fix this we can set
>   dummy encrypted inode operations for the respective filesystem with an
>   initialized offset.
> 
> * For both fscrypt & fsverity the biggest issue is that every codepath
>   that currently calls make_bad_inode() after having initialized fscrypt
>   or fsverity data will override inode->i_op with bad_inode_ops. At
>   which point we're back to the previous problem: The offset isn't
>   available anymore. So when inode->i_sb->s_op->evict_inode() is called
>   fscrypt_put_encryption_info() doesn't have the offset available
>   anymore and would corrupt the hell out of everything and also leak
>   memory.
> 
>   Obviously we could use a flag to detect a bad inodes instead of i_op
>   and let the filesystem assign it's own bad inode operations including
>   the correct offset. Is it worth it?
> 
>   The other way I see we can fix this if we require fixed offsets in the
>   filesystems inode so fscrypt and fsverity always now what offset to
>   calculate. We could use two consecutive pointers at the beginning of
>   the filesystem's inode. Does that always work and is it worth it?

Another, way less idiotic but way more obvious solution is to move the
offsets to struct super_operations. That will mean one additional
pointer deref but it will have the big advantage that the patch will
become really really simple. Thoughts? Otherwise I'd implement that.

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode
  2025-07-22 12:57 ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode Christian Brauner
                     ` (13 preceding siblings ...)
  2025-07-22 13:09   ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of " Christian Brauner
@ 2025-07-22 13:50   ` Jeff Layton
  14 siblings, 0 replies; 67+ messages in thread
From: Jeff Layton @ 2025-07-22 13:50 UTC (permalink / raw)
  To: Christian Brauner, Jan Kara, Christoph Hellwig, Jens Axboe,
	Josef Bacik
  Cc: Eric Biggers, Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt,
	fsverity

On Tue, 2025-07-22 at 14:57 +0200, Christian Brauner wrote:
> Hey,
> 
> This is a POC. We're still discussing alternatives and I want to provide
> some useful data on what I learned about using offsets to drop fscrypt
> and fsverity from struct inode.
> 
> As discussed, this moves the fscrypt and fsverity pointers out of struct
> inode shrinking it by 16 bytes. The pointers move into the individual
> filesystems that actually do make use of them.
> 
> In order to find the fscrypt and fsverity data pointers offsets from the
> embedded struct inode in the filesystem's private inode data are
> stored in struct inode_operations. This means we get fast access to the
> data pointers without having to rely on indirect calls.
> 
> Bugs & Issues
> =============
> 
> * For fscrypt specifically the biggest issue is
>   fscrypt_prepare_new_inode() is called in filesystem's inode allocation
>   functions before inode->i_op is set. That means the offset isn't
>   available at the time when we would need it. To fix this we can set
>   dummy encrypted inode operations for the respective filesystem with an
>   initialized offset.
> 
> * For both fscrypt & fsverity the biggest issue is that every codepath
>   that currently calls make_bad_inode() after having initialized fscrypt
>   or fsverity data will override inode->i_op with bad_inode_ops. At
>   which point we're back to the previous problem: The offset isn't
>   available anymore. So when inode->i_sb->s_op->evict_inode() is called
>   fscrypt_put_encryption_info() doesn't have the offset available
>   anymore and would corrupt the hell out of everything and also leak
>   memory.
> 
>   Obviously we could use a flag to detect a bad inodes instead of i_op
>   and let the filesystem assign it's own bad inode operations including
>   the correct offset. Is it worth it?
> 
>   The other way I see we can fix this if we require fixed offsets in the
>   filesystems inode so fscrypt and fsverity always now what offset to
>   calculate. We could use two consecutive pointers at the beginning of
>   the filesystem's inode. Does that always work and is it worth it?
> 

We could store the offsets in the superblock. It's an extra pointer
chase to get to the offset in that case, but presumably it should be in
cache in most cases.

We could even do both -- store it in i_ops and somehow allow falling
back to looking in the superblock when i_ops isn't set or when
make_bad_inode has been called.

> Thanks!
> Christian
> 
> Test results:
> 
> + sudo ./check -g encrypt,verity
> FSTYP         -- ext4
> PLATFORM      -- Linux/x86_64 localhost 6.16.0-rc1-g15c8eb9cdbd3 #267 SMP PREEMPT_DYNAMIC Fri Jun  5 15:58:00 CEST 2015
> MKFS_OPTIONS  -- -F /dev/nvme3n1p6
> MOUNT_OPTIONS -- -o acl,user_xattr /dev/nvme3n1p6 /mnt/scratch
> 
> ext4/024 3s ...  3s
> generic/395 4s ...  4s
> generic/396 3s ...  3s
> generic/397 4s ...  3s
> generic/398 4s ...  4s
> generic/399 39s ...  35s
> generic/419 3s ...  4s
> generic/421 4s ...  4s
> generic/429 14s ...  14s
> generic/435 23s ...  22s
> generic/440 3s ...  4s
> generic/548 10s ...  9s
> generic/549 9s ...  9s
> generic/550       [not run] encryption policy '-c 9 -n 9 -f 0' is unusable; probably missing kernel crypto API support
> generic/572        6s
> generic/573        4s
> generic/574        28s
> generic/575        9s
> generic/576 5s ...  4s
> generic/577        4s
> generic/579        24s
> generic/580 4s ...  4s
> generic/581 10s ...  11s
> generic/582 10s ...  9s
> generic/583 9s ...  9s
> generic/584       [not run] encryption policy '-c 9 -n 9 -v 2 -f 0' is unusable; probably missing kernel crypto API support
> generic/592 10s ...  10s
> generic/593 4s ...  4s
> generic/595 7s ...  7s
> generic/602 9s ...  10s
> generic/613 20s ...  20s
> generic/621 9s ...  9s
> generic/624        3s
> generic/625        3s
> generic/692        5s
> generic/693       [not run] encryption policy '-c 1 -n 10 -v 2 -f 0' is unusable; probably missing kernel crypto API support
> generic/739 17s ...  18s
> Ran: ext4/024 generic/395 generic/396 generic/397 generic/398 generic/399 generic/419 generic/421 generic/429 generic/435 generic/440 generic/548 generic/549 generic/550 generic/572 generic/573 generic/574 generic/575 generic/576 generic/577 generic/579 generic/580 generic/581 generic/582 generic/583 generic/584 generic/592 generic/593 generic/595 generic/602 generic/613 generic/621 generic/624 generic/625 generic/692 generic/693 generic/739
> Not run: generic/550 generic/584 generic/693
> Passed all 37 tests
> 
> ---
> Changes in v2:
> - First full implementation.
> - Link to v1: https://lore.kernel.org/20250715-work-inode-fscrypt-v1-1-aa3ef6f44b6b@kernel.org
> 
> ---
> Christian Brauner (13):
>       fs: add fscrypt offset
>       fs/crypto: use accessors
>       ext4: move fscrypt to filesystem inode
>       ubifs: move fscrypt to filesystem inode
>       f2fs: move fscrypt to filesystem inode
>       ceph: move fscrypt to filesystem inode
>       fs: drop i_crypt_info from struct inode
>       fs: add fsverity offset
>       fs/verity: use accessors
>       btrfs: move fsverity to filesystem inode
>       ext4: move fsverity to filesystem inode
>       f2fs: move fsverity to filesystem inode
>       fs: drop i_verity_info from struct inode
> 
>  fs/btrfs/btrfs_inode.h       |  3 +++
>  fs/btrfs/inode.c             | 20 ++++++++++++++++-
>  fs/ceph/dir.c                |  8 +++++++
>  fs/ceph/inode.c              | 21 ++++++++++++++++++
>  fs/crypto/bio.c              |  2 +-
>  fs/crypto/crypto.c           |  8 +++----
>  fs/crypto/fname.c            |  8 +++----
>  fs/crypto/fscrypt_private.h  |  2 +-
>  fs/crypto/hooks.c            |  2 +-
>  fs/crypto/inline_crypt.c     | 10 ++++-----
>  fs/crypto/keysetup.c         | 27 +++++++++++++----------
>  fs/crypto/policy.c           |  6 ++---
>  fs/ext4/ext4.h               |  9 ++++++++
>  fs/ext4/file.c               |  8 +++++++
>  fs/ext4/ialloc.c             |  2 ++
>  fs/ext4/inode.c              |  1 +
>  fs/ext4/mballoc.c            |  3 +++
>  fs/ext4/namei.c              | 23 ++++++++++++++++++++
>  fs/ext4/super.c              |  6 +++++
>  fs/ext4/symlink.c            | 24 ++++++++++++++++++++
>  fs/f2fs/f2fs.h               |  7 ++++++
>  fs/f2fs/file.c               |  8 +++++++
>  fs/f2fs/inode.c              |  1 +
>  fs/f2fs/namei.c              | 41 ++++++++++++++++++++++++++++++++++
>  fs/f2fs/super.c              |  6 +++++
>  fs/ubifs/dir.c               | 52 ++++++++++++++++++++++++--------------------
>  fs/ubifs/file.c              |  8 +++++++
>  fs/ubifs/super.c             |  8 +++++++
>  fs/ubifs/ubifs.h             |  3 +++
>  fs/verity/enable.c           |  2 +-
>  fs/verity/fsverity_private.h |  2 +-
>  fs/verity/open.c             | 18 +++++++++------
>  fs/verity/verify.c           |  2 +-
>  include/linux/fs.h           | 10 ++-------
>  include/linux/fscrypt.h      | 31 ++++++++++++++++++++++++--
>  include/linux/fsverity.h     | 21 ++++++++++++------
>  include/linux/netfs.h        |  6 +++++
>  37 files changed, 337 insertions(+), 82 deletions(-)
> ---
> base-commit: 19272b37aa4f83ca52bdf9c16d5d81bdd1354494
> change-id: 20250715-work-inode-fscrypt-2b63b276e793

-- 
Jeff Layton <jlayton@kernel.org>

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v3 00/13] Move fscrypt and fsverity out of struct inode
  2025-07-22 13:09   ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of " Christian Brauner
@ 2025-07-22 19:27     ` Christian Brauner
  2025-07-22 19:27       ` [PATCH v3 01/13] fs: add fscrypt offset Christian Brauner
                         ` (13 more replies)
  0 siblings, 14 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 19:27 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Hey,

As discussed, this moves the fscrypt and fsverity pointers out of struct
inode shrinking it by 16 bytes. The pointers move into the individual
filesystems that actually do make use of them.

In order to find the fscrypt and fsverity data pointers offsets from the
embedded struct inode in the filesystem's private inode data are stored
in struct super_operations. This means we get fast access to the data
pointers without having to rely on indirect calls.

Thanks!
Christian

Test results:

+ sudo ./check -g encrypt,verity
FSTYP         -- ext4
PLATFORM      -- Linux/x86_64 localhost 6.16.0-rc1-g9cfff4adb101 #268 SMP PREEMPT_DYNAMIC Fri Jun  5 15:58:00 CEST 2015
MKFS_OPTIONS  -- -F /dev/nvme1n1p6
MOUNT_OPTIONS -- -o acl,user_xattr /dev/nvme1n1p6 /mnt/scratch

ext4/024        3s
generic/395        5s
generic/396        3s
generic/397        3s
generic/398        4s
generic/399        35s
generic/419        3s
generic/421        5s
generic/429        13s
generic/435        23s
generic/440        4s
generic/548        10s
generic/549        9s
generic/550       [not run] encryption policy '-c 9 -n 9 -f 0' is unusable; probably missing kernel crypto API support
generic/572        6s
generic/573        4s
generic/574        36s
generic/575        9s
generic/576        5s
generic/577        4s
generic/579        24s
generic/580        5s
generic/581        11s
generic/582        10s
generic/583        9s
generic/584       [not run] encryption policy '-c 9 -n 9 -v 2 -f 0' is unusable; probably missing kernel crypto API support
generic/592        10s
generic/593        4s
generic/595        7s
generic/602        9s
generic/613        20s
generic/621        8s
generic/624        4s
generic/625        4s
generic/692        5s
generic/693       [not run] encryption policy '-c 1 -n 10 -v 2 -f 0' is unusable; probably missing kernel crypto API support
generic/739        18s
Ran: ext4/024 generic/395 generic/396 generic/397 generic/398 generic/399 generic/419 generic/421 generic/429 generic/435 generic/440 generic/548 generic/549 generic/550 generic/572 generic/573 generic/574 generic/575 generic/576 generic/577 generic/579 generic/580 generic/581 generic/582 generic/583 generic/584 generic/592 generic/593 generic/595 generic/602 generic/613 generic/621 generic/624 generic/625 generic/692 generic/693 generic/739
Not run: generic/550 generic/584 generic/693
Passed all 37 tests

+ sudo ./check -g encrypt,verity
FSTYP         -- f2fs
PLATFORM      -- Linux/x86_64 localhost 6.16.0-rc1-g9cfff4adb101 #268 SMP PREEMPT_DYNAMIC Fri Jun  5 15:58:00 CEST 2015
MKFS_OPTIONS  -- /dev/nvme1n1p6
MOUNT_OPTIONS -- -o acl,user_xattr /dev/nvme1n1p6 /mnt/scratch

f2fs/002       [not run] lz4 utility required, skipped this test
generic/395 5s ...  4s
generic/396 3s ...  4s
generic/397 3s ...  4s
generic/398 4s ...  4s
generic/399 35s ...  20s
generic/419 3s ...  4s
generic/421 5s ...  5s
generic/429 13s ...  14s
generic/435 23s ...  32s
generic/440 4s ...  4s
generic/548 10s ...  12s
generic/549 9s ...  12s
generic/550       [not run] encryption policy '-c 9 -n 9 -f 0' is unusable; probably missing kernel crypto API support
generic/572 6s ...  6s
generic/573 4s ...  4s
generic/574 36s ...  27s
generic/575 9s ...  10s
generic/576 5s ...  5s
generic/577 4s ...  4s
generic/579 24s ...  26s
generic/580 5s ...  5s
generic/581 11s ...  12s
generic/582 10s ...  12s
generic/583 9s ...  12s
generic/584       [not run] encryption policy '-c 9 -n 9 -v 2 -f 0' is unusable; probably missing kernel crypto API support
generic/592 10s ...  13s
generic/593 4s ...  4s
generic/595 7s ...  7s
generic/602 9s ...  13s
generic/613 20s ...  24s
generic/621 8s ...  9s
generic/624 4s ...  3s
generic/625 4s ...  4s
generic/692 5s ...  5s
generic/693       [not run] encryption policy '-c 1 -n 10 -v 2 -f 0' is unusable; probably missing kernel crypto API support
generic/739 18s ...  23s
Ran: f2fs/002 generic/395 generic/396 generic/397 generic/398 generic/399 generic/419 generic/421 generic/429 generic/435 generic/440 generic/548 generic/549 generic/550 generic/572 generic/573 generic/574 generic/575 generic/576 generic/577 generic/579 generic/580 generic/581 generic/582 generic/583 generic/584 generic/592 generic/593 generic/595 generic/602 generic/613 generic/621 generic/624 generic/625 generic/692 generic/693 generic/739
Not run: f2fs/002 generic/550 generic/584 generic/693
Passed all 37 tests

+ sudo ./check -g encrypt,verity
FSTYP         -- btrfs
PLATFORM      -- Linux/x86_64 localhost 6.16.0-rc1-g9cfff4adb101 #268 SMP PREEMPT_DYNAMIC Fri Jun  5 15:58:00 CEST 2015
MKFS_OPTIONS  -- /dev/nvme1n1p6
MOUNT_OPTIONS -- /dev/nvme1n1p6 /mnt/scratch

btrfs/277       [not run] kernel does not support send stream 3
btrfs/290       [not run] btrfs-corrupt-block utility required, skipped this test
btrfs/291       [not run] This test requires a valid $LOGWRITES_DEV
generic/395 4s ... [not run] No encryption support for btrfs
generic/396 4s ... [not run] No encryption support for btrfs
generic/397 4s ... [not run] No encryption support for btrfs
generic/398 4s ... [not run] No encryption support for btrfs
generic/399 20s ... [not run] No encryption support for btrfs
generic/419 4s ... [not run] No encryption support for btrfs
generic/421 5s ... [not run] No encryption support for btrfs
generic/429 14s ... [not run] No encryption support for btrfs
generic/435 32s ... [not run] No encryption support for btrfs
generic/440 4s ... [not run] No encryption support for btrfs
generic/548 12s ... [not run] No encryption support for btrfs
generic/549 12s ... [not run] No encryption support for btrfs
generic/550       [not run] No encryption support for btrfs
generic/572 6s ...  6s
generic/573 4s ...  3s
generic/574 27s ... [not run] btrfs-corrupt-block utility required, skipped this test
generic/575 10s ...  8s
generic/576 5s ... [not run] No encryption support for btrfs
generic/577 4s ...  5s
generic/579 26s ...  24s
generic/580 5s ... [not run] No encryption support for btrfs
generic/581 12s ... [not run] No encryption support for btrfs
generic/582 12s ... [not run] No encryption support for btrfs
generic/583 12s ... [not run] No encryption support for btrfs
generic/584       [not run] No encryption support for btrfs
generic/592 13s ... [not run] No encryption support for btrfs
generic/593 4s ... [not run] No encryption support for btrfs
generic/595 7s ... [not run] No encryption support for btrfs
generic/602 13s ... [not run] No encryption support for btrfs
generic/613 24s ... [not run] No encryption support for btrfs
generic/621 9s ... [not run] No encryption support for btrfs
generic/624 3s ...  2s
generic/625 4s ...  2s
generic/692 5s ...  3s
generic/693       [not run] No encryption support for btrfs
generic/739 23s ... [not run] No encryption support for btrfs
Ran: btrfs/277 btrfs/290 btrfs/291 generic/395 generic/396 generic/397 generic/398 generic/399 generic/419 generic/421 generic/429 generic/435 generic/440 generic/548 generic/549 generic/550 generic/572 generic/573 generic/574 generic/575 generic/576 generic/577 generic/579 generic/580 generic/581 generic/582 generic/583 generic/584 generic/592 generic/593 generic/595 generic/602 generic/613 generic/621 generic/624 generic/625 generic/692 generic/693 generic/739
Not run: btrfs/277 btrfs/290 btrfs/291 generic/395 generic/396 generic/397 generic/398 generic/399 generic/419 generic/421 generic/429 generic/435 generic/440 generic/548 generic/549 generic/550 generic/574 generic/576 generic/580 generic/581 generic/582 generic/583 generic/584 generic/592 generic/593 generic/595 generic/602 generic/613 generic/621 generic/693 generic/739
Passed all 39 tests

---
Changes in v3:
- Stash offsets in struct super_operations.
- Link to v2: https://lore.kernel.org/20250722-work-inode-fscrypt-v2-0-782f1fdeaeba@kernel.org

Changes in v2:
- First full implementation.
- Link to v1: https://lore.kernel.org/20250715-work-inode-fscrypt-v1-1-aa3ef6f44b6b@kernel.org

---
Christian Brauner (13):
      fs: add fscrypt offset
      fs/crypto: use accessors
      ext4: move fscrypt to filesystem inode
      ubifs: move fscrypt to filesystem inode
      f2fs: move fscrypt to filesystem inode
      ceph: move fscrypt to filesystem inode
      fs: drop i_crypt_info from struct inode
      fs: add fsverity offset
      fs/verity: use accessors
      btrfs: move fsverity to filesystem inode
      ext4: move fsverity to filesystem inode
      f2fs: move fsverity to filesystem inode
      fs: drop i_verity_info from struct inode

 fs/btrfs/btrfs_inode.h       |  3 +++
 fs/btrfs/inode.c             |  3 +++
 fs/btrfs/super.c             |  4 ++++
 fs/ceph/super.c              |  4 ++++
 fs/crypto/bio.c              |  2 +-
 fs/crypto/crypto.c           |  8 ++++----
 fs/crypto/fname.c            |  8 ++++----
 fs/crypto/fscrypt_private.h  |  2 +-
 fs/crypto/hooks.c            |  2 +-
 fs/crypto/inline_crypt.c     | 10 +++++-----
 fs/crypto/keysetup.c         | 27 ++++++++++++++++-----------
 fs/crypto/policy.c           |  6 +++---
 fs/ext4/ext4.h               |  8 ++++++++
 fs/ext4/mballoc-test.c       |  4 ++++
 fs/ext4/super.c              | 14 ++++++++++++++
 fs/f2fs/f2fs.h               |  6 ++++++
 fs/f2fs/super.c              | 14 ++++++++++++++
 fs/ubifs/super.c             |  4 ++++
 fs/ubifs/ubifs.h             |  3 +++
 fs/verity/enable.c           |  2 +-
 fs/verity/fsverity_private.h |  2 +-
 fs/verity/open.c             | 17 ++++++++++-------
 fs/verity/verify.c           |  2 +-
 include/linux/fs.h           | 10 ++--------
 include/linux/fscrypt.h      | 31 +++++++++++++++++++++++++++++--
 include/linux/fsverity.h     | 21 ++++++++++++++-------
 include/linux/netfs.h        |  6 ++++++
 27 files changed, 166 insertions(+), 57 deletions(-)
---
base-commit: 19272b37aa4f83ca52bdf9c16d5d81bdd1354494
change-id: 20250715-work-inode-fscrypt-2b63b276e793


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v3 01/13] fs: add fscrypt offset
  2025-07-22 19:27     ` [PATCH v3 " Christian Brauner
@ 2025-07-22 19:27       ` Christian Brauner
  2025-07-22 20:02         ` Eric Biggers
  2025-07-23  3:49         ` Al Viro
  2025-07-22 19:27       ` [PATCH v3 02/13] fs/crypto: use accessors Christian Brauner
                         ` (12 subsequent siblings)
  13 siblings, 2 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 19:27 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Store the offset of the fscrypt data pointer from struct inode in struct
super_operations. Both are embedded in the filesystem's private inode.

This will allow us to drop the fscrypt data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 include/linux/fs.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index 96c7925a6551..991089969e71 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2332,6 +2332,7 @@ enum freeze_holder {
 };
 
 struct super_operations {
+	ptrdiff_t i_fscrypt;
    	struct inode *(*alloc_inode)(struct super_block *sb);
 	void (*destroy_inode)(struct inode *);
 	void (*free_inode)(struct inode *);

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 02/13] fs/crypto: use accessors
  2025-07-22 19:27     ` [PATCH v3 " Christian Brauner
  2025-07-22 19:27       ` [PATCH v3 01/13] fs: add fscrypt offset Christian Brauner
@ 2025-07-22 19:27       ` Christian Brauner
  2025-07-22 19:27       ` [PATCH v3 03/13] ext4: move fscrypt to filesystem inode Christian Brauner
                         ` (11 subsequent siblings)
  13 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 19:27 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Use accessor to get and set the fscrypt info from the filesystem.
They can be removed once all filesystems have been converted to make
room for fscrypt info in their own inodes.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/crypto/bio.c          |  2 +-
 fs/crypto/crypto.c       |  8 ++++----
 fs/crypto/fname.c        |  8 ++++----
 fs/crypto/hooks.c        |  2 +-
 fs/crypto/inline_crypt.c | 10 +++++-----
 fs/crypto/keysetup.c     | 12 +++++++++---
 fs/crypto/policy.c       |  6 +++---
 include/linux/fscrypt.h  | 36 ++++++++++++++++++++++++++++++++++++
 8 files changed, 63 insertions(+), 21 deletions(-)

diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index 0ad8c30b8fa5..73e46d2af511 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -111,7 +111,7 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
 int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
 			  sector_t pblk, unsigned int len)
 {
-	const struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 	const unsigned int du_bits = ci->ci_data_unit_bits;
 	const unsigned int du_size = 1U << du_bits;
 	const unsigned int du_per_page_bits = PAGE_SHIFT - du_bits;
diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
index b74b5937e695..c27ea8baaf52 100644
--- a/fs/crypto/crypto.c
+++ b/fs/crypto/crypto.c
@@ -181,7 +181,7 @@ struct page *fscrypt_encrypt_pagecache_blocks(struct folio *folio,
 		size_t len, size_t offs, gfp_t gfp_flags)
 {
 	const struct inode *inode = folio->mapping->host;
-	const struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 	const unsigned int du_bits = ci->ci_data_unit_bits;
 	const unsigned int du_size = 1U << du_bits;
 	struct page *ciphertext_page;
@@ -241,7 +241,7 @@ int fscrypt_encrypt_block_inplace(const struct inode *inode, struct page *page,
 {
 	if (WARN_ON_ONCE(inode->i_sb->s_cop->supports_subblock_data_units))
 		return -EOPNOTSUPP;
-	return fscrypt_crypt_data_unit(inode->i_crypt_info, FS_ENCRYPT,
+	return fscrypt_crypt_data_unit(fscrypt_get_inode_info_raw(inode), FS_ENCRYPT,
 				       lblk_num, page, page, len, offs,
 				       gfp_flags);
 }
@@ -265,7 +265,7 @@ int fscrypt_decrypt_pagecache_blocks(struct folio *folio, size_t len,
 				     size_t offs)
 {
 	const struct inode *inode = folio->mapping->host;
-	const struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 	const unsigned int du_bits = ci->ci_data_unit_bits;
 	const unsigned int du_size = 1U << du_bits;
 	u64 index = ((u64)folio->index << (PAGE_SHIFT - du_bits)) +
@@ -316,7 +316,7 @@ int fscrypt_decrypt_block_inplace(const struct inode *inode, struct page *page,
 {
 	if (WARN_ON_ONCE(inode->i_sb->s_cop->supports_subblock_data_units))
 		return -EOPNOTSUPP;
-	return fscrypt_crypt_data_unit(inode->i_crypt_info, FS_DECRYPT,
+	return fscrypt_crypt_data_unit(fscrypt_get_inode_info_raw(inode), FS_DECRYPT,
 				       lblk_num, page, page, len, offs,
 				       GFP_NOFS);
 }
diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c
index 010f9c0a4c2f..674b5fb11ac1 100644
--- a/fs/crypto/fname.c
+++ b/fs/crypto/fname.c
@@ -94,7 +94,7 @@ int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
 {
 	struct skcipher_request *req = NULL;
 	DECLARE_CRYPTO_WAIT(wait);
-	const struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 	struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;
 	union fscrypt_iv iv;
 	struct scatterlist sg;
@@ -151,7 +151,7 @@ static int fname_decrypt(const struct inode *inode,
 	struct skcipher_request *req = NULL;
 	DECLARE_CRYPTO_WAIT(wait);
 	struct scatterlist src_sg, dst_sg;
-	const struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 	struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;
 	union fscrypt_iv iv;
 	int res;
@@ -293,7 +293,7 @@ bool __fscrypt_fname_encrypted_size(const union fscrypt_policy *policy,
 bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len,
 				  u32 max_len, u32 *encrypted_len_ret)
 {
-	return __fscrypt_fname_encrypted_size(&inode->i_crypt_info->ci_policy,
+	return __fscrypt_fname_encrypted_size(&fscrypt_get_inode_info_raw(inode)->ci_policy,
 					      orig_len, max_len,
 					      encrypted_len_ret);
 }
@@ -562,7 +562,7 @@ EXPORT_SYMBOL_GPL(fscrypt_match_name);
  */
 u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name)
 {
-	const struct fscrypt_inode_info *ci = dir->i_crypt_info;
+	const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(dir);
 
 	WARN_ON_ONCE(!ci->ci_dirhash_key_initialized);
 
diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c
index d8d5049b8fe1..61bbe7d46df4 100644
--- a/fs/crypto/hooks.c
+++ b/fs/crypto/hooks.c
@@ -197,7 +197,7 @@ int fscrypt_prepare_setflags(struct inode *inode,
 		err = fscrypt_require_key(inode);
 		if (err)
 			return err;
-		ci = inode->i_crypt_info;
+		ci = fscrypt_get_inode_info_raw(inode);
 		if (ci->ci_policy.version != FSCRYPT_POLICY_V2)
 			return -EINVAL;
 		mk = ci->ci_master_key;
diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c
index 1d008c440cb6..6c2784b8e67a 100644
--- a/fs/crypto/inline_crypt.c
+++ b/fs/crypto/inline_crypt.c
@@ -262,7 +262,7 @@ int fscrypt_derive_sw_secret(struct super_block *sb,
 
 bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode)
 {
-	return inode->i_crypt_info->ci_inlinecrypt;
+	return fscrypt_get_inode_info_raw(inode)->ci_inlinecrypt;
 }
 EXPORT_SYMBOL_GPL(__fscrypt_inode_uses_inline_crypto);
 
@@ -306,7 +306,7 @@ void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode,
 
 	if (!fscrypt_inode_uses_inline_crypto(inode))
 		return;
-	ci = inode->i_crypt_info;
+	ci = fscrypt_get_inode_info_raw(inode);
 
 	fscrypt_generate_dun(ci, first_lblk, dun);
 	bio_crypt_set_ctx(bio, ci->ci_enc_key.blk_key, dun, gfp_mask);
@@ -396,10 +396,10 @@ bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode,
 	 * uses the same pointer.  I.e., there's currently no need to support
 	 * merging requests where the keys are the same but the pointers differ.
 	 */
-	if (bc->bc_key != inode->i_crypt_info->ci_enc_key.blk_key)
+	if (bc->bc_key != fscrypt_get_inode_info_raw(inode)->ci_enc_key.blk_key)
 		return false;
 
-	fscrypt_generate_dun(inode->i_crypt_info, next_lblk, next_dun);
+	fscrypt_generate_dun(fscrypt_get_inode_info_raw(inode), next_lblk, next_dun);
 	return bio_crypt_dun_is_contiguous(bc, bio->bi_iter.bi_size, next_dun);
 }
 EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio);
@@ -501,7 +501,7 @@ u64 fscrypt_limit_io_blocks(const struct inode *inode, u64 lblk, u64 nr_blocks)
 	if (nr_blocks <= 1)
 		return nr_blocks;
 
-	ci = inode->i_crypt_info;
+	ci = fscrypt_get_inode_info_raw(inode);
 	if (!(fscrypt_policy_flags(&ci->ci_policy) &
 	      FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32))
 		return nr_blocks;
diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
index 0d71843af946..0f0ebe819783 100644
--- a/fs/crypto/keysetup.c
+++ b/fs/crypto/keysetup.c
@@ -644,7 +644,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
 	 * fscrypt_get_inode_info().  I.e., here we publish ->i_crypt_info with
 	 * a RELEASE barrier so that other tasks can ACQUIRE it.
 	 */
-	if (cmpxchg_release(&inode->i_crypt_info, NULL, crypt_info) == NULL) {
+	if (fscrypt_set_inode_info(inode, crypt_info)) {
 		/*
 		 * We won the race and set ->i_crypt_info to our crypt_info.
 		 * Now link it into the master key's inode list.
@@ -797,8 +797,14 @@ EXPORT_SYMBOL_GPL(fscrypt_prepare_new_inode);
  */
 void fscrypt_put_encryption_info(struct inode *inode)
 {
-	put_crypt_info(inode->i_crypt_info);
-	inode->i_crypt_info = NULL;
+	struct fscrypt_inode_info **crypt_info;
+
+	if (inode->i_sb->s_op->i_fscrypt)
+		crypt_info = fscrypt_addr(inode);
+	else
+		crypt_info = &inode->i_crypt_info;
+	put_crypt_info(*crypt_info);
+	*crypt_info = NULL;
 }
 EXPORT_SYMBOL(fscrypt_put_encryption_info);
 
diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c
index 701259991277..d9fb2898a14a 100644
--- a/fs/crypto/policy.c
+++ b/fs/crypto/policy.c
@@ -725,7 +725,7 @@ const union fscrypt_policy *fscrypt_policy_to_inherit(struct inode *dir)
 		err = fscrypt_require_key(dir);
 		if (err)
 			return ERR_PTR(err);
-		return &dir->i_crypt_info->ci_policy;
+		return &fscrypt_get_inode_info_raw(dir)->ci_policy;
 	}
 
 	return fscrypt_get_dummy_policy(dir->i_sb);
@@ -744,7 +744,7 @@ const union fscrypt_policy *fscrypt_policy_to_inherit(struct inode *dir)
  */
 int fscrypt_context_for_new_inode(void *ctx, struct inode *inode)
 {
-	struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 
 	BUILD_BUG_ON(sizeof(union fscrypt_context) !=
 			FSCRYPT_SET_CONTEXT_MAX_SIZE);
@@ -769,7 +769,7 @@ EXPORT_SYMBOL_GPL(fscrypt_context_for_new_inode);
  */
 int fscrypt_set_context(struct inode *inode, void *fs_data)
 {
-	struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 	union fscrypt_context ctx;
 	int ctxsize;
 
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 56fad33043d5..685780ce3579 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -195,6 +195,38 @@ struct fscrypt_operations {
 int fscrypt_d_revalidate(struct inode *dir, const struct qstr *name,
 			 struct dentry *dentry, unsigned int flags);
 
+static inline struct fscrypt_inode_info **fscrypt_addr(const struct inode *inode)
+{
+	return ((void *)inode + inode->i_sb->s_op->i_fscrypt);
+}
+
+static inline bool fscrypt_set_inode_info(struct inode *inode,
+					  struct fscrypt_inode_info *crypt_info)
+{
+	void *p;
+
+	/*
+	 * For existing inodes, multiple tasks may race to set ->i_crypt_info.
+	 * So use cmpxchg_release().  This pairs with the smp_load_acquire() in
+	 * fscrypt_get_inode_info().  I.e., here we publish ->i_crypt_info with
+	 * a RELEASE barrier so that other tasks can ACQUIRE it.
+	 */
+
+	if (inode->i_sb->s_op->i_fscrypt)
+		p = cmpxchg_release(fscrypt_addr(inode), NULL, crypt_info);
+	else
+		p = cmpxchg_release(&inode->i_crypt_info, NULL, crypt_info);
+	return p == NULL;
+}
+
+static inline struct fscrypt_inode_info *
+fscrypt_get_inode_info_raw(const struct inode *inode)
+{
+	if (inode->i_sb->s_op->i_fscrypt)
+		return *fscrypt_addr(inode);
+	return inode->i_crypt_info;
+}
+
 static inline struct fscrypt_inode_info *
 fscrypt_get_inode_info(const struct inode *inode)
 {
@@ -204,6 +236,10 @@ fscrypt_get_inode_info(const struct inode *inode)
 	 * a RELEASE barrier.  We need to use smp_load_acquire() here to safely
 	 * ACQUIRE the memory the other task published.
 	 */
+
+	if (inode->i_sb->s_op->i_fscrypt)
+		return smp_load_acquire(fscrypt_addr(inode));
+
 	return smp_load_acquire(&inode->i_crypt_info);
 }
 

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 03/13] ext4: move fscrypt to filesystem inode
  2025-07-22 19:27     ` [PATCH v3 " Christian Brauner
  2025-07-22 19:27       ` [PATCH v3 01/13] fs: add fscrypt offset Christian Brauner
  2025-07-22 19:27       ` [PATCH v3 02/13] fs/crypto: use accessors Christian Brauner
@ 2025-07-22 19:27       ` Christian Brauner
  2025-07-22 20:07         ` Eric Biggers
  2025-07-22 19:27       ` [PATCH v3 04/13] ubifs: " Christian Brauner
                         ` (10 subsequent siblings)
  13 siblings, 1 reply; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 19:27 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fscrypt data pointer into the filesystem's private inode and record
the offset from the embedded struct inode.

This will allow us to drop the fscrypt data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/ext4/ext4.h         | 4 ++++
 fs/ext4/mballoc-test.c | 4 ++++
 fs/ext4/super.c        | 7 +++++++
 3 files changed, 15 insertions(+)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 18373de980f2..f27d57aea316 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1197,6 +1197,10 @@ struct ext4_inode_info {
 	__u32 i_csum_seed;
 
 	kprojid_t i_projid;
+
+#ifdef CONFIG_FS_ENCRYPTION
+	struct fscrypt_inode_info	*i_fscrypt_info;
+#endif
 };
 
 /*
diff --git a/fs/ext4/mballoc-test.c b/fs/ext4/mballoc-test.c
index d634c12f1984..b8e039a666c3 100644
--- a/fs/ext4/mballoc-test.c
+++ b/fs/ext4/mballoc-test.c
@@ -53,6 +53,10 @@ static void mbt_free_inode(struct inode *inode)
 }
 
 static const struct super_operations mbt_sops = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt	= offsetof(struct ext4_inode_info, i_fscrypt_info) -
+			  offsetof(struct ext4_inode_info, vfs_inode),
+#endif
 	.alloc_inode	= mbt_alloc_inode,
 	.free_inode	= mbt_free_inode,
 };
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index c7d39da7e733..2a03835b67d5 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1412,6 +1412,9 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
 	INIT_WORK(&ei->i_rsv_conversion_work, ext4_end_io_rsv_work);
 	ext4_fc_init_inode(&ei->vfs_inode);
 	spin_lock_init(&ei->i_fc_lock);
+#ifdef CONFIG_FS_ENCRYPTION
+	ei->i_fscrypt_info = NULL;
+#endif
 	return &ei->vfs_inode;
 }
 
@@ -1607,6 +1610,10 @@ static const struct quotactl_ops ext4_qctl_operations = {
 #endif
 
 static const struct super_operations ext4_sops = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt	= offsetof(struct ext4_inode_info, i_fscrypt_info) -
+			  offsetof(struct ext4_inode_info, vfs_inode),
+#endif
 	.alloc_inode	= ext4_alloc_inode,
 	.free_inode	= ext4_free_in_core_inode,
 	.destroy_inode	= ext4_destroy_inode,

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 04/13] ubifs: move fscrypt to filesystem inode
  2025-07-22 19:27     ` [PATCH v3 " Christian Brauner
                         ` (2 preceding siblings ...)
  2025-07-22 19:27       ` [PATCH v3 03/13] ext4: move fscrypt to filesystem inode Christian Brauner
@ 2025-07-22 19:27       ` Christian Brauner
  2025-07-22 19:27       ` [PATCH v3 05/13] f2fs: " Christian Brauner
                         ` (9 subsequent siblings)
  13 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 19:27 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fscrypt data pointer into the filesystem's private inode and record
the offset from the embedded struct inode.

This will allow us to drop the fscrypt data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/ubifs/super.c | 4 ++++
 fs/ubifs/ubifs.h | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index f3e3b2068608..5b484f054faf 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -2003,6 +2003,10 @@ static int ubifs_reconfigure(struct fs_context *fc)
 }
 
 const struct super_operations ubifs_super_operations = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt	= offsetof(struct ubifs_inode, i_fscrypt_info) -
+			  offsetof(struct ubifs_inode, vfs_inode),
+#endif
 	.alloc_inode   = ubifs_alloc_inode,
 	.free_inode    = ubifs_free_inode,
 	.put_super     = ubifs_put_super,
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 256dbaeeb0de..0442782a54ab 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -416,6 +416,9 @@ struct ubifs_inode {
 	pgoff_t read_in_a_row;
 	int data_len;
 	void *data;
+#ifdef CONFIG_FS_ENCRYPTION
+	struct fscrypt_inode_info *i_fscrypt_info;
+#endif
 };
 
 /**

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 05/13] f2fs: move fscrypt to filesystem inode
  2025-07-22 19:27     ` [PATCH v3 " Christian Brauner
                         ` (3 preceding siblings ...)
  2025-07-22 19:27       ` [PATCH v3 04/13] ubifs: " Christian Brauner
@ 2025-07-22 19:27       ` Christian Brauner
  2025-07-22 19:27       ` [PATCH v3 06/13] ceph: " Christian Brauner
                         ` (8 subsequent siblings)
  13 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 19:27 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fscrypt data pointer into the filesystem's private inode and record
the offset from the embedded struct inode.

This will allow us to drop the fscrypt data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/f2fs/f2fs.h  | 3 +++
 fs/f2fs/super.c | 7 +++++++
 2 files changed, 10 insertions(+)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 9333a22b9a01..14e69c00e679 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -905,6 +905,9 @@ struct f2fs_inode_info {
 
 	unsigned int atomic_write_cnt;
 	loff_t original_i_size;		/* original i_size before atomic write */
+#ifdef CONFIG_FS_ENCRYPTION
+	struct fscrypt_inode_info *i_fscrypt_info; /* filesystem encryption info */
+#endif
 };
 
 static inline void get_read_extent_info(struct extent_info *ext,
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index bbf1dad6843f..969ba46990ea 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1453,6 +1453,9 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
 
 	/* Will be used by directory only */
 	fi->i_dir_level = F2FS_SB(sb)->dir_level;
+#ifdef CONFIG_FS_ENCRYPTION
+	fi->i_fscrypt_info = NULL;
+#endif
 
 	return &fi->vfs_inode;
 }
@@ -3246,6 +3249,10 @@ void f2fs_quota_off_umount(struct super_block *sb)
 #endif
 
 static const struct super_operations f2fs_sops = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt	= offsetof(struct f2fs_inode_info, i_fscrypt_info) -
+			  offsetof(struct f2fs_inode_info, vfs_inode),
+#endif
 	.alloc_inode	= f2fs_alloc_inode,
 	.free_inode	= f2fs_free_inode,
 	.drop_inode	= f2fs_drop_inode,

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 06/13] ceph: move fscrypt to filesystem inode
  2025-07-22 19:27     ` [PATCH v3 " Christian Brauner
                         ` (4 preceding siblings ...)
  2025-07-22 19:27       ` [PATCH v3 05/13] f2fs: " Christian Brauner
@ 2025-07-22 19:27       ` Christian Brauner
  2025-07-22 20:14         ` Eric Biggers
  2025-07-22 19:27       ` [PATCH v3 07/13] fs: drop i_crypt_info from struct inode Christian Brauner
                         ` (7 subsequent siblings)
  13 siblings, 1 reply; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 19:27 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fscrypt data pointer into the filesystem's private inode and record
the offset from the embedded struct inode.

This will allow us to drop the fscrypt data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/ceph/super.c       | 4 ++++
 include/linux/netfs.h | 6 ++++++
 2 files changed, 10 insertions(+)

diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 2b8438d8a324..540b32e746de 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -1039,6 +1039,10 @@ void ceph_umount_begin(struct super_block *sb)
 }
 
 static const struct super_operations ceph_super_ops = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.i_fscrypt = offsetof(struct ceph_inode_info, netfs.i_fscrypt_info) -
+		     offsetof(struct ceph_inode_info, netfs.inode),
+#endif
 	.alloc_inode	= ceph_alloc_inode,
 	.free_inode	= ceph_free_inode,
 	.write_inode    = ceph_write_inode,
diff --git a/include/linux/netfs.h b/include/linux/netfs.h
index 065c17385e53..fda1321da861 100644
--- a/include/linux/netfs.h
+++ b/include/linux/netfs.h
@@ -57,6 +57,9 @@ typedef void (*netfs_io_terminated_t)(void *priv, ssize_t transferred_or_error);
  */
 struct netfs_inode {
 	struct inode		inode;		/* The VFS inode */
+#ifdef CONFIG_FS_ENCRYPTION
+	struct fscrypt_inode_info *i_fscrypt_info;
+#endif
 	const struct netfs_request_ops *ops;
 #if IS_ENABLED(CONFIG_FSCACHE)
 	struct fscache_cookie	*cache;
@@ -503,6 +506,9 @@ static inline void netfs_inode_init(struct netfs_inode *ctx,
 		ctx->zero_point = ctx->remote_i_size;
 		mapping_set_release_always(ctx->inode.i_mapping);
 	}
+#ifdef CONFIG_FS_ENCRYPTION
+	ctx->i_fscrypt_info = NULL;
+#endif
 }
 
 /**

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 07/13] fs: drop i_crypt_info from struct inode
  2025-07-22 19:27     ` [PATCH v3 " Christian Brauner
                         ` (5 preceding siblings ...)
  2025-07-22 19:27       ` [PATCH v3 06/13] ceph: " Christian Brauner
@ 2025-07-22 19:27       ` Christian Brauner
  2025-07-22 20:19         ` Eric Biggers
  2025-07-22 19:27       ` [PATCH v3 08/13] fs: add fsverity offset Christian Brauner
                         ` (6 subsequent siblings)
  13 siblings, 1 reply; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 19:27 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Now that all filesystems store the fscrypt data pointer in their private
inode, drop the data pointer from struct inode itself freeing up 8
bytes.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/crypto/fscrypt_private.h |  2 +-
 fs/crypto/keysetup.c        | 25 ++++++++++++-------------
 include/linux/fs.h          |  4 ----
 include/linux/fscrypt.h     | 21 ++++++---------------
 4 files changed, 19 insertions(+), 33 deletions(-)

diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
index c1d92074b65c..53a72dc909d9 100644
--- a/fs/crypto/fscrypt_private.h
+++ b/fs/crypto/fscrypt_private.h
@@ -231,7 +231,7 @@ struct fscrypt_prepared_key {
  * fscrypt_inode_info - the "encryption key" for an inode
  *
  * When an encrypted file's key is made available, an instance of this struct is
- * allocated and stored in ->i_crypt_info.  Once created, it remains until the
+ * allocated and stored in ->i_fscrypt_info.  Once created, it remains until the
  * inode is evicted.
  */
 struct fscrypt_inode_info {
diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
index 0f0ebe819783..13fe17d87e97 100644
--- a/fs/crypto/keysetup.c
+++ b/fs/crypto/keysetup.c
@@ -639,14 +639,14 @@ fscrypt_setup_encryption_info(struct inode *inode,
 		goto out;
 
 	/*
-	 * For existing inodes, multiple tasks may race to set ->i_crypt_info.
+	 * For existing inodes, multiple tasks may race to set ->i_fscrypt_info.
 	 * So use cmpxchg_release().  This pairs with the smp_load_acquire() in
-	 * fscrypt_get_inode_info().  I.e., here we publish ->i_crypt_info with
+	 * fscrypt_get_inode_info().  I.e., here we publish ->i_fscrypt_info with
 	 * a RELEASE barrier so that other tasks can ACQUIRE it.
 	 */
 	if (fscrypt_set_inode_info(inode, crypt_info)) {
 		/*
-		 * We won the race and set ->i_crypt_info to our crypt_info.
+		 * We won the race and set ->i_fscrypt_info to our crypt_info.
 		 * Now link it into the master key's inode list.
 		 */
 		if (mk) {
@@ -678,12 +678,12 @@ fscrypt_setup_encryption_info(struct inode *inode,
  *		       %false unless the operation being performed is needed in
  *		       order for files (or directories) to be deleted.
  *
- * Set up ->i_crypt_info, if it hasn't already been done.
+ * Set up ->i_fscrypt_info, if it hasn't already been done.
  *
- * Note: unless ->i_crypt_info is already set, this isn't %GFP_NOFS-safe.  So
+ * Note: unless ->i_fscrypt_info is already set, this isn't %GFP_NOFS-safe.  So
  * generally this shouldn't be called from within a filesystem transaction.
  *
- * Return: 0 if ->i_crypt_info was set or was already set, *or* if the
+ * Return: 0 if ->i_fscrypt_info was set or was already set, *or* if the
  *	   encryption key is unavailable.  (Use fscrypt_has_encryption_key() to
  *	   distinguish these cases.)  Also can return another -errno code.
  */
@@ -738,9 +738,9 @@ int fscrypt_get_encryption_info(struct inode *inode, bool allow_unsupported)
  *	   ->i_ino doesn't need to be set yet.
  * @encrypt_ret: (output) set to %true if the new inode will be encrypted
  *
- * If the directory is encrypted, set up its ->i_crypt_info in preparation for
+ * If the directory is encrypted, set up its ->i_fscrypt_info in preparation for
  * encrypting the name of the new file.  Also, if the new inode will be
- * encrypted, set up its ->i_crypt_info and set *encrypt_ret=true.
+ * encrypted, set up its ->i_fscrypt_info 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.  For this reason, ->i_ino
@@ -799,12 +799,11 @@ void fscrypt_put_encryption_info(struct inode *inode)
 {
 	struct fscrypt_inode_info **crypt_info;
 
-	if (inode->i_sb->s_op->i_fscrypt)
+	if (inode->i_sb->s_op->i_fscrypt) {
 		crypt_info = fscrypt_addr(inode);
-	else
-		crypt_info = &inode->i_crypt_info;
-	put_crypt_info(*crypt_info);
-	*crypt_info = NULL;
+		put_crypt_info(*crypt_info);
+		*crypt_info = NULL;
+	}
 }
 EXPORT_SYMBOL(fscrypt_put_encryption_info);
 
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 991089969e71..a2bf23b51bb9 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -778,10 +778,6 @@ struct inode {
 	struct fsnotify_mark_connector __rcu	*i_fsnotify_marks;
 #endif
 
-#ifdef CONFIG_FS_ENCRYPTION
-	struct fscrypt_inode_info	*i_crypt_info;
-#endif
-
 #ifdef CONFIG_FS_VERITY
 	struct fsverity_info	*i_verity_info;
 #endif
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 685780ce3579..988e48ea9775 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -203,28 +203,20 @@ static inline struct fscrypt_inode_info **fscrypt_addr(const struct inode *inode
 static inline bool fscrypt_set_inode_info(struct inode *inode,
 					  struct fscrypt_inode_info *crypt_info)
 {
-	void *p;
-
 	/*
-	 * For existing inodes, multiple tasks may race to set ->i_crypt_info.
+	 * For existing inodes, multiple tasks may race to set ->i_fscrypt_info.
 	 * So use cmpxchg_release().  This pairs with the smp_load_acquire() in
-	 * fscrypt_get_inode_info().  I.e., here we publish ->i_crypt_info with
+	 * fscrypt_get_inode_info().  I.e., here we publish ->i_fscrypt_info with
 	 * a RELEASE barrier so that other tasks can ACQUIRE it.
 	 */
 
-	if (inode->i_sb->s_op->i_fscrypt)
-		p = cmpxchg_release(fscrypt_addr(inode), NULL, crypt_info);
-	else
-		p = cmpxchg_release(&inode->i_crypt_info, NULL, crypt_info);
-	return p == NULL;
+	return cmpxchg_release(fscrypt_addr(inode), NULL, crypt_info) == NULL;
 }
 
 static inline struct fscrypt_inode_info *
 fscrypt_get_inode_info_raw(const struct inode *inode)
 {
-	if (inode->i_sb->s_op->i_fscrypt)
-		return *fscrypt_addr(inode);
-	return inode->i_crypt_info;
+	return *fscrypt_addr(inode);
 }
 
 static inline struct fscrypt_inode_info *
@@ -232,15 +224,14 @@ fscrypt_get_inode_info(const struct inode *inode)
 {
 	/*
 	 * Pairs with the cmpxchg_release() in fscrypt_setup_encryption_info().
-	 * I.e., another task may publish ->i_crypt_info concurrently, executing
+	 * I.e., another task may publish ->i_fscrypt_info concurrently, executing
 	 * a RELEASE barrier.  We need to use smp_load_acquire() here to safely
 	 * ACQUIRE the memory the other task published.
 	 */
 
 	if (inode->i_sb->s_op->i_fscrypt)
 		return smp_load_acquire(fscrypt_addr(inode));
-
-	return smp_load_acquire(&inode->i_crypt_info);
+	return NULL;
 }
 
 /**

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 08/13] fs: add fsverity offset
  2025-07-22 19:27     ` [PATCH v3 " Christian Brauner
                         ` (6 preceding siblings ...)
  2025-07-22 19:27       ` [PATCH v3 07/13] fs: drop i_crypt_info from struct inode Christian Brauner
@ 2025-07-22 19:27       ` Christian Brauner
  2025-07-23  3:53         ` Al Viro
  2025-07-22 19:27       ` [PATCH v3 09/13] fs/verity: use accessors Christian Brauner
                         ` (5 subsequent siblings)
  13 siblings, 1 reply; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 19:27 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Store the offset of the fsverity data pointer from struct inode in
struct super_operations. Both are embedded in the filesystem's private
inode.

This will allow us to drop the fsverity data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 include/linux/fs.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index a2bf23b51bb9..f7acf17550f1 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2329,6 +2329,7 @@ enum freeze_holder {
 
 struct super_operations {
 	ptrdiff_t i_fscrypt;
+	ptrdiff_t i_fsverity;
    	struct inode *(*alloc_inode)(struct super_block *sb);
 	void (*destroy_inode)(struct inode *);
 	void (*free_inode)(struct inode *);

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 09/13] fs/verity: use accessors
  2025-07-22 19:27     ` [PATCH v3 " Christian Brauner
                         ` (7 preceding siblings ...)
  2025-07-22 19:27       ` [PATCH v3 08/13] fs: add fsverity offset Christian Brauner
@ 2025-07-22 19:27       ` Christian Brauner
  2025-07-22 20:25         ` Eric Biggers
  2025-07-22 19:27       ` [PATCH v3 10/13] btrfs: move fsverity to filesystem inode Christian Brauner
                         ` (4 subsequent siblings)
  13 siblings, 1 reply; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 19:27 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Use accessor to get and set the verity info from the filesystem.
They can be removed once all filesystems have been converted to make
room for verity info in their own inodes.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/verity/open.c         | 18 +++++++++++++++---
 fs/verity/verify.c       |  2 +-
 include/linux/fsverity.h |  9 ++++++++-
 3 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/fs/verity/open.c b/fs/verity/open.c
index fdeb95eca3af..9368eeac6fb6 100644
--- a/fs/verity/open.c
+++ b/fs/verity/open.c
@@ -250,13 +250,20 @@ struct fsverity_info *fsverity_create_info(const struct inode *inode,
 
 void fsverity_set_info(struct inode *inode, struct fsverity_info *vi)
 {
+	void *p;
+
 	/*
 	 * Multiple tasks may race to set ->i_verity_info, so use
 	 * cmpxchg_release().  This pairs with the smp_load_acquire() in
 	 * fsverity_get_info().  I.e., here we publish ->i_verity_info with a
 	 * RELEASE barrier so that other tasks can ACQUIRE it.
 	 */
-	if (cmpxchg_release(&inode->i_verity_info, NULL, vi) != NULL) {
+
+	if (inode->i_sb->s_op->i_fsverity)
+		p = cmpxchg_release(fsverity_addr(inode), NULL, vi);
+	else
+		p = cmpxchg_release(&inode->i_verity_info, NULL, vi);
+	if (p != NULL) {
 		/* Lost the race, so free the fsverity_info we allocated. */
 		fsverity_free_info(vi);
 		/*
@@ -402,8 +409,13 @@ EXPORT_SYMBOL_GPL(__fsverity_prepare_setattr);
 
 void __fsverity_cleanup_inode(struct inode *inode)
 {
-	fsverity_free_info(inode->i_verity_info);
-	inode->i_verity_info = NULL;
+	struct fsverity_info **vi;
+
+	vi = fsverity_addr(inode);
+	if (!*vi)
+		vi = &inode->i_verity_info;
+	fsverity_free_info(*vi);
+	*vi = NULL;
 }
 EXPORT_SYMBOL_GPL(__fsverity_cleanup_inode);
 
diff --git a/fs/verity/verify.c b/fs/verity/verify.c
index 4fcad0825a12..a9c2f5c86991 100644
--- a/fs/verity/verify.c
+++ b/fs/verity/verify.c
@@ -247,7 +247,7 @@ verify_data_blocks(struct folio *data_folio, size_t len, size_t offset,
 		   unsigned long max_ra_pages)
 {
 	struct inode *inode = data_folio->mapping->host;
-	struct fsverity_info *vi = inode->i_verity_info;
+	struct fsverity_info *vi = fsverity_get_info(inode);
 	const unsigned int block_size = vi->tree_params.block_size;
 	u64 pos = (u64)data_folio->index << PAGE_SHIFT;
 
diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h
index 1eb7eae580be..341cb1ec73f8 100644
--- a/include/linux/fsverity.h
+++ b/include/linux/fsverity.h
@@ -124,6 +124,11 @@ struct fsverity_operations {
 
 #ifdef CONFIG_FS_VERITY
 
+static inline struct fsverity_info **fsverity_addr(const struct inode *inode)
+{
+	return ((void *)inode + inode->i_sb->s_op->i_fsverity);
+}
+
 static inline struct fsverity_info *fsverity_get_info(const struct inode *inode)
 {
 	/*
@@ -132,6 +137,8 @@ static inline struct fsverity_info *fsverity_get_info(const struct inode *inode)
 	 * executing a RELEASE barrier.  We need to use smp_load_acquire() here
 	 * to safely ACQUIRE the memory the other task published.
 	 */
+	if (inode->i_sb->s_op->i_fsverity)
+		return smp_load_acquire(fsverity_addr(inode));
 	return smp_load_acquire(&inode->i_verity_info);
 }
 
@@ -160,7 +167,7 @@ void __fsverity_cleanup_inode(struct inode *inode);
  */
 static inline void fsverity_cleanup_inode(struct inode *inode)
 {
-	if (inode->i_verity_info)
+	if (inode->i_verity_info || inode->i_sb->s_op->i_fsverity)
 		__fsverity_cleanup_inode(inode);
 }
 

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 10/13] btrfs: move fsverity to filesystem inode
  2025-07-22 19:27     ` [PATCH v3 " Christian Brauner
                         ` (8 preceding siblings ...)
  2025-07-22 19:27       ` [PATCH v3 09/13] fs/verity: use accessors Christian Brauner
@ 2025-07-22 19:27       ` Christian Brauner
  2025-07-22 19:27       ` [PATCH v3 11/13] ext4: " Christian Brauner
                         ` (3 subsequent siblings)
  13 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 19:27 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fsverity data pointer into the filesystem's private inode and
record the offset from the embedded struct inode.

This will allow us to drop the fsverity data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/btrfs/btrfs_inode.h | 3 +++
 fs/btrfs/inode.c       | 3 +++
 fs/btrfs/super.c       | 4 ++++
 3 files changed, 10 insertions(+)

diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
index a79fa0726f1d..10852d13fa00 100644
--- a/fs/btrfs/btrfs_inode.h
+++ b/fs/btrfs/btrfs_inode.h
@@ -339,6 +339,9 @@ struct btrfs_inode {
 
 	struct rw_semaphore i_mmap_lock;
 	struct inode vfs_inode;
+#ifdef CONFIG_FS_VERITY
+	struct fsverity_info *i_fsverity_info;
+#endif
 };
 
 static inline u64 btrfs_get_first_dir_index_to_log(const struct btrfs_inode *inode)
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index c0c778243bf1..ff0e0bde221a 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -7873,6 +7873,9 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
 	INIT_LIST_HEAD(&ei->delalloc_inodes);
 	INIT_LIST_HEAD(&ei->delayed_iput);
 	init_rwsem(&ei->i_mmap_lock);
+#ifdef CONFIG_FS_VERITY
+	ei->i_fsverity_info = NULL;
+#endif
 
 	return inode;
 }
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index a0c65adce1ab..e5def2ce85d9 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -2395,6 +2395,10 @@ static long btrfs_free_cached_objects(struct super_block *sb, struct shrink_cont
 }
 
 static const struct super_operations btrfs_super_ops = {
+#ifdef CONFIG_FS_VERITY
+	.i_fsverity	= offsetof(struct btrfs_inode, i_fsverity_info) -
+			  offsetof(struct btrfs_inode, vfs_inode),
+#endif
 	.drop_inode	= btrfs_drop_inode,
 	.evict_inode	= btrfs_evict_inode,
 	.put_super	= btrfs_put_super,

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 11/13] ext4: move fsverity to filesystem inode
  2025-07-22 19:27     ` [PATCH v3 " Christian Brauner
                         ` (9 preceding siblings ...)
  2025-07-22 19:27       ` [PATCH v3 10/13] btrfs: move fsverity to filesystem inode Christian Brauner
@ 2025-07-22 19:27       ` Christian Brauner
  2025-07-22 19:27       ` [PATCH v3 12/13] f2fs: " Christian Brauner
                         ` (2 subsequent siblings)
  13 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 19:27 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fsverity data pointer into the filesystem's private inode and
record the offset from the embedded struct inode.

This will allow us to drop the fsverity data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/ext4/ext4.h  | 4 ++++
 fs/ext4/super.c | 7 +++++++
 2 files changed, 11 insertions(+)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index f27d57aea316..4ae1a8aa8bac 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1201,6 +1201,10 @@ struct ext4_inode_info {
 #ifdef CONFIG_FS_ENCRYPTION
 	struct fscrypt_inode_info	*i_fscrypt_info;
 #endif
+
+#ifdef CONFIG_FS_VERITY
+	struct fsverity_info	*i_fsverity_info;
+#endif
 };
 
 /*
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 2a03835b67d5..37ef8fa4ebeb 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1414,6 +1414,9 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
 	spin_lock_init(&ei->i_fc_lock);
 #ifdef CONFIG_FS_ENCRYPTION
 	ei->i_fscrypt_info = NULL;
+#endif
+#ifdef CONFIG_FS_VERITY
+	ei->i_fsverity_info = NULL;
 #endif
 	return &ei->vfs_inode;
 }
@@ -1613,6 +1616,10 @@ static const struct super_operations ext4_sops = {
 #ifdef CONFIG_FS_ENCRYPTION
 	.i_fscrypt	= offsetof(struct ext4_inode_info, i_fscrypt_info) -
 			  offsetof(struct ext4_inode_info, vfs_inode),
+#endif
+#ifdef CONFIG_FS_VERITY
+	.i_fsverity	= offsetof(struct ext4_inode_info, i_fsverity_info) -
+			  offsetof(struct ext4_inode_info, vfs_inode),
 #endif
 	.alloc_inode	= ext4_alloc_inode,
 	.free_inode	= ext4_free_in_core_inode,

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 12/13] f2fs: move fsverity to filesystem inode
  2025-07-22 19:27     ` [PATCH v3 " Christian Brauner
                         ` (10 preceding siblings ...)
  2025-07-22 19:27       ` [PATCH v3 11/13] ext4: " Christian Brauner
@ 2025-07-22 19:27       ` Christian Brauner
  2025-07-22 19:27       ` [PATCH v3 13/13] fs: drop i_verity_info from struct inode Christian Brauner
  2025-07-23 10:57       ` [PATCH v4 00/15] Move fscrypt and fsverity out of " Christian Brauner
  13 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 19:27 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fsverity data pointer into the filesystem's private inode and
record the offset from the embedded struct inode.

This will allow us to drop the fsverity data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/f2fs/f2fs.h  | 3 +++
 fs/f2fs/super.c | 7 +++++++
 2 files changed, 10 insertions(+)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 14e69c00e679..dc43a957a693 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -908,6 +908,9 @@ struct f2fs_inode_info {
 #ifdef CONFIG_FS_ENCRYPTION
 	struct fscrypt_inode_info *i_fscrypt_info; /* filesystem encryption info */
 #endif
+#ifdef CONFIG_FS_VERITY
+	struct fsverity_info	*i_fsverity_info;
+#endif
 };
 
 static inline void get_read_extent_info(struct extent_info *ext,
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 969ba46990ea..75e7661be462 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1456,6 +1456,9 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
 #ifdef CONFIG_FS_ENCRYPTION
 	fi->i_fscrypt_info = NULL;
 #endif
+#ifdef CONFIG_FS_VERITY
+	fi->i_fsverity_info = NULL;
+#endif
 
 	return &fi->vfs_inode;
 }
@@ -3252,6 +3255,10 @@ static const struct super_operations f2fs_sops = {
 #ifdef CONFIG_FS_ENCRYPTION
 	.i_fscrypt	= offsetof(struct f2fs_inode_info, i_fscrypt_info) -
 			  offsetof(struct f2fs_inode_info, vfs_inode),
+#endif
+#ifdef CONFIG_FS_VERITY
+	.i_fsverity	= offsetof(struct f2fs_inode_info, i_fsverity_info) -
+			  offsetof(struct f2fs_inode_info, vfs_inode),
 #endif
 	.alloc_inode	= f2fs_alloc_inode,
 	.free_inode	= f2fs_free_inode,

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v3 13/13] fs: drop i_verity_info from struct inode
  2025-07-22 19:27     ` [PATCH v3 " Christian Brauner
                         ` (11 preceding siblings ...)
  2025-07-22 19:27       ` [PATCH v3 12/13] f2fs: " Christian Brauner
@ 2025-07-22 19:27       ` Christian Brauner
  2025-07-23 10:57       ` [PATCH v4 00/15] Move fscrypt and fsverity out of " Christian Brauner
  13 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-22 19:27 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Now that all filesystems store the fsverity data pointer in their
private inode, drop the data pointer from struct inode itself freeing up
8 bytes.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/verity/enable.c           |  2 +-
 fs/verity/fsverity_private.h |  2 +-
 fs/verity/open.c             | 19 +++++--------------
 include/linux/fs.h           |  4 ----
 include/linux/fsverity.h     | 14 +++++++-------
 5 files changed, 14 insertions(+), 27 deletions(-)

diff --git a/fs/verity/enable.c b/fs/verity/enable.c
index c284f46d1b53..255cf73f6c03 100644
--- a/fs/verity/enable.c
+++ b/fs/verity/enable.c
@@ -287,7 +287,7 @@ static int enable_verity(struct file *filp,
 		/* Successfully enabled verity */
 
 		/*
-		 * Readers can start using ->i_verity_info immediately, so it
+		 * Readers can start using ->i_fsverity_info immediately, so it
 		 * can't be rolled back once set.  So don't set it until just
 		 * after the filesystem has successfully enabled verity.
 		 */
diff --git a/fs/verity/fsverity_private.h b/fs/verity/fsverity_private.h
index b3506f56e180..358cbc3aa7ea 100644
--- a/fs/verity/fsverity_private.h
+++ b/fs/verity/fsverity_private.h
@@ -58,7 +58,7 @@ struct merkle_tree_params {
  * fsverity_info - cached verity metadata for an inode
  *
  * When a verity file is first opened, an instance of this struct is allocated
- * and stored in ->i_verity_info; it remains until the inode is evicted.  It
+ * and stored in ->i_fsverity_info; it remains until the inode is evicted.  It
  * caches information about the Merkle tree that's needed to efficiently verify
  * data read from the file.  It also caches the file digest.  The Merkle tree
  * pages themselves are not cached here, but the filesystem may cache them.
diff --git a/fs/verity/open.c b/fs/verity/open.c
index 9368eeac6fb6..20c6020d59fa 100644
--- a/fs/verity/open.c
+++ b/fs/verity/open.c
@@ -250,24 +250,17 @@ struct fsverity_info *fsverity_create_info(const struct inode *inode,
 
 void fsverity_set_info(struct inode *inode, struct fsverity_info *vi)
 {
-	void *p;
-
 	/*
-	 * Multiple tasks may race to set ->i_verity_info, so use
+	 * Multiple tasks may race to set ->i_fsverity_info, so use
 	 * cmpxchg_release().  This pairs with the smp_load_acquire() in
-	 * fsverity_get_info().  I.e., here we publish ->i_verity_info with a
+	 * fsverity_get_info().  I.e., here we publish ->i_fsverity_info with a
 	 * RELEASE barrier so that other tasks can ACQUIRE it.
 	 */
-
-	if (inode->i_sb->s_op->i_fsverity)
-		p = cmpxchg_release(fsverity_addr(inode), NULL, vi);
-	else
-		p = cmpxchg_release(&inode->i_verity_info, NULL, vi);
-	if (p != NULL) {
+	if (cmpxchg_release(fsverity_addr(inode), NULL, vi) != NULL) {
 		/* Lost the race, so free the fsverity_info we allocated. */
 		fsverity_free_info(vi);
 		/*
-		 * Afterwards, the caller may access ->i_verity_info directly,
+		 * Afterwards, the caller may access ->i_fsverity_info directly,
 		 * so make sure to ACQUIRE the winning fsverity_info.
 		 */
 		(void)fsverity_get_info(inode);
@@ -364,7 +357,7 @@ int fsverity_get_descriptor(struct inode *inode,
 	return 0;
 }
 
-/* Ensure the inode has an ->i_verity_info */
+/* Ensure the inode has an ->i_fsverity_info */
 static int ensure_verity_info(struct inode *inode)
 {
 	struct fsverity_info *vi = fsverity_get_info(inode);
@@ -412,8 +405,6 @@ void __fsverity_cleanup_inode(struct inode *inode)
 	struct fsverity_info **vi;
 
 	vi = fsverity_addr(inode);
-	if (!*vi)
-		vi = &inode->i_verity_info;
 	fsverity_free_info(*vi);
 	*vi = NULL;
 }
diff --git a/include/linux/fs.h b/include/linux/fs.h
index f7acf17550f1..a9031a937959 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -778,10 +778,6 @@ struct inode {
 	struct fsnotify_mark_connector __rcu	*i_fsnotify_marks;
 #endif
 
-#ifdef CONFIG_FS_VERITY
-	struct fsverity_info	*i_verity_info;
-#endif
-
 	void			*i_private; /* fs or device private pointer */
 } __randomize_layout;
 
diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h
index 341cb1ec73f8..7c876d149a63 100644
--- a/include/linux/fsverity.h
+++ b/include/linux/fsverity.h
@@ -133,13 +133,13 @@ static inline struct fsverity_info *fsverity_get_info(const struct inode *inode)
 {
 	/*
 	 * Pairs with the cmpxchg_release() in fsverity_set_info().
-	 * I.e., another task may publish ->i_verity_info concurrently,
+	 * I.e., another task may publish ->i_fsverity_info concurrently,
 	 * executing a RELEASE barrier.  We need to use smp_load_acquire() here
 	 * to safely ACQUIRE the memory the other task published.
 	 */
 	if (inode->i_sb->s_op->i_fsverity)
 		return smp_load_acquire(fsverity_addr(inode));
-	return smp_load_acquire(&inode->i_verity_info);
+	return NULL;
 }
 
 /* enable.c */
@@ -163,11 +163,11 @@ void __fsverity_cleanup_inode(struct inode *inode);
  * fsverity_cleanup_inode() - free the inode's verity info, if present
  * @inode: an inode being evicted
  *
- * Filesystems must call this on inode eviction to free ->i_verity_info.
+ * Filesystems must call this on inode eviction to free ->i_fsverity_info.
  */
 static inline void fsverity_cleanup_inode(struct inode *inode)
 {
-	if (inode->i_verity_info || inode->i_sb->s_op->i_fsverity)
+	if (inode->i_sb->s_op->i_fsverity)
 		__fsverity_cleanup_inode(inode);
 }
 
@@ -274,12 +274,12 @@ static inline bool fsverity_verify_page(struct page *page)
  * fsverity_active() - do reads from the inode need to go through fs-verity?
  * @inode: inode to check
  *
- * This checks whether ->i_verity_info has been set.
+ * This checks whether ->i_fsverity_info has been set.
  *
  * Filesystems call this from ->readahead() to check whether the pages need to
  * be verified or not.  Don't use IS_VERITY() for this purpose; it's subject to
  * a race condition where the file is being read concurrently with
- * FS_IOC_ENABLE_VERITY completing.  (S_VERITY is set before ->i_verity_info.)
+ * FS_IOC_ENABLE_VERITY completing.  (S_VERITY is set before ->i_fsverity_info.)
  *
  * Return: true if reads need to go through fs-verity, otherwise false
  */
@@ -294,7 +294,7 @@ static inline bool fsverity_active(const struct inode *inode)
  * @filp: the struct file being set up
  *
  * When opening a verity file, deny the open if it is for writing.  Otherwise,
- * set up the inode's ->i_verity_info if not already done.
+ * set up the inode's ->i_fsverity_info if not already done.
  *
  * When combined with fscrypt, this must be called after fscrypt_file_open().
  * Otherwise, we won't have the key set up to decrypt the verity metadata.

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 01/13] fs: add fscrypt offset
  2025-07-22 19:27       ` [PATCH v3 01/13] fs: add fscrypt offset Christian Brauner
@ 2025-07-22 20:02         ` Eric Biggers
  2025-07-23  7:48           ` Christian Brauner
  2025-07-23  3:49         ` Al Viro
  1 sibling, 1 reply; 67+ messages in thread
From: Eric Biggers @ 2025-07-22 20:02 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik,
	Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt, fsverity

On Tue, Jul 22, 2025 at 09:27:19PM +0200, Christian Brauner wrote:
> Store the offset of the fscrypt data pointer from struct inode in struct
> super_operations. Both are embedded in the filesystem's private inode.
> 
> This will allow us to drop the fscrypt data pointer from struct inode
> itself and move it into the filesystem's inode.
> 
> Signed-off-by: Christian Brauner <brauner@kernel.org>
> ---
>  include/linux/fs.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index 96c7925a6551..991089969e71 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -2332,6 +2332,7 @@ enum freeze_holder {
>  };
>  
>  struct super_operations {
> +	ptrdiff_t i_fscrypt;
>     	struct inode *(*alloc_inode)(struct super_block *sb);
>  	void (*destroy_inode)(struct inode *);
>  	void (*free_inode)(struct inode *);

If using inode_operations was ruled out, so we have to go through the
super_block to get to an operations struct anyway, wouldn't it make more
sense to use fscrypt_operations and fsverity_operations?  They are
accessible as inode->i_sb->s_cop and inode->i_sb->s_vop.  Same number of
dereferences as getting to inode->i_sb->s_op.

For the naming, how about fscrypt_operations::inode_info_offs and
fsverity_operations::inode_info_offs?

- Eric

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 03/13] ext4: move fscrypt to filesystem inode
  2025-07-22 19:27       ` [PATCH v3 03/13] ext4: move fscrypt to filesystem inode Christian Brauner
@ 2025-07-22 20:07         ` Eric Biggers
  2025-07-23  8:59           ` Christian Brauner
  0 siblings, 1 reply; 67+ messages in thread
From: Eric Biggers @ 2025-07-22 20:07 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik,
	Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt, fsverity

On Tue, Jul 22, 2025 at 09:27:21PM +0200, Christian Brauner wrote:
> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
> index 18373de980f2..f27d57aea316 100644
> --- a/fs/ext4/ext4.h
> +++ b/fs/ext4/ext4.h
> @@ -1197,6 +1197,10 @@ struct ext4_inode_info {
>  	__u32 i_csum_seed;
>  
>  	kprojid_t i_projid;
> +
> +#ifdef CONFIG_FS_ENCRYPTION
> +	struct fscrypt_inode_info	*i_fscrypt_info;
> +#endif

Did you consider keeping the name as i_crypt_info instead of changing it
to i_fscrypt_info?  The rationale for i_crypt_info in the first place is
that it's filesystem code, so fs is implied.

I see you also had to replace i_crypt_info with i_fscrypt_info in a
bunch of comments.  It might make more sense to rephrase those to not
refer to the exact field name.  E.g. instead of "Set up
->i_fscrypt_info", we could write "Set up the inode's fscrypt info".

- Eric

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 06/13] ceph: move fscrypt to filesystem inode
  2025-07-22 19:27       ` [PATCH v3 06/13] ceph: " Christian Brauner
@ 2025-07-22 20:14         ` Eric Biggers
  2025-07-23  8:58           ` Christian Brauner
  0 siblings, 1 reply; 67+ messages in thread
From: Eric Biggers @ 2025-07-22 20:14 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik,
	Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt, fsverity

On Tue, Jul 22, 2025 at 09:27:24PM +0200, Christian Brauner wrote:
> Move fscrypt data pointer into the filesystem's private inode and record
> the offset from the embedded struct inode.
> 
> This will allow us to drop the fscrypt data pointer from struct inode
> itself and move it into the filesystem's inode.
> 
> Signed-off-by: Christian Brauner <brauner@kernel.org>
> ---
>  fs/ceph/super.c       | 4 ++++
>  include/linux/netfs.h | 6 ++++++
>  2 files changed, 10 insertions(+)
> 
> diff --git a/fs/ceph/super.c b/fs/ceph/super.c
> index 2b8438d8a324..540b32e746de 100644
> --- a/fs/ceph/super.c
> +++ b/fs/ceph/super.c
> @@ -1039,6 +1039,10 @@ void ceph_umount_begin(struct super_block *sb)
>  }
>  
>  static const struct super_operations ceph_super_ops = {
> +#ifdef CONFIG_FS_ENCRYPTION
> +	.i_fscrypt = offsetof(struct ceph_inode_info, netfs.i_fscrypt_info) -
> +		     offsetof(struct ceph_inode_info, netfs.inode),
> +#endif
>  	.alloc_inode	= ceph_alloc_inode,
>  	.free_inode	= ceph_free_inode,
>  	.write_inode    = ceph_write_inode,
> diff --git a/include/linux/netfs.h b/include/linux/netfs.h
> index 065c17385e53..fda1321da861 100644
> --- a/include/linux/netfs.h
> +++ b/include/linux/netfs.h
> @@ -57,6 +57,9 @@ typedef void (*netfs_io_terminated_t)(void *priv, ssize_t transferred_or_error);
>   */
>  struct netfs_inode {
>  	struct inode		inode;		/* The VFS inode */
> +#ifdef CONFIG_FS_ENCRYPTION
> +	struct fscrypt_inode_info *i_fscrypt_info;
> +#endif
>  	const struct netfs_request_ops *ops;
>  #if IS_ENABLED(CONFIG_FSCACHE)
>  	struct fscache_cookie	*cache;
> @@ -503,6 +506,9 @@ static inline void netfs_inode_init(struct netfs_inode *ctx,
>  		ctx->zero_point = ctx->remote_i_size;
>  		mapping_set_release_always(ctx->inode.i_mapping);
>  	}
> +#ifdef CONFIG_FS_ENCRYPTION
> +	ctx->i_fscrypt_info = NULL;
> +#endif

Why netfs_inode instead of ceph_inode_info?

- Eric

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 07/13] fs: drop i_crypt_info from struct inode
  2025-07-22 19:27       ` [PATCH v3 07/13] fs: drop i_crypt_info from struct inode Christian Brauner
@ 2025-07-22 20:19         ` Eric Biggers
  2025-07-23  8:52           ` Christian Brauner
  0 siblings, 1 reply; 67+ messages in thread
From: Eric Biggers @ 2025-07-22 20:19 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik,
	Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt, fsverity

On Tue, Jul 22, 2025 at 09:27:25PM +0200, Christian Brauner wrote:
> @@ -799,12 +799,11 @@ void fscrypt_put_encryption_info(struct inode *inode)
>  {
>  	struct fscrypt_inode_info **crypt_info;
>  
> -	if (inode->i_sb->s_op->i_fscrypt)
> +	if (inode->i_sb->s_op->i_fscrypt) {
>  		crypt_info = fscrypt_addr(inode);
> -	else
> -		crypt_info = &inode->i_crypt_info;
> -	put_crypt_info(*crypt_info);
> -	*crypt_info = NULL;
> +		put_crypt_info(*crypt_info);
> +		*crypt_info = NULL;
> +	}
>  }

This could use an IS_ENCRYPTED(inode) check at the beginning, to
minimize the overhead on unencrypted files.  Before we just loaded
inode:i_crypt_info, but now that accessing the fscrypt_inode_info will
be more expensive it would be worthwhile to check IS_ENCRYPTED() first.

>  static inline struct fscrypt_inode_info *
> @@ -232,15 +224,14 @@ fscrypt_get_inode_info(const struct inode *inode)
>  {
>  	/*
>  	 * Pairs with the cmpxchg_release() in fscrypt_setup_encryption_info().
> -	 * I.e., another task may publish ->i_crypt_info concurrently, executing
> +	 * I.e., another task may publish ->i_fscrypt_info concurrently, executing
>  	 * a RELEASE barrier.  We need to use smp_load_acquire() here to safely
>  	 * ACQUIRE the memory the other task published.
>  	 */
>  
>  	if (inode->i_sb->s_op->i_fscrypt)
>  		return smp_load_acquire(fscrypt_addr(inode));
> -
> -	return smp_load_acquire(&inode->i_crypt_info);
> +	return NULL;

The conditional here shouldn't be needed, since this should be called
only on filesystems that support encryption.  Did you find a case where
it isn't?

- Eric

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 09/13] fs/verity: use accessors
  2025-07-22 19:27       ` [PATCH v3 09/13] fs/verity: use accessors Christian Brauner
@ 2025-07-22 20:25         ` Eric Biggers
  2025-07-23  8:55           ` Christian Brauner
  0 siblings, 1 reply; 67+ messages in thread
From: Eric Biggers @ 2025-07-22 20:25 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik,
	Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt, fsverity

On Tue, Jul 22, 2025 at 09:27:27PM +0200, Christian Brauner wrote:
>  static inline void fsverity_cleanup_inode(struct inode *inode)
>  {
> -	if (inode->i_verity_info)
> +	if (inode->i_verity_info || inode->i_sb->s_op->i_fsverity)
>  		__fsverity_cleanup_inode(inode);

Similarly to fscrypt_put_encryption_info(): I think this should look
like:

    if (IS_VERITY(inode))
            __fsverity_cleanup_inode(inode);

i_verity_info != NULL implies IS_VERITY(), so that would work and avoid
adding extra dereferences to non-verity files.

The converse isn't necessarily true, but that's okay as long as
__fsverity_cleanup_inode() handles i_verity_info == NULL.

- Eric

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 01/13] fs: add fscrypt offset
  2025-07-22 19:27       ` [PATCH v3 01/13] fs: add fscrypt offset Christian Brauner
  2025-07-22 20:02         ` Eric Biggers
@ 2025-07-23  3:49         ` Al Viro
  1 sibling, 0 replies; 67+ messages in thread
From: Al Viro @ 2025-07-23  3:49 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik,
	Eric Biggers, Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt,
	fsverity

On Tue, Jul 22, 2025 at 09:27:19PM +0200, Christian Brauner wrote:
> Store the offset of the fscrypt data pointer from struct inode in struct
> super_operations. Both are embedded in the filesystem's private inode.
> 
> This will allow us to drop the fscrypt data pointer from struct inode
> itself and move it into the filesystem's inode.
> 
> Signed-off-by: Christian Brauner <brauner@kernel.org>
> ---
>  include/linux/fs.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index 96c7925a6551..991089969e71 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -2332,6 +2332,7 @@ enum freeze_holder {
>  };
>  
>  struct super_operations {
> +	ptrdiff_t i_fscrypt;

Umm...  Why not put that into super_block itself?

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 08/13] fs: add fsverity offset
  2025-07-22 19:27       ` [PATCH v3 08/13] fs: add fsverity offset Christian Brauner
@ 2025-07-23  3:53         ` Al Viro
  0 siblings, 0 replies; 67+ messages in thread
From: Al Viro @ 2025-07-23  3:53 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik,
	Eric Biggers, Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt,
	fsverity

On Tue, Jul 22, 2025 at 09:27:26PM +0200, Christian Brauner wrote:
> Store the offset of the fsverity data pointer from struct inode in
> struct super_operations. Both are embedded in the filesystem's private
> inode.
> 
> This will allow us to drop the fsverity data pointer from struct inode
> itself and move it into the filesystem's inode.

Same point re store in super_block itself.

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 01/13] fs: add fscrypt offset
  2025-07-22 20:02         ` Eric Biggers
@ 2025-07-23  7:48           ` Christian Brauner
  0 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-23  7:48 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Jeff Layton, Jan Kara, Alexander Viro, Christoph Hellwig,
	Jens Axboe, Josef Bacik, Theodore Y. Ts'o, linux-fsdevel,
	linux-fscrypt, fsverity

On Tue, Jul 22, 2025 at 01:02:25PM -0700, Eric Biggers wrote:
> On Tue, Jul 22, 2025 at 09:27:19PM +0200, Christian Brauner wrote:
> > Store the offset of the fscrypt data pointer from struct inode in struct
> > super_operations. Both are embedded in the filesystem's private inode.
> > 
> > This will allow us to drop the fscrypt data pointer from struct inode
> > itself and move it into the filesystem's inode.
> > 
> > Signed-off-by: Christian Brauner <brauner@kernel.org>
> > ---
> >  include/linux/fs.h | 1 +
> >  1 file changed, 1 insertion(+)
> > 
> > diff --git a/include/linux/fs.h b/include/linux/fs.h
> > index 96c7925a6551..991089969e71 100644
> > --- a/include/linux/fs.h
> > +++ b/include/linux/fs.h
> > @@ -2332,6 +2332,7 @@ enum freeze_holder {
> >  };
> >  
> >  struct super_operations {
> > +	ptrdiff_t i_fscrypt;
> >     	struct inode *(*alloc_inode)(struct super_block *sb);
> >  	void (*destroy_inode)(struct inode *);
> >  	void (*free_inode)(struct inode *);
> 
> If using inode_operations was ruled out, so we have to go through the
> super_block to get to an operations struct anyway, wouldn't it make more
> sense to use fscrypt_operations and fsverity_operations?  They are

Good idea.

> accessible as inode->i_sb->s_cop and inode->i_sb->s_vop.  Same number of
> dereferences as getting to inode->i_sb->s_op.

I also like Al's idea to move the offset directly into struct
super_block.

Hm, but conceptually moving it into the respective operations would make
a lot more sense...

I'll just sketch both and see what feels cleaner.

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 07/13] fs: drop i_crypt_info from struct inode
  2025-07-22 20:19         ` Eric Biggers
@ 2025-07-23  8:52           ` Christian Brauner
  0 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-23  8:52 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik,
	Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt, fsverity

On Tue, Jul 22, 2025 at 01:19:45PM -0700, Eric Biggers wrote:
> On Tue, Jul 22, 2025 at 09:27:25PM +0200, Christian Brauner wrote:
> > @@ -799,12 +799,11 @@ void fscrypt_put_encryption_info(struct inode *inode)
> >  {
> >  	struct fscrypt_inode_info **crypt_info;
> >  
> > -	if (inode->i_sb->s_op->i_fscrypt)
> > +	if (inode->i_sb->s_op->i_fscrypt) {
> >  		crypt_info = fscrypt_addr(inode);
> > -	else
> > -		crypt_info = &inode->i_crypt_info;
> > -	put_crypt_info(*crypt_info);
> > -	*crypt_info = NULL;
> > +		put_crypt_info(*crypt_info);
> > +		*crypt_info = NULL;
> > +	}
> >  }
> 
> This could use an IS_ENCRYPTED(inode) check at the beginning, to
> minimize the overhead on unencrypted files.  Before we just loaded
> inode:i_crypt_info, but now that accessing the fscrypt_inode_info will
> be more expensive it would be worthwhile to check IS_ENCRYPTED() first.

Done.

> 
> >  static inline struct fscrypt_inode_info *
> > @@ -232,15 +224,14 @@ fscrypt_get_inode_info(const struct inode *inode)
> >  {
> >  	/*
> >  	 * Pairs with the cmpxchg_release() in fscrypt_setup_encryption_info().
> > -	 * I.e., another task may publish ->i_crypt_info concurrently, executing
> > +	 * I.e., another task may publish ->i_fscrypt_info concurrently, executing
> >  	 * a RELEASE barrier.  We need to use smp_load_acquire() here to safely
> >  	 * ACQUIRE the memory the other task published.
> >  	 */
> >  
> >  	if (inode->i_sb->s_op->i_fscrypt)
> >  		return smp_load_acquire(fscrypt_addr(inode));
> > -
> > -	return smp_load_acquire(&inode->i_crypt_info);
> > +	return NULL;
> 
> The conditional here shouldn't be needed, since this should be called
> only on filesystems that support encryption.  Did you find a case where
> it isn't?

Ok, if that can't happen let's still place a VFS_WARN_ON_ONCE() here so
we catch bugs when CONFIG_DEBUG_VFS is set.

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 09/13] fs/verity: use accessors
  2025-07-22 20:25         ` Eric Biggers
@ 2025-07-23  8:55           ` Christian Brauner
  0 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-23  8:55 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik,
	Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt, fsverity

On Tue, Jul 22, 2025 at 01:25:31PM -0700, Eric Biggers wrote:
> On Tue, Jul 22, 2025 at 09:27:27PM +0200, Christian Brauner wrote:
> >  static inline void fsverity_cleanup_inode(struct inode *inode)
> >  {
> > -	if (inode->i_verity_info)
> > +	if (inode->i_verity_info || inode->i_sb->s_op->i_fsverity)
> >  		__fsverity_cleanup_inode(inode);
> 
> Similarly to fscrypt_put_encryption_info(): I think this should look
> like:
> 
>     if (IS_VERITY(inode))
>             __fsverity_cleanup_inode(inode);
> 
> i_verity_info != NULL implies IS_VERITY(), so that would work and avoid
> adding extra dereferences to non-verity files.
> 
> The converse isn't necessarily true, but that's okay as long as
> __fsverity_cleanup_inode() handles i_verity_info == NULL.

Done.

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 06/13] ceph: move fscrypt to filesystem inode
  2025-07-22 20:14         ` Eric Biggers
@ 2025-07-23  8:58           ` Christian Brauner
  0 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-23  8:58 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik,
	Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt, fsverity

On Tue, Jul 22, 2025 at 01:14:06PM -0700, Eric Biggers wrote:
> On Tue, Jul 22, 2025 at 09:27:24PM +0200, Christian Brauner wrote:
> > Move fscrypt data pointer into the filesystem's private inode and record
> > the offset from the embedded struct inode.
> > 
> > This will allow us to drop the fscrypt data pointer from struct inode
> > itself and move it into the filesystem's inode.
> > 
> > Signed-off-by: Christian Brauner <brauner@kernel.org>
> > ---
> >  fs/ceph/super.c       | 4 ++++
> >  include/linux/netfs.h | 6 ++++++
> >  2 files changed, 10 insertions(+)
> > 
> > diff --git a/fs/ceph/super.c b/fs/ceph/super.c
> > index 2b8438d8a324..540b32e746de 100644
> > --- a/fs/ceph/super.c
> > +++ b/fs/ceph/super.c
> > @@ -1039,6 +1039,10 @@ void ceph_umount_begin(struct super_block *sb)
> >  }
> >  
> >  static const struct super_operations ceph_super_ops = {
> > +#ifdef CONFIG_FS_ENCRYPTION
> > +	.i_fscrypt = offsetof(struct ceph_inode_info, netfs.i_fscrypt_info) -
> > +		     offsetof(struct ceph_inode_info, netfs.inode),
> > +#endif
> >  	.alloc_inode	= ceph_alloc_inode,
> >  	.free_inode	= ceph_free_inode,
> >  	.write_inode    = ceph_write_inode,
> > diff --git a/include/linux/netfs.h b/include/linux/netfs.h
> > index 065c17385e53..fda1321da861 100644
> > --- a/include/linux/netfs.h
> > +++ b/include/linux/netfs.h
> > @@ -57,6 +57,9 @@ typedef void (*netfs_io_terminated_t)(void *priv, ssize_t transferred_or_error);
> >   */
> >  struct netfs_inode {
> >  	struct inode		inode;		/* The VFS inode */
> > +#ifdef CONFIG_FS_ENCRYPTION
> > +	struct fscrypt_inode_info *i_fscrypt_info;
> > +#endif
> >  	const struct netfs_request_ops *ops;
> >  #if IS_ENABLED(CONFIG_FSCACHE)
> >  	struct fscache_cookie	*cache;
> > @@ -503,6 +506,9 @@ static inline void netfs_inode_init(struct netfs_inode *ctx,
> >  		ctx->zero_point = ctx->remote_i_size;
> >  		mapping_set_release_always(ctx->inode.i_mapping);
> >  	}
> > +#ifdef CONFIG_FS_ENCRYPTION
> > +	ctx->i_fscrypt_info = NULL;
> > +#endif
> 
> Why netfs_inode instead of ceph_inode_info?

If we add asserts that struct inode must be located at the beginning of
struct netfs_inode then I would feel comfortable doing that. I'll do
that.

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v3 03/13] ext4: move fscrypt to filesystem inode
  2025-07-22 20:07         ` Eric Biggers
@ 2025-07-23  8:59           ` Christian Brauner
  0 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-23  8:59 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik,
	Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt, fsverity

On Tue, Jul 22, 2025 at 01:07:51PM -0700, Eric Biggers wrote:
> On Tue, Jul 22, 2025 at 09:27:21PM +0200, Christian Brauner wrote:
> > diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
> > index 18373de980f2..f27d57aea316 100644
> > --- a/fs/ext4/ext4.h
> > +++ b/fs/ext4/ext4.h
> > @@ -1197,6 +1197,10 @@ struct ext4_inode_info {
> >  	__u32 i_csum_seed;
> >  
> >  	kprojid_t i_projid;
> > +
> > +#ifdef CONFIG_FS_ENCRYPTION
> > +	struct fscrypt_inode_info	*i_fscrypt_info;
> > +#endif
> 
> Did you consider keeping the name as i_crypt_info instead of changing it
> to i_fscrypt_info?  The rationale for i_crypt_info in the first place is
> that it's filesystem code, so fs is implied.

Ok.

> 
> I see you also had to replace i_crypt_info with i_fscrypt_info in a
> bunch of comments.  It might make more sense to rephrase those to not
> refer to the exact field name.  E.g. instead of "Set up
> ->i_fscrypt_info", we could write "Set up the inode's fscrypt info".

Ok, I'll do that.

^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v4 00/15] Move fscrypt and fsverity out of struct inode
  2025-07-22 19:27     ` [PATCH v3 " Christian Brauner
                         ` (12 preceding siblings ...)
  2025-07-22 19:27       ` [PATCH v3 13/13] fs: drop i_verity_info from struct inode Christian Brauner
@ 2025-07-23 10:57       ` Christian Brauner
  2025-07-23 10:57         ` [PATCH v4 01/15] fs: add fscrypt offset Christian Brauner
                           ` (14 more replies)
  13 siblings, 15 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-23 10:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Hey,

As discussed, this moves the fscrypt and fsverity pointers out of struct
inode shrinking it by 16 bytes. The pointers move into the individual
filesystems that actually do make use of them.

In order to find the fscrypt and fsverity data pointers offsets from the
embedded struct inode in the filesystem's private inode data are stored
in struct fscrypt_operations and struct fsverity_operations
respectively. This means we get fast access to the data pointers without
having to rely on indirect calls.

Thanks to everyone for the very helpful reviews! The two obvious
suggestions other than moving it into struct super_operations were
moving it directly into struct super_block and moving it into struct
fscrypt_operations and struct fsverity_operations. I chose the latter as
I think that's just cleaner.

Thanks!
Christian

Test results:

+ sudo ./check -g encrypt,verity
FSTYP         -- ext4
PLATFORM      -- Linux/x86_64 localhost 6.16.0-rc1-gaa8ca50672ad #275 SMP PREEMPT_DYNAMIC Fri Jun  5 15:58:00 CEST 2015
MKFS_OPTIONS  -- -F /dev/nvme0n1p6
MOUNT_OPTIONS -- -o acl,user_xattr /dev/nvme0n1p6 /mnt/scratch

ext4/024        3s
generic/395        4s
generic/396        3s
generic/397        4s
generic/398        4s
generic/399        35s
generic/419        4s
generic/421        4s
generic/429        14s
generic/435        23s
generic/440        4s
generic/548        9s
generic/549        9s
generic/550       [not run] encryption policy '-c 9 -n 9 -f 0' is unusable; probably missing kernel crypto API support
generic/572        6s
generic/573        3s
generic/574        38s
generic/575        10s
generic/576        5s
generic/577        4s
generic/579        25s
generic/580        4s
generic/581        11s
generic/582        10s
generic/583        10s
generic/584       [not run] encryption policy '-c 9 -n 9 -v 2 -f 0' is unusable; probably missing kernel crypto API support
generic/592        10s
generic/593        4s
generic/595        8s
generic/602        11s
generic/613        21s
generic/621        9s
generic/624        4s
generic/625        4s
generic/692        5s
generic/693       [not run] encryption policy '-c 1 -n 10 -v 2 -f 0' is unusable; probably missing kernel crypto API support
generic/739        18s
Ran: ext4/024 generic/395 generic/396 generic/397 generic/398 generic/399 generic/419 generic/421 generic/429 generic/435 generic/440 generic/548 generic/549 generic/550 generic/572 generic/573 generic/574 generic/575 generic/576 generic/577 generic/579 generic/580 generic/581 generic/582 generic/583 generic/584 generic/592 generic/593 generic/595 generic/602 generic/613 generic/621 generic/624 generic/625 generic/692 generic/693 generic/739
Not run: generic/550 generic/584 generic/693
Passed all 37 tests

+ sudo ./check -g encrypt,verity
FSTYP         -- btrfs
PLATFORM      -- Linux/x86_64 localhost 6.16.0-rc1-gaa8ca50672ad #275 SMP PREEMPT_DYNAMIC Fri Jun  5 15:58:00 CEST 2015
MKFS_OPTIONS  -- /dev/nvme0n1p6
MOUNT_OPTIONS -- /dev/nvme0n1p6 /mnt/scratch

btrfs/277       [not run] kernel does not support send stream 3
btrfs/290       [not run] btrfs-corrupt-block utility required, skipped this test
btrfs/291       [not run] This test requires a valid $LOGWRITES_DEV
generic/395 4s ... [not run] No encryption support for btrfs
generic/396 3s ... [not run] No encryption support for btrfs
generic/397 4s ... [not run] No encryption support for btrfs
generic/398 5s ... [not run] No encryption support for btrfs
generic/399 35s ... [not run] No encryption support for btrfs
generic/419 4s ... [not run] No encryption support for btrfs
generic/421 4s ... [not run] No encryption support for btrfs
generic/429 14s ... [not run] No encryption support for btrfs
generic/435 23s ... [not run] No encryption support for btrfs
generic/440 4s ... [not run] No encryption support for btrfs
generic/548 9s ... [not run] No encryption support for btrfs
generic/549 9s ... [not run] No encryption support for btrfs
generic/550       [not run] No encryption support for btrfs
generic/572 6s ...  7s
generic/573 3s ...  3s
generic/574 38s ... [not run] btrfs-corrupt-block utility required, skipped this test
generic/575 10s ...  9s
generic/576 5s ... [not run] No encryption support for btrfs
generic/577 4s ...  4s
generic/579 25s ...  24s
generic/580 4s ... [not run] No encryption support for btrfs
generic/581 11s ... [not run] No encryption support for btrfs
generic/582 10s ... [not run] No encryption support for btrfs
generic/583 10s ... [not run] No encryption support for btrfs
generic/584       [not run] No encryption support for btrfs
generic/592 10s ... [not run] No encryption support for btrfs
generic/593 4s ... [not run] No encryption support for btrfs
generic/595 8s ... [not run] No encryption support for btrfs
generic/602 11s ... [not run] No encryption support for btrfs
generic/613 21s ... [not run] No encryption support for btrfs
generic/621 9s ... [not run] No encryption support for btrfs
generic/624 4s ...  4s
generic/625 4s ...  3s
generic/692 5s ...  5s
generic/693       [not run] No encryption support for btrfs
generic/739 18s ... [not run] No encryption support for btrfs
Ran: btrfs/277 btrfs/290 btrfs/291 generic/395 generic/396 generic/397 generic/398 generic/399 generic/419 generic/421 generic/429 generic/435 generic/440 generic/548 generic/549 generic/550 generic/572 generic/573 generic/574 generic/575 generic/576 generic/577 generic/579 generic/580 generic/581 generic/582 generic/583 generic/584 generic/592 generic/593 generic/595 generic/602 generic/613 generic/621 generic/624 generic/625 generic/692 generic/693 generic/739
Not run: btrfs/277 btrfs/290 btrfs/291 generic/395 generic/396 generic/397 generic/398 generic/399 generic/419 generic/421 generic/429 generic/435 generic/440 generic/548 generic/549 generic/550 generic/574 generic/576 generic/580 generic/581 generic/582 generic/583 generic/584 generic/592 generic/593 generic/595 generic/602 generic/613 generic/621 generic/693 generic/739
Passed all 39 tests

+ sudo ./check -g encrypt,verity
FSTYP         -- f2fs
PLATFORM      -- Linux/x86_64 localhost 6.16.0-rc1-gaa8ca50672ad #275 SMP PREEMPT_DYNAMIC Fri Jun  5 15:58:00 CEST 2015
MKFS_OPTIONS  -- /dev/nvme0n1p6
MOUNT_OPTIONS -- -o acl,user_xattr /dev/nvme0n1p6 /mnt/scratch

f2fs/002        22s
generic/395 4s ...  4s
generic/396 3s ...  3s
generic/397 4s ...  4s
generic/398 5s ...  5s
generic/399 35s ...  19s
generic/419 4s ...  4s
generic/421 4s ...  5s
generic/429 14s ...  14s
generic/435 23s ...  34s
generic/440 4s ...  5s
generic/548 9s ...  12s
generic/549 9s ...  12s
generic/550       [not run] encryption policy '-c 9 -n 9 -f 0' is unusable; probably missing kernel crypto API support
generic/572 7s ...  7s
generic/573 3s ...  4s
generic/574 38s ...  29s
generic/575 9s ...  10s
generic/576 5s ...  5s
generic/577 4s ...  4s
generic/579 24s ...  25s
generic/580 4s ...  3s
generic/581 11s ...  8s
generic/582 10s ...  9s
generic/583 10s ...  9s
generic/584       [not run] encryption policy '-c 9 -n 9 -v 2 -f 0' is unusable; probably missing kernel crypto API support
generic/592 10s ...  9s
generic/593 4s ...  3s
generic/595 8s ...  7s
generic/602 11s ...  9s
generic/613 21s ...  18s
generic/621 9s ...  8s
generic/624 4s ...  2s
generic/625 3s ...  3s
generic/692 5s ...  3s
generic/693       [not run] encryption policy '-c 1 -n 10 -v 2 -f 0' is unusable; probably missing kernel crypto API support
generic/739 18s ...  17s
Ran: f2fs/002 generic/395 generic/396 generic/397 generic/398 generic/399 generic/419 generic/421 generic/429 generic/435 generic/440 generic/548 generic/549 generic/550 generic/572 generic/573 generic/574 generic/575 generic/576 generic/577 generic/579 generic/580 generic/581 generic/582 generic/583 generic/584 generic/592 generic/593 generic/595 generic/602 generic/613 generic/621 generic/624 generic/625 generic/692 generic/693 generic/739
Not run: generic/550 generic/584 generic/693
Passed all 37 tests

---
Changes in v4:
- Stash offsets in struct fscrypt_operations and struct
  fsverity_operations.
- Link to v3: https://lore.kernel.org/20250722-work-inode-fscrypt-v3-0-bdc1033420a0@kernel.org

Changes in v3:
- Stash offsets in struct super_operations.
- Link to v2: https://lore.kernel.org/20250722-work-inode-fscrypt-v2-0-782f1fdeaeba@kernel.org

Changes in v2:
- First full implementation.
- Link to v1: https://lore.kernel.org/20250715-work-inode-fscrypt-v1-1-aa3ef6f44b6b@kernel.org

---
Christian Brauner (15):
      fs: add fscrypt offset
      fs/crypto: use accessors
      ext4: move fscrypt to filesystem inode
      ubifs: move fscrypt to filesystem inode
      f2fs: move fscrypt to filesystem inode
      ceph: move fscrypt to filesystem inode
      fs: drop i_crypt_info from struct inode
      fscrypt: rephrase documentation and comments
      fs: add fsverity offset
      fs/verity: use accessors
      btrfs: move fsverity to filesystem inode
      ext4: move fsverity to filesystem inode
      f2fs: move fsverity to filesystem inode
      fs: drop i_verity_info from struct inode
      fsverity: rephrase documentation and comments

 fs/btrfs/btrfs_inode.h       |  3 +++
 fs/btrfs/inode.c             |  3 +++
 fs/btrfs/verity.c            |  4 ++++
 fs/ceph/crypto.c             |  4 ++++
 fs/ceph/inode.c              |  1 +
 fs/ceph/super.h              |  1 +
 fs/crypto/bio.c              |  2 +-
 fs/crypto/crypto.c           |  8 ++++----
 fs/crypto/fname.c            |  8 ++++----
 fs/crypto/fscrypt_private.h  |  4 ++--
 fs/crypto/hooks.c            |  2 +-
 fs/crypto/inline_crypt.c     | 10 +++++-----
 fs/crypto/keysetup.c         | 44 +++++++++++++++++++++++++++-----------------
 fs/crypto/policy.c           |  6 +++---
 fs/ext4/crypto.c             |  4 ++++
 fs/ext4/ext4.h               |  8 ++++++++
 fs/ext4/super.c              |  6 ++++++
 fs/ext4/verity.c             |  4 ++++
 fs/f2fs/f2fs.h               |  6 ++++++
 fs/f2fs/super.c              | 10 ++++++++++
 fs/f2fs/verity.c             |  4 ++++
 fs/ubifs/crypto.c            |  4 ++++
 fs/ubifs/ubifs.h             |  3 +++
 fs/verity/enable.c           |  6 +++---
 fs/verity/fsverity_private.h |  9 +++++----
 fs/verity/open.c             | 25 ++++++++++++++++---------
 fs/verity/verify.c           |  2 +-
 include/linux/fs.h           | 10 ----------
 include/linux/fscrypt.h      | 42 ++++++++++++++++++++++++++++++++++++++----
 include/linux/fsverity.h     | 34 +++++++++++++++++++++++++++-------
 include/linux/netfs.h        |  7 +++++++
 31 files changed, 209 insertions(+), 75 deletions(-)
---
base-commit: 19272b37aa4f83ca52bdf9c16d5d81bdd1354494
change-id: 20250715-work-inode-fscrypt-2b63b276e793


^ permalink raw reply	[flat|nested] 67+ messages in thread

* [PATCH v4 01/15] fs: add fscrypt offset
  2025-07-23 10:57       ` [PATCH v4 00/15] Move fscrypt and fsverity out of " Christian Brauner
@ 2025-07-23 10:57         ` Christian Brauner
  2025-07-23 10:57         ` [PATCH v4 02/15] fs/crypto: use accessors Christian Brauner
                           ` (13 subsequent siblings)
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-23 10:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Store the offset of the fscrypt data pointer from struct inode in struct
fscrypt_operations. Both are embedded in the filesystem's private inode.

This will allow us to drop the fscrypt data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 include/linux/fscrypt.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 56fad33043d5..0ece9d443c82 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -61,6 +61,11 @@ struct fscrypt_name {
 
 /* Crypto operations for filesystems */
 struct fscrypt_operations {
+	/**
+	 * The offset of struct fscrypt_inode_info from struct inode embedded
+	 * in the filesystem's inode.
+	 */
+	ptrdiff_t inode_info_offs;
 
 	/*
 	 * If set, then fs/crypto/ will allocate a global bounce page pool the

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v4 02/15] fs/crypto: use accessors
  2025-07-23 10:57       ` [PATCH v4 00/15] Move fscrypt and fsverity out of " Christian Brauner
  2025-07-23 10:57         ` [PATCH v4 01/15] fs: add fscrypt offset Christian Brauner
@ 2025-07-23 10:57         ` Christian Brauner
  2025-07-25  0:29           ` Eric Biggers
  2025-07-25  4:01           ` Eric Biggers
  2025-07-23 10:57         ` [PATCH v4 03/15] ext4: move fscrypt to filesystem inode Christian Brauner
                           ` (12 subsequent siblings)
  14 siblings, 2 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-23 10:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Use accessor to get and set the fscrypt info from the filesystem.
They can be removed once all filesystems have been converted to make
room for fscrypt info in their own inodes.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/crypto/bio.c          |  2 +-
 fs/crypto/crypto.c       |  8 ++++----
 fs/crypto/fname.c        |  8 ++++----
 fs/crypto/hooks.c        |  2 +-
 fs/crypto/inline_crypt.c | 10 +++++-----
 fs/crypto/keysetup.c     | 12 +++++++++---
 fs/crypto/policy.c       |  6 +++---
 include/linux/fscrypt.h  | 36 ++++++++++++++++++++++++++++++++++++
 8 files changed, 63 insertions(+), 21 deletions(-)

diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index 0ad8c30b8fa5..73e46d2af511 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -111,7 +111,7 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
 int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
 			  sector_t pblk, unsigned int len)
 {
-	const struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 	const unsigned int du_bits = ci->ci_data_unit_bits;
 	const unsigned int du_size = 1U << du_bits;
 	const unsigned int du_per_page_bits = PAGE_SHIFT - du_bits;
diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
index b74b5937e695..c27ea8baaf52 100644
--- a/fs/crypto/crypto.c
+++ b/fs/crypto/crypto.c
@@ -181,7 +181,7 @@ struct page *fscrypt_encrypt_pagecache_blocks(struct folio *folio,
 		size_t len, size_t offs, gfp_t gfp_flags)
 {
 	const struct inode *inode = folio->mapping->host;
-	const struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 	const unsigned int du_bits = ci->ci_data_unit_bits;
 	const unsigned int du_size = 1U << du_bits;
 	struct page *ciphertext_page;
@@ -241,7 +241,7 @@ int fscrypt_encrypt_block_inplace(const struct inode *inode, struct page *page,
 {
 	if (WARN_ON_ONCE(inode->i_sb->s_cop->supports_subblock_data_units))
 		return -EOPNOTSUPP;
-	return fscrypt_crypt_data_unit(inode->i_crypt_info, FS_ENCRYPT,
+	return fscrypt_crypt_data_unit(fscrypt_get_inode_info_raw(inode), FS_ENCRYPT,
 				       lblk_num, page, page, len, offs,
 				       gfp_flags);
 }
@@ -265,7 +265,7 @@ int fscrypt_decrypt_pagecache_blocks(struct folio *folio, size_t len,
 				     size_t offs)
 {
 	const struct inode *inode = folio->mapping->host;
-	const struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 	const unsigned int du_bits = ci->ci_data_unit_bits;
 	const unsigned int du_size = 1U << du_bits;
 	u64 index = ((u64)folio->index << (PAGE_SHIFT - du_bits)) +
@@ -316,7 +316,7 @@ int fscrypt_decrypt_block_inplace(const struct inode *inode, struct page *page,
 {
 	if (WARN_ON_ONCE(inode->i_sb->s_cop->supports_subblock_data_units))
 		return -EOPNOTSUPP;
-	return fscrypt_crypt_data_unit(inode->i_crypt_info, FS_DECRYPT,
+	return fscrypt_crypt_data_unit(fscrypt_get_inode_info_raw(inode), FS_DECRYPT,
 				       lblk_num, page, page, len, offs,
 				       GFP_NOFS);
 }
diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c
index 010f9c0a4c2f..674b5fb11ac1 100644
--- a/fs/crypto/fname.c
+++ b/fs/crypto/fname.c
@@ -94,7 +94,7 @@ int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
 {
 	struct skcipher_request *req = NULL;
 	DECLARE_CRYPTO_WAIT(wait);
-	const struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 	struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;
 	union fscrypt_iv iv;
 	struct scatterlist sg;
@@ -151,7 +151,7 @@ static int fname_decrypt(const struct inode *inode,
 	struct skcipher_request *req = NULL;
 	DECLARE_CRYPTO_WAIT(wait);
 	struct scatterlist src_sg, dst_sg;
-	const struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 	struct crypto_skcipher *tfm = ci->ci_enc_key.tfm;
 	union fscrypt_iv iv;
 	int res;
@@ -293,7 +293,7 @@ bool __fscrypt_fname_encrypted_size(const union fscrypt_policy *policy,
 bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len,
 				  u32 max_len, u32 *encrypted_len_ret)
 {
-	return __fscrypt_fname_encrypted_size(&inode->i_crypt_info->ci_policy,
+	return __fscrypt_fname_encrypted_size(&fscrypt_get_inode_info_raw(inode)->ci_policy,
 					      orig_len, max_len,
 					      encrypted_len_ret);
 }
@@ -562,7 +562,7 @@ EXPORT_SYMBOL_GPL(fscrypt_match_name);
  */
 u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name)
 {
-	const struct fscrypt_inode_info *ci = dir->i_crypt_info;
+	const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(dir);
 
 	WARN_ON_ONCE(!ci->ci_dirhash_key_initialized);
 
diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c
index d8d5049b8fe1..61bbe7d46df4 100644
--- a/fs/crypto/hooks.c
+++ b/fs/crypto/hooks.c
@@ -197,7 +197,7 @@ int fscrypt_prepare_setflags(struct inode *inode,
 		err = fscrypt_require_key(inode);
 		if (err)
 			return err;
-		ci = inode->i_crypt_info;
+		ci = fscrypt_get_inode_info_raw(inode);
 		if (ci->ci_policy.version != FSCRYPT_POLICY_V2)
 			return -EINVAL;
 		mk = ci->ci_master_key;
diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c
index 1d008c440cb6..6c2784b8e67a 100644
--- a/fs/crypto/inline_crypt.c
+++ b/fs/crypto/inline_crypt.c
@@ -262,7 +262,7 @@ int fscrypt_derive_sw_secret(struct super_block *sb,
 
 bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode)
 {
-	return inode->i_crypt_info->ci_inlinecrypt;
+	return fscrypt_get_inode_info_raw(inode)->ci_inlinecrypt;
 }
 EXPORT_SYMBOL_GPL(__fscrypt_inode_uses_inline_crypto);
 
@@ -306,7 +306,7 @@ void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode,
 
 	if (!fscrypt_inode_uses_inline_crypto(inode))
 		return;
-	ci = inode->i_crypt_info;
+	ci = fscrypt_get_inode_info_raw(inode);
 
 	fscrypt_generate_dun(ci, first_lblk, dun);
 	bio_crypt_set_ctx(bio, ci->ci_enc_key.blk_key, dun, gfp_mask);
@@ -396,10 +396,10 @@ bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode,
 	 * uses the same pointer.  I.e., there's currently no need to support
 	 * merging requests where the keys are the same but the pointers differ.
 	 */
-	if (bc->bc_key != inode->i_crypt_info->ci_enc_key.blk_key)
+	if (bc->bc_key != fscrypt_get_inode_info_raw(inode)->ci_enc_key.blk_key)
 		return false;
 
-	fscrypt_generate_dun(inode->i_crypt_info, next_lblk, next_dun);
+	fscrypt_generate_dun(fscrypt_get_inode_info_raw(inode), next_lblk, next_dun);
 	return bio_crypt_dun_is_contiguous(bc, bio->bi_iter.bi_size, next_dun);
 }
 EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio);
@@ -501,7 +501,7 @@ u64 fscrypt_limit_io_blocks(const struct inode *inode, u64 lblk, u64 nr_blocks)
 	if (nr_blocks <= 1)
 		return nr_blocks;
 
-	ci = inode->i_crypt_info;
+	ci = fscrypt_get_inode_info_raw(inode);
 	if (!(fscrypt_policy_flags(&ci->ci_policy) &
 	      FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32))
 		return nr_blocks;
diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
index 0d71843af946..8fd89ce0b614 100644
--- a/fs/crypto/keysetup.c
+++ b/fs/crypto/keysetup.c
@@ -644,7 +644,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
 	 * fscrypt_get_inode_info().  I.e., here we publish ->i_crypt_info with
 	 * a RELEASE barrier so that other tasks can ACQUIRE it.
 	 */
-	if (cmpxchg_release(&inode->i_crypt_info, NULL, crypt_info) == NULL) {
+	if (fscrypt_set_inode_info(inode, crypt_info)) {
 		/*
 		 * We won the race and set ->i_crypt_info to our crypt_info.
 		 * Now link it into the master key's inode list.
@@ -797,8 +797,14 @@ EXPORT_SYMBOL_GPL(fscrypt_prepare_new_inode);
  */
 void fscrypt_put_encryption_info(struct inode *inode)
 {
-	put_crypt_info(inode->i_crypt_info);
-	inode->i_crypt_info = NULL;
+	struct fscrypt_inode_info **crypt_info;
+
+	if (inode->i_sb->s_cop->inode_info_offs)
+		crypt_info = fscrypt_addr(inode);
+	else
+		crypt_info = &inode->i_crypt_info;
+	put_crypt_info(*crypt_info);
+	*crypt_info = NULL;
 }
 EXPORT_SYMBOL(fscrypt_put_encryption_info);
 
diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c
index 701259991277..d9fb2898a14a 100644
--- a/fs/crypto/policy.c
+++ b/fs/crypto/policy.c
@@ -725,7 +725,7 @@ const union fscrypt_policy *fscrypt_policy_to_inherit(struct inode *dir)
 		err = fscrypt_require_key(dir);
 		if (err)
 			return ERR_PTR(err);
-		return &dir->i_crypt_info->ci_policy;
+		return &fscrypt_get_inode_info_raw(dir)->ci_policy;
 	}
 
 	return fscrypt_get_dummy_policy(dir->i_sb);
@@ -744,7 +744,7 @@ const union fscrypt_policy *fscrypt_policy_to_inherit(struct inode *dir)
  */
 int fscrypt_context_for_new_inode(void *ctx, struct inode *inode)
 {
-	struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 
 	BUILD_BUG_ON(sizeof(union fscrypt_context) !=
 			FSCRYPT_SET_CONTEXT_MAX_SIZE);
@@ -769,7 +769,7 @@ EXPORT_SYMBOL_GPL(fscrypt_context_for_new_inode);
  */
 int fscrypt_set_context(struct inode *inode, void *fs_data)
 {
-	struct fscrypt_inode_info *ci = inode->i_crypt_info;
+	struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
 	union fscrypt_context ctx;
 	int ctxsize;
 
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 0ece9d443c82..123871dd394c 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -200,6 +200,38 @@ struct fscrypt_operations {
 int fscrypt_d_revalidate(struct inode *dir, const struct qstr *name,
 			 struct dentry *dentry, unsigned int flags);
 
+static inline struct fscrypt_inode_info **fscrypt_addr(const struct inode *inode)
+{
+	return ((void *)inode + inode->i_sb->s_cop->inode_info_offs);
+}
+
+static inline bool fscrypt_set_inode_info(struct inode *inode,
+					  struct fscrypt_inode_info *crypt_info)
+{
+	void *p;
+
+	/*
+	 * For existing inodes, multiple tasks may race to set ->i_crypt_info.
+	 * So use cmpxchg_release().  This pairs with the smp_load_acquire() in
+	 * fscrypt_get_inode_info().  I.e., here we publish ->i_crypt_info with
+	 * a RELEASE barrier so that other tasks can ACQUIRE it.
+	 */
+
+	if (inode->i_sb->s_cop->inode_info_offs)
+		p = cmpxchg_release(fscrypt_addr(inode), NULL, crypt_info);
+	else
+		p = cmpxchg_release(&inode->i_crypt_info, NULL, crypt_info);
+	return p == NULL;
+}
+
+static inline struct fscrypt_inode_info *
+fscrypt_get_inode_info_raw(const struct inode *inode)
+{
+	if (inode->i_sb->s_cop->inode_info_offs)
+		return *fscrypt_addr(inode);
+	return inode->i_crypt_info;
+}
+
 static inline struct fscrypt_inode_info *
 fscrypt_get_inode_info(const struct inode *inode)
 {
@@ -209,6 +241,10 @@ fscrypt_get_inode_info(const struct inode *inode)
 	 * a RELEASE barrier.  We need to use smp_load_acquire() here to safely
 	 * ACQUIRE the memory the other task published.
 	 */
+
+	if (inode->i_sb->s_cop->inode_info_offs)
+		return smp_load_acquire(fscrypt_addr(inode));
+
 	return smp_load_acquire(&inode->i_crypt_info);
 }
 

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v4 03/15] ext4: move fscrypt to filesystem inode
  2025-07-23 10:57       ` [PATCH v4 00/15] Move fscrypt and fsverity out of " Christian Brauner
  2025-07-23 10:57         ` [PATCH v4 01/15] fs: add fscrypt offset Christian Brauner
  2025-07-23 10:57         ` [PATCH v4 02/15] fs/crypto: use accessors Christian Brauner
@ 2025-07-23 10:57         ` Christian Brauner
  2025-07-25  0:32           ` Eric Biggers
  2025-07-23 10:57         ` [PATCH v4 04/15] ubifs: " Christian Brauner
                           ` (11 subsequent siblings)
  14 siblings, 1 reply; 67+ messages in thread
From: Christian Brauner @ 2025-07-23 10:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fscrypt data pointer into the filesystem's private inode and record
the offset from the embedded struct inode.

This will allow us to drop the fscrypt data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/ext4/crypto.c | 4 ++++
 fs/ext4/ext4.h   | 4 ++++
 fs/ext4/super.c  | 3 +++
 3 files changed, 11 insertions(+)

diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
index 0a056d97e640..9837cbfa9159 100644
--- a/fs/ext4/crypto.c
+++ b/fs/ext4/crypto.c
@@ -227,6 +227,10 @@ static bool ext4_has_stable_inodes(struct super_block *sb)
 }
 
 const struct fscrypt_operations ext4_cryptops = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.inode_info_offs	= offsetof(struct ext4_inode_info, i_crypt_info) -
+				  offsetof(struct ext4_inode_info, vfs_inode),
+#endif
 	.needs_bounce_pages	= 1,
 	.has_32bit_inodes	= 1,
 	.supports_subblock_data_units = 1,
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 18373de980f2..75209a09b19f 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1197,6 +1197,10 @@ struct ext4_inode_info {
 	__u32 i_csum_seed;
 
 	kprojid_t i_projid;
+
+#ifdef CONFIG_FS_ENCRYPTION
+	struct fscrypt_inode_info *i_crypt_info;
+#endif
 };
 
 /*
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index c7d39da7e733..47c450c68a3b 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1412,6 +1412,9 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
 	INIT_WORK(&ei->i_rsv_conversion_work, ext4_end_io_rsv_work);
 	ext4_fc_init_inode(&ei->vfs_inode);
 	spin_lock_init(&ei->i_fc_lock);
+#ifdef CONFIG_FS_ENCRYPTION
+	ei->i_crypt_info = NULL;
+#endif
 	return &ei->vfs_inode;
 }
 

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v4 04/15] ubifs: move fscrypt to filesystem inode
  2025-07-23 10:57       ` [PATCH v4 00/15] Move fscrypt and fsverity out of " Christian Brauner
                           ` (2 preceding siblings ...)
  2025-07-23 10:57         ` [PATCH v4 03/15] ext4: move fscrypt to filesystem inode Christian Brauner
@ 2025-07-23 10:57         ` Christian Brauner
  2025-07-23 10:57         ` [PATCH v4 05/15] f2fs: " Christian Brauner
                           ` (10 subsequent siblings)
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-23 10:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fscrypt data pointer into the filesystem's private inode and record
the offset from the embedded struct inode.

This will allow us to drop the fscrypt data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/ubifs/crypto.c | 4 ++++
 fs/ubifs/ubifs.h  | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/fs/ubifs/crypto.c b/fs/ubifs/crypto.c
index 921f9033d0d2..9f34ed9d5356 100644
--- a/fs/ubifs/crypto.c
+++ b/fs/ubifs/crypto.c
@@ -88,6 +88,10 @@ int ubifs_decrypt(const struct inode *inode, struct ubifs_data_node *dn,
 }
 
 const struct fscrypt_operations ubifs_crypt_operations = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.inode_info_offs	= offsetof(struct ubifs_inode, i_crypt_info) -
+				  offsetof(struct ubifs_inode, vfs_inode),
+#endif
 	.legacy_key_prefix	= "ubifs:",
 	.get_context		= ubifs_crypt_get_context,
 	.set_context		= ubifs_crypt_set_context,
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 256dbaeeb0de..6c1baa11e073 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -416,6 +416,9 @@ struct ubifs_inode {
 	pgoff_t read_in_a_row;
 	int data_len;
 	void *data;
+#ifdef CONFIG_FS_ENCRYPTION
+	struct fscrypt_inode_info *i_crypt_info;
+#endif
 };
 
 /**

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v4 05/15] f2fs: move fscrypt to filesystem inode
  2025-07-23 10:57       ` [PATCH v4 00/15] Move fscrypt and fsverity out of " Christian Brauner
                           ` (3 preceding siblings ...)
  2025-07-23 10:57         ` [PATCH v4 04/15] ubifs: " Christian Brauner
@ 2025-07-23 10:57         ` Christian Brauner
  2025-07-23 10:57         ` [PATCH v4 06/15] ceph: " Christian Brauner
                           ` (9 subsequent siblings)
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-23 10:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fscrypt data pointer into the filesystem's private inode and record
the offset from the embedded struct inode.

This will allow us to drop the fscrypt data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/f2fs/f2fs.h  | 3 +++
 fs/f2fs/super.c | 7 +++++++
 2 files changed, 10 insertions(+)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 9333a22b9a01..53cb6b6fc70b 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -905,6 +905,9 @@ struct f2fs_inode_info {
 
 	unsigned int atomic_write_cnt;
 	loff_t original_i_size;		/* original i_size before atomic write */
+#ifdef CONFIG_FS_ENCRYPTION
+	struct fscrypt_inode_info *i_crypt_info; /* filesystem encryption info */
+#endif
 };
 
 static inline void get_read_extent_info(struct extent_info *ext,
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index bbf1dad6843f..dab4078c2f6a 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1453,6 +1453,9 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
 
 	/* Will be used by directory only */
 	fi->i_dir_level = F2FS_SB(sb)->dir_level;
+#ifdef CONFIG_FS_ENCRYPTION
+	fi->i_crypt_info = NULL;
+#endif
 
 	return &fi->vfs_inode;
 }
@@ -3326,6 +3329,10 @@ static struct block_device **f2fs_get_devices(struct super_block *sb,
 }
 
 static const struct fscrypt_operations f2fs_cryptops = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.inode_info_offs	= offsetof(struct f2fs_inode_info, i_crypt_info) -
+				  offsetof(struct f2fs_inode_info, vfs_inode),
+#endif
 	.needs_bounce_pages	= 1,
 	.has_32bit_inodes	= 1,
 	.supports_subblock_data_units = 1,

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v4 06/15] ceph: move fscrypt to filesystem inode
  2025-07-23 10:57       ` [PATCH v4 00/15] Move fscrypt and fsverity out of " Christian Brauner
                           ` (4 preceding siblings ...)
  2025-07-23 10:57         ` [PATCH v4 05/15] f2fs: " Christian Brauner
@ 2025-07-23 10:57         ` Christian Brauner
  2025-07-25  0:34           ` Eric Biggers
  2025-07-23 10:57         ` [PATCH v4 07/15] fs: drop i_crypt_info from struct inode Christian Brauner
                           ` (8 subsequent siblings)
  14 siblings, 1 reply; 67+ messages in thread
From: Christian Brauner @ 2025-07-23 10:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fscrypt data pointer into the filesystem's private inode and record
the offset from the embedded struct inode.

This will allow us to drop the fscrypt data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/ceph/crypto.c      | 4 ++++
 fs/ceph/inode.c       | 1 +
 fs/ceph/super.h       | 1 +
 include/linux/netfs.h | 7 +++++++
 4 files changed, 13 insertions(+)

diff --git a/fs/ceph/crypto.c b/fs/ceph/crypto.c
index 3b3c4d8d401e..9be1fb3f7b35 100644
--- a/fs/ceph/crypto.c
+++ b/fs/ceph/crypto.c
@@ -133,6 +133,10 @@ static const union fscrypt_policy *ceph_get_dummy_policy(struct super_block *sb)
 }
 
 static struct fscrypt_operations ceph_fscrypt_ops = {
+#ifdef CONFIG_FS_ENCRYPTION
+	.inode_info_offs	= offsetof(struct ceph_inode_info, i_crypt_info) -
+				  offsetof(struct ceph_inode_info, netfs),
+#endif
 	.needs_bounce_pages	= 1,
 	.get_context		= ceph_crypt_get_context,
 	.set_context		= ceph_crypt_set_context,
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 06cd2963e41e..73dd882ad018 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -665,6 +665,7 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
 	ci->i_work_mask = 0;
 	memset(&ci->i_btime, '\0', sizeof(ci->i_btime));
 #ifdef CONFIG_FS_ENCRYPTION
+	ci->i_crypt_info = NULL;
 	ci->fscrypt_auth = NULL;
 	ci->fscrypt_auth_len = 0;
 #endif
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index bb0db0cc8003..d55e20d61e22 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -463,6 +463,7 @@ struct ceph_inode_info {
 	unsigned long  i_work_mask;
 
 #ifdef CONFIG_FS_ENCRYPTION
+	struct fscrypt_inode_info *i_crypt_info;
 	u32 fscrypt_auth_len;
 	u32 fscrypt_file_len;
 	u8 *fscrypt_auth;
diff --git a/include/linux/netfs.h b/include/linux/netfs.h
index 065c17385e53..66f9ae1995e4 100644
--- a/include/linux/netfs.h
+++ b/include/linux/netfs.h
@@ -73,6 +73,13 @@ struct netfs_inode {
 #define NETFS_ICTX_SINGLE_NO_UPLOAD 4		/* Monolithic payload, cache but no upload */
 };
 
+/*
+ * struct inode must be the first member so we can easily calculate offsets for
+ * e.g., fscrypt or fsverity when embedded in filesystem specific inodes.
+ */
+static_assert(__same_type(((struct netfs_inode *)NULL)->inode, struct inode));
+static_assert(offsetof(struct netfs_inode, inode) == 0);
+
 /*
  * A netfs group - for instance a ceph snap.  This is marked on dirty pages and
  * pages marked with a group must be flushed before they can be written under

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v4 07/15] fs: drop i_crypt_info from struct inode
  2025-07-23 10:57       ` [PATCH v4 00/15] Move fscrypt and fsverity out of " Christian Brauner
                           ` (5 preceding siblings ...)
  2025-07-23 10:57         ` [PATCH v4 06/15] ceph: " Christian Brauner
@ 2025-07-23 10:57         ` Christian Brauner
  2025-07-25  0:38           ` Eric Biggers
  2025-07-23 10:57         ` [PATCH v4 08/15] fscrypt: rephrase documentation and comments Christian Brauner
                           ` (7 subsequent siblings)
  14 siblings, 1 reply; 67+ messages in thread
From: Christian Brauner @ 2025-07-23 10:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Now that all filesystems store the fscrypt data pointer in their private
inode, drop the data pointer from struct inode itself freeing up 8
bytes.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/crypto/keysetup.c    |  9 +++++----
 include/linux/fs.h      |  5 -----
 include/linux/fscrypt.h | 23 +++++++----------------
 3 files changed, 12 insertions(+), 25 deletions(-)

diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
index 8fd89ce0b614..352d0cfda17d 100644
--- a/fs/crypto/keysetup.c
+++ b/fs/crypto/keysetup.c
@@ -799,10 +799,11 @@ void fscrypt_put_encryption_info(struct inode *inode)
 {
 	struct fscrypt_inode_info **crypt_info;
 
-	if (inode->i_sb->s_cop->inode_info_offs)
-		crypt_info = fscrypt_addr(inode);
-	else
-		crypt_info = &inode->i_crypt_info;
+	if (!IS_ENCRYPTED(inode))
+		return;
+	VFS_WARN_ON_ONCE(!inode->i_sb->s_cop);
+	VFS_WARN_ON_ONCE(!inode->i_sb->s_cop->inode_info_offs);
+	crypt_info = fscrypt_addr(inode);
 	put_crypt_info(*crypt_info);
 	*crypt_info = NULL;
 }
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 96c7925a6551..b76a10fc765b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -72,7 +72,6 @@ struct swap_info_struct;
 struct seq_file;
 struct workqueue_struct;
 struct iov_iter;
-struct fscrypt_inode_info;
 struct fscrypt_operations;
 struct fsverity_info;
 struct fsverity_operations;
@@ -778,10 +777,6 @@ struct inode {
 	struct fsnotify_mark_connector __rcu	*i_fsnotify_marks;
 #endif
 
-#ifdef CONFIG_FS_ENCRYPTION
-	struct fscrypt_inode_info	*i_crypt_info;
-#endif
-
 #ifdef CONFIG_FS_VERITY
 	struct fsverity_info	*i_verity_info;
 #endif
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 123871dd394c..a62879456873 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -208,28 +208,21 @@ static inline struct fscrypt_inode_info **fscrypt_addr(const struct inode *inode
 static inline bool fscrypt_set_inode_info(struct inode *inode,
 					  struct fscrypt_inode_info *crypt_info)
 {
-	void *p;
-
 	/*
 	 * For existing inodes, multiple tasks may race to set ->i_crypt_info.
 	 * So use cmpxchg_release().  This pairs with the smp_load_acquire() in
 	 * fscrypt_get_inode_info().  I.e., here we publish ->i_crypt_info with
 	 * a RELEASE barrier so that other tasks can ACQUIRE it.
 	 */
-
-	if (inode->i_sb->s_cop->inode_info_offs)
-		p = cmpxchg_release(fscrypt_addr(inode), NULL, crypt_info);
-	else
-		p = cmpxchg_release(&inode->i_crypt_info, NULL, crypt_info);
-	return p == NULL;
+	return cmpxchg_release(fscrypt_addr(inode), NULL, crypt_info) == NULL;
 }
 
 static inline struct fscrypt_inode_info *
 fscrypt_get_inode_info_raw(const struct inode *inode)
 {
-	if (inode->i_sb->s_cop->inode_info_offs)
-		return *fscrypt_addr(inode);
-	return inode->i_crypt_info;
+	VFS_WARN_ON_ONCE(!inode->i_sb->s_cop);
+	VFS_WARN_ON_ONCE(!inode->i_sb->s_cop->inode_info_offs);
+	return *fscrypt_addr(inode);
 }
 
 static inline struct fscrypt_inode_info *
@@ -241,11 +234,9 @@ fscrypt_get_inode_info(const struct inode *inode)
 	 * a RELEASE barrier.  We need to use smp_load_acquire() here to safely
 	 * ACQUIRE the memory the other task published.
 	 */
-
-	if (inode->i_sb->s_cop->inode_info_offs)
-		return smp_load_acquire(fscrypt_addr(inode));
-
-	return smp_load_acquire(&inode->i_crypt_info);
+	VFS_WARN_ON_ONCE(!inode->i_sb->s_cop);
+	VFS_WARN_ON_ONCE(!inode->i_sb->s_cop->inode_info_offs);
+	return smp_load_acquire(fscrypt_addr(inode));
 }
 
 /**

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v4 08/15] fscrypt: rephrase documentation and comments
  2025-07-23 10:57       ` [PATCH v4 00/15] Move fscrypt and fsverity out of " Christian Brauner
                           ` (6 preceding siblings ...)
  2025-07-23 10:57         ` [PATCH v4 07/15] fs: drop i_crypt_info from struct inode Christian Brauner
@ 2025-07-23 10:57         ` Christian Brauner
  2025-07-25  0:35           ` Eric Biggers
  2025-07-23 10:57         ` [PATCH v4 09/15] fs: add fsverity offset Christian Brauner
                           ` (6 subsequent siblings)
  14 siblings, 1 reply; 67+ messages in thread
From: Christian Brauner @ 2025-07-23 10:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Now that we moved fscrypt out of struct inode update the comments to not
imply that it's still located in there.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/crypto/fscrypt_private.h |  4 ++--
 fs/crypto/keysetup.c        | 31 +++++++++++++++++--------------
 include/linux/fscrypt.h     | 16 +++++++++-------
 3 files changed, 28 insertions(+), 23 deletions(-)

diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
index c1d92074b65c..691009df5689 100644
--- a/fs/crypto/fscrypt_private.h
+++ b/fs/crypto/fscrypt_private.h
@@ -231,8 +231,8 @@ struct fscrypt_prepared_key {
  * fscrypt_inode_info - the "encryption key" for an inode
  *
  * When an encrypted file's key is made available, an instance of this struct is
- * allocated and stored in ->i_crypt_info.  Once created, it remains until the
- * inode is evicted.
+ * allocated and stored in the inode's fscrypt info.  Once created, it remains
+ * until the inode is evicted.
  */
 struct fscrypt_inode_info {
 
diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
index 352d0cfda17d..86bf7724dd27 100644
--- a/fs/crypto/keysetup.c
+++ b/fs/crypto/keysetup.c
@@ -639,15 +639,16 @@ fscrypt_setup_encryption_info(struct inode *inode,
 		goto out;
 
 	/*
-	 * For existing inodes, multiple tasks may race to set ->i_crypt_info.
-	 * So use cmpxchg_release().  This pairs with the smp_load_acquire() in
-	 * fscrypt_get_inode_info().  I.e., here we publish ->i_crypt_info with
-	 * a RELEASE barrier so that other tasks can ACQUIRE it.
+	 * For existing inodes, multiple tasks may race to set the inode's
+	 * fscrypt info. So use cmpxchg_release().  This pairs with the
+	 * smp_load_acquire() in fscrypt_get_inode_info().  I.e., here we
+	 * publish the inode's fscrypt info with a RELEASE barrier so that
+	 * other tasks can ACQUIRE it.
 	 */
 	if (fscrypt_set_inode_info(inode, crypt_info)) {
 		/*
-		 * We won the race and set ->i_crypt_info to our crypt_info.
-		 * Now link it into the master key's inode list.
+		 * We won the race and set the inode's fscrypt info to our
+		 * crypt_info. Now link it into the master key's inode list.
 		 */
 		if (mk) {
 			crypt_info->ci_master_key = mk;
@@ -678,14 +679,16 @@ fscrypt_setup_encryption_info(struct inode *inode,
  *		       %false unless the operation being performed is needed in
  *		       order for files (or directories) to be deleted.
  *
- * Set up ->i_crypt_info, if it hasn't already been done.
+ * Set up the inode's fscrypt info, if it hasn't already been done.
  *
- * Note: unless ->i_crypt_info is already set, this isn't %GFP_NOFS-safe.  So
- * generally this shouldn't be called from within a filesystem transaction.
+ * Note: unless the inode's fscrypt info is already set, this isn't
+ * %GFP_NOFS-safe.  So generally this shouldn't be called from within a
+ * filesystem transaction.
  *
- * Return: 0 if ->i_crypt_info was set or was already set, *or* if the
- *	   encryption key is unavailable.  (Use fscrypt_has_encryption_key() to
- *	   distinguish these cases.)  Also can return another -errno code.
+ * Return: 0 if the inode's fscrypt info was set or was already set, *or* if
+ *         the encryption key is unavailable.  (Use
+ *         fscrypt_has_encryption_key() to distinguish these cases.)  Also can
+ *         return another -errno code.
  */
 int fscrypt_get_encryption_info(struct inode *inode, bool allow_unsupported)
 {
@@ -738,9 +741,9 @@ int fscrypt_get_encryption_info(struct inode *inode, bool allow_unsupported)
  *	   ->i_ino doesn't need to be set yet.
  * @encrypt_ret: (output) set to %true if the new inode will be encrypted
  *
- * If the directory is encrypted, set up its ->i_crypt_info in preparation for
+ * If the directory is encrypted, set up its fscrypt info in preparation for
  * encrypting the name of the new file.  Also, if the new inode will be
- * encrypted, set up its ->i_crypt_info and set *encrypt_ret=true.
+ * encrypted, set up its fscrypt info 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.  For this reason, ->i_ino
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index a62879456873..9a333fd6fe7a 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -209,10 +209,11 @@ static inline bool fscrypt_set_inode_info(struct inode *inode,
 					  struct fscrypt_inode_info *crypt_info)
 {
 	/*
-	 * For existing inodes, multiple tasks may race to set ->i_crypt_info.
-	 * So use cmpxchg_release().  This pairs with the smp_load_acquire() in
-	 * fscrypt_get_inode_info().  I.e., here we publish ->i_crypt_info with
-	 * a RELEASE barrier so that other tasks can ACQUIRE it.
+	 * For existing inodes, multiple tasks may race to set up the inode's
+	 * fscrypt info. So use cmpxchg_release().  This pairs with the
+	 * smp_load_acquire() in fscrypt_get_inode_info().  I.e., here we
+	 * publish the inode's fscrypt info with a RELEASE barrier so that
+	 * other tasks can ACQUIRE it.
 	 */
 	return cmpxchg_release(fscrypt_addr(inode), NULL, crypt_info) == NULL;
 }
@@ -230,9 +231,10 @@ fscrypt_get_inode_info(const struct inode *inode)
 {
 	/*
 	 * Pairs with the cmpxchg_release() in fscrypt_setup_encryption_info().
-	 * I.e., another task may publish ->i_crypt_info concurrently, executing
-	 * a RELEASE barrier.  We need to use smp_load_acquire() here to safely
-	 * ACQUIRE the memory the other task published.
+	 * I.e., another task may publish the inode's fscrypt info
+	 * concurrently, executing a RELEASE barrier.  We need to use
+	 * smp_load_acquire() here to safely ACQUIRE the memory the other task
+	 * published.
 	 */
 	VFS_WARN_ON_ONCE(!inode->i_sb->s_cop);
 	VFS_WARN_ON_ONCE(!inode->i_sb->s_cop->inode_info_offs);

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v4 09/15] fs: add fsverity offset
  2025-07-23 10:57       ` [PATCH v4 00/15] Move fscrypt and fsverity out of " Christian Brauner
                           ` (7 preceding siblings ...)
  2025-07-23 10:57         ` [PATCH v4 08/15] fscrypt: rephrase documentation and comments Christian Brauner
@ 2025-07-23 10:57         ` Christian Brauner
  2025-07-25  0:45           ` Eric Biggers
  2025-07-23 10:57         ` [PATCH v4 10/15] fs/verity: use accessors Christian Brauner
                           ` (5 subsequent siblings)
  14 siblings, 1 reply; 67+ messages in thread
From: Christian Brauner @ 2025-07-23 10:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Store the offset of the fsverity data pointer from struct inode in
struct super_operations. Both are embedded in the filesystem's private
inode.

This will allow us to drop the fsverity data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 include/linux/fsverity.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h
index 1eb7eae580be..85831f36e2f8 100644
--- a/include/linux/fsverity.h
+++ b/include/linux/fsverity.h
@@ -28,6 +28,11 @@
 
 /* Verity operations for filesystems */
 struct fsverity_operations {
+	/**
+	 * The offset of struct fsverity_info from struct inode embedded in
+	 * the filesystem's inode.
+	 */
+	ptrdiff_t inode_info_offs;
 
 	/**
 	 * Begin enabling verity on the given file.

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v4 10/15] fs/verity: use accessors
  2025-07-23 10:57       ` [PATCH v4 00/15] Move fscrypt and fsverity out of " Christian Brauner
                           ` (8 preceding siblings ...)
  2025-07-23 10:57         ` [PATCH v4 09/15] fs: add fsverity offset Christian Brauner
@ 2025-07-23 10:57         ` Christian Brauner
  2025-07-23 10:57         ` [PATCH v4 11/15] btrfs: move fsverity to filesystem inode Christian Brauner
                           ` (4 subsequent siblings)
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-23 10:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Use accessor to get and set the verity info from the filesystem.
They can be removed once all filesystems have been converted to make
room for verity info in their own inodes.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/verity/open.c         | 19 ++++++++++++++++---
 fs/verity/verify.c       |  2 +-
 include/linux/fsverity.h | 12 +++++++++++-
 3 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/fs/verity/open.c b/fs/verity/open.c
index fdeb95eca3af..a4d7388e2f71 100644
--- a/fs/verity/open.c
+++ b/fs/verity/open.c
@@ -250,13 +250,20 @@ struct fsverity_info *fsverity_create_info(const struct inode *inode,
 
 void fsverity_set_info(struct inode *inode, struct fsverity_info *vi)
 {
+	void *p;
+
 	/*
 	 * Multiple tasks may race to set ->i_verity_info, so use
 	 * cmpxchg_release().  This pairs with the smp_load_acquire() in
 	 * fsverity_get_info().  I.e., here we publish ->i_verity_info with a
 	 * RELEASE barrier so that other tasks can ACQUIRE it.
 	 */
-	if (cmpxchg_release(&inode->i_verity_info, NULL, vi) != NULL) {
+
+	if (inode->i_sb->s_vop->inode_info_offs)
+		p = cmpxchg_release(fsverity_addr(inode), NULL, vi);
+	else
+		p = cmpxchg_release(&inode->i_verity_info, NULL, vi);
+	if (p != NULL) {
 		/* Lost the race, so free the fsverity_info we allocated. */
 		fsverity_free_info(vi);
 		/*
@@ -402,8 +409,14 @@ EXPORT_SYMBOL_GPL(__fsverity_prepare_setattr);
 
 void __fsverity_cleanup_inode(struct inode *inode)
 {
-	fsverity_free_info(inode->i_verity_info);
-	inode->i_verity_info = NULL;
+	struct fsverity_info **vi;
+
+	if (inode->i_sb->s_vop->inode_info_offs)
+		vi = fsverity_addr(inode);
+	else
+		vi = &inode->i_verity_info;
+	fsverity_free_info(*vi);
+	*vi = NULL;
 }
 EXPORT_SYMBOL_GPL(__fsverity_cleanup_inode);
 
diff --git a/fs/verity/verify.c b/fs/verity/verify.c
index 4fcad0825a12..a9c2f5c86991 100644
--- a/fs/verity/verify.c
+++ b/fs/verity/verify.c
@@ -247,7 +247,7 @@ verify_data_blocks(struct folio *data_folio, size_t len, size_t offset,
 		   unsigned long max_ra_pages)
 {
 	struct inode *inode = data_folio->mapping->host;
-	struct fsverity_info *vi = inode->i_verity_info;
+	struct fsverity_info *vi = fsverity_get_info(inode);
 	const unsigned int block_size = vi->tree_params.block_size;
 	u64 pos = (u64)data_folio->index << PAGE_SHIFT;
 
diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h
index 85831f36e2f8..75ff6c9c50ef 100644
--- a/include/linux/fsverity.h
+++ b/include/linux/fsverity.h
@@ -129,14 +129,24 @@ struct fsverity_operations {
 
 #ifdef CONFIG_FS_VERITY
 
+static inline struct fsverity_info **fsverity_addr(const struct inode *inode)
+{
+	return ((void *)inode + inode->i_sb->s_vop->inode_info_offs);
+}
+
 static inline struct fsverity_info *fsverity_get_info(const struct inode *inode)
 {
+	if (!inode->i_sb->s_vop)
+		return NULL;
+
 	/*
 	 * Pairs with the cmpxchg_release() in fsverity_set_info().
 	 * I.e., another task may publish ->i_verity_info concurrently,
 	 * executing a RELEASE barrier.  We need to use smp_load_acquire() here
 	 * to safely ACQUIRE the memory the other task published.
 	 */
+	if (inode->i_sb->s_vop->inode_info_offs)
+		return smp_load_acquire(fsverity_addr(inode));
 	return smp_load_acquire(&inode->i_verity_info);
 }
 
@@ -165,7 +175,7 @@ void __fsverity_cleanup_inode(struct inode *inode);
  */
 static inline void fsverity_cleanup_inode(struct inode *inode)
 {
-	if (inode->i_verity_info)
+	if (IS_VERITY(inode))
 		__fsverity_cleanup_inode(inode);
 }
 

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v4 11/15] btrfs: move fsverity to filesystem inode
  2025-07-23 10:57       ` [PATCH v4 00/15] Move fscrypt and fsverity out of " Christian Brauner
                           ` (9 preceding siblings ...)
  2025-07-23 10:57         ` [PATCH v4 10/15] fs/verity: use accessors Christian Brauner
@ 2025-07-23 10:57         ` Christian Brauner
  2025-07-23 10:57         ` [PATCH v4 12/15] ext4: " Christian Brauner
                           ` (3 subsequent siblings)
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-23 10:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fsverity data pointer into the filesystem's private inode and
record the offset from the embedded struct inode.

This will allow us to drop the fsverity data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/btrfs/btrfs_inode.h | 3 +++
 fs/btrfs/inode.c       | 3 +++
 fs/btrfs/verity.c      | 4 ++++
 3 files changed, 10 insertions(+)

diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h
index a79fa0726f1d..45a9221cf6cc 100644
--- a/fs/btrfs/btrfs_inode.h
+++ b/fs/btrfs/btrfs_inode.h
@@ -339,6 +339,9 @@ struct btrfs_inode {
 
 	struct rw_semaphore i_mmap_lock;
 	struct inode vfs_inode;
+#ifdef CONFIG_FS_VERITY
+	struct fsverity_info *i_verity_info;
+#endif
 };
 
 static inline u64 btrfs_get_first_dir_index_to_log(const struct btrfs_inode *inode)
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index c0c778243bf1..a5c39e93a6cd 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -7873,6 +7873,9 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
 	INIT_LIST_HEAD(&ei->delalloc_inodes);
 	INIT_LIST_HEAD(&ei->delayed_iput);
 	init_rwsem(&ei->i_mmap_lock);
+#ifdef CONFIG_FS_VERITY
+	ei->i_verity_info = NULL;
+#endif
 
 	return inode;
 }
diff --git a/fs/btrfs/verity.c b/fs/btrfs/verity.c
index b7a96a005487..487d6d00eff3 100644
--- a/fs/btrfs/verity.c
+++ b/fs/btrfs/verity.c
@@ -802,6 +802,10 @@ static int btrfs_write_merkle_tree_block(struct inode *inode, const void *buf,
 }
 
 const struct fsverity_operations btrfs_verityops = {
+#ifdef CONFIG_FS_VERITY
+	.inode_info_offs	= offsetof(struct btrfs_inode, i_verity_info) -
+				  offsetof(struct btrfs_inode, vfs_inode),
+#endif
 	.begin_enable_verity     = btrfs_begin_enable_verity,
 	.end_enable_verity       = btrfs_end_enable_verity,
 	.get_verity_descriptor   = btrfs_get_verity_descriptor,

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v4 12/15] ext4: move fsverity to filesystem inode
  2025-07-23 10:57       ` [PATCH v4 00/15] Move fscrypt and fsverity out of " Christian Brauner
                           ` (10 preceding siblings ...)
  2025-07-23 10:57         ` [PATCH v4 11/15] btrfs: move fsverity to filesystem inode Christian Brauner
@ 2025-07-23 10:57         ` Christian Brauner
  2025-07-23 10:57         ` [PATCH v4 13/15] f2fs: " Christian Brauner
                           ` (2 subsequent siblings)
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-23 10:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fsverity data pointer into the filesystem's private inode and
record the offset from the embedded struct inode.

This will allow us to drop the fsverity data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/ext4/ext4.h   | 4 ++++
 fs/ext4/super.c  | 3 +++
 fs/ext4/verity.c | 4 ++++
 3 files changed, 11 insertions(+)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 75209a09b19f..d7befc610ca2 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1201,6 +1201,10 @@ struct ext4_inode_info {
 #ifdef CONFIG_FS_ENCRYPTION
 	struct fscrypt_inode_info *i_crypt_info;
 #endif
+
+#ifdef CONFIG_FS_VERITY
+	struct fsverity_info *i_verity_info;
+#endif
 };
 
 /*
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 47c450c68a3b..ff4070df5d77 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1414,6 +1414,9 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
 	spin_lock_init(&ei->i_fc_lock);
 #ifdef CONFIG_FS_ENCRYPTION
 	ei->i_crypt_info = NULL;
+#endif
+#ifdef CONFIG_FS_VERITY
+	ei->i_verity_info = NULL;
 #endif
 	return &ei->vfs_inode;
 }
diff --git a/fs/ext4/verity.c b/fs/ext4/verity.c
index d9203228ce97..70d9c6c73313 100644
--- a/fs/ext4/verity.c
+++ b/fs/ext4/verity.c
@@ -389,6 +389,10 @@ static int ext4_write_merkle_tree_block(struct inode *inode, const void *buf,
 }
 
 const struct fsverity_operations ext4_verityops = {
+#ifdef CONFIG_FS_VERITY
+	.inode_info_offs	= offsetof(struct ext4_inode_info, i_verity_info) -
+				  offsetof(struct ext4_inode_info, vfs_inode),
+#endif
 	.begin_enable_verity	= ext4_begin_enable_verity,
 	.end_enable_verity	= ext4_end_enable_verity,
 	.get_verity_descriptor	= ext4_get_verity_descriptor,

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v4 13/15] f2fs: move fsverity to filesystem inode
  2025-07-23 10:57       ` [PATCH v4 00/15] Move fscrypt and fsverity out of " Christian Brauner
                           ` (11 preceding siblings ...)
  2025-07-23 10:57         ` [PATCH v4 12/15] ext4: " Christian Brauner
@ 2025-07-23 10:57         ` Christian Brauner
  2025-07-23 10:57         ` [PATCH v4 14/15] fs: drop i_verity_info from struct inode Christian Brauner
  2025-07-23 10:57         ` [PATCH v4 15/15] fsverity: rephrase documentation and comments Christian Brauner
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-23 10:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Move fsverity data pointer into the filesystem's private inode and
record the offset from the embedded struct inode.

This will allow us to drop the fsverity data pointer from struct inode
itself and move it into the filesystem's inode.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/f2fs/f2fs.h   | 3 +++
 fs/f2fs/super.c  | 3 +++
 fs/f2fs/verity.c | 4 ++++
 3 files changed, 10 insertions(+)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 53cb6b6fc70b..f4d04f6fd680 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -908,6 +908,9 @@ struct f2fs_inode_info {
 #ifdef CONFIG_FS_ENCRYPTION
 	struct fscrypt_inode_info *i_crypt_info; /* filesystem encryption info */
 #endif
+#ifdef CONFIG_FS_VERITY
+	struct fsverity_info *i_verity_info;
+#endif
 };
 
 static inline void get_read_extent_info(struct extent_info *ext,
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index dab4078c2f6a..628469ee2b28 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1456,6 +1456,9 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
 #ifdef CONFIG_FS_ENCRYPTION
 	fi->i_crypt_info = NULL;
 #endif
+#ifdef CONFIG_FS_VERITY
+	fi->i_verity_info = NULL;
+#endif
 
 	return &fi->vfs_inode;
 }
diff --git a/fs/f2fs/verity.c b/fs/f2fs/verity.c
index 2287f238ae09..1529fe072ff9 100644
--- a/fs/f2fs/verity.c
+++ b/fs/f2fs/verity.c
@@ -287,6 +287,10 @@ static int f2fs_write_merkle_tree_block(struct inode *inode, const void *buf,
 }
 
 const struct fsverity_operations f2fs_verityops = {
+#ifdef CONFIG_FS_VERITY
+	.inode_info_offs	= offsetof(struct f2fs_inode_info, i_verity_info) -
+				  offsetof(struct f2fs_inode_info, vfs_inode),
+#endif
 	.begin_enable_verity	= f2fs_begin_enable_verity,
 	.end_enable_verity	= f2fs_end_enable_verity,
 	.get_verity_descriptor	= f2fs_get_verity_descriptor,

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v4 14/15] fs: drop i_verity_info from struct inode
  2025-07-23 10:57       ` [PATCH v4 00/15] Move fscrypt and fsverity out of " Christian Brauner
                           ` (12 preceding siblings ...)
  2025-07-23 10:57         ` [PATCH v4 13/15] f2fs: " Christian Brauner
@ 2025-07-23 10:57         ` Christian Brauner
  2025-07-25  0:43           ` Eric Biggers
  2025-07-23 10:57         ` [PATCH v4 15/15] fsverity: rephrase documentation and comments Christian Brauner
  14 siblings, 1 reply; 67+ messages in thread
From: Christian Brauner @ 2025-07-23 10:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Now that all filesystems store the fsverity data pointer in their
private inode, drop the data pointer from struct inode itself freeing up
8 bytes.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/verity/open.c         | 18 ++++++------------
 include/linux/fs.h       |  5 -----
 include/linux/fsverity.h | 11 +++++++----
 3 files changed, 13 insertions(+), 21 deletions(-)

diff --git a/fs/verity/open.c b/fs/verity/open.c
index a4d7388e2f71..0dcd33f00361 100644
--- a/fs/verity/open.c
+++ b/fs/verity/open.c
@@ -250,20 +250,15 @@ struct fsverity_info *fsverity_create_info(const struct inode *inode,
 
 void fsverity_set_info(struct inode *inode, struct fsverity_info *vi)
 {
-	void *p;
-
 	/*
 	 * Multiple tasks may race to set ->i_verity_info, so use
 	 * cmpxchg_release().  This pairs with the smp_load_acquire() in
 	 * fsverity_get_info().  I.e., here we publish ->i_verity_info with a
 	 * RELEASE barrier so that other tasks can ACQUIRE it.
 	 */
-
-	if (inode->i_sb->s_vop->inode_info_offs)
-		p = cmpxchg_release(fsverity_addr(inode), NULL, vi);
-	else
-		p = cmpxchg_release(&inode->i_verity_info, NULL, vi);
-	if (p != NULL) {
+	VFS_WARN_ON_ONCE(!inode->i_sb->s_vop);
+	VFS_WARN_ON_ONCE(!inode->i_sb->s_vop->inode_info_offs);
+	if (cmpxchg_release(fsverity_addr(inode), NULL, vi) != NULL) {
 		/* Lost the race, so free the fsverity_info we allocated. */
 		fsverity_free_info(vi);
 		/*
@@ -411,10 +406,9 @@ void __fsverity_cleanup_inode(struct inode *inode)
 {
 	struct fsverity_info **vi;
 
-	if (inode->i_sb->s_vop->inode_info_offs)
-		vi = fsverity_addr(inode);
-	else
-		vi = &inode->i_verity_info;
+	VFS_WARN_ON_ONCE(!inode->i_sb->s_vop);
+	VFS_WARN_ON_ONCE(!inode->i_sb->s_vop->inode_info_offs);
+	vi = fsverity_addr(inode);
 	fsverity_free_info(*vi);
 	*vi = NULL;
 }
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b76a10fc765b..cb249b6646f3 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -73,7 +73,6 @@ struct seq_file;
 struct workqueue_struct;
 struct iov_iter;
 struct fscrypt_operations;
-struct fsverity_info;
 struct fsverity_operations;
 struct fsnotify_mark_connector;
 struct fsnotify_sb_info;
@@ -777,10 +776,6 @@ struct inode {
 	struct fsnotify_mark_connector __rcu	*i_fsnotify_marks;
 #endif
 
-#ifdef CONFIG_FS_VERITY
-	struct fsverity_info	*i_verity_info;
-#endif
-
 	void			*i_private; /* fs or device private pointer */
 } __randomize_layout;
 
diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h
index 75ff6c9c50ef..0ee5b2fea389 100644
--- a/include/linux/fsverity.h
+++ b/include/linux/fsverity.h
@@ -136,7 +136,11 @@ static inline struct fsverity_info **fsverity_addr(const struct inode *inode)
 
 static inline struct fsverity_info *fsverity_get_info(const struct inode *inode)
 {
-	if (!inode->i_sb->s_vop)
+	/*
+	 * We're called from fsverity_active() which might be called on
+	 * inodes from filesystems that don't support fsverity at all.
+	 */
+	if (likely(!inode->i_sb->s_vop))
 		return NULL;
 
 	/*
@@ -145,9 +149,8 @@ static inline struct fsverity_info *fsverity_get_info(const struct inode *inode)
 	 * executing a RELEASE barrier.  We need to use smp_load_acquire() here
 	 * to safely ACQUIRE the memory the other task published.
 	 */
-	if (inode->i_sb->s_vop->inode_info_offs)
-		return smp_load_acquire(fsverity_addr(inode));
-	return smp_load_acquire(&inode->i_verity_info);
+	VFS_WARN_ON_ONCE(!inode->i_sb->s_vop->inode_info_offs);
+	return smp_load_acquire(fsverity_addr(inode));
 }
 
 /* enable.c */

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* [PATCH v4 15/15] fsverity: rephrase documentation and comments
  2025-07-23 10:57       ` [PATCH v4 00/15] Move fscrypt and fsverity out of " Christian Brauner
                           ` (13 preceding siblings ...)
  2025-07-23 10:57         ` [PATCH v4 14/15] fs: drop i_verity_info from struct inode Christian Brauner
@ 2025-07-23 10:57         ` Christian Brauner
  14 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-23 10:57 UTC (permalink / raw)
  To: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik
  Cc: Christian Brauner, Eric Biggers, Theodore Y. Ts'o,
	linux-fsdevel, linux-fscrypt, fsverity

Now that we moved fsverity out of struct inode update the comments to
not imply that it's still located in there.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 fs/verity/enable.c           |  6 +++---
 fs/verity/fsverity_private.h |  9 +++++----
 fs/verity/open.c             | 12 ++++++------
 include/linux/fsverity.h     | 12 +++++++-----
 4 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/fs/verity/enable.c b/fs/verity/enable.c
index c284f46d1b53..760824611abc 100644
--- a/fs/verity/enable.c
+++ b/fs/verity/enable.c
@@ -287,9 +287,9 @@ static int enable_verity(struct file *filp,
 		/* Successfully enabled verity */
 
 		/*
-		 * Readers can start using ->i_verity_info immediately, so it
-		 * can't be rolled back once set.  So don't set it until just
-		 * after the filesystem has successfully enabled verity.
+		 * Readers can start using the inode's verity info immediately,
+		 * so it can't be rolled back once set.  So don't set it until
+		 * just after the filesystem has successfully enabled verity.
 		 */
 		fsverity_set_info(inode, vi);
 	}
diff --git a/fs/verity/fsverity_private.h b/fs/verity/fsverity_private.h
index b3506f56e180..1b45dc5f52cc 100644
--- a/fs/verity/fsverity_private.h
+++ b/fs/verity/fsverity_private.h
@@ -58,10 +58,11 @@ struct merkle_tree_params {
  * fsverity_info - cached verity metadata for an inode
  *
  * When a verity file is first opened, an instance of this struct is allocated
- * and stored in ->i_verity_info; it remains until the inode is evicted.  It
- * caches information about the Merkle tree that's needed to efficiently verify
- * data read from the file.  It also caches the file digest.  The Merkle tree
- * pages themselves are not cached here, but the filesystem may cache them.
+ * and stored in inode's verity pointer; it remains until the inode is evicted.
+ * It caches information about the Merkle tree that's needed to efficiently
+ * verify data read from the file.  It also caches the file digest.  The Merkle
+ * tree pages themselves are not cached here, but the filesystem may cache
+ * them.
  */
 struct fsverity_info {
 	struct merkle_tree_params tree_params;
diff --git a/fs/verity/open.c b/fs/verity/open.c
index 0dcd33f00361..c4a0c94dde2c 100644
--- a/fs/verity/open.c
+++ b/fs/verity/open.c
@@ -251,10 +251,10 @@ struct fsverity_info *fsverity_create_info(const struct inode *inode,
 void fsverity_set_info(struct inode *inode, struct fsverity_info *vi)
 {
 	/*
-	 * Multiple tasks may race to set ->i_verity_info, so use
+	 * Multiple tasks may race to set the inode's verity info, so use
 	 * cmpxchg_release().  This pairs with the smp_load_acquire() in
-	 * fsverity_get_info().  I.e., here we publish ->i_verity_info with a
-	 * RELEASE barrier so that other tasks can ACQUIRE it.
+	 * fsverity_get_info().  I.e., here we publish the inode's verity info
+	 * with a RELEASE barrier so that other tasks can ACQUIRE it.
 	 */
 	VFS_WARN_ON_ONCE(!inode->i_sb->s_vop);
 	VFS_WARN_ON_ONCE(!inode->i_sb->s_vop->inode_info_offs);
@@ -262,8 +262,8 @@ void fsverity_set_info(struct inode *inode, struct fsverity_info *vi)
 		/* Lost the race, so free the fsverity_info we allocated. */
 		fsverity_free_info(vi);
 		/*
-		 * Afterwards, the caller may access ->i_verity_info directly,
-		 * so make sure to ACQUIRE the winning fsverity_info.
+		 * Afterwards, the caller may access the inode's verity info
+		 * directly, so make sure to ACQUIRE the winning fsverity_info.
 		 */
 		(void)fsverity_get_info(inode);
 	}
@@ -359,7 +359,7 @@ int fsverity_get_descriptor(struct inode *inode,
 	return 0;
 }
 
-/* Ensure the inode has an ->i_verity_info */
+/* Ensure the inode has fsverity info set */
 static int ensure_verity_info(struct inode *inode)
 {
 	struct fsverity_info *vi = fsverity_get_info(inode);
diff --git a/include/linux/fsverity.h b/include/linux/fsverity.h
index 0ee5b2fea389..9e204d5c5691 100644
--- a/include/linux/fsverity.h
+++ b/include/linux/fsverity.h
@@ -145,7 +145,7 @@ static inline struct fsverity_info *fsverity_get_info(const struct inode *inode)
 
 	/*
 	 * Pairs with the cmpxchg_release() in fsverity_set_info().
-	 * I.e., another task may publish ->i_verity_info concurrently,
+	 * I.e., another task may publish the inode's verity info concurrently,
 	 * executing a RELEASE barrier.  We need to use smp_load_acquire() here
 	 * to safely ACQUIRE the memory the other task published.
 	 */
@@ -174,7 +174,8 @@ void __fsverity_cleanup_inode(struct inode *inode);
  * fsverity_cleanup_inode() - free the inode's verity info, if present
  * @inode: an inode being evicted
  *
- * Filesystems must call this on inode eviction to free ->i_verity_info.
+ * Filesystems must call this on inode eviction to free -the inode's
+ * verity info.
  */
 static inline void fsverity_cleanup_inode(struct inode *inode)
 {
@@ -285,12 +286,13 @@ static inline bool fsverity_verify_page(struct page *page)
  * fsverity_active() - do reads from the inode need to go through fs-verity?
  * @inode: inode to check
  *
- * This checks whether ->i_verity_info has been set.
+ * This checks whether the inode's verity info has been set.
  *
  * Filesystems call this from ->readahead() to check whether the pages need to
  * be verified or not.  Don't use IS_VERITY() for this purpose; it's subject to
  * a race condition where the file is being read concurrently with
- * FS_IOC_ENABLE_VERITY completing.  (S_VERITY is set before ->i_verity_info.)
+ * FS_IOC_ENABLE_VERITY completing.  (S_VERITY is set before the inode's
+ * verity info.)
  *
  * Return: true if reads need to go through fs-verity, otherwise false
  */
@@ -305,7 +307,7 @@ static inline bool fsverity_active(const struct inode *inode)
  * @filp: the struct file being set up
  *
  * When opening a verity file, deny the open if it is for writing.  Otherwise,
- * set up the inode's ->i_verity_info if not already done.
+ * set up the inode's verity info if not already done.
  *
  * When combined with fscrypt, this must be called after fscrypt_file_open().
  * Otherwise, we won't have the key set up to decrypt the verity metadata.

-- 
2.47.2


^ permalink raw reply related	[flat|nested] 67+ messages in thread

* Re: [PATCH v4 02/15] fs/crypto: use accessors
  2025-07-23 10:57         ` [PATCH v4 02/15] fs/crypto: use accessors Christian Brauner
@ 2025-07-25  0:29           ` Eric Biggers
  2025-07-25  4:01           ` Eric Biggers
  1 sibling, 0 replies; 67+ messages in thread
From: Eric Biggers @ 2025-07-25  0:29 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik,
	Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt, fsverity

On Wed, Jul 23, 2025 at 12:57:40PM +0200, Christian Brauner wrote:
> fs/crypto: use accessors

fscrypt: use accessors to get/set inode info pointer

> Use accessor to get and set the fscrypt info from the filesystem.
> They can be removed once all filesystems have been converted to make
> room for fscrypt info in their own inodes.
> 
> Signed-off-by: Christian Brauner <brauner@kernel.org>

It would make more sense for this to be patch 1.

Patch 2 then would be "fscrypt: add support for inode_info_offs", adding
the field and the support for it in the accessors.

- Eric

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v4 03/15] ext4: move fscrypt to filesystem inode
  2025-07-23 10:57         ` [PATCH v4 03/15] ext4: move fscrypt to filesystem inode Christian Brauner
@ 2025-07-25  0:32           ` Eric Biggers
  0 siblings, 0 replies; 67+ messages in thread
From: Eric Biggers @ 2025-07-25  0:32 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik,
	Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt, fsverity

On Wed, Jul 23, 2025 at 12:57:41PM +0200, Christian Brauner wrote:
> ext4: move fscrypt to filesystem inode

ext4: move fscrypt_inode_info pointer to ext4_inode_info

Similarly in other patches.  Calling the pointer the "fscrypt" (or the
"fsverity") is kind of an abuse of terminology.

>  const struct fscrypt_operations ext4_cryptops = {
> +#ifdef CONFIG_FS_ENCRYPTION
> +	.inode_info_offs	= offsetof(struct ext4_inode_info, i_crypt_info) -
> +				  offsetof(struct ext4_inode_info, vfs_inode),
> +#endif
>  	.needs_bounce_pages	= 1,
>  	.has_32bit_inodes	= 1,
>  	.supports_subblock_data_units = 1,

No need for #ifdef CONFIG_FS_ENCRYPTION in this file, since it is
compiled only when CONFIG_FS_ENCRYPTION=y.  Similarly in other patches.

- Eric

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v4 06/15] ceph: move fscrypt to filesystem inode
  2025-07-23 10:57         ` [PATCH v4 06/15] ceph: " Christian Brauner
@ 2025-07-25  0:34           ` Eric Biggers
  2025-07-25  8:15             ` Christian Brauner
  0 siblings, 1 reply; 67+ messages in thread
From: Eric Biggers @ 2025-07-25  0:34 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik,
	Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt, fsverity

On Wed, Jul 23, 2025 at 12:57:44PM +0200, Christian Brauner wrote:
> +#ifdef CONFIG_FS_ENCRYPTION
> +	.inode_info_offs	= offsetof(struct ceph_inode_info, i_crypt_info) -
> +				  offsetof(struct ceph_inode_info, netfs),
> +#endif

This should use the offset to the VFS inode:

    offsetof(struct ceph_inode_info, netfs.inode)

> +/*
> + * struct inode must be the first member so we can easily calculate offsets for
> + * e.g., fscrypt or fsverity when embedded in filesystem specific inodes.
> + */
> +static_assert(__same_type(((struct netfs_inode *)NULL)->inode, struct inode));
> +static_assert(offsetof(struct netfs_inode, inode) == 0);

Then no need for this.

- Eric

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v4 08/15] fscrypt: rephrase documentation and comments
  2025-07-23 10:57         ` [PATCH v4 08/15] fscrypt: rephrase documentation and comments Christian Brauner
@ 2025-07-25  0:35           ` Eric Biggers
  0 siblings, 0 replies; 67+ messages in thread
From: Eric Biggers @ 2025-07-25  0:35 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik,
	Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt, fsverity

On Wed, Jul 23, 2025 at 12:57:46PM +0200, Christian Brauner wrote:
>  	/*
>  	 * Pairs with the cmpxchg_release() in fscrypt_setup_encryption_info().
> -	 * I.e., another task may publish ->i_crypt_info concurrently, executing
> -	 * a RELEASE barrier.  We need to use smp_load_acquire() here to safely
> -	 * ACQUIRE the memory the other task published.
> +	 * I.e., another task may publish the inode's fscrypt info
> +	 * concurrently, executing a RELEASE barrier.  We need to use
> +	 * smp_load_acquire() here to safely ACQUIRE the memory the other task
> +	 * published.
>  	 */

Please make sure to wrap at 80 columns, not 79.

- Eric

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v4 07/15] fs: drop i_crypt_info from struct inode
  2025-07-23 10:57         ` [PATCH v4 07/15] fs: drop i_crypt_info from struct inode Christian Brauner
@ 2025-07-25  0:38           ` Eric Biggers
  0 siblings, 0 replies; 67+ messages in thread
From: Eric Biggers @ 2025-07-25  0:38 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik,
	Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt, fsverity

On Wed, Jul 23, 2025 at 12:57:45PM +0200, Christian Brauner wrote:
> +	VFS_WARN_ON_ONCE(!inode->i_sb->s_cop);
> +	VFS_WARN_ON_ONCE(!inode->i_sb->s_cop->inode_info_offs);

These warnings seem odd.  The first is redundant with the fact that
there would be a NULL dereference anyway.  The second should probably be
located in fscrypt_addr() so that it applies everywhere inode_info_offs
is used.

- Eric

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v4 14/15] fs: drop i_verity_info from struct inode
  2025-07-23 10:57         ` [PATCH v4 14/15] fs: drop i_verity_info from struct inode Christian Brauner
@ 2025-07-25  0:43           ` Eric Biggers
  0 siblings, 0 replies; 67+ messages in thread
From: Eric Biggers @ 2025-07-25  0:43 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik,
	Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt, fsverity

On Wed, Jul 23, 2025 at 12:57:52PM +0200, Christian Brauner wrote:
>  static inline struct fsverity_info *fsverity_get_info(const struct inode *inode)
>  {
> -	if (!inode->i_sb->s_vop)
> +	/*
> +	 * We're called from fsverity_active() which might be called on
> +	 * inodes from filesystems that don't support fsverity at all.
> +	 */
> +	if (likely(!inode->i_sb->s_vop))
>  		return NULL;

!IS_VERITY().

Also the proposed comment is misleading, since fsverity_get_digest() and
bpf_get_fsverity_digest() similarly can call this on arbitrary inodes.

- Eric

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v4 09/15] fs: add fsverity offset
  2025-07-23 10:57         ` [PATCH v4 09/15] fs: add fsverity offset Christian Brauner
@ 2025-07-25  0:45           ` Eric Biggers
  0 siblings, 0 replies; 67+ messages in thread
From: Eric Biggers @ 2025-07-25  0:45 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik,
	Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt, fsverity

On Wed, Jul 23, 2025 at 12:57:47PM +0200, Christian Brauner wrote:
> +	/**
> +	 * The offset of struct fsverity_info from struct inode embedded in
> +	 * the filesystem's inode.
> +	 */
> +	ptrdiff_t inode_info_offs;

It's the offset to the pointer to the struct fsverity_info, not the
offset to the struct fsverity_info itself.

Similarly for the fscrypt patch.

- Eric

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v4 02/15] fs/crypto: use accessors
  2025-07-23 10:57         ` [PATCH v4 02/15] fs/crypto: use accessors Christian Brauner
  2025-07-25  0:29           ` Eric Biggers
@ 2025-07-25  4:01           ` Eric Biggers
  1 sibling, 0 replies; 67+ messages in thread
From: Eric Biggers @ 2025-07-25  4:01 UTC (permalink / raw)
  To: Christian Brauner
  Cc: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik,
	Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt, fsverity

On Wed, Jul 23, 2025 at 12:57:40PM +0200, Christian Brauner wrote:
> They can be removed once all filesystems have been converted to make
> room for fscrypt info in their own inodes.

Also note that the accessors still exist at the end of the series.  I'm
not sure what the above sentence is trying to say.

> @@ -396,10 +396,10 @@ bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode,
>  	 * uses the same pointer.  I.e., there's currently no need to support
>  	 * merging requests where the keys are the same but the pointers differ.
>  	 */
> -	if (bc->bc_key != inode->i_crypt_info->ci_enc_key.blk_key)
> +	if (bc->bc_key != fscrypt_get_inode_info_raw(inode)->ci_enc_key.blk_key)
>  		return false;
>  
> -	fscrypt_generate_dun(inode->i_crypt_info, next_lblk, next_dun);
> +	fscrypt_generate_dun(fscrypt_get_inode_info_raw(inode), next_lblk, next_dun);
>  	return bio_crypt_dun_is_contiguous(bc, bio->bi_iter.bi_size, next_dun);
>  }

This function could use a 'ci' local variable now.  It's not clear that
the second fscrypt_get_inode_info_raw() will get optimized out.

- Eric

^ permalink raw reply	[flat|nested] 67+ messages in thread

* Re: [PATCH v4 06/15] ceph: move fscrypt to filesystem inode
  2025-07-25  0:34           ` Eric Biggers
@ 2025-07-25  8:15             ` Christian Brauner
  0 siblings, 0 replies; 67+ messages in thread
From: Christian Brauner @ 2025-07-25  8:15 UTC (permalink / raw)
  To: Eric Biggers
  Cc: Jeff Layton, Jan Kara, Christoph Hellwig, Jens Axboe, Josef Bacik,
	Theodore Y. Ts'o, linux-fsdevel, linux-fscrypt, fsverity

On Thu, Jul 24, 2025 at 05:34:04PM -0700, Eric Biggers wrote:
> On Wed, Jul 23, 2025 at 12:57:44PM +0200, Christian Brauner wrote:
> > +#ifdef CONFIG_FS_ENCRYPTION
> > +	.inode_info_offs	= offsetof(struct ceph_inode_info, i_crypt_info) -
> > +				  offsetof(struct ceph_inode_info, netfs),
> > +#endif
> 
> This should use the offset to the VFS inode:
> 
>     offsetof(struct ceph_inode_info, netfs.inode)
> 
> > +/*
> > + * struct inode must be the first member so we can easily calculate offsets for
> > + * e.g., fscrypt or fsverity when embedded in filesystem specific inodes.
> > + */
> > +static_assert(__same_type(((struct netfs_inode *)NULL)->inode, struct inode));
> > +static_assert(offsetof(struct netfs_inode, inode) == 0);
> 
> Then no need for this.

Ok.

^ permalink raw reply	[flat|nested] 67+ messages in thread

end of thread, other threads:[~2025-07-25  8:15 UTC | newest]

Thread overview: 67+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <fhppu2rnsykr5obrib3btw7wemislq36wufnbl67salvoguaof@kkxaosrv3oho>
2025-07-22 12:57 ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode Christian Brauner
2025-07-22 12:57   ` [PATCH RFC DRAFT v2 01/13] fs: add fscrypt offset Christian Brauner
2025-07-22 12:57   ` [PATCH RFC DRAFT v2 02/13] fs/crypto: use accessors Christian Brauner
2025-07-22 12:57   ` [PATCH RFC DRAFT v2 03/13] ext4: move fscrypt to filesystem inode Christian Brauner
2025-07-22 12:57   ` [PATCH RFC DRAFT v2 04/13] ubifs: " Christian Brauner
2025-07-22 12:57   ` [PATCH RFC DRAFT v2 05/13] f2fs: " Christian Brauner
2025-07-22 12:57   ` [PATCH RFC DRAFT v2 06/13] ceph: " Christian Brauner
2025-07-22 12:57   ` [PATCH RFC DRAFT v2 07/13] fs: drop i_crypt_info from struct inode Christian Brauner
2025-07-22 12:57   ` [PATCH RFC DRAFT v2 08/13] fs: add fsverity offset Christian Brauner
2025-07-22 12:57   ` [PATCH RFC DRAFT v2 09/13] fs/verity: use accessors Christian Brauner
2025-07-22 12:57   ` [PATCH RFC DRAFT v2 10/13] btrfs: move fsverity to filesystem inode Christian Brauner
2025-07-22 12:57   ` [PATCH RFC DRAFT v2 11/13] ext4: " Christian Brauner
2025-07-22 12:57   ` [PATCH RFC DRAFT v2 12/13] f2fs: " Christian Brauner
2025-07-22 12:57   ` [PATCH RFC DRAFT v2 13/13] fs: drop i_verity_info from struct inode Christian Brauner
2025-07-22 13:09   ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of " Christian Brauner
2025-07-22 19:27     ` [PATCH v3 " Christian Brauner
2025-07-22 19:27       ` [PATCH v3 01/13] fs: add fscrypt offset Christian Brauner
2025-07-22 20:02         ` Eric Biggers
2025-07-23  7:48           ` Christian Brauner
2025-07-23  3:49         ` Al Viro
2025-07-22 19:27       ` [PATCH v3 02/13] fs/crypto: use accessors Christian Brauner
2025-07-22 19:27       ` [PATCH v3 03/13] ext4: move fscrypt to filesystem inode Christian Brauner
2025-07-22 20:07         ` Eric Biggers
2025-07-23  8:59           ` Christian Brauner
2025-07-22 19:27       ` [PATCH v3 04/13] ubifs: " Christian Brauner
2025-07-22 19:27       ` [PATCH v3 05/13] f2fs: " Christian Brauner
2025-07-22 19:27       ` [PATCH v3 06/13] ceph: " Christian Brauner
2025-07-22 20:14         ` Eric Biggers
2025-07-23  8:58           ` Christian Brauner
2025-07-22 19:27       ` [PATCH v3 07/13] fs: drop i_crypt_info from struct inode Christian Brauner
2025-07-22 20:19         ` Eric Biggers
2025-07-23  8:52           ` Christian Brauner
2025-07-22 19:27       ` [PATCH v3 08/13] fs: add fsverity offset Christian Brauner
2025-07-23  3:53         ` Al Viro
2025-07-22 19:27       ` [PATCH v3 09/13] fs/verity: use accessors Christian Brauner
2025-07-22 20:25         ` Eric Biggers
2025-07-23  8:55           ` Christian Brauner
2025-07-22 19:27       ` [PATCH v3 10/13] btrfs: move fsverity to filesystem inode Christian Brauner
2025-07-22 19:27       ` [PATCH v3 11/13] ext4: " Christian Brauner
2025-07-22 19:27       ` [PATCH v3 12/13] f2fs: " Christian Brauner
2025-07-22 19:27       ` [PATCH v3 13/13] fs: drop i_verity_info from struct inode Christian Brauner
2025-07-23 10:57       ` [PATCH v4 00/15] Move fscrypt and fsverity out of " Christian Brauner
2025-07-23 10:57         ` [PATCH v4 01/15] fs: add fscrypt offset Christian Brauner
2025-07-23 10:57         ` [PATCH v4 02/15] fs/crypto: use accessors Christian Brauner
2025-07-25  0:29           ` Eric Biggers
2025-07-25  4:01           ` Eric Biggers
2025-07-23 10:57         ` [PATCH v4 03/15] ext4: move fscrypt to filesystem inode Christian Brauner
2025-07-25  0:32           ` Eric Biggers
2025-07-23 10:57         ` [PATCH v4 04/15] ubifs: " Christian Brauner
2025-07-23 10:57         ` [PATCH v4 05/15] f2fs: " Christian Brauner
2025-07-23 10:57         ` [PATCH v4 06/15] ceph: " Christian Brauner
2025-07-25  0:34           ` Eric Biggers
2025-07-25  8:15             ` Christian Brauner
2025-07-23 10:57         ` [PATCH v4 07/15] fs: drop i_crypt_info from struct inode Christian Brauner
2025-07-25  0:38           ` Eric Biggers
2025-07-23 10:57         ` [PATCH v4 08/15] fscrypt: rephrase documentation and comments Christian Brauner
2025-07-25  0:35           ` Eric Biggers
2025-07-23 10:57         ` [PATCH v4 09/15] fs: add fsverity offset Christian Brauner
2025-07-25  0:45           ` Eric Biggers
2025-07-23 10:57         ` [PATCH v4 10/15] fs/verity: use accessors Christian Brauner
2025-07-23 10:57         ` [PATCH v4 11/15] btrfs: move fsverity to filesystem inode Christian Brauner
2025-07-23 10:57         ` [PATCH v4 12/15] ext4: " Christian Brauner
2025-07-23 10:57         ` [PATCH v4 13/15] f2fs: " Christian Brauner
2025-07-23 10:57         ` [PATCH v4 14/15] fs: drop i_verity_info from struct inode Christian Brauner
2025-07-25  0:43           ` Eric Biggers
2025-07-23 10:57         ` [PATCH v4 15/15] fsverity: rephrase documentation and comments Christian Brauner
2025-07-22 13:50   ` [PATCH RFC DRAFT v2 00/13] Move fscrypt and fsverity out of struct inode Jeff Layton

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).