Btrfs: Better block record keeping, real mkfs
authorChris Mason <chris.mason@oracle.com>
Wed, 21 Mar 2007 00:35:03 +0000 (20:35 -0400)
committerDavid Woodhouse <dwmw2@hera.kernel.org>
Wed, 21 Mar 2007 00:35:03 +0000 (20:35 -0400)
Signed-off-by: Chris Mason <chris.mason@oracle.com>
fs/btrfs/Makefile
fs/btrfs/ctree.h
fs/btrfs/debug-tree.c
fs/btrfs/dir-test.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/mkfs.c

index 636c63efde6f642f8eb49f81d05f044f952ddc1c..0720169b6d66cc4e559b5e83a7655b348ca69031 100644 (file)
@@ -2,7 +2,7 @@ CC=gcc
 CFLAGS = -g -Wall -Werror
 headers = radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h list.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 \
          inode-map.o \
 
@@ -16,7 +16,10 @@ check=sparse $(CHECKFLAGS)
        $(check) $<
        $(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
        gcc $(CFLAGS) -o debug-tree $(objects) debug-tree.o
index b30b2ce724550ccd0d633c8c4d6e06060e50f278..1a4d1d6fa4016f7aa87cb777564653b2ac4c2ffe 100644 (file)
@@ -223,6 +223,7 @@ struct btrfs_fs_info {
        int cache_size;
        int fp;
        struct btrfs_trans_handle *running_transaction;
+       struct btrfs_super_block *disk_super;
 };
 
 /*
index d9f36efc3dd19ea505ad2976e27abcf4973620fa..fd07969600c67da363e91212041ec847e56992eb 100644 (file)
 int main(int ac, char **av) {
        struct btrfs_super_block super;
        struct btrfs_root *root;
+
+       if (ac != 2) {
+               fprintf(stderr, "usage: %s device\n", av[0]);
+               exit(1);
+       }
        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");
        btrfs_print_tree(root, root->node);
        printf("map tree\n");
@@ -23,5 +32,7 @@ int main(int ac, char **av) {
        printf("root tree\n");
        btrfs_print_tree(root->fs_info->tree_root,
                         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;
 }
index 8fc77c83a35128522df73eb9e9edb2ebf1285171..b673982a1f3c13743829351c8167351f5dde1e35 100644 (file)
@@ -425,8 +425,6 @@ int main(int ac, char **av)
        struct btrfs_trans_handle *trans;
        radix_tree_init();
 
-       printf("removing old tree\n");
-       unlink("dbfile");
        root = open_ctree("dbfile", &super);
        trans = btrfs_start_transaction(root, 1);
 
index bacaa38ea82efe977e2ce08e8f984683c168d09f..0322c55162cba155c6b40cdb123ea20dba595d63 100644 (file)
@@ -293,20 +293,15 @@ struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super)
        fs_info->inode_root = inode_root;
        fs_info->last_inode_alloc = 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->last_insert, 0, sizeof(fs_info->last_insert));
 
        ret = pread(fp, super, sizeof(struct btrfs_super_block),
                     BTRFS_SUPER_INFO_OFFSET);
        if (ret == 0 || btrfs_super_root(super) == 0) {
-               printf("making new FS!\n");
-               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;
+               BUG();
+               return NULL;
        }
        BUG_ON(ret < 0);
 
index 09eeeb4d9d285c4f0aab5bacf039e5c7b7713e35..9bc4ad38876dfa65a5114d04400658d04fb8294e 100644 (file)
@@ -134,6 +134,8 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct
        struct btrfs_extent_item extent_item;
        int i;
        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_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++) {
                ins.objectid = extent_root->fs_info->current_insert.objectid +
                                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,
                                        sizeof(extent_item));
                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_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;
        struct btrfs_extent_item *ei;
        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;
        btrfs_set_extent_refs(ei, refs);
        if (refs == 0) {
+               u64 super_blocks_used;
                if (pin) {
                        int err;
                        radix_tree_preload(GFP_KERNEL);
-                       err = radix_tree_insert(
-                                       &extent_root->fs_info->pinned_radix,
-                                       blocknr, (void *)blocknr);
+                       err = radix_tree_insert(&info->pinned_radix,
+                                               blocknr, (void *)blocknr);
                        BUG_ON(err);
                        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);
                if (!pin && extent_root->fs_info->last_insert.objectid >
                    blocknr)
@@ -392,7 +401,9 @@ static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root
 {
        int 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;
 
        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)
                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,
                                sizeof(extent_item));
 
index 1cac5ab114dde64f7819b13ab990afcd47184e20..f7efc8a5fb1a234a1087ce5c9f179c572d005bf1 100644 (file)
@@ -1,4 +1,8 @@
 #define _XOPEN_SOURCE 500
+#ifndef __CHECKER__
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include "ctree.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)
 {
        struct btrfs_super_block super;
@@ -27,7 +42,7 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize)
        strcpy((char *)(&super.magic), BTRFS_MAGIC);
        btrfs_set_super_blocksize(&super, blocksize);
        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);
        memset(block, 0, blocksize);
@@ -160,3 +175,81 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize)
                return -1;
        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;
+}
+