2 * Copyright (C) 2007 Oracle. All rights reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
20 * Btrfs convert design:
22 * The overall design of btrfs convert is like the following:
24 * |<------------------Old fs----------------------------->|
25 * |<- used ->| |<- used ->| |<- used ->|
28 * |<---------------Btrfs fs------------------------------>|
29 * |<- Old data chunk ->|< new chunk (D/M/S)>|<- ODC ->|
30 * |<-Old-FE->| |<-Old-FE->|<- Btrfs extents ->|<-Old-FE->|
32 * ODC = Old data chunk, btrfs chunks containing old fs data
33 * Mapped 1:1 (logical address == device offset)
34 * Old-FE = file extents pointing to old fs.
36 * So old fs used space is (mostly) kept as is, while btrfs will insert
37 * its chunk (Data/Meta/Sys) into large enough free space.
38 * In this way, we can create different profiles for metadata/data for
41 * We must reserve and relocate 3 ranges for btrfs:
42 * * [0, 1M) - area never used for any data except the first
44 * * [btrfs_sb_offset(1), +64K) - 1st superblock backup copy
45 * * [btrfs_sb_offset(2), +64K) - 2nd, dtto
47 * Most work is spent handling corner cases around these reserved ranges.
49 * Detailed workflow is:
50 * 1) Scan old fs used space and calculate data chunk layout
52 * We can a map used space of old fs
54 * 1.2) Calculate data chunk layout - this is the hard part
55 * New data chunks must meet 3 conditions using result fomr 1.1
56 * a. Large enough to be a chunk
57 * b. Doesn't intersect reserved ranges
58 * c. Covers all the remaining old fs used space
60 * NOTE: This can be simplified if we don't need to handle backup supers
62 * 1.3) Calculate usable space for new btrfs chunks
63 * Btrfs chunk usable space must meet 3 conditions using result from 1.2
64 * a. Large enough to be a chunk
65 * b. Doesn't intersect reserved ranges
66 * c. Doesn't cover any data chunks in 1.1
68 * 2) Create basic btrfs filesystem structure
69 * Initial metadata and sys chunks are inserted in the first availabe
70 * space found in step 1.3
71 * Then insert all data chunks into the basic btrfs
73 * 3) Create convert image
74 * We need to relocate reserved ranges here.
75 * After this step, the convert image is done, and we can use the image
76 * as reflink source to create old files
78 * 4) Iterate old fs to create files
79 * We just reflink file extents from old fs to newly created files on
83 #include "kerncompat.h"
87 #include <sys/types.h>
97 #include "transaction.h"
99 #include "task-utils.h"
101 #include "mkfs/common.h"
102 #include "convert/common.h"
103 #include "convert/source-fs.h"
104 #include "fsfeatures.h"
106 extern const struct btrfs_convert_operations ext2_convert_ops
;
107 extern const struct btrfs_convert_operations reiserfs_convert_ops
;
109 static const struct btrfs_convert_operations
*convert_operations
[] = {
110 #if BTRFSCONVERT_EXT2
113 #if BTRFSCONVERT_REISERFS
114 &reiserfs_convert_ops
,
118 static void *print_copied_inodes(void *p
)
120 struct task_ctx
*priv
= p
;
121 const char work_indicator
[] = { '.', 'o', 'O', 'o' };
124 task_period_start(priv
->info
, 1000 /* 1s */);
127 pthread_mutex_lock(&priv
->mutex
);
128 printf("copy inodes [%c] [%10llu/%10llu]\r",
129 work_indicator
[count
% 4],
130 (unsigned long long)priv
->cur_copy_inodes
,
131 (unsigned long long)priv
->max_copy_inodes
);
132 pthread_mutex_unlock(&priv
->mutex
);
134 task_period_wait(priv
->info
);
140 static int after_copied_inodes(void *p
)
148 static inline int copy_inodes(struct btrfs_convert_context
*cctx
,
149 struct btrfs_root
*root
, u32 convert_flags
,
152 return cctx
->convert_ops
->copy_inodes(cctx
, root
, convert_flags
, p
);
155 static inline void convert_close_fs(struct btrfs_convert_context
*cctx
)
157 cctx
->convert_ops
->close_fs(cctx
);
160 static inline int convert_check_state(struct btrfs_convert_context
*cctx
)
162 return cctx
->convert_ops
->check_state(cctx
);
165 static int csum_disk_extent(struct btrfs_trans_handle
*trans
,
166 struct btrfs_root
*root
,
167 u64 disk_bytenr
, u64 num_bytes
)
169 u32 blocksize
= root
->fs_info
->sectorsize
;
174 buffer
= malloc(blocksize
);
177 for (offset
= 0; offset
< num_bytes
; offset
+= blocksize
) {
178 ret
= read_disk_extent(root
, disk_bytenr
+ offset
,
182 ret
= btrfs_csum_file_block(trans
,
183 root
->fs_info
->csum_root
,
184 disk_bytenr
+ num_bytes
,
185 disk_bytenr
+ offset
,
194 static int create_image_file_range(struct btrfs_trans_handle
*trans
,
195 struct btrfs_root
*root
,
196 struct cache_tree
*used
,
197 struct btrfs_inode_item
*inode
,
198 u64 ino
, u64 bytenr
, u64
*ret_len
,
201 struct cache_extent
*cache
;
202 struct btrfs_block_group_cache
*bg_cache
;
207 u32 datacsum
= convert_flags
& CONVERT_FLAG_DATACSUM
;
209 if (bytenr
!= round_down(bytenr
, root
->fs_info
->sectorsize
)) {
210 error("bytenr not sectorsize aligned: %llu",
211 (unsigned long long)bytenr
);
214 if (len
!= round_down(len
, root
->fs_info
->sectorsize
)) {
215 error("length not sectorsize aligned: %llu",
216 (unsigned long long)len
);
219 len
= min_t(u64
, len
, BTRFS_MAX_EXTENT_SIZE
);
222 * Skip reserved ranges first
224 * Or we will insert a hole into current image file, and later
225 * migrate block will fail as there is already a file extent.
227 for (i
= 0; i
< ARRAY_SIZE(btrfs_reserved_ranges
); i
++) {
228 const struct simple_range
*reserved
= &btrfs_reserved_ranges
[i
];
234 * |---- reserved ----|
236 * Skip to reserved range end
238 if (bytenr
>= reserved
->start
&& bytenr
< range_end(reserved
)) {
239 *ret_len
= range_end(reserved
) - bytenr
;
246 * Leading part may still create a file extent
248 if (bytenr
< reserved
->start
&&
249 bytenr
+ len
>= range_end(reserved
)) {
250 len
= min_t(u64
, len
, reserved
->start
- bytenr
);
255 /* Check if we are going to insert regular file extent, or hole */
256 cache
= search_cache_extent(used
, bytenr
);
258 if (cache
->start
<= bytenr
) {
260 * |///////Used///////|
263 * Insert one real file extent
265 len
= min_t(u64
, len
, cache
->start
+ cache
->size
-
267 disk_bytenr
= bytenr
;
275 len
= min(len
, cache
->start
- bytenr
);
291 /* Check if the range is in a data block group */
292 bg_cache
= btrfs_lookup_block_group(root
->fs_info
, bytenr
);
295 if (!(bg_cache
->flags
& BTRFS_BLOCK_GROUP_DATA
))
298 /* The extent should never cross block group boundary */
299 len
= min_t(u64
, len
, bg_cache
->key
.objectid
+
300 bg_cache
->key
.offset
- bytenr
);
303 if (len
!= round_down(len
, root
->fs_info
->sectorsize
)) {
304 error("remaining length not sectorsize aligned: %llu",
305 (unsigned long long)len
);
308 ret
= btrfs_record_file_extent(trans
, root
, ino
, inode
, bytenr
,
314 ret
= csum_disk_extent(trans
, root
, bytenr
, len
);
320 * Relocate old fs data in one reserved ranges
322 * Since all old fs data in reserved range is not covered by any chunk nor
323 * data extent, we don't need to handle any reference but add new
324 * extent/reference, which makes codes more clear
326 static int migrate_one_reserved_range(struct btrfs_trans_handle
*trans
,
327 struct btrfs_root
*root
,
328 struct cache_tree
*used
,
329 struct btrfs_inode_item
*inode
, int fd
,
330 u64 ino
, const struct simple_range
*range
,
333 u64 cur_off
= range
->start
;
334 u64 cur_len
= range
->len
;
335 u64 hole_start
= range
->start
;
337 struct cache_extent
*cache
;
338 struct btrfs_key key
;
339 struct extent_buffer
*eb
;
343 * It's possible that there are holes in reserved range:
344 * |<---------------- Reserved range ---------------------->|
345 * |<- Old fs data ->| |<- Old fs data ->|
346 * So here we need to iterate through old fs used space and only
347 * migrate ranges that covered by old fs data.
349 while (cur_off
< range_end(range
)) {
350 cache
= search_cache_extent(used
, cur_off
);
353 cur_off
= max(cache
->start
, cur_off
);
354 if (cur_off
>= range_end(range
))
356 cur_len
= min(cache
->start
+ cache
->size
, range_end(range
)) -
358 BUG_ON(cur_len
< root
->fs_info
->sectorsize
);
360 /* reserve extent for the data */
361 ret
= btrfs_reserve_extent(trans
, root
, cur_len
, 0, 0, (u64
)-1,
366 eb
= malloc(sizeof(*eb
) + cur_len
);
372 ret
= pread(fd
, eb
->data
, cur_len
, cur_off
);
374 ret
= (ret
< 0 ? ret
: -EIO
);
378 eb
->start
= key
.objectid
;
379 eb
->len
= key
.offset
;
382 ret
= write_and_map_eb(root
->fs_info
, eb
);
387 /* Now handle extent item and file extent things */
388 ret
= btrfs_record_file_extent(trans
, root
, ino
, inode
, cur_off
,
389 key
.objectid
, key
.offset
);
392 /* Finally, insert csum items */
393 if (convert_flags
& CONVERT_FLAG_DATACSUM
)
394 ret
= csum_disk_extent(trans
, root
, key
.objectid
,
397 /* Don't forget to insert hole */
398 hole_len
= cur_off
- hole_start
;
400 ret
= btrfs_record_file_extent(trans
, root
, ino
, inode
,
401 hole_start
, 0, hole_len
);
406 cur_off
+= key
.offset
;
407 hole_start
= cur_off
;
408 cur_len
= range_end(range
) - cur_off
;
412 * |<---- reserved -------->|
413 * |<- Old fs data ->| |
416 if (range_end(range
) - hole_start
> 0)
417 ret
= btrfs_record_file_extent(trans
, root
, ino
, inode
,
418 hole_start
, 0, range_end(range
) - hole_start
);
423 * Relocate the used source fs data in reserved ranges
425 static int migrate_reserved_ranges(struct btrfs_trans_handle
*trans
,
426 struct btrfs_root
*root
,
427 struct cache_tree
*used
,
428 struct btrfs_inode_item
*inode
, int fd
,
429 u64 ino
, u64 total_bytes
, u32 convert_flags
)
434 for (i
= 0; i
< ARRAY_SIZE(btrfs_reserved_ranges
); i
++) {
435 const struct simple_range
*range
= &btrfs_reserved_ranges
[i
];
437 if (range
->start
> total_bytes
)
439 ret
= migrate_one_reserved_range(trans
, root
, used
, inode
, fd
,
440 ino
, range
, convert_flags
);
449 * Helper for expand and merge extent_cache for wipe_one_reserved_range() to
450 * handle wiping a range that exists in cache.
452 static int _expand_extent_cache(struct cache_tree
*tree
,
453 struct cache_extent
*entry
,
454 u64 min_stripe_size
, int backward
)
456 struct cache_extent
*ce
;
459 if (entry
->size
>= min_stripe_size
)
461 diff
= min_stripe_size
- entry
->size
;
464 ce
= prev_cache_extent(entry
);
467 if (ce
->start
+ ce
->size
>= entry
->start
- diff
) {
468 /* Directly merge with previous extent */
469 ce
->size
= entry
->start
+ entry
->size
- ce
->start
;
470 remove_cache_extent(tree
, entry
);
475 /* No overlap, normal extent */
476 if (entry
->start
< diff
) {
477 error("cannot find space for data chunk layout");
480 entry
->start
-= diff
;
484 ce
= next_cache_extent(entry
);
487 if (entry
->start
+ entry
->size
+ diff
>= ce
->start
) {
488 /* Directly merge with next extent */
489 entry
->size
= ce
->start
+ ce
->size
- entry
->start
;
490 remove_cache_extent(tree
, ce
);
500 * Remove one reserve range from given cache tree
501 * if min_stripe_size is non-zero, it will ensure for split case,
502 * all its split cache extent is no smaller than @min_strip_size / 2.
504 static int wipe_one_reserved_range(struct cache_tree
*tree
,
505 u64 start
, u64 len
, u64 min_stripe_size
,
508 struct cache_extent
*cache
;
511 BUG_ON(ensure_size
&& min_stripe_size
== 0);
513 * The logical here is simplified to handle special cases only
514 * So we don't need to consider merge case for ensure_size
516 BUG_ON(min_stripe_size
&& (min_stripe_size
< len
* 2 ||
517 min_stripe_size
/ 2 < BTRFS_STRIPE_LEN
));
519 /* Also, wipe range should already be aligned */
520 BUG_ON(start
!= round_down(start
, BTRFS_STRIPE_LEN
) ||
521 start
+ len
!= round_up(start
+ len
, BTRFS_STRIPE_LEN
));
523 min_stripe_size
/= 2;
525 cache
= lookup_cache_extent(tree
, start
, len
);
529 if (start
<= cache
->start
) {
531 * |--------cache---------|
534 BUG_ON(start
+ len
<= cache
->start
);
537 * The wipe size is smaller than min_stripe_size / 2,
538 * so the result length should still meet min_stripe_size
539 * And no need to do alignment
541 cache
->size
-= (start
+ len
- cache
->start
);
542 if (cache
->size
== 0) {
543 remove_cache_extent(tree
, cache
);
548 BUG_ON(ensure_size
&& cache
->size
< min_stripe_size
);
550 cache
->start
= start
+ len
;
552 } else if (start
> cache
->start
&& start
+ len
< cache
->start
+
555 * |-------cache-----|
558 u64 old_start
= cache
->start
;
559 u64 old_len
= cache
->size
;
560 u64 insert_start
= start
+ len
;
563 cache
->size
= start
- cache
->start
;
564 /* Expand the leading half part if needed */
565 if (ensure_size
&& cache
->size
< min_stripe_size
) {
566 ret
= _expand_extent_cache(tree
, cache
,
572 /* And insert the new one */
573 insert_len
= old_start
+ old_len
- start
- len
;
574 ret
= add_merge_cache_extent(tree
, insert_start
, insert_len
);
578 /* Expand the last half part if needed */
579 if (ensure_size
&& insert_len
< min_stripe_size
) {
580 cache
= lookup_cache_extent(tree
, insert_start
,
582 if (!cache
|| cache
->start
!= insert_start
||
583 cache
->size
!= insert_len
)
585 ret
= _expand_extent_cache(tree
, cache
,
594 * Wipe len should be small enough and no need to expand the
597 cache
->size
= start
- cache
->start
;
598 BUG_ON(ensure_size
&& cache
->size
< min_stripe_size
);
603 * Remove reserved ranges from given cache_tree
605 * It will remove the following ranges
607 * 2) 2nd superblock, +64K (make sure chunks are 64K aligned)
608 * 3) 3rd superblock, +64K
610 * @min_stripe must be given for safety check
611 * and if @ensure_size is given, it will ensure affected cache_extent will be
612 * larger than min_stripe_size
614 static int wipe_reserved_ranges(struct cache_tree
*tree
, u64 min_stripe_size
,
620 for (i
= 0; i
< ARRAY_SIZE(btrfs_reserved_ranges
); i
++) {
621 const struct simple_range
*range
= &btrfs_reserved_ranges
[i
];
623 ret
= wipe_one_reserved_range(tree
, range
->start
, range
->len
,
624 min_stripe_size
, ensure_size
);
631 static int calculate_available_space(struct btrfs_convert_context
*cctx
)
633 struct cache_tree
*used
= &cctx
->used_space
;
634 struct cache_tree
*data_chunks
= &cctx
->data_chunks
;
635 struct cache_tree
*free
= &cctx
->free_space
;
636 struct cache_extent
*cache
;
639 * Twice the minimal chunk size, to allow later wipe_reserved_ranges()
640 * works without need to consider overlap
642 u64 min_stripe_size
= SZ_32M
;
645 /* Calculate data_chunks */
646 for (cache
= first_cache_extent(used
); cache
;
647 cache
= next_cache_extent(cache
)) {
650 if (cache
->start
+ cache
->size
< cur_off
)
652 if (cache
->start
> cur_off
+ min_stripe_size
)
653 cur_off
= cache
->start
;
654 cur_len
= max(cache
->start
+ cache
->size
- cur_off
,
656 ret
= add_merge_cache_extent(data_chunks
, cur_off
, cur_len
);
662 * remove reserved ranges, so we won't ever bother relocating an old
663 * filesystem extent to other place.
665 ret
= wipe_reserved_ranges(data_chunks
, min_stripe_size
, 1);
671 * Calculate free space
672 * Always round up the start bytenr, to avoid metadata extent corss
673 * stripe boundary, as later mkfs_convert() won't have all the extent
676 for (cache
= first_cache_extent(data_chunks
); cache
;
677 cache
= next_cache_extent(cache
)) {
678 if (cache
->start
< cur_off
)
680 if (cache
->start
> cur_off
) {
684 len
= cache
->start
- round_up(cur_off
,
686 insert_start
= round_up(cur_off
, BTRFS_STRIPE_LEN
);
688 ret
= add_merge_cache_extent(free
, insert_start
, len
);
692 cur_off
= cache
->start
+ cache
->size
;
694 /* Don't forget the last range */
695 if (cctx
->total_bytes
> cur_off
) {
696 u64 len
= cctx
->total_bytes
- cur_off
;
699 insert_start
= round_up(cur_off
, BTRFS_STRIPE_LEN
);
701 ret
= add_merge_cache_extent(free
, insert_start
, len
);
706 /* Remove reserved bytes */
707 ret
= wipe_reserved_ranges(free
, min_stripe_size
, 0);
713 * Read used space, and since we have the used space,
714 * calcuate data_chunks and free for later mkfs
716 static int convert_read_used_space(struct btrfs_convert_context
*cctx
)
720 ret
= cctx
->convert_ops
->read_used_space(cctx
);
724 ret
= calculate_available_space(cctx
);
729 * Create the fs image file of old filesystem.
731 * This is completely fs independent as we have cctx->used, only
732 * need to create file extents pointing to all the positions.
734 static int create_image(struct btrfs_root
*root
,
735 struct btrfs_mkfs_config
*cfg
,
736 struct btrfs_convert_context
*cctx
, int fd
,
737 u64 size
, char *name
, u32 convert_flags
)
739 struct btrfs_inode_item buf
;
740 struct btrfs_trans_handle
*trans
;
741 struct btrfs_path path
;
742 struct btrfs_key key
;
743 struct cache_extent
*cache
;
744 struct cache_tree used_tmp
;
747 u64 flags
= BTRFS_INODE_READONLY
;
750 if (!(convert_flags
& CONVERT_FLAG_DATACSUM
))
751 flags
|= BTRFS_INODE_NODATASUM
;
753 trans
= btrfs_start_transaction(root
, 1);
755 return PTR_ERR(trans
);
757 cache_tree_init(&used_tmp
);
758 btrfs_init_path(&path
);
760 ret
= btrfs_find_free_objectid(trans
, root
, BTRFS_FIRST_FREE_OBJECTID
,
764 ret
= btrfs_new_inode(trans
, root
, ino
, 0400 | S_IFREG
);
767 ret
= btrfs_change_inode_flags(trans
, root
, ino
, flags
);
770 ret
= btrfs_add_link(trans
, root
, ino
, BTRFS_FIRST_FREE_OBJECTID
, name
,
771 strlen(name
), BTRFS_FT_REG_FILE
, NULL
, 1);
776 key
.type
= BTRFS_INODE_ITEM_KEY
;
779 ret
= btrfs_search_slot(trans
, root
, &key
, &path
, 0, 1);
781 ret
= (ret
> 0 ? -ENOENT
: ret
);
784 read_extent_buffer(path
.nodes
[0], &buf
,
785 btrfs_item_ptr_offset(path
.nodes
[0], path
.slots
[0]),
787 btrfs_release_path(&path
);
790 * Create a new used space cache, which doesn't contain the reserved
793 for (cache
= first_cache_extent(&cctx
->used_space
); cache
;
794 cache
= next_cache_extent(cache
)) {
795 ret
= add_cache_extent(&used_tmp
, cache
->start
, cache
->size
);
799 ret
= wipe_reserved_ranges(&used_tmp
, 0, 0);
804 * Start from 1M, as 0~1M is reserved, and create_image_file_range()
805 * can't handle bytenr 0(will consider it as a hole)
809 u64 len
= size
- cur
;
811 ret
= create_image_file_range(trans
, root
, &used_tmp
,
812 &buf
, ino
, cur
, &len
,
818 /* Handle the reserved ranges */
819 ret
= migrate_reserved_ranges(trans
, root
, &cctx
->used_space
, &buf
, fd
,
820 ino
, cfg
->num_bytes
, convert_flags
);
823 key
.type
= BTRFS_INODE_ITEM_KEY
;
825 ret
= btrfs_search_slot(trans
, root
, &key
, &path
, 0, 1);
827 ret
= (ret
> 0 ? -ENOENT
: ret
);
830 btrfs_set_stack_inode_size(&buf
, cfg
->num_bytes
);
831 write_extent_buffer(path
.nodes
[0], &buf
,
832 btrfs_item_ptr_offset(path
.nodes
[0], path
.slots
[0]),
835 free_extent_cache_tree(&used_tmp
);
836 btrfs_release_path(&path
);
837 btrfs_commit_transaction(trans
, root
);
841 static int create_subvol(struct btrfs_trans_handle
*trans
,
842 struct btrfs_root
*root
, u64 root_objectid
)
844 struct extent_buffer
*tmp
;
845 struct btrfs_root
*new_root
;
846 struct btrfs_key key
;
847 struct btrfs_root_item root_item
;
850 ret
= btrfs_copy_root(trans
, root
, root
->node
, &tmp
,
855 memcpy(&root_item
, &root
->root_item
, sizeof(root_item
));
856 btrfs_set_root_bytenr(&root_item
, tmp
->start
);
857 btrfs_set_root_level(&root_item
, btrfs_header_level(tmp
));
858 btrfs_set_root_generation(&root_item
, trans
->transid
);
859 free_extent_buffer(tmp
);
861 key
.objectid
= root_objectid
;
862 key
.type
= BTRFS_ROOT_ITEM_KEY
;
863 key
.offset
= trans
->transid
;
864 ret
= btrfs_insert_root(trans
, root
->fs_info
->tree_root
,
867 key
.offset
= (u64
)-1;
868 new_root
= btrfs_read_fs_root(root
->fs_info
, &key
);
869 if (!new_root
|| IS_ERR(new_root
)) {
870 error("unable to fs read root: %lu", PTR_ERR(new_root
));
871 return PTR_ERR(new_root
);
874 ret
= btrfs_make_root_dir(trans
, new_root
, BTRFS_FIRST_FREE_OBJECTID
);
880 * New make_btrfs() has handle system and meta chunks quite well.
881 * So only need to add remaining data chunks.
883 static int make_convert_data_block_groups(struct btrfs_trans_handle
*trans
,
884 struct btrfs_fs_info
*fs_info
,
885 struct btrfs_mkfs_config
*cfg
,
886 struct btrfs_convert_context
*cctx
)
888 struct btrfs_root
*extent_root
= fs_info
->extent_root
;
889 struct cache_tree
*data_chunks
= &cctx
->data_chunks
;
890 struct cache_extent
*cache
;
895 * Don't create data chunk over 10% of the convert device
896 * And for single chunk, don't create chunk larger than 1G.
898 max_chunk_size
= cfg
->num_bytes
/ 10;
899 max_chunk_size
= min((u64
)(SZ_1G
), max_chunk_size
);
900 max_chunk_size
= round_down(max_chunk_size
,
901 extent_root
->fs_info
->sectorsize
);
903 for (cache
= first_cache_extent(data_chunks
); cache
;
904 cache
= next_cache_extent(cache
)) {
905 u64 cur
= cache
->start
;
907 while (cur
< cache
->start
+ cache
->size
) {
909 u64 cur_backup
= cur
;
911 len
= min(max_chunk_size
,
912 cache
->start
+ cache
->size
- cur
);
913 ret
= btrfs_alloc_data_chunk(trans
, fs_info
,
915 BTRFS_BLOCK_GROUP_DATA
, 1);
918 ret
= btrfs_make_block_group(trans
, fs_info
, 0,
919 BTRFS_BLOCK_GROUP_DATA
,
920 BTRFS_FIRST_CHUNK_TREE_OBJECTID
,
931 * Init the temp btrfs to a operational status.
933 * It will fix the extent usage accounting(XXX: Do we really need?) and
934 * insert needed data chunks, to ensure all old fs data extents are covered
935 * by DATA chunks, preventing wrong chunks are allocated.
937 * And also create convert image subvolume and relocation tree.
938 * (XXX: Not need again?)
939 * But the convert image subvolume is *NOT* linked to fs tree yet.
941 static int init_btrfs(struct btrfs_mkfs_config
*cfg
, struct btrfs_root
*root
,
942 struct btrfs_convert_context
*cctx
, u32 convert_flags
)
944 struct btrfs_key location
;
945 struct btrfs_trans_handle
*trans
;
946 struct btrfs_fs_info
*fs_info
= root
->fs_info
;
950 * Don't alloc any metadata/system chunk, as we don't want
951 * any meta/sys chunk allcated before all data chunks are inserted.
952 * Or we screw up the chunk layout just like the old implement.
954 fs_info
->avoid_sys_chunk_alloc
= 1;
955 fs_info
->avoid_meta_chunk_alloc
= 1;
956 trans
= btrfs_start_transaction(root
, 1);
958 error("unable to start transaction");
959 ret
= PTR_ERR(trans
);
962 ret
= btrfs_fix_block_accounting(trans
, root
);
965 ret
= make_convert_data_block_groups(trans
, fs_info
, cfg
, cctx
);
968 ret
= btrfs_make_root_dir(trans
, fs_info
->tree_root
,
969 BTRFS_ROOT_TREE_DIR_OBJECTID
);
972 memcpy(&location
, &root
->root_key
, sizeof(location
));
973 location
.offset
= (u64
)-1;
974 ret
= btrfs_insert_dir_item(trans
, fs_info
->tree_root
, "default", 7,
975 btrfs_super_root_dir(fs_info
->super_copy
),
976 &location
, BTRFS_FT_DIR
, 0);
979 ret
= btrfs_insert_inode_ref(trans
, fs_info
->tree_root
, "default", 7,
981 btrfs_super_root_dir(fs_info
->super_copy
), 0);
984 btrfs_set_root_dirid(&fs_info
->fs_root
->root_item
,
985 BTRFS_FIRST_FREE_OBJECTID
);
987 /* subvol for fs image file */
988 ret
= create_subvol(trans
, root
, CONV_IMAGE_SUBVOL_OBJECTID
);
990 error("failed to create subvolume image root: %d", ret
);
993 /* subvol for data relocation tree */
994 ret
= create_subvol(trans
, root
, BTRFS_DATA_RELOC_TREE_OBJECTID
);
996 error("failed to create DATA_RELOC root: %d", ret
);
1000 ret
= btrfs_commit_transaction(trans
, root
);
1001 fs_info
->avoid_sys_chunk_alloc
= 0;
1002 fs_info
->avoid_meta_chunk_alloc
= 0;
1008 * Migrate super block to its default position and zero 0 ~ 16k
1010 static int migrate_super_block(int fd
, u64 old_bytenr
)
1013 struct extent_buffer
*buf
;
1014 struct btrfs_super_block
*super
;
1018 buf
= malloc(sizeof(*buf
) + BTRFS_SUPER_INFO_SIZE
);
1022 buf
->len
= BTRFS_SUPER_INFO_SIZE
;
1023 ret
= pread(fd
, buf
->data
, BTRFS_SUPER_INFO_SIZE
, old_bytenr
);
1024 if (ret
!= BTRFS_SUPER_INFO_SIZE
)
1027 super
= (struct btrfs_super_block
*)buf
->data
;
1028 BUG_ON(btrfs_super_bytenr(super
) != old_bytenr
);
1029 btrfs_set_super_bytenr(super
, BTRFS_SUPER_INFO_OFFSET
);
1031 csum_tree_block_size(buf
, BTRFS_CRC32_SIZE
, 0);
1032 ret
= pwrite(fd
, buf
->data
, BTRFS_SUPER_INFO_SIZE
,
1033 BTRFS_SUPER_INFO_OFFSET
);
1034 if (ret
!= BTRFS_SUPER_INFO_SIZE
)
1041 memset(buf
->data
, 0, BTRFS_SUPER_INFO_SIZE
);
1042 for (bytenr
= 0; bytenr
< BTRFS_SUPER_INFO_OFFSET
; ) {
1043 len
= BTRFS_SUPER_INFO_OFFSET
- bytenr
;
1044 if (len
> BTRFS_SUPER_INFO_SIZE
)
1045 len
= BTRFS_SUPER_INFO_SIZE
;
1046 ret
= pwrite(fd
, buf
->data
, len
, bytenr
);
1048 fprintf(stderr
, "unable to zero fill device\n");
1062 static int convert_open_fs(const char *devname
,
1063 struct btrfs_convert_context
*cctx
)
1067 for (i
= 0; i
< ARRAY_SIZE(convert_operations
); i
++) {
1068 int ret
= convert_operations
[i
]->open_fs(cctx
, devname
);
1071 cctx
->convert_ops
= convert_operations
[i
];
1076 error("no file system found to convert");
1080 static int do_convert(const char *devname
, u32 convert_flags
, u32 nodesize
,
1081 const char *fslabel
, int progress
, u64 features
)
1087 struct btrfs_root
*root
;
1088 struct btrfs_root
*image_root
;
1089 struct btrfs_convert_context cctx
;
1090 struct btrfs_key key
;
1091 char subvol_name
[SOURCE_FS_NAME_LEN
+ 8];
1092 struct task_ctx ctx
;
1093 char features_buf
[64];
1094 struct btrfs_mkfs_config mkfs_cfg
;
1096 init_convert_context(&cctx
);
1097 ret
= convert_open_fs(devname
, &cctx
);
1100 ret
= convert_check_state(&cctx
);
1103 "source filesystem is not clean, running filesystem check is recommended");
1104 ret
= convert_read_used_space(&cctx
);
1108 blocksize
= cctx
.blocksize
;
1109 total_bytes
= (u64
)blocksize
* (u64
)cctx
.block_count
;
1110 if (blocksize
< 4096) {
1111 error("block size is too small: %u < 4096", blocksize
);
1114 if (btrfs_check_nodesize(nodesize
, blocksize
, features
))
1116 fd
= open(devname
, O_RDWR
);
1118 error("unable to open %s: %s", devname
, strerror(errno
));
1121 btrfs_parse_features_to_string(features_buf
, features
);
1122 if (features
== BTRFS_MKFS_DEFAULT_FEATURES
)
1123 strcat(features_buf
, " (default)");
1125 printf("create btrfs filesystem:\n");
1126 printf("\tblocksize: %u\n", blocksize
);
1127 printf("\tnodesize: %u\n", nodesize
);
1128 printf("\tfeatures: %s\n", features_buf
);
1130 memset(&mkfs_cfg
, 0, sizeof(mkfs_cfg
));
1131 mkfs_cfg
.label
= cctx
.volume_name
;
1132 mkfs_cfg
.num_bytes
= total_bytes
;
1133 mkfs_cfg
.nodesize
= nodesize
;
1134 mkfs_cfg
.sectorsize
= blocksize
;
1135 mkfs_cfg
.stripesize
= blocksize
;
1136 mkfs_cfg
.features
= features
;
1138 ret
= make_convert_btrfs(fd
, &mkfs_cfg
, &cctx
);
1140 error("unable to create initial ctree: %s", strerror(-ret
));
1144 root
= open_ctree_fd(fd
, devname
, mkfs_cfg
.super_bytenr
,
1145 OPEN_CTREE_WRITES
| OPEN_CTREE_FS_PARTIAL
);
1147 error("unable to open ctree");
1150 ret
= init_btrfs(&mkfs_cfg
, root
, &cctx
, convert_flags
);
1152 error("unable to setup the root tree: %d", ret
);
1156 printf("creating %s image file\n", cctx
.convert_ops
->name
);
1157 snprintf(subvol_name
, sizeof(subvol_name
), "%s_saved",
1158 cctx
.convert_ops
->name
);
1159 key
.objectid
= CONV_IMAGE_SUBVOL_OBJECTID
;
1160 key
.offset
= (u64
)-1;
1161 key
.type
= BTRFS_ROOT_ITEM_KEY
;
1162 image_root
= btrfs_read_fs_root(root
->fs_info
, &key
);
1164 error("unable to create image subvolume");
1167 ret
= create_image(image_root
, &mkfs_cfg
, &cctx
, fd
,
1168 mkfs_cfg
.num_bytes
, "image",
1171 error("failed to create %s/image: %d", subvol_name
, ret
);
1175 printf("creating btrfs metadata\n");
1176 ret
= pthread_mutex_init(&ctx
.mutex
, NULL
);
1178 error("failed to initialize mutex: %d", ret
);
1181 ctx
.max_copy_inodes
= (cctx
.inodes_count
- cctx
.free_inodes_count
);
1182 ctx
.cur_copy_inodes
= 0;
1185 ctx
.info
= task_init(print_copied_inodes
, after_copied_inodes
,
1187 task_start(ctx
.info
);
1189 ret
= copy_inodes(&cctx
, root
, convert_flags
, &ctx
);
1191 error("error during copy_inodes %d", ret
);
1195 task_stop(ctx
.info
);
1196 task_deinit(ctx
.info
);
1199 image_root
= btrfs_mksubvol(root
, subvol_name
,
1200 CONV_IMAGE_SUBVOL_OBJECTID
, true);
1202 error("unable to link subvolume %s", subvol_name
);
1206 memset(root
->fs_info
->super_copy
->label
, 0, BTRFS_LABEL_SIZE
);
1207 if (convert_flags
& CONVERT_FLAG_COPY_LABEL
) {
1208 __strncpy_null(root
->fs_info
->super_copy
->label
,
1209 cctx
.volume_name
, BTRFS_LABEL_SIZE
- 1);
1210 printf("copy label '%s'\n", root
->fs_info
->super_copy
->label
);
1211 } else if (convert_flags
& CONVERT_FLAG_SET_LABEL
) {
1212 strcpy(root
->fs_info
->super_copy
->label
, fslabel
);
1213 printf("set label to '%s'\n", fslabel
);
1216 ret
= close_ctree(root
);
1218 error("close_ctree failed: %d", ret
);
1221 convert_close_fs(&cctx
);
1222 clean_convert_context(&cctx
);
1225 * If this step succeed, we get a mountable btrfs. Otherwise
1226 * the source fs is left unchanged.
1228 ret
= migrate_super_block(fd
, mkfs_cfg
.super_bytenr
);
1230 error("unable to migrate super block: %d", ret
);
1234 root
= open_ctree_fd(fd
, devname
, 0,
1235 OPEN_CTREE_WRITES
| OPEN_CTREE_FS_PARTIAL
);
1237 error("unable to open ctree for finalization");
1240 root
->fs_info
->finalize_on_close
= 1;
1244 printf("conversion complete\n");
1247 clean_convert_context(&cctx
);
1251 "an error occurred during conversion, filesystem is partially created but not finalized and not mountable");
1256 * Read out data of convert image which is in btrfs reserved ranges so we can
1257 * use them to overwrite the ranges during rollback.
1259 static int read_reserved_ranges(struct btrfs_root
*root
, u64 ino
,
1260 u64 total_bytes
, char *reserved_ranges
[])
1265 for (i
= 0; i
< ARRAY_SIZE(btrfs_reserved_ranges
); i
++) {
1266 const struct simple_range
*range
= &btrfs_reserved_ranges
[i
];
1268 if (range
->start
+ range
->len
>= total_bytes
)
1270 ret
= btrfs_read_file(root
, ino
, range
->start
, range
->len
,
1271 reserved_ranges
[i
]);
1272 if (ret
< range
->len
) {
1274 "failed to read data of convert image, offset=%llu len=%llu ret=%d",
1275 range
->start
, range
->len
, ret
);
1285 static bool is_subset_of_reserved_ranges(u64 start
, u64 len
)
1290 for (i
= 0; i
< ARRAY_SIZE(btrfs_reserved_ranges
); i
++) {
1291 const struct simple_range
*range
= &btrfs_reserved_ranges
[i
];
1293 if (start
>= range
->start
&& start
+ len
<= range_end(range
)) {
1301 static bool is_chunk_direct_mapped(struct btrfs_fs_info
*fs_info
, u64 start
)
1303 struct cache_extent
*ce
;
1304 struct map_lookup
*map
;
1307 ce
= search_cache_extent(&fs_info
->mapping_tree
.cache_tree
, start
);
1310 if (ce
->start
> start
|| ce
->start
+ ce
->size
< start
)
1313 map
= container_of(ce
, struct map_lookup
, ce
);
1315 /* Not SINGLE chunk */
1316 if (map
->num_stripes
!= 1)
1319 /* Chunk's logical doesn't match with phisical, not 1:1 mapped */
1320 if (map
->ce
.start
!= map
->stripes
[0].physical
)
1328 * Iterate all file extents of the convert image.
1330 * All file extents except ones in btrfs_reserved_ranges must be mapped 1:1
1331 * on disk. (Means thier file_offset must match their on disk bytenr)
1333 * File extents in reserved ranges can be relocated to other place, and in
1334 * that case we will read them out for later use.
1336 static int check_convert_image(struct btrfs_root
*image_root
, u64 ino
,
1337 u64 total_size
, char *reserved_ranges
[])
1339 struct btrfs_key key
;
1340 struct btrfs_path path
;
1341 struct btrfs_fs_info
*fs_info
= image_root
->fs_info
;
1342 u64 checked_bytes
= 0;
1347 key
.type
= BTRFS_EXTENT_DATA_KEY
;
1349 btrfs_init_path(&path
);
1350 ret
= btrfs_search_slot(NULL
, image_root
, &key
, &path
, 0, 0);
1352 * It's possible that some fs doesn't store any (including sb)
1353 * data into 0~1M range, and NO_HOLES is enabled.
1355 * So we only need to check if ret < 0
1358 error("failed to iterate file extents at offset 0: %s",
1360 btrfs_release_path(&path
);
1364 /* Loop from the first file extents */
1366 struct btrfs_file_extent_item
*fi
;
1367 struct extent_buffer
*leaf
= path
.nodes
[0];
1371 int slot
= path
.slots
[0];
1373 if (slot
>= btrfs_header_nritems(leaf
))
1375 btrfs_item_key_to_cpu(leaf
, &key
, slot
);
1378 * Iteration is done, exit normally, we have extra check out of
1381 if (key
.objectid
!= ino
|| key
.type
!= BTRFS_EXTENT_DATA_KEY
) {
1385 file_offset
= key
.offset
;
1386 fi
= btrfs_item_ptr(leaf
, slot
, struct btrfs_file_extent_item
);
1387 if (btrfs_file_extent_type(leaf
, fi
) != BTRFS_FILE_EXTENT_REG
) {
1390 "ino %llu offset %llu doesn't have a regular file extent",
1394 if (btrfs_file_extent_compression(leaf
, fi
) ||
1395 btrfs_file_extent_encryption(leaf
, fi
) ||
1396 btrfs_file_extent_other_encoding(leaf
, fi
)) {
1399 "ino %llu offset %llu doesn't have a plain file extent",
1404 disk_bytenr
= btrfs_file_extent_disk_bytenr(leaf
, fi
);
1405 ram_bytes
= btrfs_file_extent_ram_bytes(leaf
, fi
);
1407 checked_bytes
+= ram_bytes
;
1409 if (disk_bytenr
== 0)
1413 * Most file extents must be 1:1 mapped, which means 2 things:
1414 * 1) File extent file offset == disk_bytenr
1415 * 2) That data chunk's logical == chunk's physical
1417 * So file extent's file offset == physical position on disk.
1419 * And after rolling back btrfs reserved range, other part
1420 * remains what old fs used to be.
1422 if (file_offset
!= disk_bytenr
||
1423 !is_chunk_direct_mapped(fs_info
, disk_bytenr
)) {
1425 * Only file extent in btrfs reserved ranges are
1426 * allowed to be non-1:1 mapped
1428 if (!is_subset_of_reserved_ranges(file_offset
,
1432 "ino %llu offset %llu file extent should not be relocated",
1438 ret
= btrfs_next_item(image_root
, &path
);
1445 btrfs_release_path(&path
);
1447 * For HOLES mode (without NO_HOLES), we must ensure file extents
1448 * cover the whole range of the image
1450 if (!ret
&& !btrfs_fs_incompat(fs_info
, NO_HOLES
)) {
1451 if (checked_bytes
!= total_size
) {
1453 error("inode %llu has some file extents not checked",
1459 /* So far so good, read old data located in btrfs reserved ranges */
1460 ret
= read_reserved_ranges(image_root
, ino
, total_size
,
1466 * btrfs rollback is just reverted convert:
1467 * |<---------------Btrfs fs------------------------------>|
1468 * |<- Old data chunk ->|< new chunk (D/M/S)>|<- ODC ->|
1469 * |<-Old-FE->| |<-Old-FE->|<- Btrfs extents ->|<-Old-FE->|
1472 * |<------------------Old fs----------------------------->|
1473 * |<- used ->| |<- used ->| |<- used ->|
1475 * However things are much easier than convert, we don't really need to
1476 * do the complex space calculation, but only to handle btrfs reserved space
1478 * |<---------------------------Btrfs fs----------------------------->|
1479 * | RSV 1 | | Old | | RSV 2 | | Old | | RSV 3 |
1480 * | 0~1M | | Fs | | SB2 + 64K | | Fs | | SB3 + 64K |
1482 * On the other hand, the converted fs image in btrfs is a completely
1485 * |<-----------------Converted fs image in btrfs-------------------->|
1486 * | RSV 1 | | Old | | RSV 2 | | Old | | RSV 3 |
1487 * | Relocated | | Fs | | Relocated | | Fs | | Relocated |
1489 * Used space in fs image should be at the same physical position on disk.
1490 * We only need to recover the data in reserved ranges, so the whole
1493 * The idea to rollback is also straightforward, we just "read" out the data
1494 * of reserved ranges, and write them back to there they should be.
1495 * Then the old fs is back.
1497 static int do_rollback(const char *devname
)
1499 struct btrfs_root
*root
;
1500 struct btrfs_root
*image_root
;
1501 struct btrfs_fs_info
*fs_info
;
1502 struct btrfs_key key
;
1503 struct btrfs_path path
;
1504 struct btrfs_dir_item
*dir
;
1505 struct btrfs_inode_item
*inode_item
;
1506 char *image_name
= "image";
1507 char *reserved_ranges
[ARRAY_SIZE(btrfs_reserved_ranges
)] = { NULL
};
1516 for (i
= 0; i
< ARRAY_SIZE(btrfs_reserved_ranges
); i
++) {
1517 const struct simple_range
*range
= &btrfs_reserved_ranges
[i
];
1519 reserved_ranges
[i
] = calloc(1, range
->len
);
1520 if (!reserved_ranges
[i
]) {
1525 fd
= open(devname
, O_RDWR
);
1527 error("unable to open %s: %s", devname
, strerror(errno
));
1531 fsize
= lseek(fd
, 0, SEEK_END
);
1532 root
= open_ctree_fd(fd
, devname
, 0, OPEN_CTREE_WRITES
);
1534 error("unable to open ctree");
1538 fs_info
= root
->fs_info
;
1541 * Search root backref first, or after subvolume deletion (orphan),
1542 * we can still rollback the image.
1544 key
.objectid
= CONV_IMAGE_SUBVOL_OBJECTID
;
1545 key
.type
= BTRFS_ROOT_BACKREF_KEY
;
1546 key
.offset
= BTRFS_FS_TREE_OBJECTID
;
1547 btrfs_init_path(&path
);
1548 ret
= btrfs_search_slot(NULL
, fs_info
->tree_root
, &key
, &path
, 0, 0);
1549 btrfs_release_path(&path
);
1551 error("unable to find source fs image subvolume, is it deleted?");
1554 } else if (ret
< 0) {
1555 error("failed to find source fs image subvolume: %s",
1560 /* Search convert subvolume */
1561 key
.objectid
= CONV_IMAGE_SUBVOL_OBJECTID
;
1562 key
.type
= BTRFS_ROOT_ITEM_KEY
;
1563 key
.offset
= (u64
)-1;
1564 image_root
= btrfs_read_fs_root(fs_info
, &key
);
1565 if (IS_ERR(image_root
)) {
1566 ret
= PTR_ERR(image_root
);
1567 error("failed to open convert image subvolume: %s",
1572 /* Search the image file */
1573 root_dir
= btrfs_root_dirid(&image_root
->root_item
);
1574 dir
= btrfs_lookup_dir_item(NULL
, image_root
, &path
, root_dir
,
1575 image_name
, strlen(image_name
), 0);
1577 if (!dir
|| IS_ERR(dir
)) {
1578 btrfs_release_path(&path
);
1583 error("failed to locate file %s: %s", image_name
,
1587 btrfs_dir_item_key_to_cpu(path
.nodes
[0], dir
, &key
);
1588 btrfs_release_path(&path
);
1590 /* Get total size of the original image */
1593 ret
= btrfs_lookup_inode(NULL
, image_root
, &path
, &key
, 0);
1596 btrfs_release_path(&path
);
1597 error("unable to find inode %llu: %s", ino
, strerror(-ret
));
1600 inode_item
= btrfs_item_ptr(path
.nodes
[0], path
.slots
[0],
1601 struct btrfs_inode_item
);
1602 total_bytes
= btrfs_inode_size(path
.nodes
[0], inode_item
);
1603 btrfs_release_path(&path
);
1605 /* Check if we can rollback the image */
1606 ret
= check_convert_image(image_root
, ino
, total_bytes
, reserved_ranges
);
1608 error("old fs image can't be rolled back");
1612 btrfs_release_path(&path
);
1613 close_ctree_fs_info(fs_info
);
1618 * Everything is OK, just write back old fs data into btrfs reserved
1621 * Here, we starts from the backup blocks first, so if something goes
1622 * wrong, the fs is still mountable
1625 for (i
= ARRAY_SIZE(btrfs_reserved_ranges
) - 1; i
>= 0; i
--) {
1627 const struct simple_range
*range
= &btrfs_reserved_ranges
[i
];
1629 if (range_end(range
) >= fsize
)
1632 real_size
= min(range_end(range
), fsize
) - range
->start
;
1633 ret
= pwrite(fd
, reserved_ranges
[i
], real_size
, range
->start
);
1634 if (ret
< real_size
) {
1639 error("failed to recover range [%llu, %llu): %s",
1640 range
->start
, real_size
, strerror(-ret
));
1647 for (i
= 0; i
< ARRAY_SIZE(btrfs_reserved_ranges
); i
++)
1648 free(reserved_ranges
[i
]);
1650 error("rollback failed");
1652 printf("rollback succeeded\n");
1656 static void print_usage(void)
1658 printf("usage: btrfs-convert [options] device\n");
1659 printf("options:\n");
1660 printf("\t-d|--no-datasum disable data checksum, sets NODATASUM\n");
1661 printf("\t-i|--no-xattr ignore xattrs and ACLs\n");
1662 printf("\t-n|--no-inline disable inlining of small files to metadata\n");
1663 printf("\t-N|--nodesize SIZE set filesystem metadata nodesize\n");
1664 printf("\t-r|--rollback roll back to the original filesystem\n");
1665 printf("\t-l|--label LABEL set filesystem label\n");
1666 printf("\t-L|--copy-label use label from converted filesystem\n");
1667 printf("\t-p|--progress show converting progress (default)\n");
1668 printf("\t-O|--features LIST comma separated list of filesystem features\n");
1669 printf("\t--no-progress show only overview, not the detailed progress\n");
1671 printf("Supported filesystems:\n");
1672 printf("\text2/3/4: %s\n", BTRFSCONVERT_EXT2
? "yes" : "no");
1673 printf("\treiserfs: %s\n", BTRFSCONVERT_REISERFS
? "yes" : "no");
1676 int main(int argc
, char *argv
[])
1682 u32 nodesize
= max_t(u32
, sysconf(_SC_PAGESIZE
),
1683 BTRFS_MKFS_DEFAULT_NODE_SIZE
);
1686 int usage_error
= 0;
1689 char fslabel
[BTRFS_LABEL_SIZE
];
1690 u64 features
= BTRFS_MKFS_DEFAULT_FEATURES
;
1693 enum { GETOPT_VAL_NO_PROGRESS
= 256 };
1694 static const struct option long_options
[] = {
1695 { "no-progress", no_argument
, NULL
,
1696 GETOPT_VAL_NO_PROGRESS
},
1697 { "no-datasum", no_argument
, NULL
, 'd' },
1698 { "no-inline", no_argument
, NULL
, 'n' },
1699 { "no-xattr", no_argument
, NULL
, 'i' },
1700 { "rollback", no_argument
, NULL
, 'r' },
1701 { "features", required_argument
, NULL
, 'O' },
1702 { "progress", no_argument
, NULL
, 'p' },
1703 { "label", required_argument
, NULL
, 'l' },
1704 { "copy-label", no_argument
, NULL
, 'L' },
1705 { "nodesize", required_argument
, NULL
, 'N' },
1706 { "help", no_argument
, NULL
, GETOPT_VAL_HELP
},
1707 { NULL
, 0, NULL
, 0 }
1709 int c
= getopt_long(argc
, argv
, "dinN:rl:LpO:", long_options
, NULL
);
1724 nodesize
= parse_size(optarg
);
1730 copylabel
= CONVERT_FLAG_SET_LABEL
;
1731 if (strlen(optarg
) >= BTRFS_LABEL_SIZE
) {
1733 "label too long, trimmed to %d bytes",
1734 BTRFS_LABEL_SIZE
- 1);
1736 __strncpy_null(fslabel
, optarg
, BTRFS_LABEL_SIZE
- 1);
1739 copylabel
= CONVERT_FLAG_COPY_LABEL
;
1745 char *orig
= strdup(optarg
);
1748 tmp
= btrfs_parse_fs_features(tmp
, &features
);
1750 error("unrecognized filesystem feature: %s",
1756 if (features
& BTRFS_FEATURE_LIST_ALL
) {
1757 btrfs_list_all_fs_features(
1758 ~BTRFS_CONVERT_ALLOWED_FEATURES
);
1761 if (features
& ~BTRFS_CONVERT_ALLOWED_FEATURES
) {
1764 btrfs_parse_features_to_string(buf
,
1765 features
& ~BTRFS_CONVERT_ALLOWED_FEATURES
);
1766 error("features not allowed for convert: %s",
1773 case GETOPT_VAL_NO_PROGRESS
:
1776 case GETOPT_VAL_HELP
:
1779 return c
!= GETOPT_VAL_HELP
;
1783 if (check_argc_exact(argc
- optind
, 1)) {
1788 if (rollback
&& (!datacsum
|| noxattr
|| !packing
)) {
1790 "Usage error: -d, -i, -n options do not apply to rollback\n");
1799 file
= argv
[optind
];
1800 ret
= check_mounted(file
);
1802 error("could not check mount status: %s", strerror(-ret
));
1805 error("%s is mounted", file
);
1810 ret
= do_rollback(file
);
1814 cf
|= datacsum
? CONVERT_FLAG_DATACSUM
: 0;
1815 cf
|= packing
? CONVERT_FLAG_INLINE_DATA
: 0;
1816 cf
|= noxattr
? 0 : CONVERT_FLAG_XATTR
;
1818 ret
= do_convert(file
, cf
, nodesize
, fslabel
, progress
, features
);