From: Omar Sandoval <osandov@xxxxxxxxxxx> Initially, only normal data extents, using the normal (non-direct) IO path, will be encrypted. This change forbids various other bits: - allows reflinking only if both inodes have the same encryption status - disables compressing encrypted inodes - disables direct IO on encrypted inodes - disable inline data on encrypted inodes Signed-off-by: Omar Sandoval <osandov@xxxxxxxxxxx> Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@xxxxxxxxxx> --- fs/btrfs/btrfs_inode.h | 3 +++ fs/btrfs/file.c | 4 ++-- fs/btrfs/inode.c | 3 ++- fs/btrfs/reflink.c | 10 ++++++++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index d21c30bf7053..5b94609f138d 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h @@ -385,6 +385,9 @@ static inline bool btrfs_inode_in_log(struct btrfs_inode *inode, u64 generation) */ static inline bool btrfs_inode_can_compress(const struct btrfs_inode *inode) { + if (IS_ENCRYPTED(&inode->vfs_inode)) + return false; + if (inode->flags & BTRFS_INODE_NODATACOW || inode->flags & BTRFS_INODE_NODATASUM) return false; diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index b7855f794ba6..1724ec898f40 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1491,7 +1491,7 @@ static ssize_t btrfs_direct_write(struct kiocb *iocb, struct iov_iter *from) goto relock; } - if (check_direct_IO(fs_info, from, pos)) { + if (IS_ENCRYPTED(inode) || check_direct_IO(fs_info, from, pos)) { btrfs_inode_unlock(inode, ilock_flags); goto buffered; } @@ -3737,7 +3737,7 @@ static ssize_t btrfs_direct_read(struct kiocb *iocb, struct iov_iter *to) ssize_t read = 0; ssize_t ret; - if (fsverity_active(inode)) + if (IS_ENCRYPTED(inode) || fsverity_active(inode)) return 0; if (check_direct_read(btrfs_sb(inode->i_sb), to, iocb->ki_pos)) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 255959574724..972a49796bb9 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -445,7 +445,8 @@ static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 size, * compressed) data fits in a leaf and the configured maximum inline * size. */ - if (size < i_size_read(&inode->vfs_inode) || + if (IS_ENCRYPTED(&inode->vfs_inode) || + size < i_size_read(&inode->vfs_inode) || size > fs_info->sectorsize || data_len > BTRFS_MAX_INLINE_DATA_SIZE(fs_info) || data_len > fs_info->max_inline) diff --git a/fs/btrfs/reflink.c b/fs/btrfs/reflink.c index 9d728107536e..579dbf057ffa 100644 --- a/fs/btrfs/reflink.c +++ b/fs/btrfs/reflink.c @@ -801,6 +801,7 @@ static int btrfs_remap_file_range_prep(struct file *file_in, loff_t pos_in, u64 bs = BTRFS_I(inode_out)->root->fs_info->sb->s_blocksize; u64 wb_len; int ret; + bool same; if (!(remap_flags & REMAP_FILE_DEDUP)) { struct btrfs_root *root_out = BTRFS_I(inode_out)->root; @@ -811,6 +812,15 @@ static int btrfs_remap_file_range_prep(struct file *file_in, loff_t pos_in, ASSERT(inode_in->i_sb == inode_out->i_sb); } + /* + * Can only reflink encrypted files if both files are encrypted. + */ + ret = fscrypt_have_same_policy(inode_in, inode_out, &same); + if (ret) + return ret; + if (!same) + return -EINVAL; + /* Don't make the dst file partly checksummed */ if ((BTRFS_I(inode_in)->flags & BTRFS_INODE_NODATASUM) != (BTRFS_I(inode_out)->flags & BTRFS_INODE_NODATASUM)) { -- 2.37.3