[PATCH v7 22/43] btrfs: populate the ordered_extent with the fscrypt context

From: Daniel Vacek

Date: Wed May 13 2026 - 05:13:05 EST


From: Josef Bacik <josef@xxxxxxxxxxxxxx>

The fscrypt_extent_info will be tied to the extent_map lifetime, so it
will be created when we create the IO em, or it'll already exist in the
NOCOW case. Use this fscrypt_info when creating the ordered extent to
make sure everything is passed through properly.

Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
Signed-off-by: Daniel Vacek <neelx@xxxxxxxx>
---

No changes in v7.
v6 changes:
* Splitted the dio-related hunks from inode.c to direct-io.c as upstream
refactored in the meantime.
* Pass fscrypt_info using the file_extent structure to follow the
upstream cleanup.
v5: https://lore.kernel.org/linux-btrfs/33e650f3e91ed0318211301beb27fa613382f28e.1706116485.git.josef@xxxxxxxxxxxxxx/
---
fs/btrfs/direct-io.c | 4 +++-
fs/btrfs/inode.c | 36 ++++++++++++++++++++++++++++++------
2 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/fs/btrfs/direct-io.c b/fs/btrfs/direct-io.c
index 5a53739e9445..e46bca590f35 100644
--- a/fs/btrfs/direct-io.c
+++ b/fs/btrfs/direct-io.c
@@ -140,7 +140,7 @@ static int lock_extent_direct(struct inode *inode, u64 lockstart, u64 lockend,
static struct extent_map *btrfs_create_dio_extent(struct btrfs_inode *inode,
struct btrfs_dio_data *dio_data,
const u64 start,
- const struct btrfs_file_extent *file_extent,
+ struct btrfs_file_extent *file_extent,
const int type)
{
struct extent_map *em = NULL;
@@ -150,6 +150,7 @@ static struct extent_map *btrfs_create_dio_extent(struct btrfs_inode *inode,
em = btrfs_create_io_em(inode, start, file_extent, type);
if (IS_ERR(em))
goto out;
+ file_extent->fscrypt_info = em->fscrypt_info;
}

ordered = btrfs_alloc_ordered_extent(inode, start, file_extent,
@@ -276,6 +277,7 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map,
}
space_reserved = true;

+ file_extent.fscrypt_info = em->fscrypt_info;
em2 = btrfs_create_dio_extent(BTRFS_I(inode), dio_data, start,
&file_extent, type);
btrfs_dec_nocow_writers(bg);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index c6c8ae05e471..eab7950372ae 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -1121,10 +1121,11 @@ static void submit_one_async_extent(struct async_chunk *async_chunk,
ret = PTR_ERR(em);
goto out_free_reserve;
}
- btrfs_free_extent_map(em);

+ file_extent.fscrypt_info = em->fscrypt_info;
ordered = btrfs_alloc_ordered_extent(inode, start, &file_extent,
1U << BTRFS_ORDERED_COMPRESSED);
+ btrfs_free_extent_map(em);
if (IS_ERR(ordered)) {
btrfs_drop_extent_map_range(inode, start, end, false);
ret = PTR_ERR(ordered);
@@ -1263,10 +1264,11 @@ static int cow_one_range(struct btrfs_inode *inode, struct folio *locked_folio,
ret = PTR_ERR(em);
goto free_reserved;
}
- btrfs_free_extent_map(em);

+ file_extent.fscrypt_info = em->fscrypt_info;
ordered = btrfs_alloc_ordered_extent(inode, file_offset, &file_extent,
1U << BTRFS_ORDERED_REGULAR);
+ btrfs_free_extent_map(em);
if (IS_ERR(ordered)) {
btrfs_drop_extent_map_range(inode, file_offset, cur_end, false);
ret = PTR_ERR(ordered);
@@ -1933,18 +1935,32 @@ static int nocow_one_range(struct btrfs_inode *inode, struct folio *locked_folio
u64 file_pos, bool is_prealloc)
{
struct btrfs_ordered_extent *ordered;
+ struct extent_map *em;
const u64 len = nocow_args->file_extent.num_bytes;
const u64 end = file_pos + len - 1;
int ret = 0;

btrfs_lock_extent(&inode->io_tree, file_pos, end, cached);

- if (is_prealloc) {
- struct extent_map *em;
+ /*
+ * We only want to do this lookup if we're encrypted, otherwise
+ * fsrypt_info will be null and we can avoid this lookup.
+ */
+ if (IS_ENCRYPTED(&inode->vfs_inode)) {
+ em = btrfs_get_extent(inode, NULL, file_pos, len);
+ if (IS_ERR(em)) {
+ btrfs_unlock_extent(&inode->io_tree, file_pos, end, cached);
+ return PTR_ERR(em);
+ }
+ nocow_args->file_extent.fscrypt_info = fscrypt_get_extent_info(em->fscrypt_info);
+ btrfs_free_extent_map(em);
+ }

+ if (is_prealloc) {
em = btrfs_create_io_em(inode, file_pos, &nocow_args->file_extent,
BTRFS_ORDERED_PREALLOC);
if (IS_ERR(em)) {
+ fscrypt_put_extent_info(nocow_args->file_extent.fscrypt_info);
ret = PTR_ERR(em);
goto error;
}
@@ -1955,6 +1971,7 @@ static int nocow_one_range(struct btrfs_inode *inode, struct folio *locked_folio
is_prealloc
? (1U << BTRFS_ORDERED_PREALLOC)
: (1U << BTRFS_ORDERED_NOCOW));
+ fscrypt_put_extent_info(nocow_args->file_extent.fscrypt_info);
if (IS_ERR(ordered)) {
if (is_prealloc)
btrfs_drop_extent_map_range(inode, file_pos, end, false);
@@ -7657,7 +7674,13 @@ 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);
+
+ if (file_extent->fscrypt_info) {
+ btrfs_extent_map_set_encryption(em, BTRFS_ENCRYPTION_FSCRYPT);
+ em->fscrypt_info = fscrypt_get_extent_info(file_extent->fscrypt_info);
+ } else {
+ btrfs_extent_map_set_encryption(em, BTRFS_ENCRYPTION_NONE);
+ }

ret = btrfs_replace_extent_map_range(inode, em, true);
if (ret) {
@@ -10209,11 +10232,12 @@ ssize_t btrfs_do_encoded_write(struct kiocb *iocb, struct iov_iter *from,
ret = PTR_ERR(em);
goto out_free_reserved;
}
- btrfs_free_extent_map(em);

+ file_extent.fscrypt_info = em->fscrypt_info;
ordered = btrfs_alloc_ordered_extent(inode, start, &file_extent,
(1U << BTRFS_ORDERED_ENCODED) |
(1U << BTRFS_ORDERED_COMPRESSED));
+ btrfs_free_extent_map(em);
if (IS_ERR(ordered)) {
btrfs_drop_extent_map_range(inode, start, end, false);
ret = PTR_ERR(ordered);
--
2.53.0