diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-10-15 16:25:14 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-10-15 16:25:14 -0400 |
commit | 38f79f9077fce76eabc5566319f33b8e800fb96d (patch) | |
tree | 2b7e92dc61209b55d5f119e1ddbf472cf32528d1 /disk-io.c | |
parent | 08c66b7738e17ae2879d767a59ebec56c7a189b2 (diff) |
Switch to byte granular allocations
Diffstat (limited to 'disk-io.c')
-rw-r--r-- | disk-io.c | 114 |
1 files changed, 71 insertions, 43 deletions
@@ -31,20 +31,20 @@ #include "transaction.h" #include "crc32c.h" -static int allocated_blocks = 0; +static u64 allocated_bytes = 0; int cache_max = 10000; int btrfs_map_bh_to_logical(struct btrfs_root *root, struct btrfs_buffer *bh, u64 logical) { bh->fd = root->fs_info->fp; - bh->dev_blocknr = logical; + bh->dev_bytenr = logical; return 0; } static int check_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf) { - if (buf->blocknr != btrfs_header_blocknr(&buf->node.header)) + if (buf->bytenr != btrfs_header_bytenr(&buf->node.header)) BUG(); if (memcmp(root->fs_info->disk_super->fsid, buf->node.header.fsid, sizeof(buf->node.header.fsid))) @@ -71,24 +71,28 @@ static int free_some_buffers(struct btrfs_root *root) return 0; } -struct btrfs_buffer *alloc_tree_block(struct btrfs_root *root, u64 blocknr) +struct btrfs_buffer *alloc_tree_block(struct btrfs_root *root, u64 bytenr, + u32 blocksize) { struct btrfs_buffer *buf; int ret; - buf = malloc(sizeof(struct btrfs_buffer) + root->sectorsize); + buf = malloc(sizeof(struct btrfs_buffer) + blocksize); if (!buf) return buf; - allocated_blocks++; - buf->blocknr = blocknr; + allocated_bytes += blocksize; + + buf->bytenr = bytenr; buf->count = 2; + buf->size = blocksize; + INIT_LIST_HEAD(&buf->dirty); free_some_buffers(root); radix_tree_preload(GFP_KERNEL); - ret = radix_tree_insert(&root->fs_info->cache_radix, blocknr, buf); + ret = radix_tree_insert(&root->fs_info->cache_radix, bytenr, buf); radix_tree_preload_end(); list_add_tail(&buf->cache, &root->fs_info->cache); - root->fs_info->cache_size++; + root->fs_info->cache_size += blocksize; if (ret) { free(buf); return NULL; @@ -96,14 +100,15 @@ struct btrfs_buffer *alloc_tree_block(struct btrfs_root *root, u64 blocknr) return buf; } -struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr) +struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 bytenr, + u32 blocksize) { struct btrfs_buffer *buf; - buf = radix_tree_lookup(&root->fs_info->cache_radix, blocknr); + buf = radix_tree_lookup(&root->fs_info->cache_radix, bytenr); if (buf) { buf->count++; } else { - buf = alloc_tree_block(root, blocknr); + buf = alloc_tree_block(root, bytenr, blocksize); if (!buf) { BUG(); return NULL; @@ -112,23 +117,24 @@ struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr) return buf; } -struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr) +struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, + u32 blocksize) { struct btrfs_buffer *buf; int ret; - buf = radix_tree_lookup(&root->fs_info->cache_radix, blocknr); + buf = radix_tree_lookup(&root->fs_info->cache_radix, bytenr); if (buf) { buf->count++; if (check_tree_block(root, buf)) BUG(); } else { - buf = alloc_tree_block(root, blocknr); + buf = alloc_tree_block(root, bytenr, blocksize); if (!buf) return NULL; - btrfs_map_bh_to_logical(root, buf, blocknr); - ret = pread(buf->fd, &buf->node, root->sectorsize, - buf->dev_blocknr * root->sectorsize); - if (ret != root->sectorsize) { + btrfs_map_bh_to_logical(root, buf, bytenr); + ret = pread(buf->fd, &buf->node, blocksize, + buf->dev_bytenr); + if (ret != blocksize) { free(buf); return NULL; } @@ -163,7 +169,8 @@ int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, int btrfs_csum_node(struct btrfs_root *root, struct btrfs_node *node) { u32 crc; - size_t len = root->sectorsize - BTRFS_CSUM_SIZE; + size_t len = btrfs_level_size(root, btrfs_header_level(&node->header)) - + BTRFS_CSUM_SIZE; crc = crc32c(0, (char *)(node) + BTRFS_CSUM_SIZE, len); memcpy(node->header.csum, &crc, BTRFS_CRC32_SIZE); @@ -189,17 +196,17 @@ int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, { int ret; - if (buf->blocknr != btrfs_header_blocknr(&buf->node.header)) + if (buf->bytenr != btrfs_header_bytenr(&buf->node.header)) BUG(); - btrfs_map_bh_to_logical(root, buf, buf->blocknr); + btrfs_map_bh_to_logical(root, buf, buf->bytenr); if (check_tree_block(root, buf)) BUG(); btrfs_csum_node(root, &buf->node); - ret = pwrite(buf->fd, &buf->node, root->sectorsize, - buf->dev_blocknr * root->sectorsize); - if (ret != root->sectorsize) + ret = pwrite(buf->fd, &buf->node, buf->size, + buf->dev_bytenr); + if (ret != buf->size) return ret; return 0; } @@ -226,17 +233,19 @@ static int commit_tree_roots(struct btrfs_trans_handle *trans, struct btrfs_fs_info *fs_info) { int ret; - u64 old_extent_block; + u64 old_extent_bytenr; struct btrfs_root *tree_root = fs_info->tree_root; struct btrfs_root *extent_root = fs_info->extent_root; btrfs_write_dirty_block_groups(trans, fs_info->extent_root); while(1) { - old_extent_block = btrfs_root_blocknr(&extent_root->root_item); - if (old_extent_block == extent_root->node->blocknr) + old_extent_bytenr = btrfs_root_bytenr(&extent_root->root_item); + if (old_extent_bytenr == extent_root->node->bytenr) break; - btrfs_set_root_blocknr(&extent_root->root_item, - extent_root->node->blocknr); + btrfs_set_root_bytenr(&extent_root->root_item, + extent_root->node->bytenr); + extent_root->root_item.level = + btrfs_header_level(&extent_root->node->node.header); ret = btrfs_update_root(trans, tree_root, &extent_root->root_key, &extent_root->root_item); @@ -259,7 +268,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct memcpy(&snap_key, &root->root_key, sizeof(snap_key)); root->root_key.offset++; - btrfs_set_root_blocknr(&root->root_item, root->node->blocknr); + btrfs_set_root_bytenr(&root->root_item, root->node->bytenr); + root->root_item.level = + btrfs_header_level(&root->node->node.header); ret = btrfs_insert_root(trans, root->fs_info->tree_root, &root->root_key, &root->root_item); BUG_ON(ret); @@ -304,6 +315,17 @@ static int __setup_root(struct btrfs_super_block *super, return 0; } +struct btrfs_buffer *read_root_block(struct btrfs_root *root, u64 bytenr, + u8 level) +{ + struct btrfs_buffer *node; + u32 size = btrfs_level_size(root, level); + + node = read_tree_block(root, bytenr, size); + BUG_ON(!node); + return node; +} + static int find_and_setup_root(struct btrfs_super_block *super, struct btrfs_root *tree_root, struct btrfs_fs_info *fs_info, @@ -316,9 +338,9 @@ static int find_and_setup_root(struct btrfs_super_block *super, ret = btrfs_find_last_root(tree_root, objectid, &root->root_item, &root->root_key); BUG_ON(ret); - - root->node = read_tree_block(root, - btrfs_root_blocknr(&root->root_item)); + root->node = read_root_block(root, + btrfs_root_bytenr(&root->root_item), + root->root_item.level); BUG_ON(!root->node); return 0; } @@ -369,7 +391,8 @@ struct btrfs_root *open_ctree_fd(int fp, struct btrfs_super_block *super) BUG_ON(ret < 0); __setup_root(super, tree_root, fs_info, BTRFS_ROOT_TREE_OBJECTID, fp); - tree_root->node = read_tree_block(tree_root, btrfs_super_root(super)); + tree_root->node = read_root_block(tree_root, btrfs_super_root(super), + btrfs_super_root_level(super)); BUG_ON(!tree_root->node); ret = find_and_setup_root(super, tree_root, fs_info, @@ -393,7 +416,9 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root { int ret; - btrfs_set_super_root(s, root->fs_info->tree_root->node->blocknr); + btrfs_set_super_root(s, root->fs_info->tree_root->node->bytenr); + btrfs_set_super_root_level(s, + btrfs_header_level(&root->fs_info->tree_root->node->node.header)); btrfs_csum_super(root, s); ret = pwrite(root->fs_info->fp, s, sizeof(*s), @@ -444,7 +469,8 @@ int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s) root->fs_info->tree_root->node); btrfs_block_release(root, root->commit_root); free(root); - printf("on close %d blocks are allocated\n", allocated_blocks); + printf("on close %llu blocks are allocated\n", + (unsigned long long)allocated_bytes); return 0; } @@ -457,15 +483,17 @@ void btrfs_block_release(struct btrfs_root *root, struct btrfs_buffer *buf) BUG_ON(!list_empty(&buf->cache)); BUG_ON(!list_empty(&buf->dirty)); if (!radix_tree_lookup(&root->fs_info->cache_radix, - buf->blocknr)) + buf->bytenr)) BUG(); - radix_tree_delete(&root->fs_info->cache_radix, buf->blocknr); + + radix_tree_delete(&root->fs_info->cache_radix, buf->bytenr); + BUG_ON(allocated_bytes == 0); + allocated_bytes -= buf->size; + BUG_ON(root->fs_info->cache_size == 0); + root->fs_info->cache_size -= buf->size; + memset(buf, 0, sizeof(*buf)); free(buf); - BUG_ON(allocated_blocks == 0); - allocated_blocks--; - BUG_ON(root->fs_info->cache_size == 0); - root->fs_info->cache_size--; } } |