From: Sweet Tea Dorminy <[email protected]> Each extent_map will end up with a pointer to its associated fscrypt_info if any, which should have the same lifetime as the extent_map. We are also going to need to track the encryption_type for the file extent items. Add the fscrypt_info to the extent_map and the subsequent code for transferring it in the split and merge cases as well as the code necessary to free them. A future patch will add the code to load them as appropriate.
Signed-off-by: Sweet Tea Dorminy <[email protected]> Signed-off-by: Josef Bacik <[email protected]> Signed-off-by: Daniel Vacek <[email protected]> --- v5: https://lore.kernel.org/linux-btrfs/9818cd4134d048d2d641b9b8ae10be6c6af51956.1706116485.git.jo...@toxicpanda.com/ * No significant changes since. Just add some btrfs_ prefixes even to static functions in extent map header file to match the style. --- fs/btrfs/extent_map.c | 32 +++++++++++++++++++++++++++++--- fs/btrfs/extent_map.h | 16 ++++++++++++++++ fs/btrfs/file-item.c | 1 + fs/btrfs/inode.c | 1 + 4 files changed, 47 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index 58589fc11802..f6b58a5c1151 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c @@ -59,6 +59,7 @@ struct extent_map *btrfs_alloc_extent_map(void) static void free_extent_map(struct extent_map *em) { + fscrypt_put_extent_info(em->fscrypt_info); kmem_cache_free(extent_map_cache, em); } @@ -99,12 +100,24 @@ void btrfs_free_extent_map_safe(struct extent_map_tree *tree, if (!em) return; - if (refcount_dec_and_test(&em->refs)) { - WARN_ON(btrfs_extent_map_in_tree(em)); - WARN_ON(!list_empty(&em->list)); + if (!refcount_dec_and_test(&em->refs)) + return; + + WARN_ON(btrfs_extent_map_in_tree(em)); + WARN_ON(!list_empty(&em->list)); + + /* + * We could take a lock freeing the fscrypt_info, so add this to the + * list of freed_extents to be freed later. + */ + if (em->fscrypt_info) { list_add_tail(&em->free_list, &tree->freed_extents); set_bit(EXTENT_MAP_TREE_PENDING_FREES, &tree->flags); + return; } + + /* Nothing scary here, just free the object. */ + free_extent_map(em); } /* @@ -291,6 +304,10 @@ static bool can_merge_extent_map(const struct extent_map *em) if (!list_empty(&em->list)) return false; + /* We can't merge encrypted extents. */ + if (em->fscrypt_info) + return false; + return true; } @@ -311,6 +328,10 @@ static bool mergeable_maps(const struct extent_map *prev, const struct extent_ma if (next->disk_bytenr < EXTENT_MAP_LAST_BYTE - 1) return btrfs_extent_map_block_start(next) == extent_map_block_end(prev); + /* Don't merge adjacent encrypted maps. */ + if (prev->fscrypt_info || next->fscrypt_info) + return false; + /* HOLES and INLINE extents. */ return next->disk_bytenr == prev->disk_bytenr; } @@ -977,6 +998,7 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end, split->generation = gen; split->flags = flags; + split->fscrypt_info = fscrypt_get_extent_info(em->fscrypt_info); replace_extent_mapping(inode, em, split, modified); btrfs_free_extent_map(split); split = split2; @@ -1005,6 +1027,7 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end, split->ram_bytes = split->len; } + split->fscrypt_info = fscrypt_get_extent_info(em->fscrypt_info); if (btrfs_extent_map_in_tree(em)) { replace_extent_mapping(inode, em, split, modified); } else { @@ -1163,6 +1186,7 @@ int btrfs_split_extent_map(struct btrfs_inode *inode, u64 start, u64 len, u64 pr split_pre->ram_bytes = split_pre->len; split_pre->flags = flags; split_pre->generation = em->generation; + split_pre->fscrypt_info = fscrypt_get_extent_info(em->fscrypt_info); replace_extent_mapping(inode, em, split_pre, true); @@ -1180,6 +1204,8 @@ int btrfs_split_extent_map(struct btrfs_inode *inode, u64 start, u64 len, u64 pr split_mid->ram_bytes = split_mid->len; split_mid->flags = flags; split_mid->generation = em->generation; + split_mid->fscrypt_info = fscrypt_get_extent_info(em->fscrypt_info); + add_extent_mapping(inode, split_mid, true); /* Once for us */ diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h index a962012be1c3..a0d5be758e7e 100644 --- a/fs/btrfs/extent_map.h +++ b/fs/btrfs/extent_map.h @@ -24,6 +24,7 @@ enum { ENUM_BIT(EXTENT_FLAG_COMPRESS_ZLIB), ENUM_BIT(EXTENT_FLAG_COMPRESS_LZO), ENUM_BIT(EXTENT_FLAG_COMPRESS_ZSTD), + ENUM_BIT(EXTENT_FLAG_ENCRYPT_FSCRYPT), /* pre-allocated extent */ ENUM_BIT(EXTENT_FLAG_PREALLOC), /* Logging this extent */ @@ -96,6 +97,7 @@ struct extent_map { u64 generation; u32 flags; refcount_t refs; + struct fscrypt_extent_info *fscrypt_info; struct list_head list; struct list_head free_list; }; @@ -114,6 +116,20 @@ struct extent_map_tree { struct btrfs_inode; +static inline void btrfs_extent_map_set_encryption(struct extent_map *em, + enum btrfs_encryption_type type) +{ + if (type == BTRFS_ENCRYPTION_FSCRYPT) + em->flags |= EXTENT_FLAG_ENCRYPT_FSCRYPT; +} + +static inline enum btrfs_encryption_type btrfs_extent_map_encryption(const struct extent_map *em) +{ + if (em->flags & EXTENT_FLAG_ENCRYPT_FSCRYPT) + return BTRFS_ENCRYPTION_FSCRYPT; + return BTRFS_ENCRYPTION_NONE; +} + static inline void btrfs_extent_map_set_compression(struct extent_map *em, enum btrfs_compression_type type) { diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index 7bd715442f3e..08dc78295707 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c @@ -1357,6 +1357,7 @@ void btrfs_extent_item_to_extent_map(struct btrfs_inode *inode, if (type == BTRFS_FILE_EXTENT_PREALLOC) em->flags |= EXTENT_FLAG_PREALLOC; } + btrfs_extent_map_set_encryption(em, btrfs_file_extent_encryption(leaf, fi)); } else if (type == BTRFS_FILE_EXTENT_INLINE) { /* Tree-checker has ensured this. */ ASSERT(extent_start == 0); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 758dde148be6..b425047f77c7 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -7580,6 +7580,7 @@ struct extent_map *btrfs_create_io_em(struct btrfs_inode *inode, u64 start, em->flags |= EXTENT_FLAG_PINNED; if (type == BTRFS_ORDERED_COMPRESSED) btrfs_extent_map_set_compression(em, file_extent->compression); + btrfs_extent_map_set_encryption(em, BTRFS_ENCRYPTION_NONE); ret = btrfs_replace_extent_map_range(inode, em, true); if (ret) { -- 2.51.0
