Btrfs: Better block record keeping, real mkfs
Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
293ffd5fd3
commit
1261ec42b3
|
@ -2,7 +2,7 @@ CC=gcc
|
||||||
CFLAGS = -g -Wall -Werror
|
CFLAGS = -g -Wall -Werror
|
||||||
headers = radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h list.h \
|
headers = radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h list.h \
|
||||||
transaction.h
|
transaction.h
|
||||||
objects = ctree.o disk-io.o radix-tree.o mkfs.o extent-tree.o print-tree.o \
|
objects = ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \
|
||||||
root-tree.o dir-item.o hash.o file-item.o inode-item.o \
|
root-tree.o dir-item.o hash.o file-item.o inode-item.o \
|
||||||
inode-map.o \
|
inode-map.o \
|
||||||
|
|
||||||
|
@ -16,7 +16,10 @@ check=sparse $(CHECKFLAGS)
|
||||||
$(check) $<
|
$(check) $<
|
||||||
$(CC) $(CFLAGS) -c $<
|
$(CC) $(CFLAGS) -c $<
|
||||||
|
|
||||||
all: tester debug-tree quick-test dir-test tags
|
all: tester debug-tree quick-test dir-test tags mkfs.btrfs
|
||||||
|
|
||||||
|
mkfs.btrfs: $(objects) mkfs.o
|
||||||
|
gcc $(CFLAGS) -o mkfs.btrfs $(objects) mkfs.o
|
||||||
|
|
||||||
debug-tree: $(objects) debug-tree.o
|
debug-tree: $(objects) debug-tree.o
|
||||||
gcc $(CFLAGS) -o debug-tree $(objects) debug-tree.o
|
gcc $(CFLAGS) -o debug-tree $(objects) debug-tree.o
|
||||||
|
|
|
@ -223,6 +223,7 @@ struct btrfs_fs_info {
|
||||||
int cache_size;
|
int cache_size;
|
||||||
int fp;
|
int fp;
|
||||||
struct btrfs_trans_handle *running_transaction;
|
struct btrfs_trans_handle *running_transaction;
|
||||||
|
struct btrfs_super_block *disk_super;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -10,8 +10,17 @@
|
||||||
int main(int ac, char **av) {
|
int main(int ac, char **av) {
|
||||||
struct btrfs_super_block super;
|
struct btrfs_super_block super;
|
||||||
struct btrfs_root *root;
|
struct btrfs_root *root;
|
||||||
|
|
||||||
|
if (ac != 2) {
|
||||||
|
fprintf(stderr, "usage: %s device\n", av[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
radix_tree_init();
|
radix_tree_init();
|
||||||
root = open_ctree("dbfile", &super);
|
root = open_ctree(av[1], &super);
|
||||||
|
if (!root) {
|
||||||
|
fprintf(stderr, "unable to open %s\n", av[1]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
printf("fs tree\n");
|
printf("fs tree\n");
|
||||||
btrfs_print_tree(root, root->node);
|
btrfs_print_tree(root, root->node);
|
||||||
printf("map tree\n");
|
printf("map tree\n");
|
||||||
|
@ -23,5 +32,7 @@ int main(int ac, char **av) {
|
||||||
printf("root tree\n");
|
printf("root tree\n");
|
||||||
btrfs_print_tree(root->fs_info->tree_root,
|
btrfs_print_tree(root->fs_info->tree_root,
|
||||||
root->fs_info->tree_root->node);
|
root->fs_info->tree_root->node);
|
||||||
|
printf("total blocks %Lu\n", btrfs_super_total_blocks(&super));
|
||||||
|
printf("blocks used %Lu\n", btrfs_super_blocks_used(&super));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -425,8 +425,6 @@ int main(int ac, char **av)
|
||||||
struct btrfs_trans_handle *trans;
|
struct btrfs_trans_handle *trans;
|
||||||
radix_tree_init();
|
radix_tree_init();
|
||||||
|
|
||||||
printf("removing old tree\n");
|
|
||||||
unlink("dbfile");
|
|
||||||
root = open_ctree("dbfile", &super);
|
root = open_ctree("dbfile", &super);
|
||||||
trans = btrfs_start_transaction(root, 1);
|
trans = btrfs_start_transaction(root, 1);
|
||||||
|
|
||||||
|
|
|
@ -293,19 +293,14 @@ struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super)
|
||||||
fs_info->inode_root = inode_root;
|
fs_info->inode_root = inode_root;
|
||||||
fs_info->last_inode_alloc = 0;
|
fs_info->last_inode_alloc = 0;
|
||||||
fs_info->last_inode_alloc_dirid = 0;
|
fs_info->last_inode_alloc_dirid = 0;
|
||||||
|
fs_info->disk_super = super;
|
||||||
memset(&fs_info->current_insert, 0, sizeof(fs_info->current_insert));
|
memset(&fs_info->current_insert, 0, sizeof(fs_info->current_insert));
|
||||||
memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert));
|
memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert));
|
||||||
|
|
||||||
ret = pread(fp, super, sizeof(struct btrfs_super_block),
|
ret = pread(fp, super, sizeof(struct btrfs_super_block),
|
||||||
BTRFS_SUPER_INFO_OFFSET);
|
BTRFS_SUPER_INFO_OFFSET);
|
||||||
if (ret == 0 || btrfs_super_root(super) == 0) {
|
if (ret == 0 || btrfs_super_root(super) == 0) {
|
||||||
printf("making new FS!\n");
|
BUG();
|
||||||
ret = mkfs(fp, 0, 1024);
|
|
||||||
if (ret)
|
|
||||||
return NULL;
|
|
||||||
ret = pread(fp, super, sizeof(struct btrfs_super_block),
|
|
||||||
BTRFS_SUPER_INFO_OFFSET);
|
|
||||||
if (ret != sizeof(struct btrfs_super_block))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
BUG_ON(ret < 0);
|
BUG_ON(ret < 0);
|
||||||
|
|
|
@ -134,6 +134,8 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
|
||||||
struct btrfs_extent_item extent_item;
|
struct btrfs_extent_item extent_item;
|
||||||
int i;
|
int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
u64 super_blocks_used;
|
||||||
|
struct btrfs_fs_info *info = extent_root->fs_info;
|
||||||
|
|
||||||
btrfs_set_extent_refs(&extent_item, 1);
|
btrfs_set_extent_refs(&extent_item, 1);
|
||||||
btrfs_set_extent_owner(&extent_item,
|
btrfs_set_extent_owner(&extent_item,
|
||||||
|
@ -145,6 +147,9 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
|
||||||
for (i = 0; i < extent_root->fs_info->current_insert.flags; i++) {
|
for (i = 0; i < extent_root->fs_info->current_insert.flags; i++) {
|
||||||
ins.objectid = extent_root->fs_info->current_insert.objectid +
|
ins.objectid = extent_root->fs_info->current_insert.objectid +
|
||||||
i;
|
i;
|
||||||
|
super_blocks_used = btrfs_super_blocks_used(info->disk_super);
|
||||||
|
btrfs_set_super_blocks_used(info->disk_super,
|
||||||
|
super_blocks_used + 1);
|
||||||
ret = btrfs_insert_item(trans, extent_root, &ins, &extent_item,
|
ret = btrfs_insert_item(trans, extent_root, &ins, &extent_item,
|
||||||
sizeof(extent_item));
|
sizeof(extent_item));
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
|
@ -161,7 +166,8 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
{
|
{
|
||||||
struct btrfs_path path;
|
struct btrfs_path path;
|
||||||
struct btrfs_key key;
|
struct btrfs_key key;
|
||||||
struct btrfs_root *extent_root = root->fs_info->extent_root;
|
struct btrfs_fs_info *info = root->fs_info;
|
||||||
|
struct btrfs_root *extent_root = info->extent_root;
|
||||||
int ret;
|
int ret;
|
||||||
struct btrfs_extent_item *ei;
|
struct btrfs_extent_item *ei;
|
||||||
struct btrfs_key ins;
|
struct btrfs_key ins;
|
||||||
|
@ -188,15 +194,18 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
refs = btrfs_extent_refs(ei) - 1;
|
refs = btrfs_extent_refs(ei) - 1;
|
||||||
btrfs_set_extent_refs(ei, refs);
|
btrfs_set_extent_refs(ei, refs);
|
||||||
if (refs == 0) {
|
if (refs == 0) {
|
||||||
|
u64 super_blocks_used;
|
||||||
if (pin) {
|
if (pin) {
|
||||||
int err;
|
int err;
|
||||||
radix_tree_preload(GFP_KERNEL);
|
radix_tree_preload(GFP_KERNEL);
|
||||||
err = radix_tree_insert(
|
err = radix_tree_insert(&info->pinned_radix,
|
||||||
&extent_root->fs_info->pinned_radix,
|
|
||||||
blocknr, (void *)blocknr);
|
blocknr, (void *)blocknr);
|
||||||
BUG_ON(err);
|
BUG_ON(err);
|
||||||
radix_tree_preload_end();
|
radix_tree_preload_end();
|
||||||
}
|
}
|
||||||
|
super_blocks_used = btrfs_super_blocks_used(info->disk_super);
|
||||||
|
btrfs_set_super_blocks_used(info->disk_super,
|
||||||
|
super_blocks_used - num_blocks);
|
||||||
ret = btrfs_del_item(trans, extent_root, &path);
|
ret = btrfs_del_item(trans, extent_root, &path);
|
||||||
if (!pin && extent_root->fs_info->last_insert.objectid >
|
if (!pin && extent_root->fs_info->last_insert.objectid >
|
||||||
blocknr)
|
blocknr)
|
||||||
|
@ -392,7 +401,9 @@ static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int pending_ret;
|
int pending_ret;
|
||||||
struct btrfs_root *extent_root = root->fs_info->extent_root;
|
u64 super_blocks_used;
|
||||||
|
struct btrfs_fs_info *info = root->fs_info;
|
||||||
|
struct btrfs_root *extent_root = info->extent_root;
|
||||||
struct btrfs_extent_item extent_item;
|
struct btrfs_extent_item extent_item;
|
||||||
|
|
||||||
btrfs_set_extent_refs(&extent_item, 1);
|
btrfs_set_extent_refs(&extent_item, 1);
|
||||||
|
@ -413,6 +424,9 @@ static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
super_blocks_used = btrfs_super_blocks_used(info->disk_super);
|
||||||
|
btrfs_set_super_blocks_used(info->disk_super, super_blocks_used +
|
||||||
|
num_blocks);
|
||||||
ret = btrfs_insert_item(trans, extent_root, ins, &extent_item,
|
ret = btrfs_insert_item(trans, extent_root, ins, &extent_item,
|
||||||
sizeof(extent_item));
|
sizeof(extent_item));
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
#define _XOPEN_SOURCE 500
|
#define _XOPEN_SOURCE 500
|
||||||
|
#ifndef __CHECKER__
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#endif
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
@ -10,6 +14,17 @@
|
||||||
#include "ctree.h"
|
#include "ctree.h"
|
||||||
#include "disk-io.h"
|
#include "disk-io.h"
|
||||||
|
|
||||||
|
#ifdef __CHECKER__
|
||||||
|
#define BLKGETSIZE64 0
|
||||||
|
static inline int ioctl(int fd, int define, u64 *size) { return 0; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
|
||||||
|
# define BLKGETSIZE64 _IOR(0x12, 114, __u64)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
int mkfs(int fd, u64 num_blocks, u32 blocksize)
|
int mkfs(int fd, u64 num_blocks, u32 blocksize)
|
||||||
{
|
{
|
||||||
struct btrfs_super_block super;
|
struct btrfs_super_block super;
|
||||||
|
@ -27,7 +42,7 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize)
|
||||||
strcpy((char *)(&super.magic), BTRFS_MAGIC);
|
strcpy((char *)(&super.magic), BTRFS_MAGIC);
|
||||||
btrfs_set_super_blocksize(&super, blocksize);
|
btrfs_set_super_blocksize(&super, blocksize);
|
||||||
btrfs_set_super_total_blocks(&super, num_blocks);
|
btrfs_set_super_total_blocks(&super, num_blocks);
|
||||||
btrfs_set_super_blocks_used(&super, 0);
|
btrfs_set_super_blocks_used(&super, start_block + 5);
|
||||||
|
|
||||||
block = malloc(blocksize);
|
block = malloc(blocksize);
|
||||||
memset(block, 0, blocksize);
|
memset(block, 0, blocksize);
|
||||||
|
@ -160,3 +175,81 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize)
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 device_size(int fd, struct stat *st)
|
||||||
|
{
|
||||||
|
u64 size;
|
||||||
|
if (S_ISREG(st->st_mode)) {
|
||||||
|
return st->st_size;
|
||||||
|
}
|
||||||
|
if (!S_ISBLK(st->st_mode)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (ioctl(fd, BLKGETSIZE64, &size) >= 0) {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int ac, char **av)
|
||||||
|
{
|
||||||
|
char *file;
|
||||||
|
u64 block_count = 0;
|
||||||
|
int fd;
|
||||||
|
struct stat st;
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
char *buf = malloc(4096);
|
||||||
|
if (ac >= 2) {
|
||||||
|
file = av[1];
|
||||||
|
if (ac == 3) {
|
||||||
|
block_count = atoi(av[2]);
|
||||||
|
if (!block_count) {
|
||||||
|
fprintf(stderr, "error finding block count\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "usage: mkfs.btrfs file [block count]\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fd = open(file, O_RDWR);
|
||||||
|
if (fd < 0) {
|
||||||
|
fprintf(stderr, "unable to open %s\n", file);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
ret = fstat(fd, &st);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "unable to stat %s\n", file);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (block_count == 0) {
|
||||||
|
block_count = device_size(fd, &st);
|
||||||
|
if (block_count == 0) {
|
||||||
|
fprintf(stderr, "unable to find %s size\n", file);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
block_count /= 4096;
|
||||||
|
if (block_count < 256) {
|
||||||
|
fprintf(stderr, "device %s is too small\n", file);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
memset(buf, 0, 4096);
|
||||||
|
for(i = 0; i < 6; i++) {
|
||||||
|
ret = write(fd, buf, 4096);
|
||||||
|
if (ret != 4096) {
|
||||||
|
fprintf(stderr, "unable to zero fill device\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = mkfs(fd, block_count, 4096);
|
||||||
|
if (ret) {
|
||||||
|
fprintf(stderr, "error during mkfs %d\n", ret);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
printf("fs created on %s blocksize %d blocks %Lu\n",
|
||||||
|
file, 4096, block_count);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue