In order to notify extents when their info is part of a master key which is going away, the fscrypt_info must have a backpointer to the extent somehow. Similarly, if a fscrypt_info is owned by an extent, the info must not have a pointer to an inode -- multiple inodes may reference a extent, and the first inode to cause an extent's creation may have a lifetime much shorter than the extent, so there is no inode pointer safe to track in an extent-owned info. Therefore, this adds a new pointer for extent-owned infos to track their extent and updates fscrypt_setup_encryption_info() accordingly. Since it's simple to track the piece of extent memory pointing to the info, and for the extent to then go from such a pointer to the whole extent via container_of(), we store that. Although some sort of generic void * or some artificial fscrypt_extent embedded structure would also work, those would require additional plumbing which doesn't seem strictly required or clarifying. Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@xxxxxxxxxx> --- fs/crypto/fscrypt_private.h | 6 ++++++ fs/crypto/keysetup.c | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 0c7b785f1d8c..dc45cd35391f 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -229,6 +229,12 @@ struct fscrypt_info { /* Back-pointer to the inode, for infos owned by a specific inode */ struct inode *ci_inode; + /* + * Back-pointer to the info pointer in the extent, for infos owned + * by an extent + */ + struct fscrypt_info **ci_info_ptr; + /* The superblock of the filesystem to which this fscrypt_info pertains */ struct super_block *ci_sb; diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c index 04f01da900ca..c611e2613aa6 100644 --- a/fs/crypto/keysetup.c +++ b/fs/crypto/keysetup.c @@ -567,7 +567,11 @@ fscrypt_setup_encryption_info(struct inode *inode, if (!crypt_info) return -ENOMEM; - crypt_info->ci_inode = inode; + if (fscrypt_uses_extent_encryption(inode)) + crypt_info->ci_info_ptr = info_ptr; + else + crypt_info->ci_inode = inode; + crypt_info->ci_sb = inode->i_sb; crypt_info->ci_policy = *policy; memcpy(crypt_info->ci_nonce, nonce, FSCRYPT_FILE_NONCE_SIZE); -- 2.38.1