btrfs-progs: Remove unused parameter
[platform/upstream/btrfs-progs.git] / convert / main.c
index 73c9d88..6bdfab4 100644 (file)
@@ -88,6 +88,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <getopt.h>
+#include <pthread.h>
 #include <stdbool.h>
 
 #include "ctree.h"
 #include "convert/source-fs.h"
 #include "fsfeatures.h"
 
-const struct btrfs_convert_operations ext2_convert_ops;
+extern const struct btrfs_convert_operations ext2_convert_ops;
+extern const struct btrfs_convert_operations reiserfs_convert_ops;
 
 static const struct btrfs_convert_operations *convert_operations[] = {
 #if BTRFSCONVERT_EXT2
        &ext2_convert_ops,
 #endif
+#if BTRFSCONVERT_REISERFS
+       &reiserfs_convert_ops,
+#endif
 };
 
 static void *print_copied_inodes(void *p)
@@ -119,10 +124,12 @@ static void *print_copied_inodes(void *p)
        task_period_start(priv->info, 1000 /* 1s */);
        while (1) {
                count++;
+               pthread_mutex_lock(&priv->mutex);
                printf("copy inodes [%c] [%10llu/%10llu]\r",
                       work_indicator[count % 4],
                       (unsigned long long)priv->cur_copy_inodes,
                       (unsigned long long)priv->max_copy_inodes);
+               pthread_mutex_unlock(&priv->mutex);
                fflush(stdout);
                task_period_wait(priv->info);
        }
@@ -159,7 +166,7 @@ static int csum_disk_extent(struct btrfs_trans_handle *trans,
                            struct btrfs_root *root,
                            u64 disk_bytenr, u64 num_bytes)
 {
-       u32 blocksize = root->sectorsize;
+       u32 blocksize = root->fs_info->sectorsize;
        u64 offset;
        char *buffer;
        int ret = 0;
@@ -199,12 +206,12 @@ static int create_image_file_range(struct btrfs_trans_handle *trans,
        int ret;
        u32 datacsum = convert_flags & CONVERT_FLAG_DATACSUM;
 
-       if (bytenr != round_down(bytenr, root->sectorsize)) {
+       if (bytenr != round_down(bytenr, root->fs_info->sectorsize)) {
                error("bytenr not sectorsize aligned: %llu",
                                (unsigned long long)bytenr);
                return -EINVAL;
        }
-       if (len != round_down(len, root->sectorsize)) {
+       if (len != round_down(len, root->fs_info->sectorsize)) {
                error("length not sectorsize aligned: %llu",
                                (unsigned long long)len);
                return -EINVAL;
@@ -218,7 +225,7 @@ static int create_image_file_range(struct btrfs_trans_handle *trans,
         * migrate block will fail as there is already a file extent.
         */
        for (i = 0; i < ARRAY_SIZE(btrfs_reserved_ranges); i++) {
-               struct simple_range *reserved = &btrfs_reserved_ranges[i];
+               const struct simple_range *reserved = &btrfs_reserved_ranges[i];
 
                /*
                 * |-- reserved --|
@@ -293,7 +300,7 @@ static int create_image_file_range(struct btrfs_trans_handle *trans,
                            bg_cache->key.offset - bytenr);
        }
 
-       if (len != round_down(len, root->sectorsize)) {
+       if (len != round_down(len, root->fs_info->sectorsize)) {
                error("remaining length not sectorsize aligned: %llu",
                                (unsigned long long)len);
                return -EINVAL;
@@ -320,7 +327,7 @@ static int migrate_one_reserved_range(struct btrfs_trans_handle *trans,
                                      struct btrfs_root *root,
                                      struct cache_tree *used,
                                      struct btrfs_inode_item *inode, int fd,
-                                     u64 ino, struct simple_range *range,
+                                     u64 ino, const struct simple_range *range,
                                      u32 convert_flags)
 {
        u64 cur_off = range->start;
@@ -340,13 +347,15 @@ static int migrate_one_reserved_range(struct btrfs_trans_handle *trans,
         * migrate ranges that covered by old fs data.
         */
        while (cur_off < range_end(range)) {
-               cache = lookup_cache_extent(used, cur_off, cur_len);
+               cache = search_cache_extent(used, cur_off);
                if (!cache)
                        break;
                cur_off = max(cache->start, cur_off);
+               if (cur_off >= range_end(range))
+                       break;
                cur_len = min(cache->start + cache->size, range_end(range)) -
                          cur_off;
-               BUG_ON(cur_len < root->sectorsize);
+               BUG_ON(cur_len < root->fs_info->sectorsize);
 
                /* reserve extent for the data */
                ret = btrfs_reserve_extent(trans, root, cur_len, 0, 0, (u64)-1,
@@ -370,7 +379,7 @@ static int migrate_one_reserved_range(struct btrfs_trans_handle *trans,
                eb->len = key.offset;
 
                /* Write the data */
-               ret = write_and_map_eb(root, eb);
+               ret = write_and_map_eb(root->fs_info, eb);
                free(eb);
                if (ret < 0)
                        break;
@@ -411,7 +420,7 @@ static int migrate_one_reserved_range(struct btrfs_trans_handle *trans,
 }
 
 /*
- * Relocate the used ext2 data in reserved ranges
+ * Relocate the used source fs data in reserved ranges
  */
 static int migrate_reserved_ranges(struct btrfs_trans_handle *trans,
                                   struct btrfs_root *root,
@@ -423,7 +432,7 @@ static int migrate_reserved_ranges(struct btrfs_trans_handle *trans,
        int ret = 0;
 
        for (i = 0; i < ARRAY_SIZE(btrfs_reserved_ranges); i++) {
-               struct simple_range *range = &btrfs_reserved_ranges[i];
+               const struct simple_range *range = &btrfs_reserved_ranges[i];
 
                if (range->start > total_bytes)
                        return ret;
@@ -609,7 +618,7 @@ static int wipe_reserved_ranges(struct cache_tree *tree, u64 min_stripe_size,
        int ret;
 
        for (i = 0; i < ARRAY_SIZE(btrfs_reserved_ranges); i++) {
-               struct simple_range *range = &btrfs_reserved_ranges[i];
+               const struct simple_range *range = &btrfs_reserved_ranges[i];
 
                ret = wipe_one_reserved_range(tree, range->start, range->len,
                                              min_stripe_size, ensure_size);
@@ -630,7 +639,7 @@ static int calculate_available_space(struct btrfs_convert_context *cctx)
         * Twice the minimal chunk size, to allow later wipe_reserved_ranges()
         * works without need to consider overlap
         */
-       u64 min_stripe_size = 2 * 16 * 1024 * 1024;
+       u64 min_stripe_size = SZ_32M;
        int ret;
 
        /* Calculate data_chunks */
@@ -742,8 +751,8 @@ static int create_image(struct btrfs_root *root,
                flags |= BTRFS_INODE_NODATASUM;
 
        trans = btrfs_start_transaction(root, 1);
-       if (!trans)
-               return -ENOMEM;
+       if (IS_ERR(trans))
+               return PTR_ERR(trans);
 
        cache_tree_init(&used_tmp);
        btrfs_init_path(&path);
@@ -759,7 +768,7 @@ static int create_image(struct btrfs_root *root,
        if (ret < 0)
                goto out;
        ret = btrfs_add_link(trans, root, ino, BTRFS_FIRST_FREE_OBJECTID, name,
-                            strlen(name), BTRFS_FT_REG_FILE, NULL, 1);
+                            strlen(name), BTRFS_FT_REG_FILE, NULL, 1, 0);
        if (ret < 0)
                goto out;
 
@@ -795,7 +804,7 @@ static int create_image(struct btrfs_root *root,
         * Start from 1M, as 0~1M is reserved, and create_image_file_range()
         * can't handle bytenr 0(will consider it as a hole)
         */
-       cur = 1024 * 1024;
+       cur = SZ_1M;
        while (cur < size) {
                u64 len = size - cur;
 
@@ -829,129 +838,6 @@ out:
        return ret;
 }
 
-static struct btrfs_root* link_subvol(struct btrfs_root *root,
-               const char *base, u64 root_objectid)
-{
-       struct btrfs_trans_handle *trans;
-       struct btrfs_fs_info *fs_info = root->fs_info;
-       struct btrfs_root *tree_root = fs_info->tree_root;
-       struct btrfs_root *new_root = NULL;
-       struct btrfs_path path;
-       struct btrfs_inode_item *inode_item;
-       struct extent_buffer *leaf;
-       struct btrfs_key key;
-       u64 dirid = btrfs_root_dirid(&root->root_item);
-       u64 index = 2;
-       char buf[BTRFS_NAME_LEN + 1]; /* for snprintf null */
-       int len;
-       int i;
-       int ret;
-
-       len = strlen(base);
-       if (len == 0 || len > BTRFS_NAME_LEN)
-               return NULL;
-
-       btrfs_init_path(&path);
-       key.objectid = dirid;
-       key.type = BTRFS_DIR_INDEX_KEY;
-       key.offset = (u64)-1;
-
-       ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
-       if (ret <= 0) {
-               error("search for DIR_INDEX dirid %llu failed: %d",
-                               (unsigned long long)dirid, ret);
-               goto fail;
-       }
-
-       if (path.slots[0] > 0) {
-               path.slots[0]--;
-               btrfs_item_key_to_cpu(path.nodes[0], &key, path.slots[0]);
-               if (key.objectid == dirid && key.type == BTRFS_DIR_INDEX_KEY)
-                       index = key.offset + 1;
-       }
-       btrfs_release_path(&path);
-
-       trans = btrfs_start_transaction(root, 1);
-       if (!trans) {
-               error("unable to start transaction");
-               goto fail;
-       }
-
-       key.objectid = dirid;
-       key.offset = 0;
-       key.type =  BTRFS_INODE_ITEM_KEY;
-
-       ret = btrfs_lookup_inode(trans, root, &path, &key, 1);
-       if (ret) {
-               error("search for INODE_ITEM %llu failed: %d",
-                               (unsigned long long)dirid, ret);
-               goto fail;
-       }
-       leaf = path.nodes[0];
-       inode_item = btrfs_item_ptr(leaf, path.slots[0],
-                                   struct btrfs_inode_item);
-
-       key.objectid = root_objectid;
-       key.offset = (u64)-1;
-       key.type = BTRFS_ROOT_ITEM_KEY;
-
-       memcpy(buf, base, len);
-       for (i = 0; i < 1024; i++) {
-               ret = btrfs_insert_dir_item(trans, root, buf, len,
-                                           dirid, &key, BTRFS_FT_DIR, index);
-               if (ret != -EEXIST)
-                       break;
-               len = snprintf(buf, ARRAY_SIZE(buf), "%s%d", base, i);
-               if (len < 1 || len > BTRFS_NAME_LEN) {
-                       ret = -EINVAL;
-                       break;
-               }
-       }
-       if (ret)
-               goto fail;
-
-       btrfs_set_inode_size(leaf, inode_item, len * 2 +
-                            btrfs_inode_size(leaf, inode_item));
-       btrfs_mark_buffer_dirty(leaf);
-       btrfs_release_path(&path);
-
-       /* add the backref first */
-       ret = btrfs_add_root_ref(trans, tree_root, root_objectid,
-                                BTRFS_ROOT_BACKREF_KEY,
-                                root->root_key.objectid,
-                                dirid, index, buf, len);
-       if (ret) {
-               error("unable to add root backref for %llu: %d",
-                               root->root_key.objectid, ret);
-               goto fail;
-       }
-
-       /* now add the forward ref */
-       ret = btrfs_add_root_ref(trans, tree_root, root->root_key.objectid,
-                                BTRFS_ROOT_REF_KEY, root_objectid,
-                                dirid, index, buf, len);
-       if (ret) {
-               error("unable to add root ref for %llu: %d",
-                               root->root_key.objectid, ret);
-               goto fail;
-       }
-
-       ret = btrfs_commit_transaction(trans, root);
-       if (ret) {
-               error("transaction commit failed: %d", ret);
-               goto fail;
-       }
-
-       new_root = btrfs_read_fs_root(fs_info, &key);
-       if (IS_ERR(new_root)) {
-               error("unable to fs read root: %lu", PTR_ERR(new_root));
-               new_root = NULL;
-       }
-fail:
-       btrfs_init_path(&path);
-       return new_root;
-}
-
 static int create_subvol(struct btrfs_trans_handle *trans,
                         struct btrfs_root *root, u64 root_objectid)
 {
@@ -1010,8 +896,9 @@ static int make_convert_data_block_groups(struct btrfs_trans_handle *trans,
         * And for single chunk, don't create chunk larger than 1G.
         */
        max_chunk_size = cfg->num_bytes / 10;
-       max_chunk_size = min((u64)(1024 * 1024 * 1024), max_chunk_size);
-       max_chunk_size = round_down(max_chunk_size, extent_root->sectorsize);
+       max_chunk_size = min((u64)(SZ_1G), max_chunk_size);
+       max_chunk_size = round_down(max_chunk_size,
+                                   extent_root->fs_info->sectorsize);
 
        for (cache = first_cache_extent(data_chunks); cache;
             cache = next_cache_extent(cache)) {
@@ -1023,15 +910,13 @@ static int make_convert_data_block_groups(struct btrfs_trans_handle *trans,
 
                        len = min(max_chunk_size,
                                  cache->start + cache->size - cur);
-                       ret = btrfs_alloc_data_chunk(trans, extent_root,
+                       ret = btrfs_alloc_data_chunk(trans, fs_info,
                                        &cur_backup, len,
                                        BTRFS_BLOCK_GROUP_DATA, 1);
                        if (ret < 0)
                                break;
-                       ret = btrfs_make_block_group(trans, extent_root, 0,
-                                       BTRFS_BLOCK_GROUP_DATA,
-                                       BTRFS_FIRST_CHUNK_TREE_OBJECTID,
-                                       cur, len);
+                       ret = btrfs_make_block_group(trans, fs_info, 0,
+                                       BTRFS_BLOCK_GROUP_DATA, cur, len);
                        if (ret < 0)
                                break;
                        cur += len;
@@ -1067,9 +952,9 @@ static int init_btrfs(struct btrfs_mkfs_config *cfg, struct btrfs_root *root,
        fs_info->avoid_sys_chunk_alloc = 1;
        fs_info->avoid_meta_chunk_alloc = 1;
        trans = btrfs_start_transaction(root, 1);
-       if (!trans) {
+       if (IS_ERR(trans)) {
                error("unable to start transaction");
-               ret = -EINVAL;
+               ret = PTR_ERR(trans);
                goto err;
        }
        ret = btrfs_fix_block_accounting(trans, root);
@@ -1141,7 +1026,7 @@ static int migrate_super_block(int fd, u64 old_bytenr)
        BUG_ON(btrfs_super_bytenr(super) != old_bytenr);
        btrfs_set_super_bytenr(super, BTRFS_SUPER_INFO_OFFSET);
 
-       csum_tree_block_size(buf, BTRFS_CRC32_SIZE, 0);
+       csum_tree_block_size(buf, btrfs_csum_sizes[BTRFS_CSUM_TYPE_CRC32], 0);
        ret = pwrite(fd, buf->data, BTRFS_SUPER_INFO_SIZE,
                BTRFS_SUPER_INFO_OFFSET);
        if (ret != BTRFS_SUPER_INFO_SIZE)
@@ -1228,7 +1113,7 @@ static int do_convert(const char *devname, u32 convert_flags, u32 nodesize,
                goto fail;
        fd = open(devname, O_RDWR);
        if (fd < 0) {
-               error("unable to open %s: %s", devname, strerror(errno));
+               error("unable to open %s: %m", devname);
                goto fail;
        }
        btrfs_parse_features_to_string(features_buf, features);
@@ -1285,7 +1170,12 @@ static int do_convert(const char *devname, u32 convert_flags, u32 nodesize,
                goto fail;
        }
 
-       printf("creating btrfs metadata");
+       printf("creating btrfs metadata\n");
+       ret = pthread_mutex_init(&ctx.mutex, NULL);
+       if (ret) {
+               error("failed to initialize mutex: %d", ret);
+               goto fail;
+       }
        ctx.max_copy_inodes = (cctx.inodes_count - cctx.free_inodes_count);
        ctx.cur_copy_inodes = 0;
 
@@ -1304,7 +1194,8 @@ static int do_convert(const char *devname, u32 convert_flags, u32 nodesize,
                task_deinit(ctx.info);
        }
 
-       image_root = link_subvol(root, subvol_name, CONV_IMAGE_SUBVOL_OBJECTID);
+       image_root = btrfs_mksubvol(root, subvol_name,
+                                   CONV_IMAGE_SUBVOL_OBJECTID, true);
        if (!image_root) {
                error("unable to link subvolume %s", subvol_name);
                goto fail;
@@ -1348,7 +1239,7 @@ static int do_convert(const char *devname, u32 convert_flags, u32 nodesize,
        close_ctree(root);
        close(fd);
 
-       printf("conversion complete");
+       printf("conversion complete\n");
        return 0;
 fail:
        clean_convert_context(&cctx);
@@ -1370,7 +1261,7 @@ static int read_reserved_ranges(struct btrfs_root *root, u64 ino,
        int ret = 0;
 
        for (i = 0; i < ARRAY_SIZE(btrfs_reserved_ranges); i++) {
-               struct simple_range *range = &btrfs_reserved_ranges[i];
+               const struct simple_range *range = &btrfs_reserved_ranges[i];
 
                if (range->start + range->len >= total_bytes)
                        break;
@@ -1395,7 +1286,7 @@ static bool is_subset_of_reserved_ranges(u64 start, u64 len)
        bool ret = false;
 
        for (i = 0; i < ARRAY_SIZE(btrfs_reserved_ranges); i++) {
-               struct simple_range *range = &btrfs_reserved_ranges[i];
+               const struct simple_range *range = &btrfs_reserved_ranges[i];
 
                if (start >= range->start && start + len <= range_end(range)) {
                        ret = true;
@@ -1550,6 +1441,8 @@ next:
                }
        }
        btrfs_release_path(&path);
+       if (ret)
+               return ret;
        /*
         * For HOLES mode (without NO_HOLES), we must ensure file extents
         * cover the whole range of the image
@@ -1559,6 +1452,7 @@ next:
                        ret = -EINVAL;
                        error("inode %llu has some file extents not checked",
                                ino);
+                       return ret;
                }
        }
 
@@ -1585,7 +1479,7 @@ next:
  * |   RSV 1   |  | Old  |   |    RSV 2  | | Old  | |   RSV 3   |
  * |   0~1M    |  | Fs   |   | SB2 + 64K | | Fs   | | SB3 + 64K |
  *
- * On the other hande, the converted fs image in btrfs is a completely 
+ * On the other hand, the converted fs image in btrfs is a completely
  * valid old fs.
  *
  * |<-----------------Converted fs image in btrfs-------------------->|
@@ -1620,7 +1514,7 @@ static int do_rollback(const char *devname)
        int i;
 
        for (i = 0; i < ARRAY_SIZE(btrfs_reserved_ranges); i++) {
-               struct simple_range *range = &btrfs_reserved_ranges[i];
+               const struct simple_range *range = &btrfs_reserved_ranges[i];
 
                reserved_ranges[i] = calloc(1, range->len);
                if (!reserved_ranges[i]) {
@@ -1630,12 +1524,18 @@ static int do_rollback(const char *devname)
        }
        fd = open(devname, O_RDWR);
        if (fd < 0) {
-               error("unable to open %s: %s", devname, strerror(errno));
+               error("unable to open %s: %m", devname);
                ret = -EIO;
                goto free_mem;
        }
        fsize = lseek(fd, 0, SEEK_END);
-       root = open_ctree_fd(fd, devname, 0, OPEN_CTREE_WRITES);
+
+       /*
+        * For rollback, we don't really need to write anything so open it
+        * read-only.  The write part will happen after we close the
+        * filesystem.
+        */
+       root = open_ctree_fd(fd, devname, 0, 0);
        if (!root) {
                error("unable to open ctree");
                ret = -EIO;
@@ -1654,11 +1554,11 @@ static int do_rollback(const char *devname)
        ret = btrfs_search_slot(NULL, fs_info->tree_root, &key, &path, 0, 0);
        btrfs_release_path(&path);
        if (ret > 0) {
-               error("unable to find ext2 image subvolume, is it deleted?");
+               error("unable to find source fs image subvolume, is it deleted?");
                ret = -ENOENT;
                goto close_fs;
        } else if (ret < 0) {
-               error("failed to find ext2 image subvolume: %s",
+               error("failed to find source fs image subvolume: %s",
                        strerror(-ret));
                goto close_fs;
        }
@@ -1730,7 +1630,7 @@ close_fs:
 
        for (i = ARRAY_SIZE(btrfs_reserved_ranges) - 1; i >= 0; i--) {
                u64 real_size;
-               struct simple_range *range = &btrfs_reserved_ranges[i];
+               const struct simple_range *range = &btrfs_reserved_ranges[i];
 
                if (range_end(range) >= fsize)
                        continue;
@@ -1776,6 +1676,7 @@ static void print_usage(void)
        printf("\n");
        printf("Supported filesystems:\n");
        printf("\text2/3/4: %s\n", BTRFSCONVERT_EXT2 ? "yes" : "no");
+       printf("\treiserfs: %s\n", BTRFSCONVERT_REISERFS ? "yes" : "no");
 }
 
 int main(int argc, char *argv[])