Skip to content

Commit 802c51b

Browse files
committed
btrfs-progs: mkfs: add --compression option
Adds an option --compression to mkfs.btrfs, to allow creating files using zstd when using --rootdir. Signed-off-by: Mark Harmstone <[email protected]>
1 parent e7f44fd commit 802c51b

File tree

11 files changed

+436
-26
lines changed

11 files changed

+436
-26
lines changed

Documentation/mkfs.btrfs.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,12 @@ OPTIONS
188188
189189
$ mkfs.btrfs -O list-all
190190
191+
--compression <algo>
192+
Try to compress files when using *--rootdir*. Supported values for *algo* are
193+
*none* (the default) and *zstd*. As with the kernel, :command:`mkfs.btrfs` won't
194+
write compressed extents when they would be larger than the uncompressed versions,
195+
and will mark a file as `nocompress` if its beginning is found to be incompressible.
196+
191197
-f|--force
192198
Forcibly overwrite the block devices when an existing filesystem is detected.
193199
By default, :command:`mkfs.btrfs` will utilize *libblkid* to check for any known

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -740,11 +740,11 @@ btrfsck.static: btrfs.static
740740

741741
mkfs.btrfs: $(mkfs_objects) $(objects) libbtrfsutil.a
742742
@echo " [LD] $@"
743-
$(Q)$(CC) -o $@ $^ $(LDFLAGS) $(LIBS)
743+
$(Q)$(CC) -o $@ $^ $(LDFLAGS) $(LIBS) $(LIBS_COMP)
744744

745745
mkfs.btrfs.static: $(static_mkfs_objects) $(static_objects) $(static_libbtrfs_objects)
746746
@echo " [LD] $@"
747-
$(Q)$(CC) -o $@ $^ $(STATIC_LDFLAGS) $(STATIC_LIBS)
747+
$(Q)$(CC) -o $@ $^ $(STATIC_LDFLAGS) $(STATIC_LIBS) $(STATIC_LIBS_COMP)
748748

749749
btrfstune: $(tune_objects) $(objects) libbtrfsutil.a
750750
@echo " [LD] $@"

common/extent-tree-utils.c

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,3 +285,93 @@ int btrfs_record_file_extent(struct btrfs_trans_handle *trans,
285285
}
286286
return ret;
287287
}
288+
289+
int btrfs_record_file_extent_comp(struct btrfs_trans_handle *trans,
290+
struct btrfs_root *root, u64 objectid,
291+
struct btrfs_inode_item *inode,
292+
u64 file_pos, u64 disk_bytenr,
293+
u64 extent_num_bytes, u64 ram_bytes,
294+
enum btrfs_compression_type comp)
295+
{
296+
struct btrfs_fs_info *info = root->fs_info;
297+
struct btrfs_root *extent_root = btrfs_extent_root(info, disk_bytenr);
298+
struct extent_buffer *leaf;
299+
struct btrfs_file_extent_item *fi;
300+
struct btrfs_key ins_key;
301+
struct btrfs_path *path;
302+
struct btrfs_extent_item *ei;
303+
u64 nbytes;
304+
u64 extent_bytenr;
305+
u64 extent_offset;
306+
int ret = 0;
307+
308+
path = btrfs_alloc_path();
309+
if (!path)
310+
return -ENOMEM;
311+
312+
ins_key.objectid = disk_bytenr;
313+
ins_key.type = BTRFS_EXTENT_ITEM_KEY;
314+
ins_key.offset = extent_num_bytes;
315+
316+
ret = btrfs_insert_empty_item(trans, extent_root, path,
317+
&ins_key, sizeof(*ei));
318+
if (ret == 0) {
319+
leaf = path->nodes[0];
320+
ei = btrfs_item_ptr(leaf, path->slots[0],
321+
struct btrfs_extent_item);
322+
323+
btrfs_set_extent_refs(leaf, ei, 0);
324+
btrfs_set_extent_generation(leaf, ei, trans->transid);
325+
btrfs_set_extent_flags(leaf, ei,
326+
BTRFS_EXTENT_FLAG_DATA);
327+
btrfs_mark_buffer_dirty(leaf);
328+
329+
ret = btrfs_update_block_group(trans, disk_bytenr,
330+
extent_num_bytes, 1, 0);
331+
if (ret)
332+
goto fail;
333+
} else if (ret != -EEXIST) {
334+
goto fail;
335+
}
336+
337+
ret = remove_from_free_space_tree(trans, disk_bytenr, extent_num_bytes);
338+
if (ret)
339+
goto fail;
340+
341+
btrfs_run_delayed_refs(trans, -1);
342+
extent_bytenr = disk_bytenr;
343+
extent_offset = 0;
344+
345+
btrfs_release_path(path);
346+
ins_key.objectid = objectid;
347+
ins_key.type = BTRFS_EXTENT_DATA_KEY;
348+
ins_key.offset = file_pos;
349+
ret = btrfs_insert_empty_item(trans, root, path, &ins_key, sizeof(*fi));
350+
if (ret)
351+
goto fail;
352+
leaf = path->nodes[0];
353+
fi = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_file_extent_item);
354+
btrfs_set_file_extent_generation(leaf, fi, trans->transid);
355+
btrfs_set_file_extent_type(leaf, fi, BTRFS_FILE_EXTENT_REG);
356+
btrfs_set_file_extent_disk_bytenr(leaf, fi, extent_bytenr);
357+
btrfs_set_file_extent_disk_num_bytes(leaf, fi, extent_num_bytes);
358+
btrfs_set_file_extent_offset(leaf, fi, extent_offset);
359+
btrfs_set_file_extent_num_bytes(leaf, fi, ram_bytes);
360+
btrfs_set_file_extent_ram_bytes(leaf, fi, ram_bytes);
361+
btrfs_set_file_extent_compression(leaf, fi, comp);
362+
btrfs_set_file_extent_encryption(leaf, fi, 0);
363+
btrfs_set_file_extent_other_encoding(leaf, fi, 0);
364+
btrfs_mark_buffer_dirty(leaf);
365+
366+
nbytes = btrfs_stack_inode_nbytes(inode) + ram_bytes;
367+
btrfs_set_stack_inode_nbytes(inode, nbytes);
368+
btrfs_release_path(path);
369+
370+
ret = btrfs_inc_extent_ref(trans, extent_bytenr, extent_num_bytes,
371+
0, root->root_key.objectid, objectid,
372+
file_pos - extent_offset);
373+
374+
fail:
375+
btrfs_free_path(path);
376+
return ret;
377+
}

common/extent-tree-utils.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "kerncompat.h"
2121
#include "kernel-lib/bitops.h"
22+
#include "kernel-shared/compression.h"
2223

2324
struct btrfs_inode_item;
2425
struct btrfs_path;
@@ -32,5 +33,11 @@ int btrfs_record_file_extent(struct btrfs_trans_handle *trans,
3233
struct btrfs_inode_item *inode,
3334
u64 file_pos, u64 disk_bytenr,
3435
u64 num_bytes);
36+
int btrfs_record_file_extent_comp(struct btrfs_trans_handle *trans,
37+
struct btrfs_root *root, u64 objectid,
38+
struct btrfs_inode_item *inode,
39+
u64 file_pos, u64 disk_bytenr,
40+
u64 num_bytes, u64 ram_bytes,
41+
enum btrfs_compression_type comp);
3542

3643
#endif

convert/source-ext2.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,8 @@ static int ext2_create_file_extents(struct btrfs_trans_handle *trans,
445445
if (num_bytes > inode_size)
446446
num_bytes = inode_size;
447447
ret = btrfs_insert_inline_extent(trans, root, objectid,
448-
0, buffer, num_bytes);
448+
0, buffer, num_bytes,
449+
0, num_bytes);
449450
if (ret)
450451
goto fail;
451452
nbytes = btrfs_stack_inode_nbytes(btrfs_inode) + num_bytes;
@@ -489,7 +490,8 @@ static int ext2_create_symlink(struct btrfs_trans_handle *trans,
489490
pathname = (char *)&(ext2_inode->i_block[0]);
490491
BUG_ON(pathname[inode_size] != 0);
491492
ret = btrfs_insert_inline_extent(trans, root, objectid, 0,
492-
pathname, inode_size + 1);
493+
pathname, inode_size + 1,
494+
0, inode_size + 1);
493495
btrfs_set_stack_inode_nbytes(btrfs_inode, inode_size + 1);
494496
return ret;
495497
}

convert/source-reiserfs.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,8 @@ static int reiserfs_convert_tail(struct btrfs_trans_handle *trans,
384384
length, offset, convert_flags);
385385

386386
ret = btrfs_insert_inline_extent(trans, root, objectid,
387-
offset, body, length);
387+
offset, body, length,
388+
0, length);
388389
if (ret)
389390
return ret;
390391

@@ -538,7 +539,7 @@ static int reiserfs_copy_symlink(struct btrfs_trans_handle *trans,
538539
len = get_ih_item_len(tp_item_head(&path));
539540

540541
ret = btrfs_insert_inline_extent(trans, root, objectid, 0,
541-
symlink, len + 1);
542+
symlink, len + 1, 0, len + 1);
542543
btrfs_set_stack_inode_nbytes(btrfs_inode, len + 1);
543544
fail:
544545
pathrelse(&path);

kernel-shared/file-item.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "kernel-shared/extent_io.h"
2727
#include "kernel-shared/uapi/btrfs.h"
2828
#include "common/internal.h"
29+
#include "common/messages.h"
2930

3031
#define MAX_CSUM_ITEMS(r, size) ((((BTRFS_LEAF_DATA_SIZE(r->fs_info) - \
3132
sizeof(struct btrfs_item) * 2) / \
@@ -86,7 +87,9 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
8687

8788
int btrfs_insert_inline_extent(struct btrfs_trans_handle *trans,
8889
struct btrfs_root *root, u64 objectid,
89-
u64 offset, const char *buffer, size_t size)
90+
u64 offset, const char *buffer, size_t size,
91+
enum btrfs_compression_type comp,
92+
u64 ram_bytes)
9093
{
9194
struct btrfs_key key;
9295
struct btrfs_path *path;
@@ -117,8 +120,8 @@ int btrfs_insert_inline_extent(struct btrfs_trans_handle *trans,
117120
struct btrfs_file_extent_item);
118121
btrfs_set_file_extent_generation(leaf, ei, trans->transid);
119122
btrfs_set_file_extent_type(leaf, ei, BTRFS_FILE_EXTENT_INLINE);
120-
btrfs_set_file_extent_ram_bytes(leaf, ei, size);
121-
btrfs_set_file_extent_compression(leaf, ei, 0);
123+
btrfs_set_file_extent_ram_bytes(leaf, ei, ram_bytes);
124+
btrfs_set_file_extent_compression(leaf, ei, comp);
122125
btrfs_set_file_extent_encryption(leaf, ei, 0);
123126
btrfs_set_file_extent_other_encoding(leaf, ei, 0);
124127

kernel-shared/file-item.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "kernel-shared/ctree.h"
1111
#include "kernel-shared/uapi/btrfs_tree.h"
1212
#include "kernel-shared/accessors.h"
13+
#include "kernel-shared/compression.h"
1314

1415
struct bio;
1516
struct inode;
@@ -91,6 +92,7 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, u64 logical,
9192
u64 csum_objectid, u32 csum_type, const char *data);
9293
int btrfs_insert_inline_extent(struct btrfs_trans_handle *trans,
9394
struct btrfs_root *root, u64 objectid,
94-
u64 offset, const char *buffer, size_t size);
95+
u64 offset, const char *buffer, size_t size,
96+
enum btrfs_compression_type comp, u64 ram_bytes);
9597

9698
#endif

mkfs/main.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@ static const char * const mkfs_usage[] = {
443443
OPTLINE("-u|--subvol SUBDIR:FLAGS", "create SUBDIR as subvolume rather than normal directory, can be specified multiple times"),
444444
OPTLINE("--shrink", "(with --rootdir) shrink the filled filesystem to minimal size"),
445445
OPTLINE("-K|--nodiscard", "do not perform whole device TRIM"),
446+
OPTLINE("--compression ALGO", "compression algorithm to use, none (default), zstd"),
446447
OPTLINE("-f|--force", "force overwrite of existing filesystem"),
447448
"General:",
448449
OPTLINE("-q|--quiet", "no messages except errors"),
@@ -1101,6 +1102,7 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
11011102
size_t source_dir_len = 0;
11021103
struct rootdir_subvol *rds;
11031104
bool has_default_subvol = false;
1105+
bool compression = false;
11041106
LIST_HEAD(subvols);
11051107

11061108
cpu_detect_flags();
@@ -1115,6 +1117,7 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
11151117
GETOPT_VAL_CHECKSUM,
11161118
GETOPT_VAL_GLOBAL_ROOTS,
11171119
GETOPT_VAL_DEVICE_UUID,
1120+
GETOPT_VAL_COMPRESSION,
11181121
};
11191122
static const struct option long_options[] = {
11201123
{ "byte-count", required_argument, NULL, 'b' },
@@ -1142,6 +1145,8 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
11421145
{ "quiet", 0, NULL, 'q' },
11431146
{ "verbose", 0, NULL, 'v' },
11441147
{ "shrink", no_argument, NULL, GETOPT_VAL_SHRINK },
1148+
{ "compression", required_argument, NULL,
1149+
GETOPT_VAL_COMPRESSION },
11451150
#if EXPERIMENTAL
11461151
{ "param", required_argument, NULL, GETOPT_VAL_PARAM },
11471152
{ "num-global-roots", required_argument, NULL, GETOPT_VAL_GLOBAL_ROOTS },
@@ -1314,6 +1319,23 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
13141319
case 'q':
13151320
bconf_be_quiet();
13161321
break;
1322+
case GETOPT_VAL_COMPRESSION:
1323+
if (!strcmp(optarg, "none")) {
1324+
compression = false;
1325+
} else if (!strcmp(optarg, "zstd")) {
1326+
#if COMPRESSION_ZSTD
1327+
compression = true;
1328+
#else
1329+
error("zstd support not compiled in");
1330+
ret = 1;
1331+
goto error;
1332+
#endif
1333+
} else {
1334+
error("unrecognized compression type %s", optarg);
1335+
ret = 1;
1336+
goto error;
1337+
}
1338+
break;
13171339
case GETOPT_VAL_DEVICE_UUID:
13181340
strncpy_null(dev_uuid, optarg, BTRFS_UUID_UNPARSED_SIZE);
13191341
break;
@@ -2014,7 +2036,7 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
20142036
}
20152037

20162038
ret = btrfs_mkfs_fill_dir(trans, source_dir, root,
2017-
&subvols);
2039+
&subvols, compression);
20182040
if (ret) {
20192041
error("error while filling filesystem: %d", ret);
20202042
btrfs_abort_transaction(trans, ret);

0 commit comments

Comments
 (0)