return -ENOSPC;
}
+static int ext2_alloc_block_range(ext2_filsys fs, u64 goal, int num,
+ u64 *block_ret)
+{
+ blk_t block;
+ ext2fs_block_bitmap bitmap = fs->block_map;
+ blk_t start = ext2fs_get_block_bitmap_start(bitmap);
+ blk_t end = ext2fs_get_block_bitmap_end(bitmap);
+
+ for (block = max_t(u64, goal, start); block + num < end; block++) {
+ if (ext2fs_fast_test_block_bitmap_range(bitmap, block, num)) {
+ ext2fs_fast_mark_block_bitmap_range(bitmap, block,
+ num);
+ *block_ret = block;
+ return 0;
+ }
+ }
+ return -ENOSPC;
+}
+
static int ext2_free_block(ext2_filsys fs, u64 block)
{
BUG_ON(block != (blk_t)block);
return 0;
}
+static int ext2_free_block_range(ext2_filsys fs, u64 block, int num)
+{
+ BUG_ON(block != (blk_t)block);
+ ext2fs_fast_unmark_block_bitmap_range(fs->block_map, block, num);
+ return 0;
+}
+
static int cache_free_extents(struct btrfs_root *root, ext2_filsys ext2_fs)
{
}
static int do_convert(const char *devname, int datacsum, int packing, int noxattr,
- int copylabel, const char *fslabel, int progress)
+ u32 nodesize, int copylabel, const char *fslabel, int progress)
{
- int i, ret;
+ int i, ret, blocks_per_node;
int fd = -1;
u32 blocksize;
u64 blocks[7];
fprintf(stderr, "filetype feature is missing\n");
goto fail;
}
+ if (btrfs_check_node_or_leaf_size(nodesize, blocksize))
+ goto fail;
+ blocks_per_node = nodesize / blocksize;
+ ret = -blocks_per_node;
for (i = 0; i < 7; i++) {
- ret = ext2_alloc_block(ext2_fs, 0, blocks + i);
+ if (nodesize == blocksize)
+ ret = ext2_alloc_block(ext2_fs, 0, blocks + i);
+ else
+ ret = ext2_alloc_block_range(ext2_fs,
+ ret + blocks_per_node, blocks_per_node,
+ blocks + i);
if (ret) {
fprintf(stderr, "not enough free space\n");
goto fail;
goto fail;
}
ret = make_btrfs(fd, devname, ext2_fs->super->s_volume_name,
- NULL, blocks, total_bytes, blocksize, blocksize,
+ NULL, blocks, total_bytes, nodesize, nodesize,
blocksize, blocksize, 0);
if (ret) {
fprintf(stderr, "unable to create initial ctree: %s\n",
/* recover block allocation bitmap */
for (i = 0; i < 7; i++) {
blocks[i] /= blocksize;
- ext2_free_block(ext2_fs, blocks[i]);
+ if (nodesize == blocksize)
+ ext2_free_block(ext2_fs, blocks[i]);
+ else
+ ext2_free_block_range(ext2_fs, blocks[i],
+ blocks_per_node);
}
ret = init_btrfs(root);
if (ret) {
printf("\t-d disable data checksum\n");
printf("\t-i ignore xattrs and ACLs\n");
printf("\t-n disable packing of small files\n");
+ printf("\t-N SIZE set filesystem nodesize\n");
printf("\t-r roll back to ext2fs\n");
printf("\t-l LABEL set filesystem label\n");
printf("\t-L use label from converted fs\n");
int packing = 1;
int noxattr = 0;
int datacsum = 1;
+ u32 nodesize = max_t(u32, sysconf(_SC_PAGESIZE),
+ BTRFS_MKFS_DEFAULT_NODE_SIZE);
int rollback = 0;
int copylabel = 0;
int usage_error = 0;
{ "no-progress", no_argument, NULL, GETOPT_VAL_IEC},
{ NULL, 0, NULL, 0 }
};
- int c = getopt_long(argc, argv, "dinrl:Lp", long_options,
+ int c = getopt_long(argc, argv, "dinN:rl:Lp", long_options,
&long_index);
if (c < 0)
case 'n':
packing = 0;
break;
+ case 'N':
+ nodesize = parse_size(optarg);
+ break;
case 'r':
rollback = 1;
break;
if (rollback) {
ret = do_rollback(file);
} else {
- ret = do_convert(file, datacsum, packing, noxattr, copylabel, fslabel, progress);
+ ret = do_convert(file, datacsum, packing, noxattr, nodesize,
+ copylabel, fslabel, progress);
}
if (ret)
return 1;