|
@@ -388,10 +388,31 @@ static noinline int add_async_extent(struct async_cow *cow,
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/*
|
|
|
|
|
+ * Check if the inode has flags compatible with compression
|
|
|
|
|
+ */
|
|
|
|
|
+static inline bool inode_can_compress(struct inode *inode)
|
|
|
|
|
+{
|
|
|
|
|
+ if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW ||
|
|
|
|
|
+ BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)
|
|
|
|
|
+ return false;
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/*
|
|
|
|
|
+ * Check if the inode needs to be submitted to compression, based on mount
|
|
|
|
|
+ * options, defragmentation, properties or heuristics.
|
|
|
|
|
+ */
|
|
|
static inline int inode_need_compress(struct inode *inode, u64 start, u64 end)
|
|
static inline int inode_need_compress(struct inode *inode, u64 start, u64 end)
|
|
|
{
|
|
{
|
|
|
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
|
|
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
|
|
|
|
|
|
|
|
|
|
+ if (!inode_can_compress(inode)) {
|
|
|
|
|
+ WARN(IS_ENABLED(CONFIG_BTRFS_DEBUG),
|
|
|
|
|
+ KERN_ERR "BTRFS: unexpected compression for ino %llu\n",
|
|
|
|
|
+ btrfs_ino(BTRFS_I(inode)));
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
/* force compress */
|
|
/* force compress */
|
|
|
if (btrfs_test_opt(fs_info, FORCE_COMPRESS))
|
|
if (btrfs_test_opt(fs_info, FORCE_COMPRESS))
|
|
|
return 1;
|
|
return 1;
|
|
@@ -1596,7 +1617,8 @@ static int run_delalloc_range(void *private_data, struct page *locked_page,
|
|
|
} else if (BTRFS_I(inode)->flags & BTRFS_INODE_PREALLOC && !force_cow) {
|
|
} else if (BTRFS_I(inode)->flags & BTRFS_INODE_PREALLOC && !force_cow) {
|
|
|
ret = run_delalloc_nocow(inode, locked_page, start, end,
|
|
ret = run_delalloc_nocow(inode, locked_page, start, end,
|
|
|
page_started, 0, nr_written);
|
|
page_started, 0, nr_written);
|
|
|
- } else if (!inode_need_compress(inode, start, end)) {
|
|
|
|
|
|
|
+ } else if (!inode_can_compress(inode) ||
|
|
|
|
|
+ !inode_need_compress(inode, start, end)) {
|
|
|
ret = cow_file_range(inode, locked_page, start, end, end,
|
|
ret = cow_file_range(inode, locked_page, start, end, end,
|
|
|
page_started, nr_written, 1, NULL);
|
|
page_started, nr_written, 1, NULL);
|
|
|
} else {
|
|
} else {
|