@@ -147,6 +147,7 @@ static int btrfs_fscrypt_set_context(struct inode *inode, const void *ctx,
goto out_err;
}
+ set_bit(BTRFS_INODE_NEEDS_FULL_SYNC, &BTRFS_I(inode)->runtime_flags);
leaf = path->nodes[0];
ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
@@ -715,6 +715,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
if (found_type == BTRFS_FILE_EXTENT_REG ||
found_type == BTRFS_FILE_EXTENT_PREALLOC) {
u64 offset;
+ u32 item_size;
unsigned long dest_offset;
struct btrfs_key ins;
@@ -722,14 +723,16 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
btrfs_fs_incompat(fs_info, NO_HOLES))
goto update_inode;
+ item_size = btrfs_item_size(eb, slot);
+
ret = btrfs_insert_empty_item(trans, root, path, key,
- sizeof(*item));
+ item_size);
if (ret)
goto out;
dest_offset = btrfs_item_ptr_offset(path->nodes[0],
path->slots[0]);
copy_extent_buffer(path->nodes[0], eb, dest_offset,
- (unsigned long)item, sizeof(*item));
+ (unsigned long)item, item_size);
ins.objectid = btrfs_file_extent_disk_bytenr(eb, item);
ins.offset = btrfs_file_extent_disk_num_bytes(eb, item);
@@ -2511,7 +2514,8 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
continue;
/* these keys are simply copied */
- if (key.type == BTRFS_XATTR_ITEM_KEY) {
+ if (key.type == BTRFS_XATTR_ITEM_KEY ||
+ key.type == BTRFS_FSCRYPT_INODE_CTX_ITEM_KEY) {
ret = overwrite_item(wc->trans, root, path,
eb, i, &key);
if (ret)
Log replay needs a few tweaks in order to make sure everything works with encryption. 1. Use the size of the item itself, not the size of the item object when we're replaying an extent. 2. Copy in the fscrypt context if we find one in the log. 3. Set NEEDS_FULL_SYNC when we update the inode context so all of the items are copied into the log at fsync time. This makes replay of encrypted files work properly. Signed-off-by: Josef Bacik <josef@toxicpanda.com> --- fs/btrfs/fscrypt.c | 1 + fs/btrfs/tree-log.c | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-)