#include "mkfs/common.h"
#include "fsfeatures.h"
+int path_cat_out(char *out, const char *p1, const char *p2);
+
static u64 index_cnt = 2;
static int verbose = 1;
return ret;
}
-static int create_data_reloc_tree(struct btrfs_trans_handle *trans,
- struct btrfs_root *root)
+static int create_tree(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root, u64 objectid)
{
struct btrfs_key location;
struct btrfs_root_item root_item;
struct extent_buffer *tmp;
- u64 objectid = BTRFS_DATA_RELOC_TREE_OBJECTID;
int ret;
ret = btrfs_copy_root(trans, root, root->node, &tmp, objectid);
return ret;
}
-static char *make_path(const char *dir, const char *name)
-{
- char *path;
-
- path = malloc(strlen(dir) + strlen(name) + 2);
- if (!path)
- return NULL;
- strcpy(path, dir);
- if (dir[strlen(dir) - 1] != '/')
- strcat(path, "/");
- strcat(path, name);
- return path;
-}
-
static int traverse_directory(struct btrfs_trans_handle *trans,
struct btrfs_root *root, const char *dir_name,
struct directory_name_entry *dir_head)
}
if (S_ISDIR(st.st_mode)) {
+ char tmp[PATH_MAX];
+
dir_entry = malloc(sizeof(struct directory_name_entry));
if (!dir_entry) {
ret = -ENOMEM;
goto fail;
}
dir_entry->dir_name = cur_file->d_name;
- dir_entry->path = make_path(parent_dir_entry->path,
- cur_file->d_name);
+ if (path_cat_out(tmp, parent_dir_entry->path,
+ cur_file->d_name)) {
+ error("invalid path: %s/%s",
+ parent_dir_entry->path,
+ cur_file->d_name);
+ ret = -EINVAL;
+ goto fail;
+ }
+ dir_entry->path = strdup(tmp);
+ if (!dir_entry->path) {
+ error("not enough memory to store path");
+ ret = -ENOMEM;
+ goto fail;
+ }
dir_entry->inum = cur_inum;
list_add_tail(&dir_entry->list, &dir_head->list);
} else if (S_ISREG(st.st_mode)) {
printf("Making image is completed.\n");
return 0;
fail:
+ /*
+ * Since we don't have btrfs_abort_transaction() yet, uncommitted trans
+ * will trigger a BUG_ON().
+ *
+ * However before mkfs is fully finished, the magic number is invalid,
+ * so even we commit transaction here, the fs still can't be mounted.
+ *
+ * To do a graceful error out, here we commit transaction as a
+ * workaround.
+ * Since we have already hit some problem, the return value doesn't
+ * matter now.
+ */
+ btrfs_commit_transaction(trans, root);
while (!list_empty(&dir_head.list)) {
dir_entry = list_entry(dir_head.list.next,
struct directory_name_entry, list);
ret = btrfs_search_slot(trans, root, &key, &path, 0, 0);
if (ret < 0)
goto out;
+ /* Don't pollute ret for >0 case */
+ if (ret > 0)
+ ret = 0;
btrfs_item_key_to_cpu(path.nodes[0], &found_key,
path.slots[0]);
int zero_end = 1;
int fd = -1;
int ret;
+ int close_ret;
int i;
int mixed = 0;
int nodesize_forced = 0;
u64 num_of_meta_chunks = 0;
u64 size_of_data = 0;
u64 source_dir_size = 0;
+ u64 min_dev_size;
int dev_cnt = 0;
int saved_optind;
char fs_uuid[BTRFS_UUID_UNPARSED_SIZE] = { 0 };
while (dev_cnt-- > 0) {
file = argv[optind++];
if (is_block_device(file) == 1)
- if (test_dev_for_mkfs(file, force_overwrite))
- goto error;
+ ret = test_dev_for_mkfs(file, force_overwrite);
+ else
+ ret = test_status_for_mkfs(file, force_overwrite);
+
+ if (ret)
+ goto error;
}
optind = saved_optind;
goto error;
}
+ min_dev_size = btrfs_min_dev_size(nodesize, mixed, metadata_profile,
+ data_profile);
/* Check device/block_count after the nodesize is determined */
- if (block_count && block_count < btrfs_min_dev_size(nodesize)) {
+ if (block_count && block_count < min_dev_size) {
error("size %llu is too small to make a usable filesystem",
block_count);
error("minimum size for btrfs filesystem is %llu",
- btrfs_min_dev_size(nodesize));
+ min_dev_size);
goto error;
}
for (i = saved_optind; i < saved_optind + dev_cnt; i++) {
char *path;
path = argv[i];
- ret = test_minimum_size(path, nodesize);
+ ret = test_minimum_size(path, min_dev_size);
if (ret < 0) {
error("failed to check size for %s: %s",
path, strerror(-ret));
error("'%s' is too small to make a usable filesystem",
path);
error("minimum size for each btrfs device is %llu",
- btrfs_min_dev_size(nodesize));
+ min_dev_size);
goto error;
}
}
}
}
- ret = create_data_reloc_tree(trans, root);
+ ret = create_tree(trans, root, BTRFS_DATA_RELOC_TREE_OBJECTID);
if (ret) {
error("unable to create data reloc tree: %d", ret);
goto out;
*/
fs_info->finalize_on_close = 1;
out:
- ret = close_ctree(root);
+ close_ret = close_ctree(root);
- if (!ret) {
+ if (!close_ret) {
optind = saved_optind;
dev_cnt = argc - optind;
while (dev_cnt-- > 0) {