X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=mkfs.c;h=f30f05742c2ad8e38c62801d841397761549ca64;hb=ea5052e51f1a284b34a2550b67b465927348fac8;hp=7d635dc2949677a7cc5cbdaa4f79c71f2f0dfe47;hpb=6936aa4c4301478aac273059c73d79d557d7774a;p=platform%2Fupstream%2Fbtrfs-progs.git diff --git a/mkfs.c b/mkfs.c index 7d635dc..f30f057 100644 --- a/mkfs.c +++ b/mkfs.c @@ -17,6 +17,7 @@ */ #include "kerncompat.h" +#include "androidcompat.h" #include #include @@ -25,7 +26,7 @@ #include #include #include -#include +/* #include included via androidcompat.h */ #include #include #include @@ -41,6 +42,7 @@ #include "volumes.h" #include "transaction.h" #include "utils.h" +#include "list_sort.h" static u64 index_cnt = 2; static int verbose = 1; @@ -86,7 +88,7 @@ static int create_metadata_block_groups(struct btrfs_root *root, int mixed, BTRFS_BLOCK_GROUP_DATA); if (ret == -ENOSPC) { fprintf(stderr, - "no space to alloc data/metadata chunk\n"); + "no space to allocate data/metadata chunk\n"); goto err; } BUG_ON(ret); @@ -102,7 +104,7 @@ static int create_metadata_block_groups(struct btrfs_root *root, int mixed, &chunk_start, &chunk_size, BTRFS_BLOCK_GROUP_METADATA); if (ret == -ENOSPC) { - fprintf(stderr, "no space to alloc metadata chunk\n"); + fprintf(stderr, "no space to allocate metadata chunk\n"); goto err; } BUG_ON(ret); @@ -134,7 +136,7 @@ static int create_data_block_groups(struct btrfs_trans_handle *trans, &chunk_start, &chunk_size, BTRFS_BLOCK_GROUP_DATA); if (ret == -ENOSPC) { - fprintf(stderr, "no space to alloc data chunk\n"); + fprintf(stderr, "no space to allocate data chunk\n"); goto err; } BUG_ON(ret); @@ -151,7 +153,7 @@ err: } static int make_root_dir(struct btrfs_trans_handle *trans, struct btrfs_root *root, - int mixed, struct mkfs_allocation *allocation) + struct mkfs_allocation *allocation) { struct btrfs_key location; int ret; @@ -250,7 +252,6 @@ static int create_raid_groups(struct btrfs_trans_handle *trans, u64 metadata_profile, int mixed, struct mkfs_allocation *allocation) { - u64 num_devices = btrfs_super_num_devices(root->fs_info->super_copy); int ret; if (metadata_profile) { @@ -269,7 +270,7 @@ static int create_raid_groups(struct btrfs_trans_handle *trans, BUG_ON(ret); } - if (!mixed && num_devices > 1 && data_profile) { + if (!mixed && data_profile) { ret = create_one_raid_group(trans, root, BTRFS_BLOCK_GROUP_DATA | data_profile, allocation); @@ -327,7 +328,6 @@ static void print_usage(int ret) fprintf(stderr, "\t-U|--uuid UUID specify the filesystem UUID\n"); fprintf(stderr, "\t-q|--quiet no messages except errors\n"); fprintf(stderr, "\t-V|--version print the mkfs.btrfs version and exit\n"); - fprintf(stderr, "%s\n", PACKAGE_STRING); exit(ret); } @@ -340,7 +340,7 @@ static void print_version(void) static u64 parse_profile(char *s) { - if (strcmp(s, "raid0") == 0) { + if (strcasecmp(s, "raid0") == 0) { return BTRFS_BLOCK_GROUP_RAID0; } else if (strcasecmp(s, "raid1") == 0) { return BTRFS_BLOCK_GROUP_RAID1; @@ -591,16 +591,15 @@ static int add_symbolic_link(struct btrfs_trans_handle *trans, u64 objectid, const char *path_name) { int ret; - u64 sectorsize = root->sectorsize; - char *buf = malloc(sectorsize); + char buf[PATH_MAX]; - ret = readlink(path_name, buf, sectorsize); + ret = readlink(path_name, buf, sizeof(buf)); if (ret <= 0) { fprintf(stderr, "readlink failed for %s\n", path_name); goto fail; } - if (ret >= sectorsize) { - fprintf(stderr, "symlink too long for %s", path_name); + if (ret >= sizeof(buf)) { + fprintf(stderr, "symlink too long for %s\n", path_name); ret = -1; goto fail; } @@ -609,7 +608,6 @@ static int add_symbolic_link(struct btrfs_trans_handle *trans, ret = btrfs_insert_inline_extent(trans, root, objectid, 0, buf, ret + 1); fail: - free(buf); return ret; } @@ -647,6 +645,12 @@ static int add_file_items(struct btrfs_trans_handle *trans, if (st->st_size <= BTRFS_MAX_INLINE_DATA_SIZE(root)) { char *buffer = malloc(st->st_size); + + if (!buffer) { + ret = -ENOMEM; + goto end; + } + ret_read = pread64(fd, buffer, st->st_size, bytes_read); if (ret_read == -1) { fprintf(stderr, "%s read failed\n", path_name); @@ -667,12 +671,11 @@ static int add_file_items(struct btrfs_trans_handle *trans, * do our IO in extent buffers so it can work * against any raid type */ - eb = malloc(sizeof(*eb) + sectorsize); + eb = calloc(1, sizeof(*eb) + sectorsize); if (!eb) { ret = -ENOMEM; goto end; } - memset(eb, 0, sizeof(*eb) + sectorsize); again: @@ -780,6 +783,8 @@ static int traverse_directory(struct btrfs_trans_handle *trans, /* Add list for source directory */ dir_entry = malloc(sizeof(struct directory_name_entry)); + if (!dir_entry) + return -ENOMEM; dir_entry->dir_name = dir_name; dir_entry->path = realpath(dir_name, real_path); if (!dir_entry->path) { @@ -881,6 +886,10 @@ static int traverse_directory(struct btrfs_trans_handle *trans, if (S_ISDIR(st.st_mode)) { 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); @@ -926,7 +935,7 @@ fail_no_dir: static int open_target(char *output_name) { int output_fd; - output_fd = open(output_name, O_CREAT | O_RDWR | O_TRUNC, + output_fd = open(output_name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); return output_fd; @@ -962,7 +971,7 @@ static int create_chunks(struct btrfs_trans_handle *trans, size_of_data = minimum_data_chunk_size; ret = btrfs_alloc_data_chunk(trans, root->fs_info->extent_root, - &chunk_start, size_of_data, data_type); + &chunk_start, size_of_data, data_type, 0); BUG_ON(ret); ret = btrfs_make_block_group(trans, root->fs_info->extent_root, 0, data_type, BTRFS_FIRST_CHUNK_TREE_OBJECTID, @@ -1020,16 +1029,15 @@ out: * This ignores symlinks with unreadable targets and subdirs that can't * be read. It's a best-effort to give a rough estimate of the size of * a subdir. It doesn't guarantee that prepopulating btrfs from this - * tree won't still run out of space. - * - * The rounding up to 4096 is questionable. Previous code used du -B 4096. + * tree won't still run out of space. */ static u64 global_total_size; +static u64 fs_block_size; static int ftw_add_entry_size(const char *fpath, const struct stat *st, int type) { if (type == FTW_F || type == FTW_D) - global_total_size += round_up(st->st_size, 4096); + global_total_size += round_up(st->st_size, fs_block_size); return 0; } @@ -1049,6 +1057,7 @@ static u64 size_sourcedir(char *dir_name, u64 sectorsize, allocated_meta_size / default_chunk_size; global_total_size = 0; + fs_block_size = sectorsize; ret = ftw(dir_name, ftw_add_entry_size, 10); dir_size = global_total_size; if (ret < 0) { @@ -1077,32 +1086,29 @@ static u64 size_sourcedir(char *dir_name, u64 sectorsize, return total_size; } -static int zero_output_file(int out_fd, u64 size, u32 sectorsize) +static int zero_output_file(int out_fd, u64 size) { - int len = sectorsize; - int loop_num = size / sectorsize; + int loop_num; u64 location = 0; - char *buf = malloc(len); + char buf[4096]; int ret = 0, i; ssize_t written; - if (!buf) - return -ENOMEM; - memset(buf, 0, len); + memset(buf, 0, 4096); + loop_num = size / 4096; for (i = 0; i < loop_num; i++) { - written = pwrite64(out_fd, buf, len, location); - if (written != len) + written = pwrite64(out_fd, buf, 4096, location); + if (written != 4096) ret = -EIO; - location += sectorsize; + location += 4096; } - free(buf); return ret; } static int is_ssd(const char *file) { blkid_probe probe; - char wholedisk[32]; + char wholedisk[PATH_MAX]; char sysfs_path[PATH_MAX]; dev_t devno; int fd; @@ -1147,6 +1153,13 @@ static int is_ssd(const char *file) return !atoi((const char *)&rotational); } +static int _cmp_device_by_id(void *priv, struct list_head *a, + struct list_head *b) +{ + return list_entry(a, struct btrfs_device, dev_list)->devid - + list_entry(b, struct btrfs_device, dev_list)->devid; +} + static void list_all_devices(struct btrfs_root *root) { struct btrfs_fs_devices *fs_devices; @@ -1159,15 +1172,14 @@ static void list_all_devices(struct btrfs_root *root) list_for_each_entry(device, &fs_devices->devices, dev_list) number_of_devices++; + list_sort(NULL, &fs_devices->devices, _cmp_device_by_id); + printf("Number of devices: %d\n", number_of_devices); /* printf("Total devices size: %10s\n", */ /* pretty_size(total_block_count)); */ printf("Devices:\n"); printf(" ID SIZE PATH\n"); - list_for_each_entry_reverse(device, &fs_devices->devices, dev_list) { - char dev_uuid[BTRFS_UUID_UNPARSED_SIZE]; - - uuid_unparse(device->uuid, dev_uuid); + list_for_each_entry(device, &fs_devices->devices, dev_list) { printf(" %3llu %10s %s\n", device->devid, pretty_size(device->total_bytes), @@ -1193,7 +1205,7 @@ static int is_temp_block_group(struct extent_buffer *node, * 1) Empty chunk * Temp chunk is always empty. * - * 2) profile dismatch with mkfs profile. + * 2) profile mismatch with mkfs profile. * Temp chunk is always in SINGLE * * 3) Size differs with mkfs_alloc @@ -1306,10 +1318,27 @@ static int cleanup_temp_chunks(struct btrfs_fs_info *fs_info, if (is_temp_block_group(path->nodes[0], bgi, data_profile, meta_profile, sys_profile)) { + u64 flags = btrfs_disk_block_group_flags(path->nodes[0], + bgi); + ret = btrfs_free_block_group(trans, fs_info, found_key.objectid, found_key.offset); if (ret < 0) goto out; + + if ((flags & BTRFS_BLOCK_GROUP_TYPE_MASK) == + BTRFS_BLOCK_GROUP_DATA) + alloc->data -= found_key.offset; + else if ((flags & BTRFS_BLOCK_GROUP_TYPE_MASK) == + BTRFS_BLOCK_GROUP_METADATA) + alloc->metadata -= found_key.offset; + else if ((flags & BTRFS_BLOCK_GROUP_TYPE_MASK) == + BTRFS_BLOCK_GROUP_SYSTEM) + alloc->system -= found_key.offset; + else if ((flags & BTRFS_BLOCK_GROUP_TYPE_MASK) == + (BTRFS_BLOCK_GROUP_METADATA | + BTRFS_BLOCK_GROUP_DATA)) + alloc->mixed -= found_key.offset; } btrfs_release_path(path); key.objectid = found_key.objectid + found_key.offset; @@ -1321,7 +1350,7 @@ out: return ret; } -int main(int ac, char **av) +int main(int argc, char **argv) { char *file; struct btrfs_root *root; @@ -1383,7 +1412,7 @@ int main(int ac, char **av) { NULL, 0, NULL, 0} }; - c = getopt_long(ac, av, "A:b:fl:n:s:m:d:L:O:r:U:VMKq", + c = getopt_long(argc, argv, "A:b:fl:n:s:m:d:L:O:r:U:VMKq", long_options, NULL); if (c < 0) break; @@ -1439,8 +1468,6 @@ int main(int ac, char **av) break; case 'b': block_count = parse_size(optarg); - if (block_count <= BTRFS_MKFS_SMALL_VOLUME_SIZE) - mixed = 1; zero_end = 0; break; case 'V': @@ -1465,11 +1492,16 @@ int main(int ac, char **av) print_usage(c != GETOPT_VAL_HELP); } } + + if (verbose) { + printf("%s\n", PACKAGE_STRING); + printf("See %s for more information.\n\n", PACKAGE_URL); + } + sectorsize = max(sectorsize, (u32)sysconf(_SC_PAGESIZE)); - if (btrfs_check_nodesize(nodesize, sectorsize)) - exit(1); + stripesize = sectorsize; saved_optind = optind; - dev_cnt = ac - optind; + dev_cnt = argc - optind; if (dev_cnt == 0) print_usage(1); @@ -1491,26 +1523,20 @@ int main(int ac, char **av) exit(1); } } - + while (dev_cnt-- > 0) { - file = av[optind++]; - if (is_block_device(file)) + file = argv[optind++]; + if (is_block_device(file) == 1) if (test_dev_for_mkfs(file, force_overwrite)) exit(1); } optind = saved_optind; - dev_cnt = ac - optind; + dev_cnt = argc - optind; - file = av[optind++]; + file = argv[optind++]; ssd = is_ssd(file); - if (is_vol_small(file) || mixed) { - if (verbose) - printf("SMALL VOLUME: forcing mixed metadata/data groups\n"); - mixed = 1; - } - /* * Set default profiles according to number of added devices. * For mixed groups defaults are single/single. @@ -1541,18 +1567,26 @@ int main(int ac, char **av) } } - if (!nodesize_forced) { + if (!nodesize_forced) nodesize = best_nodesize; - if (btrfs_check_nodesize(nodesize, sectorsize)) - exit(1); - } - if (nodesize != sectorsize) { - fprintf(stderr, "Error: mixed metadata/data block groups " - "require metadata blocksizes equal to the sectorsize\n"); - exit(1); - } } + /* + * FS features that can be set by other means than -O + * just set the bit here + */ + if (mixed) + features |= BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS; + + if ((data_profile | metadata_profile) & + (BTRFS_BLOCK_GROUP_RAID5 | BTRFS_BLOCK_GROUP_RAID6)) { + features |= BTRFS_FEATURE_INCOMPAT_RAID56; + } + + if (btrfs_check_nodesize(nodesize, sectorsize, + features)) + exit(1); + /* Check device/block_count after the nodesize is determined */ if (block_count && block_count < btrfs_min_dev_size(nodesize)) { fprintf(stderr, @@ -1566,7 +1600,7 @@ int main(int ac, char **av) for (i = saved_optind; i < saved_optind + dev_cnt; i++) { char *path; - path = av[i]; + path = argv[i]; ret = test_minimum_size(path, nodesize); if (ret < 0) { fprintf(stderr, "Failed to check size for '%s': %s\n", @@ -1584,16 +1618,10 @@ int main(int ac, char **av) } } ret = test_num_disk_vs_raid(metadata_profile, data_profile, - dev_cnt, mixed); + dev_cnt, mixed, ssd); if (ret) exit(1); - /* if we are here that means all devs are good to btrfsify */ - if (verbose) { - printf("%s\n", PACKAGE_STRING); - printf("See %s for more information.\n\n", PACKAGE_URL); - } - dev_cnt--; if (!source_dir_set) { @@ -1608,8 +1636,11 @@ int main(int ac, char **av) strerror(errno)); exit(1); } - ret = btrfs_prepare_device(fd, file, zero_end, &dev_block_count, - block_count, &mixed, discard); + ret = btrfs_prepare_device(fd, file, &dev_block_count, + block_count, + (zero_end ? PREP_DEVICE_ZERO_END : 0) | + (discard ? PREP_DEVICE_DISCARD : 0) | + (verbose ? PREP_DEVICE_VERBOSE : 0)); if (ret) { close(fd); exit(1); @@ -1629,7 +1660,7 @@ int main(int ac, char **av) &num_of_meta_chunks, &size_of_data); if(block_count < source_dir_size) block_count = source_dir_size; - ret = zero_output_file(fd, block_count, sectorsize); + ret = zero_output_file(fd, block_count); if (ret) { fprintf(stderr, "unable to zero the output file\n"); exit(1); @@ -1653,19 +1684,7 @@ int main(int ac, char **av) if (group_profile_max_safe_loss(metadata_profile) < group_profile_max_safe_loss(data_profile)){ fprintf(stderr, - "WARNING: metatdata has lower redundancy than data!\n\n"); - } - - /* - * FS features that can be set by other means than -O - * just set the bit here - */ - if (mixed) - features |= BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS; - - if ((data_profile | metadata_profile) & - (BTRFS_BLOCK_GROUP_RAID5 | BTRFS_BLOCK_GROUP_RAID6)) { - features |= BTRFS_FEATURE_INCOMPAT_RAID56; + "WARNING: metadata has lower redundancy than data!\n\n"); } mkfs_cfg.label = label; @@ -1677,7 +1696,7 @@ int main(int ac, char **av) mkfs_cfg.stripesize = stripesize; mkfs_cfg.features = features; - ret = make_btrfs(fd, &mkfs_cfg); + ret = make_btrfs(fd, &mkfs_cfg, NULL); if (ret) { fprintf(stderr, "error during mkfs: %s\n", strerror(-ret)); exit(1); @@ -1709,7 +1728,7 @@ int main(int ac, char **av) exit(1); } - ret = make_root_dir(trans, root, mixed, &allocation); + ret = make_root_dir(trans, root, &allocation); if (ret) { fprintf(stderr, "failed to setup the root directory\n"); exit(1); @@ -1723,16 +1742,14 @@ int main(int ac, char **av) exit(1); } - if (is_block_device(file)) + if (is_block_device(file) == 1) btrfs_register_one_device(file); if (dev_cnt == 0) goto raid_groups; while (dev_cnt-- > 0) { - int old_mixed = mixed; - - file = av[optind++]; + file = argv[optind++]; /* * open without O_EXCL so that the problem should not @@ -1753,13 +1770,15 @@ int main(int ac, char **av) close(fd); continue; } - ret = btrfs_prepare_device(fd, file, zero_end, &dev_block_count, - block_count, &mixed, discard); + ret = btrfs_prepare_device(fd, file, &dev_block_count, + block_count, + (verbose ? PREP_DEVICE_VERBOSE : 0) | + (zero_end ? PREP_DEVICE_ZERO_END : 0) | + (discard ? PREP_DEVICE_DISCARD : 0)); if (ret) { close(fd); exit(1); } - mixed = old_mixed; ret = btrfs_add_to_fsid(trans, root, fd, file, dev_block_count, sectorsize, sectorsize, sectorsize); @@ -1773,7 +1792,7 @@ int main(int ac, char **av) (unsigned long long)device->devid); } - if (is_block_device(file)) + if (is_block_device(file) == 1) btrfs_register_one_device(file); } @@ -1843,6 +1862,7 @@ raid_groups: out: ret = close_ctree(root); BUG_ON(ret); + btrfs_close_all_devices(); free(label); return 0; }