vfs-6.18-rc1.inode

-----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQRAhzRXHqcMeLMyaSiRxhvAZXjcogUCaNZQQgAKCRCRxhvAZXjc
 oud9AQD5IG4sNnzCjsvcTDpQkbX5eZW+LFIiAiiN+nztZ+OcRQEAvC2N7YovfqM3
 TWpVoNDKvEPdtDc9ttFMUKqBZYvxvgE=
 =sEaL
 -----END PGP SIGNATURE-----

Merge tag 'vfs-6.18-rc1.inode' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull vfs inode updates from Christian Brauner:
 "This contains a series I originally wrote and that Eric brought over
  the finish line. It moves out the i_crypt_info and i_verity_info
  pointers out of 'struct inode' and into the fs-specific part of the
  inode.

  So now the few filesytems that actually make use of this pay the price
  in their own private inode storage instead of forcing it upon every
  user of struct inode.

  The pointer for the crypt and verity info is simply found by storing
  an offset to its address in struct fsverity_operations and struct
  fscrypt_operations. This shrinks struct inode by 16 bytes.

  I hope to move a lot more out of it in the future so that struct inode
  becomes really just about very core stuff that we need, much like
  struct dentry and struct file, instead of the dumping ground it has
  become over the years.

  On top of this are a various changes associated with the ongoing inode
  lifetime handling rework that multiple people are pushing forward:

   - Stop accessing inode->i_count directly in f2fs and gfs2. They
     simply should use the __iget() and iput() helpers

   - Make the i_state flags an enum

   - Rework the iput() logic

     Currently, if we are the last iput, and we have the I_DIRTY_TIME
     bit set, we will grab a reference on the inode again and then mark
     it dirty and then redo the put. This is to make sure we delay the
     time update for as long as possible

     We can rework this logic to simply dec i_count if it is not 1, and
     if it is do the time update while still holding the i_count
     reference

     Then we can replace the atomic_dec_and_lock with locking the
     ->i_lock and doing atomic_dec_and_test, since we did the
     atomic_add_unless above

   - Add an icount_read() helper and convert everyone that accesses
     inode->i_count directly for this purpose to use the helper

   - Expand dump_inode() to dump more information about an inode helping
     in debugging

   - Add some might_sleep() annotations to iput() and associated
     helpers"

* tag 'vfs-6.18-rc1.inode' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
  fs: add might_sleep() annotation to iput() and more
  fs: expand dump_inode()
  inode: fix whitespace issues
  fs: add an icount_read helper
  fs: rework iput logic
  fs: make the i_state flags an enum
  fs: stop accessing ->i_count directly in f2fs and gfs2
  fsverity: check IS_VERITY() in fsverity_cleanup_inode()
  fs: remove inode::i_verity_info
  btrfs: move verity info pointer to fs-specific part of inode
  f2fs: move verity info pointer to fs-specific part of inode
  ext4: move verity info pointer to fs-specific part of inode
  fsverity: add support for info in fs-specific part of inode
  fs: remove inode::i_crypt_info
  ceph: move crypt info pointer to fs-specific part of inode
  ubifs: move crypt info pointer to fs-specific part of inode
  f2fs: move crypt info pointer to fs-specific part of inode
  ext4: move crypt info pointer to fs-specific part of inode
  fscrypt: add support for info in fs-specific part of inode
  fscrypt: replace raw loads of info pointer with helper function
This commit is contained in:
Linus Torvalds 2025-09-29 09:42:30 -07:00
commit 56e7b31071
45 changed files with 428 additions and 234 deletions

View File

@ -1430,7 +1430,7 @@ static int spufs_mfc_open(struct inode *inode, struct file *file)
if (ctx->owner != current->mm) if (ctx->owner != current->mm)
return -EINVAL; return -EINVAL;
if (atomic_read(&inode->i_count) != 1) if (icount_read(inode) != 1)
return -EBUSY; return -EBUSY;
mutex_lock(&ctx->mapping_lock); mutex_lock(&ctx->mapping_lock);

View File

@ -338,6 +338,11 @@ struct btrfs_inode {
struct list_head delayed_iput; struct list_head delayed_iput;
struct rw_semaphore i_mmap_lock; struct rw_semaphore i_mmap_lock;
#ifdef CONFIG_FS_VERITY
struct fsverity_info *i_verity_info;
#endif
struct inode vfs_inode; struct inode vfs_inode;
}; };

View File

@ -4556,7 +4556,7 @@ static void btrfs_prune_dentries(struct btrfs_root *root)
inode = btrfs_find_first_inode(root, min_ino); inode = btrfs_find_first_inode(root, min_ino);
while (inode) { while (inode) {
if (atomic_read(&inode->vfs_inode.i_count) > 1) if (icount_read(&inode->vfs_inode) > 1)
d_prune_aliases(&inode->vfs_inode); d_prune_aliases(&inode->vfs_inode);
min_ino = btrfs_ino(inode) + 1; min_ino = btrfs_ino(inode) + 1;
@ -7981,6 +7981,9 @@ static void init_once(void *foo)
struct btrfs_inode *ei = foo; struct btrfs_inode *ei = foo;
inode_init_once(&ei->vfs_inode); inode_init_once(&ei->vfs_inode);
#ifdef CONFIG_FS_VERITY
ei->i_verity_info = NULL;
#endif
} }
void __cold btrfs_destroy_cachep(void) void __cold btrfs_destroy_cachep(void)

View File

@ -802,6 +802,8 @@ static int btrfs_write_merkle_tree_block(struct inode *inode, const void *buf,
} }
const struct fsverity_operations btrfs_verityops = { const struct fsverity_operations btrfs_verityops = {
.inode_info_offs = (int)offsetof(struct btrfs_inode, i_verity_info) -
(int)offsetof(struct btrfs_inode, vfs_inode),
.begin_enable_verity = btrfs_begin_enable_verity, .begin_enable_verity = btrfs_begin_enable_verity,
.end_enable_verity = btrfs_end_enable_verity, .end_enable_verity = btrfs_end_enable_verity,
.get_verity_descriptor = btrfs_get_verity_descriptor, .get_verity_descriptor = btrfs_get_verity_descriptor,

View File

@ -133,6 +133,8 @@ static const union fscrypt_policy *ceph_get_dummy_policy(struct super_block *sb)
} }
static struct fscrypt_operations ceph_fscrypt_ops = { static struct fscrypt_operations ceph_fscrypt_ops = {
.inode_info_offs = (int)offsetof(struct ceph_inode_info, i_crypt_info) -
(int)offsetof(struct ceph_inode_info, netfs.inode),
.needs_bounce_pages = 1, .needs_bounce_pages = 1,
.get_context = ceph_crypt_get_context, .get_context = ceph_crypt_get_context,
.set_context = ceph_crypt_set_context, .set_context = ceph_crypt_set_context,

View File

@ -711,6 +711,7 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
ci->i_work_mask = 0; ci->i_work_mask = 0;
memset(&ci->i_btime, '\0', sizeof(ci->i_btime)); memset(&ci->i_btime, '\0', sizeof(ci->i_btime));
#ifdef CONFIG_FS_ENCRYPTION #ifdef CONFIG_FS_ENCRYPTION
ci->i_crypt_info = NULL;
ci->fscrypt_auth = NULL; ci->fscrypt_auth = NULL;
ci->fscrypt_auth_len = 0; ci->fscrypt_auth_len = 0;
#endif #endif

View File

@ -2221,7 +2221,7 @@ static int trim_caps_cb(struct inode *inode, int mds, void *arg)
int count; int count;
dput(dentry); dput(dentry);
d_prune_aliases(inode); d_prune_aliases(inode);
count = atomic_read(&inode->i_count); count = icount_read(inode);
if (count == 1) if (count == 1)
(*remaining)--; (*remaining)--;
doutc(cl, "%p %llx.%llx cap %p pruned, count now %d\n", doutc(cl, "%p %llx.%llx cap %p pruned, count now %d\n",

View File

@ -463,6 +463,7 @@ struct ceph_inode_info {
unsigned long i_work_mask; unsigned long i_work_mask;
#ifdef CONFIG_FS_ENCRYPTION #ifdef CONFIG_FS_ENCRYPTION
struct fscrypt_inode_info *i_crypt_info;
u32 fscrypt_auth_len; u32 fscrypt_auth_len;
u32 fscrypt_file_len; u32 fscrypt_file_len;
u8 *fscrypt_auth; u8 *fscrypt_auth;

View File

@ -113,7 +113,7 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
sector_t pblk, unsigned int len) 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_bits = ci->ci_data_unit_bits;
const unsigned int du_size = 1U << du_bits; const unsigned int du_size = 1U << du_bits;
const unsigned int du_per_page_bits = PAGE_SHIFT - du_bits; const unsigned int du_per_page_bits = PAGE_SHIFT - du_bits;

View File

@ -173,7 +173,7 @@ struct page *fscrypt_encrypt_pagecache_blocks(struct folio *folio,
size_t len, size_t offs, gfp_t gfp_flags) size_t len, size_t offs, gfp_t gfp_flags)
{ {
const struct inode *inode = folio->mapping->host; 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_bits = ci->ci_data_unit_bits;
const unsigned int du_size = 1U << du_bits; const unsigned int du_size = 1U << du_bits;
struct page *ciphertext_page; struct page *ciphertext_page;
@ -232,8 +232,9 @@ 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)) if (WARN_ON_ONCE(inode->i_sb->s_cop->supports_subblock_data_units))
return -EOPNOTSUPP; return -EOPNOTSUPP;
return fscrypt_crypt_data_unit(inode->i_crypt_info, FS_ENCRYPT, return fscrypt_crypt_data_unit(fscrypt_get_inode_info_raw(inode),
lblk_num, page, page, len, offs); FS_ENCRYPT, lblk_num, page, page, len,
offs);
} }
EXPORT_SYMBOL(fscrypt_encrypt_block_inplace); EXPORT_SYMBOL(fscrypt_encrypt_block_inplace);
@ -255,7 +256,7 @@ int fscrypt_decrypt_pagecache_blocks(struct folio *folio, size_t len,
size_t offs) size_t offs)
{ {
const struct inode *inode = folio->mapping->host; 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_bits = ci->ci_data_unit_bits;
const unsigned int du_size = 1U << du_bits; const unsigned int du_size = 1U << du_bits;
u64 index = ((u64)folio->index << (PAGE_SHIFT - du_bits)) + u64 index = ((u64)folio->index << (PAGE_SHIFT - du_bits)) +
@ -305,8 +306,9 @@ 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)) if (WARN_ON_ONCE(inode->i_sb->s_cop->supports_subblock_data_units))
return -EOPNOTSUPP; return -EOPNOTSUPP;
return fscrypt_crypt_data_unit(inode->i_crypt_info, FS_DECRYPT, return fscrypt_crypt_data_unit(fscrypt_get_inode_info_raw(inode),
lblk_num, page, page, len, offs); FS_DECRYPT, lblk_num, page, page, len,
offs);
} }
EXPORT_SYMBOL(fscrypt_decrypt_block_inplace); EXPORT_SYMBOL(fscrypt_decrypt_block_inplace);

View File

@ -94,7 +94,7 @@ static inline bool fscrypt_is_dot_dotdot(const struct qstr *str)
int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname, int fscrypt_fname_encrypt(const struct inode *inode, const struct qstr *iname,
u8 *out, unsigned int olen) u8 *out, unsigned int olen)
{ {
const struct fscrypt_inode_info *ci = inode->i_crypt_info; const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
struct crypto_sync_skcipher *tfm = ci->ci_enc_key.tfm; struct crypto_sync_skcipher *tfm = ci->ci_enc_key.tfm;
SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm); SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm);
union fscrypt_iv iv; union fscrypt_iv iv;
@ -138,7 +138,7 @@ static int fname_decrypt(const struct inode *inode,
const struct fscrypt_str *iname, const struct fscrypt_str *iname,
struct fscrypt_str *oname) struct fscrypt_str *oname)
{ {
const struct fscrypt_inode_info *ci = inode->i_crypt_info; const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
struct crypto_sync_skcipher *tfm = ci->ci_enc_key.tfm; struct crypto_sync_skcipher *tfm = ci->ci_enc_key.tfm;
SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm); SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm);
union fscrypt_iv iv; union fscrypt_iv iv;
@ -274,8 +274,9 @@ bool __fscrypt_fname_encrypted_size(const union fscrypt_policy *policy,
bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len, bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len,
u32 max_len, u32 *encrypted_len_ret) u32 max_len, u32 *encrypted_len_ret)
{ {
return __fscrypt_fname_encrypted_size(&inode->i_crypt_info->ci_policy, const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode);
orig_len, max_len,
return __fscrypt_fname_encrypted_size(&ci->ci_policy, orig_len, max_len,
encrypted_len_ret); encrypted_len_ret);
} }
EXPORT_SYMBOL_GPL(fscrypt_fname_encrypted_size); EXPORT_SYMBOL_GPL(fscrypt_fname_encrypted_size);
@ -543,7 +544,7 @@ EXPORT_SYMBOL_GPL(fscrypt_match_name);
*/ */
u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *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); WARN_ON_ONCE(!ci->ci_dirhash_key_initialized);

View File

@ -249,8 +249,8 @@ struct fscrypt_prepared_key {
* fscrypt_inode_info - the "encryption key" for an inode * fscrypt_inode_info - the "encryption key" for an inode
* *
* When an encrypted file's key is made available, an instance of this struct is * 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 a pointer to it is stored in the file's in-memory inode. Once
* inode is evicted. * created, it remains until the inode is evicted.
*/ */
struct fscrypt_inode_info { struct fscrypt_inode_info {

View File

@ -199,7 +199,7 @@ int fscrypt_prepare_setflags(struct inode *inode,
err = fscrypt_require_key(inode); err = fscrypt_require_key(inode);
if (err) if (err)
return err; return err;
ci = inode->i_crypt_info; ci = fscrypt_get_inode_info_raw(inode);
if (ci->ci_policy.version != FSCRYPT_POLICY_V2) if (ci->ci_policy.version != FSCRYPT_POLICY_V2)
return -EINVAL; return -EINVAL;
mk = ci->ci_master_key; mk = ci->ci_master_key;

View File

@ -263,7 +263,7 @@ int fscrypt_derive_sw_secret(struct super_block *sb,
bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode) 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); EXPORT_SYMBOL_GPL(__fscrypt_inode_uses_inline_crypto);
@ -307,7 +307,7 @@ void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode,
if (!fscrypt_inode_uses_inline_crypto(inode)) if (!fscrypt_inode_uses_inline_crypto(inode))
return; return;
ci = inode->i_crypt_info; ci = fscrypt_get_inode_info_raw(inode);
fscrypt_generate_dun(ci, first_lblk, dun); fscrypt_generate_dun(ci, first_lblk, dun);
bio_crypt_set_ctx(bio, ci->ci_enc_key.blk_key, dun, gfp_mask); bio_crypt_set_ctx(bio, ci->ci_enc_key.blk_key, dun, gfp_mask);
@ -385,22 +385,24 @@ bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode,
u64 next_lblk) u64 next_lblk)
{ {
const struct bio_crypt_ctx *bc = bio->bi_crypt_context; const struct bio_crypt_ctx *bc = bio->bi_crypt_context;
const struct fscrypt_inode_info *ci;
u64 next_dun[BLK_CRYPTO_DUN_ARRAY_SIZE]; u64 next_dun[BLK_CRYPTO_DUN_ARRAY_SIZE];
if (!!bc != fscrypt_inode_uses_inline_crypto(inode)) if (!!bc != fscrypt_inode_uses_inline_crypto(inode))
return false; return false;
if (!bc) if (!bc)
return true; return true;
ci = fscrypt_get_inode_info_raw(inode);
/* /*
* Comparing the key pointers is good enough, as all I/O for each key * Comparing the key pointers is good enough, as all I/O for each key
* uses the same pointer. I.e., there's currently no need to support * 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. * 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 != ci->ci_enc_key.blk_key)
return false; return false;
fscrypt_generate_dun(inode->i_crypt_info, next_lblk, next_dun); fscrypt_generate_dun(ci, next_lblk, next_dun);
return bio_crypt_dun_is_contiguous(bc, bio->bi_iter.bi_size, next_dun); return bio_crypt_dun_is_contiguous(bc, bio->bi_iter.bi_size, next_dun);
} }
EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio); EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio);
@ -502,7 +504,7 @@ u64 fscrypt_limit_io_blocks(const struct inode *inode, u64 lblk, u64 nr_blocks)
if (nr_blocks <= 1) if (nr_blocks <= 1)
return nr_blocks; return nr_blocks;
ci = inode->i_crypt_info; ci = fscrypt_get_inode_info_raw(inode);
if (!(fscrypt_policy_flags(&ci->ci_policy) & if (!(fscrypt_policy_flags(&ci->ci_policy) &
FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32))
return nr_blocks; return nr_blocks;

View File

@ -642,15 +642,16 @@ fscrypt_setup_encryption_info(struct inode *inode,
goto out; goto out;
/* /*
* For existing inodes, multiple tasks may race to set ->i_crypt_info. * For existing inodes, multiple tasks may race to set the inode's
* So use cmpxchg_release(). This pairs with the smp_load_acquire() in * fscrypt info pointer. So use cmpxchg_release(). This pairs with the
* fscrypt_get_inode_info(). I.e., here we publish ->i_crypt_info with * smp_load_acquire() in fscrypt_get_inode_info(). I.e., publish the
* a RELEASE barrier so that other tasks can ACQUIRE it. * pointer with a RELEASE barrier so that other tasks can ACQUIRE it.
*/ */
if (cmpxchg_release(&inode->i_crypt_info, NULL, crypt_info) == NULL) { if (cmpxchg_release(fscrypt_inode_info_addr(inode), NULL, crypt_info) ==
NULL) {
/* /*
* We won the race and set ->i_crypt_info to our crypt_info. * We won the race and set the inode's fscrypt info to our
* Now link it into the master key's inode list. * crypt_info. Now link it into the master key's inode list.
*/ */
if (mk) { if (mk) {
crypt_info->ci_master_key = mk; crypt_info->ci_master_key = mk;
@ -681,13 +682,13 @@ fscrypt_setup_encryption_info(struct inode *inode,
* %false unless the operation being performed is needed in * %false unless the operation being performed is needed in
* order for files (or directories) to be deleted. * 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 encryption key, if it hasn't already been done.
* *
* Note: unless ->i_crypt_info is already set, this isn't %GFP_NOFS-safe. So * Note: unless the key setup was already done, this isn't %GFP_NOFS-safe. So
* generally this shouldn't be called from within a filesystem transaction. * 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 the key is now set up, *or* if it couldn't be set up because the
* encryption key is unavailable. (Use fscrypt_has_encryption_key() to * needed master key is absent. (Use fscrypt_has_encryption_key() to
* distinguish these cases.) Also can return another -errno code. * distinguish these cases.) Also can return another -errno code.
*/ */
int fscrypt_get_encryption_info(struct inode *inode, bool allow_unsupported) int fscrypt_get_encryption_info(struct inode *inode, bool allow_unsupported)
@ -741,9 +742,9 @@ int fscrypt_get_encryption_info(struct inode *inode, bool allow_unsupported)
* ->i_ino doesn't need to be set yet. * ->i_ino doesn't need to be set yet.
* @encrypt_ret: (output) set to %true if the new inode will be encrypted * @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 encryption key in preparation for
* encrypting the name of the new file. Also, if the new inode will be * 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 encryption key too and set *encrypt_ret=true.
* *
* This isn't %GFP_NOFS-safe, and therefore it should be called before starting * 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 * any filesystem transaction to create the inode. For this reason, ->i_ino
@ -752,8 +753,8 @@ int fscrypt_get_encryption_info(struct inode *inode, bool allow_unsupported)
* This doesn't persist the new inode's encryption context. That still needs to * This doesn't persist the new inode's encryption context. That still needs to
* be done later by calling fscrypt_set_context(). * be done later by calling fscrypt_set_context().
* *
* Return: 0 on success, -ENOKEY if the encryption key is missing, or another * Return: 0 on success, -ENOKEY if a key needs to be set up for @dir or @inode
* -errno code * but the needed master key is absent, or another -errno code
*/ */
int fscrypt_prepare_new_inode(struct inode *dir, struct inode *inode, int fscrypt_prepare_new_inode(struct inode *dir, struct inode *inode,
bool *encrypt_ret) bool *encrypt_ret)
@ -800,8 +801,16 @@ EXPORT_SYMBOL_GPL(fscrypt_prepare_new_inode);
*/ */
void fscrypt_put_encryption_info(struct inode *inode) void fscrypt_put_encryption_info(struct inode *inode)
{ {
put_crypt_info(inode->i_crypt_info); /*
inode->i_crypt_info = NULL; * Ideally we'd start with a lightweight IS_ENCRYPTED() check here
* before proceeding to retrieve and check the pointer. However, during
* inode creation, the fscrypt_inode_info is set before S_ENCRYPTED. If
* an error occurs, it needs to be cleaned up regardless.
*/
struct fscrypt_inode_info **ci_addr = fscrypt_inode_info_addr(inode);
put_crypt_info(*ci_addr);
*ci_addr = NULL;
} }
EXPORT_SYMBOL(fscrypt_put_encryption_info); EXPORT_SYMBOL(fscrypt_put_encryption_info);

View File

@ -727,7 +727,7 @@ const union fscrypt_policy *fscrypt_policy_to_inherit(struct inode *dir)
err = fscrypt_require_key(dir); err = fscrypt_require_key(dir);
if (err) if (err)
return ERR_PTR(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); return fscrypt_get_dummy_policy(dir->i_sb);
@ -746,7 +746,7 @@ const union fscrypt_policy *fscrypt_policy_to_inherit(struct inode *dir)
*/ */
int fscrypt_context_for_new_inode(void *ctx, struct inode *inode) 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) != BUILD_BUG_ON(sizeof(union fscrypt_context) !=
FSCRYPT_SET_CONTEXT_MAX_SIZE); FSCRYPT_SET_CONTEXT_MAX_SIZE);
@ -771,7 +771,7 @@ EXPORT_SYMBOL_GPL(fscrypt_context_for_new_inode);
*/ */
int fscrypt_set_context(struct inode *inode, void *fs_data) int fscrypt_set_context(struct inode *inode, void *fs_data)
{ {
struct fscrypt_inode_info *ci = inode->i_crypt_info; struct fscrypt_inode_info *ci;
union fscrypt_context ctx; union fscrypt_context ctx;
int ctxsize; int ctxsize;
@ -783,6 +783,7 @@ int fscrypt_set_context(struct inode *inode, void *fs_data)
* This may be the first time the inode number is available, so do any * This may be the first time the inode number is available, so do any
* delayed key setup that requires the inode number. * delayed key setup that requires the inode number.
*/ */
ci = fscrypt_get_inode_info_raw(inode);
if (ci->ci_policy.version == FSCRYPT_POLICY_V2 && if (ci->ci_policy.version == FSCRYPT_POLICY_V2 &&
(ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32))
fscrypt_hash_inode_number(ci, ci->ci_master_key); fscrypt_hash_inode_number(ci, ci->ci_master_key);

View File

@ -227,6 +227,8 @@ static bool ext4_has_stable_inodes(struct super_block *sb)
} }
const struct fscrypt_operations ext4_cryptops = { const struct fscrypt_operations ext4_cryptops = {
.inode_info_offs = (int)offsetof(struct ext4_inode_info, i_crypt_info) -
(int)offsetof(struct ext4_inode_info, vfs_inode),
.needs_bounce_pages = 1, .needs_bounce_pages = 1,
.has_32bit_inodes = 1, .has_32bit_inodes = 1,
.supports_subblock_data_units = 1, .supports_subblock_data_units = 1,

View File

@ -1182,6 +1182,14 @@ struct ext4_inode_info {
__u32 i_csum_seed; __u32 i_csum_seed;
kprojid_t i_projid; kprojid_t i_projid;
#ifdef CONFIG_FS_ENCRYPTION
struct fscrypt_inode_info *i_crypt_info;
#endif
#ifdef CONFIG_FS_VERITY
struct fsverity_info *i_verity_info;
#endif
}; };
/* /*

View File

@ -252,10 +252,10 @@ void ext4_free_inode(handle_t *handle, struct inode *inode)
"nonexistent device\n", __func__, __LINE__); "nonexistent device\n", __func__, __LINE__);
return; return;
} }
if (atomic_read(&inode->i_count) > 1) { if (icount_read(inode) > 1) {
ext4_msg(sb, KERN_ERR, "%s:%d: inode #%lu: count=%d", ext4_msg(sb, KERN_ERR, "%s:%d: inode #%lu: count=%d",
__func__, __LINE__, inode->i_ino, __func__, __LINE__, inode->i_ino,
atomic_read(&inode->i_count)); icount_read(inode));
return; return;
} }
if (inode->i_nlink) { if (inode->i_nlink) {

View File

@ -1470,6 +1470,12 @@ static void init_once(void *foo)
init_rwsem(&ei->i_data_sem); init_rwsem(&ei->i_data_sem);
inode_init_once(&ei->vfs_inode); inode_init_once(&ei->vfs_inode);
ext4_fc_init_inode(&ei->vfs_inode); ext4_fc_init_inode(&ei->vfs_inode);
#ifdef CONFIG_FS_ENCRYPTION
ei->i_crypt_info = NULL;
#endif
#ifdef CONFIG_FS_VERITY
ei->i_verity_info = NULL;
#endif
} }
static int __init init_inodecache(void) static int __init init_inodecache(void)

View File

@ -389,6 +389,8 @@ static int ext4_write_merkle_tree_block(struct inode *inode, const void *buf,
} }
const struct fsverity_operations ext4_verityops = { const struct fsverity_operations ext4_verityops = {
.inode_info_offs = (int)offsetof(struct ext4_inode_info, i_verity_info) -
(int)offsetof(struct ext4_inode_info, vfs_inode),
.begin_enable_verity = ext4_begin_enable_verity, .begin_enable_verity = ext4_begin_enable_verity,
.end_enable_verity = ext4_end_enable_verity, .end_enable_verity = ext4_end_enable_verity,
.get_verity_descriptor = ext4_get_verity_descriptor, .get_verity_descriptor = ext4_get_verity_descriptor,

View File

@ -907,6 +907,12 @@ struct f2fs_inode_info {
unsigned int atomic_write_cnt; unsigned int atomic_write_cnt;
loff_t original_i_size; /* original i_size before atomic write */ 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
#ifdef CONFIG_FS_VERITY
struct fsverity_info *i_verity_info; /* filesystem verity info */
#endif
}; };
static inline void get_read_extent_info(struct extent_info *ext, static inline void get_read_extent_info(struct extent_info *ext,

View File

@ -480,6 +480,12 @@ static void init_once(void *foo)
struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo; struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo;
inode_init_once(&fi->vfs_inode); inode_init_once(&fi->vfs_inode);
#ifdef CONFIG_FS_ENCRYPTION
fi->i_crypt_info = NULL;
#endif
#ifdef CONFIG_FS_VERITY
fi->i_verity_info = NULL;
#endif
} }
#ifdef CONFIG_QUOTA #ifdef CONFIG_QUOTA
@ -1744,7 +1750,7 @@ static int f2fs_drop_inode(struct inode *inode)
if ((!inode_unhashed(inode) && inode->i_state & I_SYNC)) { if ((!inode_unhashed(inode) && inode->i_state & I_SYNC)) {
if (!inode->i_nlink && !is_bad_inode(inode)) { if (!inode->i_nlink && !is_bad_inode(inode)) {
/* to avoid evict_inode call simultaneously */ /* to avoid evict_inode call simultaneously */
atomic_inc(&inode->i_count); __iget(inode);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
/* should remain fi->extent_tree for writepage */ /* should remain fi->extent_tree for writepage */
@ -1763,7 +1769,7 @@ static int f2fs_drop_inode(struct inode *inode)
sb_end_intwrite(inode->i_sb); sb_end_intwrite(inode->i_sb);
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
atomic_dec(&inode->i_count); iput(inode);
} }
trace_f2fs_drop_inode(inode, 0); trace_f2fs_drop_inode(inode, 0);
return 0; return 0;
@ -3570,6 +3576,8 @@ static struct block_device **f2fs_get_devices(struct super_block *sb,
} }
static const struct fscrypt_operations f2fs_cryptops = { static const struct fscrypt_operations f2fs_cryptops = {
.inode_info_offs = (int)offsetof(struct f2fs_inode_info, i_crypt_info) -
(int)offsetof(struct f2fs_inode_info, vfs_inode),
.needs_bounce_pages = 1, .needs_bounce_pages = 1,
.has_32bit_inodes = 1, .has_32bit_inodes = 1,
.supports_subblock_data_units = 1, .supports_subblock_data_units = 1,
@ -3581,7 +3589,7 @@ static const struct fscrypt_operations f2fs_cryptops = {
.has_stable_inodes = f2fs_has_stable_inodes, .has_stable_inodes = f2fs_has_stable_inodes,
.get_devices = f2fs_get_devices, .get_devices = f2fs_get_devices,
}; };
#endif #endif /* CONFIG_FS_ENCRYPTION */
static struct inode *f2fs_nfs_get_inode(struct super_block *sb, static struct inode *f2fs_nfs_get_inode(struct super_block *sb,
u64 ino, u32 generation) u64 ino, u32 generation)

View File

@ -287,6 +287,8 @@ static int f2fs_write_merkle_tree_block(struct inode *inode, const void *buf,
} }
const struct fsverity_operations f2fs_verityops = { const struct fsverity_operations f2fs_verityops = {
.inode_info_offs = (int)offsetof(struct f2fs_inode_info, i_verity_info) -
(int)offsetof(struct f2fs_inode_info, vfs_inode),
.begin_enable_verity = f2fs_begin_enable_verity, .begin_enable_verity = f2fs_begin_enable_verity,
.end_enable_verity = f2fs_end_enable_verity, .end_enable_verity = f2fs_end_enable_verity,
.get_verity_descriptor = f2fs_get_verity_descriptor, .get_verity_descriptor = f2fs_get_verity_descriptor,

View File

@ -1767,7 +1767,7 @@ static int writeback_single_inode(struct inode *inode,
int ret = 0; int ret = 0;
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
if (!atomic_read(&inode->i_count)) if (!icount_read(inode))
WARN_ON(!(inode->i_state & (I_WILL_FREE|I_FREEING))); WARN_ON(!(inode->i_state & (I_WILL_FREE|I_FREEING)));
else else
WARN_ON(inode->i_state & I_WILL_FREE); WARN_ON(inode->i_state & I_WILL_FREE);

View File

@ -1754,7 +1754,7 @@ static void gfs2_evict_inodes(struct super_block *sb)
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
continue; continue;
} }
atomic_inc(&inode->i_count); __iget(inode);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
spin_unlock(&sb->s_inode_list_lock); spin_unlock(&sb->s_inode_list_lock);

View File

@ -184,7 +184,7 @@ void hpfs_write_inode(struct inode *i)
struct hpfs_inode_info *hpfs_inode = hpfs_i(i); struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
struct inode *parent; struct inode *parent;
if (i->i_ino == hpfs_sb(i->i_sb)->sb_root) return; if (i->i_ino == hpfs_sb(i->i_sb)->sb_root) return;
if (hpfs_inode->i_rddir_off && !atomic_read(&i->i_count)) { if (hpfs_inode->i_rddir_off && !icount_read(i)) {
if (*hpfs_inode->i_rddir_off) if (*hpfs_inode->i_rddir_off)
pr_err("write_inode: some position still there\n"); pr_err("write_inode: some position still there\n");
kfree(hpfs_inode->i_rddir_off); kfree(hpfs_inode->i_rddir_off);

View File

@ -534,7 +534,7 @@ static void __inode_add_lru(struct inode *inode, bool rotate)
{ {
if (inode->i_state & (I_DIRTY_ALL | I_SYNC | I_FREEING | I_WILL_FREE)) if (inode->i_state & (I_DIRTY_ALL | I_SYNC | I_FREEING | I_WILL_FREE))
return; return;
if (atomic_read(&inode->i_count)) if (icount_read(inode))
return; return;
if (!(inode->i_sb->s_flags & SB_ACTIVE)) if (!(inode->i_sb->s_flags & SB_ACTIVE))
return; return;
@ -550,11 +550,11 @@ static void __inode_add_lru(struct inode *inode, bool rotate)
struct wait_queue_head *inode_bit_waitqueue(struct wait_bit_queue_entry *wqe, struct wait_queue_head *inode_bit_waitqueue(struct wait_bit_queue_entry *wqe,
struct inode *inode, u32 bit) struct inode *inode, u32 bit)
{ {
void *bit_address; void *bit_address;
bit_address = inode_state_wait_address(inode, bit); bit_address = inode_state_wait_address(inode, bit);
init_wait_var_entry(wqe, bit_address, 0); init_wait_var_entry(wqe, bit_address, 0);
return __var_waitqueue(bit_address); return __var_waitqueue(bit_address);
} }
EXPORT_SYMBOL(inode_bit_waitqueue); EXPORT_SYMBOL(inode_bit_waitqueue);
@ -871,11 +871,11 @@ void evict_inodes(struct super_block *sb)
again: again:
spin_lock(&sb->s_inode_list_lock); spin_lock(&sb->s_inode_list_lock);
list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
if (atomic_read(&inode->i_count)) if (icount_read(inode))
continue; continue;
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
if (atomic_read(&inode->i_count)) { if (icount_read(inode)) {
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
continue; continue;
} }
@ -937,7 +937,7 @@ static enum lru_status inode_lru_isolate(struct list_head *item,
* unreclaimable for a while. Remove them lazily here; iput, * unreclaimable for a while. Remove them lazily here; iput,
* sync, or the last page cache deletion will requeue them. * sync, or the last page cache deletion will requeue them.
*/ */
if (atomic_read(&inode->i_count) || if (icount_read(inode) ||
(inode->i_state & ~I_REFERENCED) || (inode->i_state & ~I_REFERENCED) ||
!mapping_shrinkable(&inode->i_data)) { !mapping_shrinkable(&inode->i_data)) {
list_lru_isolate(lru, &inode->i_lru); list_lru_isolate(lru, &inode->i_lru);
@ -1279,6 +1279,8 @@ struct inode *inode_insert5(struct inode *inode, unsigned long hashval,
struct hlist_head *head = inode_hashtable + hash(inode->i_sb, hashval); struct hlist_head *head = inode_hashtable + hash(inode->i_sb, hashval);
struct inode *old; struct inode *old;
might_sleep();
again: again:
spin_lock(&inode_hash_lock); spin_lock(&inode_hash_lock);
old = find_inode(inode->i_sb, head, test, data, true); old = find_inode(inode->i_sb, head, test, data, true);
@ -1382,6 +1384,8 @@ struct inode *iget5_locked_rcu(struct super_block *sb, unsigned long hashval,
struct hlist_head *head = inode_hashtable + hash(sb, hashval); struct hlist_head *head = inode_hashtable + hash(sb, hashval);
struct inode *inode, *new; struct inode *inode, *new;
might_sleep();
again: again:
inode = find_inode(sb, head, test, data, false); inode = find_inode(sb, head, test, data, false);
if (inode) { if (inode) {
@ -1422,6 +1426,9 @@ struct inode *iget_locked(struct super_block *sb, unsigned long ino)
{ {
struct hlist_head *head = inode_hashtable + hash(sb, ino); struct hlist_head *head = inode_hashtable + hash(sb, ino);
struct inode *inode; struct inode *inode;
might_sleep();
again: again:
inode = find_inode_fast(sb, head, ino, false); inode = find_inode_fast(sb, head, ino, false);
if (inode) { if (inode) {
@ -1605,6 +1612,9 @@ struct inode *ilookup5(struct super_block *sb, unsigned long hashval,
int (*test)(struct inode *, void *), void *data) int (*test)(struct inode *, void *), void *data)
{ {
struct inode *inode; struct inode *inode;
might_sleep();
again: again:
inode = ilookup5_nowait(sb, hashval, test, data); inode = ilookup5_nowait(sb, hashval, test, data);
if (inode) { if (inode) {
@ -1630,6 +1640,9 @@ struct inode *ilookup(struct super_block *sb, unsigned long ino)
{ {
struct hlist_head *head = inode_hashtable + hash(sb, ino); struct hlist_head *head = inode_hashtable + hash(sb, ino);
struct inode *inode; struct inode *inode;
might_sleep();
again: again:
inode = find_inode_fast(sb, head, ino, false); inode = find_inode_fast(sb, head, ino, false);
@ -1780,6 +1793,8 @@ int insert_inode_locked(struct inode *inode)
ino_t ino = inode->i_ino; ino_t ino = inode->i_ino;
struct hlist_head *head = inode_hashtable + hash(sb, ino); struct hlist_head *head = inode_hashtable + hash(sb, ino);
might_sleep();
while (1) { while (1) {
struct inode *old = NULL; struct inode *old = NULL;
spin_lock(&inode_hash_lock); spin_lock(&inode_hash_lock);
@ -1826,6 +1841,8 @@ int insert_inode_locked4(struct inode *inode, unsigned long hashval,
{ {
struct inode *old; struct inode *old;
might_sleep();
inode->i_state |= I_CREATING; inode->i_state |= I_CREATING;
old = inode_insert5(inode, hashval, test, NULL, data); old = inode_insert5(inode, hashval, test, NULL, data);
@ -1908,20 +1925,45 @@ static void iput_final(struct inode *inode)
*/ */
void iput(struct inode *inode) void iput(struct inode *inode)
{ {
if (!inode) might_sleep();
if (unlikely(!inode))
return; return;
BUG_ON(inode->i_state & I_CLEAR);
retry: retry:
if (atomic_dec_and_lock(&inode->i_count, &inode->i_lock)) { lockdep_assert_not_held(&inode->i_lock);
if (inode->i_nlink && (inode->i_state & I_DIRTY_TIME)) { VFS_BUG_ON_INODE(inode->i_state & I_CLEAR, inode);
atomic_inc(&inode->i_count); /*
spin_unlock(&inode->i_lock); * Note this assert is technically racy as if the count is bogusly
trace_writeback_lazytime_iput(inode); * equal to one, then two CPUs racing to further drop it can both
mark_inode_dirty_sync(inode); * conclude it's fine.
goto retry; */
} VFS_BUG_ON_INODE(atomic_read(&inode->i_count) < 1, inode);
iput_final(inode);
if (atomic_add_unless(&inode->i_count, -1, 1))
return;
if ((inode->i_state & I_DIRTY_TIME) && inode->i_nlink) {
trace_writeback_lazytime_iput(inode);
mark_inode_dirty_sync(inode);
goto retry;
} }
spin_lock(&inode->i_lock);
if (unlikely((inode->i_state & I_DIRTY_TIME) && inode->i_nlink)) {
spin_unlock(&inode->i_lock);
goto retry;
}
if (!atomic_dec_and_test(&inode->i_count)) {
spin_unlock(&inode->i_lock);
return;
}
/*
* iput_final() drops ->i_lock, we can't assert on it as the inode may
* be deallocated by the time the call returns.
*/
iput_final(inode);
} }
EXPORT_SYMBOL(iput); EXPORT_SYMBOL(iput);
@ -2917,10 +2959,18 @@ EXPORT_SYMBOL(mode_strip_sgid);
* *
* TODO: add a proper inode dumping routine, this is a stub to get debug off the * TODO: add a proper inode dumping routine, this is a stub to get debug off the
* ground. * ground.
*
* TODO: handle getting to fs type with get_kernel_nofault()?
* See dump_mapping() above.
*/ */
void dump_inode(struct inode *inode, const char *reason) void dump_inode(struct inode *inode, const char *reason)
{ {
pr_warn("%s encountered for inode %px (%s)\n", reason, inode, inode->i_sb->s_type->name); struct super_block *sb = inode->i_sb;
pr_warn("%s encountered for inode %px\n"
"fs %s mode %ho opflags 0x%hx flags 0x%x state 0x%x count %d\n",
reason, inode, sb->s_type->name, inode->i_mode, inode->i_opflags,
inode->i_flags, inode->i_state, atomic_read(&inode->i_count));
} }
EXPORT_SYMBOL(dump_inode); EXPORT_SYMBOL(dump_inode);

View File

@ -608,7 +608,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
inode->i_sb->s_id, inode->i_sb->s_id,
(unsigned long long)NFS_FILEID(inode), (unsigned long long)NFS_FILEID(inode),
nfs_display_fhandle_hash(fh), nfs_display_fhandle_hash(fh),
atomic_read(&inode->i_count)); icount_read(inode));
out: out:
return inode; return inode;
@ -2236,7 +2236,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
dfprintk(VFS, "NFS: %s(%s/%lu fh_crc=0x%08x ct=%d info=0x%llx)\n", dfprintk(VFS, "NFS: %s(%s/%lu fh_crc=0x%08x ct=%d info=0x%llx)\n",
__func__, inode->i_sb->s_id, inode->i_ino, __func__, inode->i_sb->s_id, inode->i_ino,
nfs_display_fhandle_hash(NFS_FH(inode)), nfs_display_fhandle_hash(NFS_FH(inode)),
atomic_read(&inode->i_count), fattr->valid); icount_read(inode), fattr->valid);
if (!(fattr->valid & NFS_ATTR_FATTR_FILEID)) { if (!(fattr->valid & NFS_ATTR_FATTR_FILEID)) {
/* Only a mounted-on-fileid? Just exit */ /* Only a mounted-on-fileid? Just exit */

View File

@ -66,7 +66,7 @@ static void fsnotify_unmount_inodes(struct super_block *sb)
* removed all zero refcount inodes, in any case. Test to * removed all zero refcount inodes, in any case. Test to
* be sure. * be sure.
*/ */
if (!atomic_read(&inode->i_count)) { if (!icount_read(inode)) {
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
continue; continue;
} }

View File

@ -2844,7 +2844,7 @@ int cifs_revalidate_dentry_attr(struct dentry *dentry)
} }
cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n", cifs_dbg(FYI, "Update attributes: %s inode 0x%p count %d dentry: 0x%p d_time %ld jiffies %ld\n",
full_path, inode, inode->i_count.counter, full_path, inode, icount_read(inode),
dentry, cifs_get_time(dentry), jiffies); dentry, cifs_get_time(dentry), jiffies);
again: again:

View File

@ -88,6 +88,8 @@ int ubifs_decrypt(const struct inode *inode, struct ubifs_data_node *dn,
} }
const struct fscrypt_operations ubifs_crypt_operations = { const struct fscrypt_operations ubifs_crypt_operations = {
.inode_info_offs = (int)offsetof(struct ubifs_inode, i_crypt_info) -
(int)offsetof(struct ubifs_inode, vfs_inode),
.legacy_key_prefix = "ubifs:", .legacy_key_prefix = "ubifs:",
.get_context = ubifs_crypt_get_context, .get_context = ubifs_crypt_get_context,
.set_context = ubifs_crypt_set_context, .set_context = ubifs_crypt_set_context,

View File

@ -358,7 +358,7 @@ static void ubifs_evict_inode(struct inode *inode)
goto out; goto out;
dbg_gen("inode %lu, mode %#x", inode->i_ino, (int)inode->i_mode); dbg_gen("inode %lu, mode %#x", inode->i_ino, (int)inode->i_mode);
ubifs_assert(c, !atomic_read(&inode->i_count)); ubifs_assert(c, !icount_read(inode));
truncate_inode_pages_final(&inode->i_data); truncate_inode_pages_final(&inode->i_data);

View File

@ -365,6 +365,7 @@ struct ubifs_gced_idx_leb {
* @read_in_a_row: number of consecutive pages read in a row (for bulk read) * @read_in_a_row: number of consecutive pages read in a row (for bulk read)
* @data_len: length of the data attached to the inode * @data_len: length of the data attached to the inode
* @data: inode's data * @data: inode's data
* @i_crypt_info: inode's fscrypt information
* *
* @ui_mutex exists for two main reasons. At first it prevents inodes from * @ui_mutex exists for two main reasons. At first it prevents inodes from
* being written back while UBIFS changing them, being in the middle of an VFS * being written back while UBIFS changing them, being in the middle of an VFS
@ -416,6 +417,9 @@ struct ubifs_inode {
pgoff_t read_in_a_row; pgoff_t read_in_a_row;
int data_len; int data_len;
void *data; void *data;
#ifdef CONFIG_FS_ENCRYPTION
struct fscrypt_inode_info *i_crypt_info;
#endif
}; };
/** /**

View File

@ -284,9 +284,9 @@ static int enable_verity(struct file *filp,
/* Successfully enabled verity */ /* Successfully enabled verity */
/* /*
* Readers can start using ->i_verity_info immediately, so it * Readers can start using the inode's verity info immediately,
* can't be rolled back once set. So don't set it until just * so it can't be rolled back once set. So don't set it until
* after the filesystem has successfully enabled verity. * just after the filesystem has successfully enabled verity.
*/ */
fsverity_set_info(inode, vi); fsverity_set_info(inode, vi);
} }

View File

@ -63,10 +63,11 @@ struct merkle_tree_params {
* fsverity_info - cached verity metadata for an inode * fsverity_info - cached verity metadata for an inode
* *
* When a verity file is first opened, an instance of this struct is allocated * 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 a pointer to it is stored in the file's in-memory inode. It remains
* caches information about the Merkle tree that's needed to efficiently verify * until the inode is evicted. It caches information about the Merkle tree
* data read from the file. It also caches the file digest. The Merkle tree * that's needed to efficiently verify data read from the file. It also caches
* pages themselves are not cached here, but the filesystem may cache them. * the file digest. The Merkle tree pages themselves are not cached here, but
* the filesystem may cache them.
*/ */
struct fsverity_info { struct fsverity_info {
struct merkle_tree_params tree_params; struct merkle_tree_params tree_params;

View File

@ -244,17 +244,17 @@ struct fsverity_info *fsverity_create_info(const struct inode *inode,
void fsverity_set_info(struct inode *inode, struct fsverity_info *vi) 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 pointer, so
* cmpxchg_release(). This pairs with the smp_load_acquire() in * 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., publish the pointer with a RELEASE
* RELEASE barrier so that other tasks can ACQUIRE it. * barrier so that other tasks can ACQUIRE it.
*/ */
if (cmpxchg_release(&inode->i_verity_info, NULL, vi) != NULL) { if (cmpxchg_release(fsverity_info_addr(inode), NULL, vi) != NULL) {
/* Lost the race, so free the fsverity_info we allocated. */ /* Lost the race, so free the verity info we allocated. */
fsverity_free_info(vi); fsverity_free_info(vi);
/* /*
* Afterwards, the caller may access ->i_verity_info directly, * Afterwards, the caller may access the inode's verity info
* so make sure to ACQUIRE the winning fsverity_info. * directly, so make sure to ACQUIRE the winning verity info.
*/ */
(void)fsverity_get_info(inode); (void)fsverity_get_info(inode);
} }
@ -350,7 +350,6 @@ int fsverity_get_descriptor(struct inode *inode,
return 0; return 0;
} }
/* Ensure the inode has an ->i_verity_info */
static int ensure_verity_info(struct inode *inode) static int ensure_verity_info(struct inode *inode)
{ {
struct fsverity_info *vi = fsverity_get_info(inode); struct fsverity_info *vi = fsverity_get_info(inode);
@ -395,8 +394,10 @@ EXPORT_SYMBOL_GPL(__fsverity_prepare_setattr);
void __fsverity_cleanup_inode(struct inode *inode) void __fsverity_cleanup_inode(struct inode *inode)
{ {
fsverity_free_info(inode->i_verity_info); struct fsverity_info **vi_addr = fsverity_info_addr(inode);
inode->i_verity_info = NULL;
fsverity_free_info(*vi_addr);
*vi_addr = NULL;
} }
EXPORT_SYMBOL_GPL(__fsverity_cleanup_inode); EXPORT_SYMBOL_GPL(__fsverity_cleanup_inode);

View File

@ -245,7 +245,7 @@ verify_data_blocks(struct folio *data_folio, size_t len, size_t offset,
unsigned long max_ra_pages) unsigned long max_ra_pages)
{ {
struct inode *inode = data_folio->mapping->host; struct inode *inode = data_folio->mapping->host;
struct fsverity_info *vi = inode->i_verity_info; struct fsverity_info *vi = *fsverity_info_addr(inode);
const unsigned int block_size = vi->tree_params.block_size; const unsigned int block_size = vi->tree_params.block_size;
u64 pos = (u64)data_folio->index << PAGE_SHIFT; u64 pos = (u64)data_folio->index << PAGE_SHIFT;

View File

@ -1035,7 +1035,7 @@ xfs_itruncate_extents_flags(
int error = 0; int error = 0;
xfs_assert_ilocked(ip, XFS_ILOCK_EXCL); xfs_assert_ilocked(ip, XFS_ILOCK_EXCL);
if (atomic_read(&VFS_I(ip)->i_count)) if (icount_read(VFS_I(ip)))
xfs_assert_ilocked(ip, XFS_IOLOCK_EXCL); xfs_assert_ilocked(ip, XFS_IOLOCK_EXCL);
ASSERT(new_size <= XFS_ISIZE(ip)); ASSERT(new_size <= XFS_ISIZE(ip));
ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);

View File

@ -1152,7 +1152,7 @@ DECLARE_EVENT_CLASS(xfs_iref_class,
TP_fast_assign( TP_fast_assign(
__entry->dev = VFS_I(ip)->i_sb->s_dev; __entry->dev = VFS_I(ip)->i_sb->s_dev;
__entry->ino = ip->i_ino; __entry->ino = ip->i_ino;
__entry->count = atomic_read(&VFS_I(ip)->i_count); __entry->count = icount_read(VFS_I(ip));
__entry->pincount = atomic_read(&ip->i_pincount); __entry->pincount = atomic_read(&ip->i_pincount);
__entry->iflags = ip->i_flags; __entry->iflags = ip->i_flags;
__entry->caller_ip = caller_ip; __entry->caller_ip = caller_ip;

View File

@ -72,9 +72,7 @@ struct swap_info_struct;
struct seq_file; struct seq_file;
struct workqueue_struct; struct workqueue_struct;
struct iov_iter; struct iov_iter;
struct fscrypt_inode_info;
struct fscrypt_operations; struct fscrypt_operations;
struct fsverity_info;
struct fsverity_operations; struct fsverity_operations;
struct fsnotify_mark_connector; struct fsnotify_mark_connector;
struct fsnotify_sb_info; struct fsnotify_sb_info;
@ -668,6 +666,124 @@ is_uncached_acl(struct posix_acl *acl)
#define IOP_MGTIME 0x0020 #define IOP_MGTIME 0x0020
#define IOP_CACHED_LINK 0x0040 #define IOP_CACHED_LINK 0x0040
/*
* Inode state bits. Protected by inode->i_lock
*
* Four bits determine the dirty state of the inode: I_DIRTY_SYNC,
* I_DIRTY_DATASYNC, I_DIRTY_PAGES, and I_DIRTY_TIME.
*
* Four bits define the lifetime of an inode. Initially, inodes are I_NEW,
* until that flag is cleared. I_WILL_FREE, I_FREEING and I_CLEAR are set at
* various stages of removing an inode.
*
* Two bits are used for locking and completion notification, I_NEW and I_SYNC.
*
* I_DIRTY_SYNC Inode is dirty, but doesn't have to be written on
* fdatasync() (unless I_DIRTY_DATASYNC is also set).
* Timestamp updates are the usual cause.
* I_DIRTY_DATASYNC Data-related inode changes pending. We keep track of
* these changes separately from I_DIRTY_SYNC so that we
* don't have to write inode on fdatasync() when only
* e.g. the timestamps have changed.
* I_DIRTY_PAGES Inode has dirty pages. Inode itself may be clean.
* I_DIRTY_TIME The inode itself has dirty timestamps, and the
* lazytime mount option is enabled. We keep track of this
* separately from I_DIRTY_SYNC in order to implement
* lazytime. This gets cleared if I_DIRTY_INODE
* (I_DIRTY_SYNC and/or I_DIRTY_DATASYNC) gets set. But
* I_DIRTY_TIME can still be set if I_DIRTY_SYNC is already
* in place because writeback might already be in progress
* and we don't want to lose the time update
* I_NEW Serves as both a mutex and completion notification.
* New inodes set I_NEW. If two processes both create
* the same inode, one of them will release its inode and
* wait for I_NEW to be released before returning.
* Inodes in I_WILL_FREE, I_FREEING or I_CLEAR state can
* also cause waiting on I_NEW, without I_NEW actually
* being set. find_inode() uses this to prevent returning
* nearly-dead inodes.
* I_WILL_FREE Must be set when calling write_inode_now() if i_count
* is zero. I_FREEING must be set when I_WILL_FREE is
* cleared.
* I_FREEING Set when inode is about to be freed but still has dirty
* pages or buffers attached or the inode itself is still
* dirty.
* I_CLEAR Added by clear_inode(). In this state the inode is
* clean and can be destroyed. Inode keeps I_FREEING.
*
* Inodes that are I_WILL_FREE, I_FREEING or I_CLEAR are
* prohibited for many purposes. iget() must wait for
* the inode to be completely released, then create it
* anew. Other functions will just ignore such inodes,
* if appropriate. I_NEW is used for waiting.
*
* I_SYNC Writeback of inode is running. The bit is set during
* data writeback, and cleared with a wakeup on the bit
* address once it is done. The bit is also used to pin
* the inode in memory for flusher thread.
*
* I_REFERENCED Marks the inode as recently references on the LRU list.
*
* I_WB_SWITCH Cgroup bdi_writeback switching in progress. Used to
* synchronize competing switching instances and to tell
* wb stat updates to grab the i_pages lock. See
* inode_switch_wbs_work_fn() for details.
*
* I_OVL_INUSE Used by overlayfs to get exclusive ownership on upper
* and work dirs among overlayfs mounts.
*
* I_CREATING New object's inode in the middle of setting up.
*
* I_DONTCACHE Evict inode as soon as it is not used anymore.
*
* I_SYNC_QUEUED Inode is queued in b_io or b_more_io writeback lists.
* Used to detect that mark_inode_dirty() should not move
* inode between dirty lists.
*
* I_PINNING_FSCACHE_WB Inode is pinning an fscache object for writeback.
*
* I_LRU_ISOLATING Inode is pinned being isolated from LRU without holding
* i_count.
*
* Q: What is the difference between I_WILL_FREE and I_FREEING?
*
* __I_{SYNC,NEW,LRU_ISOLATING} are used to derive unique addresses to wait
* upon. There's one free address left.
*/
enum inode_state_bits {
__I_NEW = 0U,
__I_SYNC = 1U,
__I_LRU_ISOLATING = 2U
/* reserved wait address bit 3 */
};
enum inode_state_flags_t {
I_NEW = (1U << __I_NEW),
I_SYNC = (1U << __I_SYNC),
I_LRU_ISOLATING = (1U << __I_LRU_ISOLATING),
/* reserved flag bit 3 */
I_DIRTY_SYNC = (1U << 4),
I_DIRTY_DATASYNC = (1U << 5),
I_DIRTY_PAGES = (1U << 6),
I_WILL_FREE = (1U << 7),
I_FREEING = (1U << 8),
I_CLEAR = (1U << 9),
I_REFERENCED = (1U << 10),
I_LINKABLE = (1U << 11),
I_DIRTY_TIME = (1U << 12),
I_WB_SWITCH = (1U << 13),
I_OVL_INUSE = (1U << 14),
I_CREATING = (1U << 15),
I_DONTCACHE = (1U << 16),
I_SYNC_QUEUED = (1U << 17),
I_PINNING_NETFS_WB = (1U << 18)
};
#define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC)
#define I_DIRTY (I_DIRTY_INODE | I_DIRTY_PAGES)
#define I_DIRTY_ALL (I_DIRTY | I_DIRTY_TIME)
/* /*
* Keep mostly read-only and often accessed (especially for * Keep mostly read-only and often accessed (especially for
* the RCU path lookup and 'stat' data) fields at the beginning * the RCU path lookup and 'stat' data) fields at the beginning
@ -726,7 +842,7 @@ struct inode {
#endif #endif
/* Misc */ /* Misc */
u32 i_state; enum inode_state_flags_t i_state;
/* 32-bit hole */ /* 32-bit hole */
struct rw_semaphore i_rwsem; struct rw_semaphore i_rwsem;
@ -782,14 +898,6 @@ struct inode {
struct fsnotify_mark_connector __rcu *i_fsnotify_marks; struct fsnotify_mark_connector __rcu *i_fsnotify_marks;
#endif #endif
#ifdef CONFIG_FS_ENCRYPTION
struct fscrypt_inode_info *i_crypt_info;
#endif
#ifdef CONFIG_FS_VERITY
struct fsverity_info *i_verity_info;
#endif
void *i_private; /* fs or device private pointer */ void *i_private; /* fs or device private pointer */
} __randomize_layout; } __randomize_layout;
@ -2492,117 +2600,6 @@ static inline void kiocb_clone(struct kiocb *kiocb, struct kiocb *kiocb_src,
}; };
} }
/*
* Inode state bits. Protected by inode->i_lock
*
* Four bits determine the dirty state of the inode: I_DIRTY_SYNC,
* I_DIRTY_DATASYNC, I_DIRTY_PAGES, and I_DIRTY_TIME.
*
* Four bits define the lifetime of an inode. Initially, inodes are I_NEW,
* until that flag is cleared. I_WILL_FREE, I_FREEING and I_CLEAR are set at
* various stages of removing an inode.
*
* Two bits are used for locking and completion notification, I_NEW and I_SYNC.
*
* I_DIRTY_SYNC Inode is dirty, but doesn't have to be written on
* fdatasync() (unless I_DIRTY_DATASYNC is also set).
* Timestamp updates are the usual cause.
* I_DIRTY_DATASYNC Data-related inode changes pending. We keep track of
* these changes separately from I_DIRTY_SYNC so that we
* don't have to write inode on fdatasync() when only
* e.g. the timestamps have changed.
* I_DIRTY_PAGES Inode has dirty pages. Inode itself may be clean.
* I_DIRTY_TIME The inode itself has dirty timestamps, and the
* lazytime mount option is enabled. We keep track of this
* separately from I_DIRTY_SYNC in order to implement
* lazytime. This gets cleared if I_DIRTY_INODE
* (I_DIRTY_SYNC and/or I_DIRTY_DATASYNC) gets set. But
* I_DIRTY_TIME can still be set if I_DIRTY_SYNC is already
* in place because writeback might already be in progress
* and we don't want to lose the time update
* I_NEW Serves as both a mutex and completion notification.
* New inodes set I_NEW. If two processes both create
* the same inode, one of them will release its inode and
* wait for I_NEW to be released before returning.
* Inodes in I_WILL_FREE, I_FREEING or I_CLEAR state can
* also cause waiting on I_NEW, without I_NEW actually
* being set. find_inode() uses this to prevent returning
* nearly-dead inodes.
* I_WILL_FREE Must be set when calling write_inode_now() if i_count
* is zero. I_FREEING must be set when I_WILL_FREE is
* cleared.
* I_FREEING Set when inode is about to be freed but still has dirty
* pages or buffers attached or the inode itself is still
* dirty.
* I_CLEAR Added by clear_inode(). In this state the inode is
* clean and can be destroyed. Inode keeps I_FREEING.
*
* Inodes that are I_WILL_FREE, I_FREEING or I_CLEAR are
* prohibited for many purposes. iget() must wait for
* the inode to be completely released, then create it
* anew. Other functions will just ignore such inodes,
* if appropriate. I_NEW is used for waiting.
*
* I_SYNC Writeback of inode is running. The bit is set during
* data writeback, and cleared with a wakeup on the bit
* address once it is done. The bit is also used to pin
* the inode in memory for flusher thread.
*
* I_REFERENCED Marks the inode as recently references on the LRU list.
*
* I_WB_SWITCH Cgroup bdi_writeback switching in progress. Used to
* synchronize competing switching instances and to tell
* wb stat updates to grab the i_pages lock. See
* inode_switch_wbs_work_fn() for details.
*
* I_OVL_INUSE Used by overlayfs to get exclusive ownership on upper
* and work dirs among overlayfs mounts.
*
* I_CREATING New object's inode in the middle of setting up.
*
* I_DONTCACHE Evict inode as soon as it is not used anymore.
*
* I_SYNC_QUEUED Inode is queued in b_io or b_more_io writeback lists.
* Used to detect that mark_inode_dirty() should not move
* inode between dirty lists.
*
* I_PINNING_FSCACHE_WB Inode is pinning an fscache object for writeback.
*
* I_LRU_ISOLATING Inode is pinned being isolated from LRU without holding
* i_count.
*
* Q: What is the difference between I_WILL_FREE and I_FREEING?
*
* __I_{SYNC,NEW,LRU_ISOLATING} are used to derive unique addresses to wait
* upon. There's one free address left.
*/
#define __I_NEW 0
#define I_NEW (1 << __I_NEW)
#define __I_SYNC 1
#define I_SYNC (1 << __I_SYNC)
#define __I_LRU_ISOLATING 2
#define I_LRU_ISOLATING (1 << __I_LRU_ISOLATING)
#define I_DIRTY_SYNC (1 << 3)
#define I_DIRTY_DATASYNC (1 << 4)
#define I_DIRTY_PAGES (1 << 5)
#define I_WILL_FREE (1 << 6)
#define I_FREEING (1 << 7)
#define I_CLEAR (1 << 8)
#define I_REFERENCED (1 << 9)
#define I_LINKABLE (1 << 10)
#define I_DIRTY_TIME (1 << 11)
#define I_WB_SWITCH (1 << 12)
#define I_OVL_INUSE (1 << 13)
#define I_CREATING (1 << 14)
#define I_DONTCACHE (1 << 15)
#define I_SYNC_QUEUED (1 << 16)
#define I_PINNING_NETFS_WB (1 << 17)
#define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC)
#define I_DIRTY (I_DIRTY_INODE | I_DIRTY_PAGES)
#define I_DIRTY_ALL (I_DIRTY | I_DIRTY_TIME)
extern void __mark_inode_dirty(struct inode *, int); extern void __mark_inode_dirty(struct inode *, int);
static inline void mark_inode_dirty(struct inode *inode) static inline void mark_inode_dirty(struct inode *inode)
{ {
@ -2614,6 +2611,11 @@ static inline void mark_inode_dirty_sync(struct inode *inode)
__mark_inode_dirty(inode, I_DIRTY_SYNC); __mark_inode_dirty(inode, I_DIRTY_SYNC);
} }
static inline int icount_read(const struct inode *inode)
{
return atomic_read(&inode->i_count);
}
/* /*
* Returns true if the given inode itself only has dirty timestamps (its pages * Returns true if the given inode itself only has dirty timestamps (its pages
* may still be dirty) and isn't currently being allocated or freed. * may still be dirty) and isn't currently being allocated or freed.

View File

@ -61,6 +61,12 @@ struct fscrypt_name {
/* Crypto operations for filesystems */ /* Crypto operations for filesystems */
struct fscrypt_operations { struct fscrypt_operations {
/*
* The offset of the pointer to struct fscrypt_inode_info in the
* filesystem-specific part of the inode, relative to the beginning of
* the common part of the inode (the 'struct inode').
*/
ptrdiff_t inode_info_offs;
/* /*
* If set, then fs/crypto/ will allocate a global bounce page pool the * If set, then fs/crypto/ will allocate a global bounce page pool the
@ -195,16 +201,44 @@ struct fscrypt_operations {
int fscrypt_d_revalidate(struct inode *dir, const struct qstr *name, int fscrypt_d_revalidate(struct inode *dir, const struct qstr *name,
struct dentry *dentry, unsigned int flags); struct dentry *dentry, unsigned int flags);
/*
* Returns the address of the fscrypt info pointer within the
* filesystem-specific part of the inode. (To save memory on filesystems that
* don't support fscrypt, a field in 'struct inode' itself is no longer used.)
*/
static inline struct fscrypt_inode_info **
fscrypt_inode_info_addr(const struct inode *inode)
{
VFS_WARN_ON_ONCE(inode->i_sb->s_cop->inode_info_offs == 0);
return (void *)inode + inode->i_sb->s_cop->inode_info_offs;
}
/*
* Load the inode's fscrypt info pointer, using a raw dereference. Since this
* uses a raw dereference with no memory barrier, it is appropriate to use only
* when the caller knows the inode's key setup already happened, resulting in
* non-NULL fscrypt info. E.g., the file contents en/decryption functions use
* this, since fscrypt_file_open() set up the key.
*/
static inline struct fscrypt_inode_info *
fscrypt_get_inode_info_raw(const struct inode *inode)
{
struct fscrypt_inode_info *ci = *fscrypt_inode_info_addr(inode);
VFS_WARN_ON_ONCE(ci == NULL);
return ci;
}
static inline struct fscrypt_inode_info * static inline struct fscrypt_inode_info *
fscrypt_get_inode_info(const struct inode *inode) fscrypt_get_inode_info(const struct inode *inode)
{ {
/* /*
* Pairs with the cmpxchg_release() in fscrypt_setup_encryption_info(). * 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 the fscrypt info concurrently,
* a RELEASE barrier. We need to use smp_load_acquire() here to safely * executing a RELEASE barrier. Use smp_load_acquire() here to safely
* ACQUIRE the memory the other task published. * ACQUIRE the memory the other task published.
*/ */
return smp_load_acquire(&inode->i_crypt_info); return smp_load_acquire(fscrypt_inode_info_addr(inode));
} }
/** /**

View File

@ -26,8 +26,16 @@
/* Arbitrary limit to bound the kmalloc() size. Can be changed. */ /* Arbitrary limit to bound the kmalloc() size. Can be changed. */
#define FS_VERITY_MAX_DESCRIPTOR_SIZE 16384 #define FS_VERITY_MAX_DESCRIPTOR_SIZE 16384
struct fsverity_info;
/* Verity operations for filesystems */ /* Verity operations for filesystems */
struct fsverity_operations { struct fsverity_operations {
/**
* The offset of the pointer to struct fsverity_info in the
* filesystem-specific part of the inode, relative to the beginning of
* the common part of the inode (the 'struct inode').
*/
ptrdiff_t inode_info_offs;
/** /**
* Begin enabling verity on the given file. * Begin enabling verity on the given file.
@ -124,15 +132,37 @@ struct fsverity_operations {
#ifdef CONFIG_FS_VERITY #ifdef CONFIG_FS_VERITY
/*
* Returns the address of the verity info pointer within the filesystem-specific
* part of the inode. (To save memory on filesystems that don't support
* fsverity, a field in 'struct inode' itself is no longer used.)
*/
static inline struct fsverity_info **
fsverity_info_addr(const struct inode *inode)
{
VFS_WARN_ON_ONCE(inode->i_sb->s_vop->inode_info_offs == 0);
return (void *)inode + inode->i_sb->s_vop->inode_info_offs;
}
static inline struct fsverity_info *fsverity_get_info(const struct inode *inode) static inline struct fsverity_info *fsverity_get_info(const struct inode *inode)
{ {
/* /*
* Pairs with the cmpxchg_release() in fsverity_set_info(). * Since this function can be called on inodes belonging to filesystems
* I.e., another task may publish ->i_verity_info concurrently, * that don't support fsverity at all, and fsverity_info_addr() doesn't
* executing a RELEASE barrier. We need to use smp_load_acquire() here * work on such filesystems, we have to start with an IS_VERITY() check.
* to safely ACQUIRE the memory the other task published. * Checking IS_VERITY() here is also useful to minimize the overhead of
* fsverity_active() on non-verity files.
*/ */
return smp_load_acquire(&inode->i_verity_info); if (!IS_VERITY(inode))
return NULL;
/*
* Pairs with the cmpxchg_release() in fsverity_set_info(). I.e.,
* another task may publish the inode's verity info concurrently,
* executing a RELEASE barrier. Use smp_load_acquire() here to safely
* ACQUIRE the memory the other task published.
*/
return smp_load_acquire(fsverity_info_addr(inode));
} }
/* enable.c */ /* enable.c */
@ -156,12 +186,19 @@ void __fsverity_cleanup_inode(struct inode *inode);
* fsverity_cleanup_inode() - free the inode's verity info, if present * fsverity_cleanup_inode() - free the inode's verity info, if present
* @inode: an inode being evicted * @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) static inline void fsverity_cleanup_inode(struct inode *inode)
{ {
if (inode->i_verity_info) /*
* Only IS_VERITY() inodes can have verity info, so start by checking
* for IS_VERITY() (which is faster than retrieving the pointer to the
* verity info). This minimizes overhead for non-verity inodes.
*/
if (IS_VERITY(inode))
__fsverity_cleanup_inode(inode); __fsverity_cleanup_inode(inode);
else
VFS_WARN_ON_ONCE(*fsverity_info_addr(inode) != NULL);
} }
/* read_metadata.c */ /* read_metadata.c */
@ -267,12 +304,12 @@ static inline bool fsverity_verify_page(struct page *page)
* fsverity_active() - do reads from the inode need to go through fs-verity? * fsverity_active() - do reads from the inode need to go through fs-verity?
* @inode: inode to check * @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 * 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 * 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 * 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 verity info.)
* *
* Return: true if reads need to go through fs-verity, otherwise false * Return: true if reads need to go through fs-verity, otherwise false
*/ */
@ -287,7 +324,7 @@ static inline bool fsverity_active(const struct inode *inode)
* @filp: the struct file being set up * @filp: the struct file being set up
* *
* When opening a verity file, deny the open if it is for writing. Otherwise, * 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(). * 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. * Otherwise, we won't have the key set up to decrypt the verity metadata.

View File

@ -190,7 +190,7 @@ TRACE_EVENT(generic_add_lease,
__entry->i_ino = inode->i_ino; __entry->i_ino = inode->i_ino;
__entry->wcount = atomic_read(&inode->i_writecount); __entry->wcount = atomic_read(&inode->i_writecount);
__entry->rcount = atomic_read(&inode->i_readcount); __entry->rcount = atomic_read(&inode->i_readcount);
__entry->icount = atomic_read(&inode->i_count); __entry->icount = icount_read(inode);
__entry->owner = fl->c.flc_owner; __entry->owner = fl->c.flc_owner;
__entry->flags = fl->c.flc_flags; __entry->flags = fl->c.flc_flags;
__entry->type = fl->c.flc_type; __entry->type = fl->c.flc_type;

View File

@ -1281,7 +1281,7 @@ static void hook_sb_delete(struct super_block *const sb)
struct landlock_object *object; struct landlock_object *object;
/* Only handles referenced inodes. */ /* Only handles referenced inodes. */
if (!atomic_read(&inode->i_count)) if (!icount_read(inode))
continue; continue;
/* /*