btrfs-progs: check: fix missing newlines
[platform/upstream/btrfs-progs.git] / btrfs-convert.c
index 727bfea..4b4cea4 100644 (file)
@@ -103,6 +103,7 @@ struct btrfs_convert_operations {
                         struct btrfs_root *root, int datacsum,
                         int packing, int noxattr, struct task_ctx *p);
        void (*close_fs)(struct btrfs_convert_context *cctx);
+       int (*check_state)(struct btrfs_convert_context *cctx);
 };
 
 static void init_convert_context(struct btrfs_convert_context *cctx)
@@ -132,6 +133,11 @@ static inline void convert_close_fs(struct btrfs_convert_context *cctx)
        cctx->convert_ops->close_fs(cctx);
 }
 
+static inline int convert_check_state(struct btrfs_convert_context *cctx)
+{
+       return cctx->convert_ops->check_state(cctx);
+}
+
 static int intersect_with_sb(u64 bytenr, u64 num_bytes)
 {
        int i;
@@ -277,7 +283,7 @@ static int record_file_blocks(struct blk_iterate_data *data,
        int ret = 0;
        struct btrfs_root *root = data->root;
        struct btrfs_root *convert_root = data->convert_root;
-       struct btrfs_path *path;
+       struct btrfs_path path;
        u64 file_pos = file_block * root->sectorsize;
        u64 old_disk_bytenr = disk_block * root->sectorsize;
        u64 num_bytes = num_blocks * root->sectorsize;
@@ -289,9 +295,7 @@ static int record_file_blocks(struct blk_iterate_data *data,
                                data->objectid, data->inode, file_pos, 0,
                                num_bytes);
 
-       path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
+       btrfs_init_path(&path);
 
        /*
         * Search real disk bytenr from convert root
@@ -310,11 +314,11 @@ static int record_file_blocks(struct blk_iterate_data *data,
                key.type = BTRFS_EXTENT_DATA_KEY;
                key.offset = cur_off;
 
-               ret = btrfs_search_slot(NULL, convert_root, &key, path, 0, 0);
+               ret = btrfs_search_slot(NULL, convert_root, &key, &path, 0, 0);
                if (ret < 0)
                        break;
                if (ret > 0) {
-                       ret = btrfs_previous_item(convert_root, path,
+                       ret = btrfs_previous_item(convert_root, &path,
                                                  data->convert_ino,
                                                  BTRFS_EXTENT_DATA_KEY);
                        if (ret < 0)
@@ -324,8 +328,8 @@ static int record_file_blocks(struct blk_iterate_data *data,
                                break;
                        }
                }
-               node = path->nodes[0];
-               slot = path->slots[0];
+               node = path.nodes[0];
+               slot = path.slots[0];
                btrfs_item_key_to_cpu(node, &key, slot);
                BUG_ON(key.type != BTRFS_EXTENT_DATA_KEY ||
                       key.objectid != data->convert_ino ||
@@ -334,7 +338,7 @@ static int record_file_blocks(struct blk_iterate_data *data,
                extent_disk_bytenr = btrfs_file_extent_disk_bytenr(node, fi);
                extent_num_bytes = btrfs_file_extent_disk_num_bytes(node, fi);
                BUG_ON(cur_off - key.offset >= extent_num_bytes);
-               btrfs_release_path(path);
+               btrfs_release_path(&path);
 
                if (extent_disk_bytenr)
                        real_disk_bytenr = cur_off - key.offset +
@@ -357,7 +361,7 @@ static int record_file_blocks(struct blk_iterate_data *data,
                 * need to waste CPU cycles now.
                 */
        }
-       btrfs_free_path(path);
+       btrfs_release_path(&path);
        return ret;
 }
 
@@ -964,7 +968,7 @@ static int create_image(struct btrfs_root *root,
 {
        struct btrfs_inode_item buf;
        struct btrfs_trans_handle *trans;
-       struct btrfs_path *path = NULL;
+       struct btrfs_path path;
        struct btrfs_key key;
        struct cache_extent *cache;
        struct cache_tree used_tmp;
@@ -981,6 +985,7 @@ static int create_image(struct btrfs_root *root,
                return -ENOMEM;
 
        cache_tree_init(&used_tmp);
+       btrfs_init_path(&path);
 
        ret = btrfs_find_free_objectid(trans, root, BTRFS_FIRST_FREE_OBJECTID,
                                       &ino);
@@ -997,24 +1002,19 @@ static int create_image(struct btrfs_root *root,
        if (ret < 0)
                goto out;
 
-       path = btrfs_alloc_path();
-       if (!path) {
-               ret = -ENOMEM;
-               goto out;
-       }
        key.objectid = ino;
        key.type = BTRFS_INODE_ITEM_KEY;
        key.offset = 0;
 
-       ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
+       ret = btrfs_search_slot(trans, root, &key, &path, 0, 1);
        if (ret) {
                ret = (ret > 0 ? -ENOENT : ret);
                goto out;
        }
-       read_extent_buffer(path->nodes[0], &buf,
-                       btrfs_item_ptr_offset(path->nodes[0], path->slots[0]),
+       read_extent_buffer(path.nodes[0], &buf,
+                       btrfs_item_ptr_offset(path.nodes[0], path.slots[0]),
                        sizeof(buf));
-       btrfs_release_path(path);
+       btrfs_release_path(&path);
 
        /*
         * Create a new used space cache, which doesn't contain the reserved
@@ -1052,18 +1052,18 @@ static int create_image(struct btrfs_root *root,
        key.objectid = ino;
        key.type = BTRFS_INODE_ITEM_KEY;
        key.offset = 0;
-       ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
+       ret = btrfs_search_slot(trans, root, &key, &path, 0, 1);
        if (ret) {
                ret = (ret > 0 ? -ENOENT : ret);
                goto out;
        }
        btrfs_set_stack_inode_size(&buf, cfg->num_bytes);
-       write_extent_buffer(path->nodes[0], &buf,
-                       btrfs_item_ptr_offset(path->nodes[0], path->slots[0]),
+       write_extent_buffer(path.nodes[0], &buf,
+                       btrfs_item_ptr_offset(path.nodes[0], path.slots[0]),
                        sizeof(buf));
 out:
        free_extent_cache_tree(&used_tmp);
-       btrfs_free_path(path);
+       btrfs_release_path(&path);
        btrfs_commit_transaction(trans, root);
        return ret;
 }
@@ -1075,7 +1075,7 @@ static struct btrfs_root* link_subvol(struct btrfs_root *root,
        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_path path;
        struct btrfs_inode_item *inode_item;
        struct extent_buffer *leaf;
        struct btrfs_key key;
@@ -1090,28 +1090,25 @@ static struct btrfs_root* link_subvol(struct btrfs_root *root,
        if (len == 0 || len > BTRFS_NAME_LEN)
                return NULL;
 
-       path = btrfs_alloc_path();
-       if (!path)
-               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);
+       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 (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);
+       btrfs_release_path(&path);
 
        trans = btrfs_start_transaction(root, 1);
        if (!trans) {
@@ -1123,14 +1120,14 @@ static struct btrfs_root* link_subvol(struct btrfs_root *root,
        key.offset = 0;
        key.type =  BTRFS_INODE_ITEM_KEY;
 
-       ret = btrfs_lookup_inode(trans, root, path, &key, 1);
+       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],
+       leaf = path.nodes[0];
+       inode_item = btrfs_item_ptr(leaf, path.slots[0],
                                    struct btrfs_inode_item);
 
        key.objectid = root_objectid;
@@ -1155,7 +1152,7 @@ static struct btrfs_root* link_subvol(struct btrfs_root *root,
        btrfs_set_inode_size(leaf, inode_item, len * 2 +
                             btrfs_inode_size(leaf, inode_item));
        btrfs_mark_buffer_dirty(leaf);
-       btrfs_release_path(path);
+       btrfs_release_path(&path);
 
        /* add the backref first */
        ret = btrfs_add_root_ref(trans, tree_root, root_objectid,
@@ -1190,7 +1187,7 @@ static struct btrfs_root* link_subvol(struct btrfs_root *root,
                new_root = NULL;
        }
 fail:
-       btrfs_free_path(path);
+       btrfs_init_path(&path);
        return new_root;
 }
 
@@ -1499,7 +1496,7 @@ static int ext2_open_fs(struct btrfs_convert_context *cctx, const char *name)
 
        if (!(ext2_fs->super->s_feature_incompat &
              EXT2_FEATURE_INCOMPAT_FILETYPE)) {
-               fprintf(stderr, "filetype feature is missing\n");
+               error("filetype feature is missing");
                goto fail;
        }
 
@@ -2183,6 +2180,42 @@ static void ext2_copy_inode_item(struct btrfs_inode_item *dst,
        }
        memset(&dst->reserved, 0, sizeof(dst->reserved));
 }
+static int ext2_check_state(struct btrfs_convert_context *cctx)
+{
+       ext2_filsys fs = cctx->fs_data;
+
+        if (!(fs->super->s_state & EXT2_VALID_FS))
+               return 1;
+       else if (fs->super->s_state & EXT2_ERROR_FS)
+               return 1;
+       else
+               return 0;
+}
+
+/* EXT2_*_FL to BTRFS_INODE_FLAG_* stringification helper */
+#define COPY_ONE_EXT2_FLAG(flags, ext2_inode, name) ({                 \
+       if (ext2_inode->i_flags & EXT2_##name##_FL)                     \
+               flags |= BTRFS_INODE_##name;                            \
+})
+
+/*
+ * Convert EXT2_*_FL to corresponding BTRFS_INODE_* flags
+ *
+ * Only a subset of EXT_*_FL is supported in btrfs.
+ */
+static void ext2_convert_inode_flags(struct btrfs_inode_item *dst,
+                                    struct ext2_inode *src)
+{
+       u64 flags = 0;
+
+       COPY_ONE_EXT2_FLAG(flags, src, APPEND);
+       COPY_ONE_EXT2_FLAG(flags, src, SYNC);
+       COPY_ONE_EXT2_FLAG(flags, src, IMMUTABLE);
+       COPY_ONE_EXT2_FLAG(flags, src, NODUMP);
+       COPY_ONE_EXT2_FLAG(flags, src, NOATIME);
+       COPY_ONE_EXT2_FLAG(flags, src, DIRSYNC);
+       btrfs_set_stack_inode_flags(dst, flags);
+}
 
 /*
  * copy a single inode. do all the required works, such as cloning
@@ -2206,6 +2239,7 @@ static int ext2_copy_single_inode(struct btrfs_trans_handle *trans,
                            BTRFS_INODE_NODATASUM;
                btrfs_set_stack_inode_flags(&btrfs_inode, flags);
        }
+       ext2_convert_inode_flags(&btrfs_inode, ext2_inode);
 
        switch (ext2_inode->i_mode & S_IFMT) {
        case S_IFREG:
@@ -2301,6 +2335,7 @@ static const struct btrfs_convert_operations ext2_convert_ops = {
        .read_used_space        = ext2_read_used_space,
        .copy_inodes            = ext2_copy_inodes,
        .close_fs               = ext2_close_fs,
+       .check_state            = ext2_check_state,
 };
 
 #endif
@@ -2327,7 +2362,7 @@ static int convert_open_fs(const char *devname,
                }
        }
 
-       fprintf(stderr, "No file system found to convert.\n");
+       error("no file system found to convert");
        return -1;
 }
 
@@ -2352,6 +2387,10 @@ static int do_convert(const char *devname, int datacsum, int packing,
        ret = convert_open_fs(devname, &cctx);
        if (ret)
                goto fail;
+       ret = convert_check_state(&cctx);
+       if (ret)
+               warning(
+               "source filesystem is not clean, running filesystem check is recommended");
        ret = convert_read_used_space(&cctx);
        if (ret)
                goto fail;
@@ -2995,7 +3034,7 @@ static void print_usage(void)
        printf("\t-O|--features LIST     comma separated list of filesystem features\n");
        printf("\t--no-progress          show only overview, not the detailed progress\n");
        printf("\n");
-       printf("Suported filesystems:\n");
+       printf("Supported filesystems:\n");
        printf("\text2/3/4: %s\n", BTRFSCONVERT_EXT2 ? "yes" : "no");
 }
 
@@ -3055,8 +3094,8 @@ int main(int argc, char *argv[])
                        case 'l':
                                copylabel = -1;
                                if (strlen(optarg) >= BTRFS_LABEL_SIZE) {
-                                       fprintf(stderr,
-                               "WARNING: label too long, trimmed to %d bytes\n",
+                                       warning(
+                                       "label too long, trimmed to %d bytes",
                                                BTRFS_LABEL_SIZE - 1);
                                }
                                __strncpy_null(fslabel, optarg, BTRFS_LABEL_SIZE - 1);
@@ -3073,8 +3112,7 @@ int main(int argc, char *argv[])
 
                                tmp = btrfs_parse_fs_features(tmp, &features);
                                if (tmp) {
-                                       fprintf(stderr,
-                                               "Unrecognized filesystem feature '%s'\n",
+                                       error("unrecognized filesystem feature: %s",
                                                        tmp);
                                        free(orig);
                                        exit(1);
@@ -3090,8 +3128,7 @@ int main(int argc, char *argv[])
 
                                        btrfs_parse_features_to_string(buf,
                                                features & ~BTRFS_CONVERT_ALLOWED_FEATURES);
-                                       fprintf(stderr,
-                                               "ERROR: features not allowed for convert: %s\n",
+                                       error("features not allowed for convert: %s",
                                                buf);
                                        exit(1);
                                }
@@ -3127,11 +3164,10 @@ int main(int argc, char *argv[])
        file = argv[optind];
        ret = check_mounted(file);
        if (ret < 0) {
-               fprintf(stderr, "Could not check mount status: %s\n",
-                       strerror(-ret));
+               error("could not check mount status: %s", strerror(-ret));
                return 1;
        } else if (ret) {
-               fprintf(stderr, "%s is mounted\n", file);
+               error("%s is mounted", file);
                return 1;
        }