[PATCH] btrfs: allow setting per extent compression

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi all,
As mentioned in https://github.com/kdave/btrfs-progs/issues/184 it
would be nice to be able to set the compression level per extent (or
file) from the IOCTL interface.
I'm not sure how submitting patches to mailing lists works, but I have
attached a patch which implements this. Any and all feedback is
appreciated.
Kind regards,
Stijn Rutjens
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index bb374042d..e1603e1cf 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -67,7 +67,7 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
 	btrfs_set_file_extent_ram_bytes(leaf, item, ram_bytes);
 	btrfs_set_file_extent_generation(leaf, item, trans->transid);
 	btrfs_set_file_extent_type(leaf, item, BTRFS_FILE_EXTENT_REG);
-	btrfs_set_file_extent_compression(leaf, item, compression);
+	btrfs_set_file_extent_compression(leaf, item, compression & 0xF);
 	btrfs_set_file_extent_encryption(leaf, item, encryption);
 	btrfs_set_file_extent_other_encoding(leaf, item, other_encoding);
 
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index dbc9bcaf5..3285d4bd3 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -227,7 +227,7 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
 			compressed_size -= cur_size;
 		}
 		btrfs_set_file_extent_compression(leaf, ei,
-						  compress_type);
+						  compress_type & 0XF);
 	} else {
 		page = find_get_page(inode->i_mapping,
 				     start >> PAGE_SHIFT);
@@ -573,14 +573,31 @@ static noinline int compress_file_range(struct async_chunk *async_chunk)
 		}
 
 		/* Compression level is applied here and only here */
-		ret = btrfs_compress_pages(
-			compress_type | (fs_info->compress_level << 4),
-					   inode->i_mapping, start,
-					   pages,
-					   &nr_pages,
-					   &total_in,
-					   &total_compressed);
-
+		/*
+		 * Check if the upper bits are set, and if so,
+		 * take them as the compression level.
+		 * the inode compression level takes precendence, if set
+		 */
+		if ((compress_type & 0xF) == compress_type) {
+			ret = btrfs_compress_pages(
+				compress_type | (fs_info->compress_level << 4),
+						inode->i_mapping, start,
+						pages,
+						&nr_pages,
+						&total_in,
+						&total_compressed);
+		} else {
+			int compress_level = btrfs_compress_set_level(
+						compress_type & 0xF,
+						compress_type>>4);
+			ret = btrfs_compress_pages(
+				compress_type | (compress_level << 4),
+				inode->i_mapping, start,
+				pages,
+				&nr_pages,
+				&total_in,
+				&total_compressed);
+		}
 		if (!ret) {
 			unsigned long offset = offset_in_page(total_compressed);
 			struct page *page = pages[nr_pages - 1];
@@ -2362,7 +2379,7 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
 	btrfs_set_file_extent_offset(leaf, fi, 0);
 	btrfs_set_file_extent_num_bytes(leaf, fi, num_bytes);
 	btrfs_set_file_extent_ram_bytes(leaf, fi, ram_bytes);
-	btrfs_set_file_extent_compression(leaf, fi, compression);
+	btrfs_set_file_extent_compression(leaf, fi, compression & 0xF);
 	btrfs_set_file_extent_encryption(leaf, fi, encryption);
 	btrfs_set_file_extent_other_encoding(leaf, fi, other_encoding);
 
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 0fa1c386d..2a9c1f312 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1414,7 +1414,11 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
 		return -EINVAL;
 
 	if (do_compress) {
-		if (range->compress_type >= BTRFS_NR_COMPRESS_TYPES)
+		/*
+		* The bottom 4 bits of compress_type are for used for the
+		* compression type, the other bits for the compression level
+		*/
+		if ((range->compress_type & 0xF) >= BTRFS_NR_COMPRESS_TYPES)
 			return -EINVAL;
 		if (range->compress_type)
 			compress_type = range->compress_type;
@@ -1572,9 +1576,9 @@ int btrfs_defrag_file(struct inode *inode, struct file *file,
 			filemap_flush(inode->i_mapping);
 	}
 
-	if (range->compress_type == BTRFS_COMPRESS_LZO) {
+	if ((range->compress_type & 0xF) == BTRFS_COMPRESS_LZO) {
 		btrfs_set_fs_incompat(fs_info, COMPRESS_LZO);
-	} else if (range->compress_type == BTRFS_COMPRESS_ZSTD) {
+	} else if ((range->compress_type & 0xF) == BTRFS_COMPRESS_ZSTD) {
 		btrfs_set_fs_incompat(fs_info, COMPRESS_ZSTD);
 	}
 

[Index of Archives]     [Linux Filesystem Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux