提交 5f39d397 编写于 作者: C Chris Mason

Btrfs: Create extent_buffer interface for large blocksizes

Signed-off-by: NChris Mason <chris.mason@oracle.com>
上级 50b78c24
...@@ -23,4 +23,6 @@ modules_install: ...@@ -23,4 +23,6 @@ modules_install:
clean: clean:
$(MAKE) -C $(KERNELDIR) M=`pwd` clean $(MAKE) -C $(KERNELDIR) M=`pwd` clean
tester:
$(MAKE) -C $(KERNELDIR) M=`pwd` tree-defrag.o transaction.o sysfs.o super.o root-tree.o inode-map.o inode-item.o inode.o file-item.o file.o extent_map.o disk-io.o ctree.o dir-item.o extent-tree.o
endif endif
此差异已折叠。
此差异已折叠。
...@@ -33,7 +33,7 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle ...@@ -33,7 +33,7 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle
int ret; int ret;
char *ptr; char *ptr;
struct btrfs_item *item; struct btrfs_item *item;
struct btrfs_leaf *leaf; struct extent_buffer *leaf;
ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size); ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
if (ret == -EEXIST) { if (ret == -EEXIST) {
...@@ -49,11 +49,11 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle ...@@ -49,11 +49,11 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle
if (ret < 0) if (ret < 0)
return ERR_PTR(ret); return ERR_PTR(ret);
WARN_ON(ret > 0); WARN_ON(ret > 0);
leaf = btrfs_buffer_leaf(path->nodes[0]); leaf = path->nodes[0];
item = leaf->items + path->slots[0]; item = btrfs_item_nr(leaf, path->slots[0]);
ptr = btrfs_item_ptr(leaf, path->slots[0], char); ptr = btrfs_item_ptr(leaf, path->slots[0], char);
BUG_ON(data_size > btrfs_item_size(item)); BUG_ON(data_size > btrfs_item_size(leaf, item));
ptr += btrfs_item_size(item) - data_size; ptr += btrfs_item_size(leaf, item) - data_size;
return (struct btrfs_dir_item *)ptr; return (struct btrfs_dir_item *)ptr;
} }
...@@ -65,12 +65,13 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -65,12 +65,13 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
int ret2 = 0; int ret2 = 0;
struct btrfs_path *path; struct btrfs_path *path;
struct btrfs_dir_item *dir_item; struct btrfs_dir_item *dir_item;
char *name_ptr; struct extent_buffer *leaf;
unsigned long name_ptr;
struct btrfs_key key; struct btrfs_key key;
struct btrfs_disk_key disk_key;
u32 data_size; u32 data_size;
key.objectid = dir; key.objectid = dir;
key.flags = 0;
btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
ret = btrfs_name_hash(name, name_len, &key.offset); ret = btrfs_name_hash(name, name_len, &key.offset);
BUG_ON(ret); BUG_ON(ret);
...@@ -85,14 +86,16 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -85,14 +86,16 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
goto out; goto out;
} }
btrfs_cpu_key_to_disk(&dir_item->location, location); leaf = path->nodes[0];
btrfs_set_dir_type(dir_item, type); btrfs_cpu_key_to_disk(&disk_key, location);
btrfs_set_dir_flags(dir_item, 0); btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
btrfs_set_dir_name_len(dir_item, name_len); btrfs_set_dir_type(leaf, dir_item, type);
name_ptr = (char *)(dir_item + 1); btrfs_set_dir_flags(leaf, dir_item, 0);
btrfs_set_dir_name_len(leaf, dir_item, name_len);
name_ptr = (unsigned long)(dir_item + 1);
btrfs_memcpy(root, path->nodes[0]->b_data, name_ptr, name, name_len); write_extent_buffer(leaf, name, name_ptr, name_len);
btrfs_mark_buffer_dirty(path->nodes[0]); btrfs_mark_buffer_dirty(leaf);
second_insert: second_insert:
/* FIXME, use some real flag for selecting the extra index */ /* FIXME, use some real flag for selecting the extra index */
...@@ -110,13 +113,15 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -110,13 +113,15 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
ret2 = PTR_ERR(dir_item); ret2 = PTR_ERR(dir_item);
goto out; goto out;
} }
btrfs_cpu_key_to_disk(&dir_item->location, location); leaf = path->nodes[0];
btrfs_set_dir_type(dir_item, type); btrfs_cpu_key_to_disk(&disk_key, location);
btrfs_set_dir_flags(dir_item, 0); btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
btrfs_set_dir_name_len(dir_item, name_len); btrfs_set_dir_type(leaf, dir_item, type);
name_ptr = (char *)(dir_item + 1); btrfs_set_dir_flags(leaf, dir_item, 0);
btrfs_memcpy(root, path->nodes[0]->b_data, name_ptr, name, name_len); btrfs_set_dir_name_len(leaf, dir_item, name_len);
btrfs_mark_buffer_dirty(path->nodes[0]); name_ptr = (unsigned long)(dir_item + 1);
write_extent_buffer(leaf, name, name_ptr, name_len);
btrfs_mark_buffer_dirty(leaf);
out: out:
btrfs_free_path(path); btrfs_free_path(path);
if (ret) if (ret)
...@@ -136,14 +141,15 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, ...@@ -136,14 +141,15 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
struct btrfs_key key; struct btrfs_key key;
int ins_len = mod < 0 ? -1 : 0; int ins_len = mod < 0 ? -1 : 0;
int cow = mod != 0; int cow = mod != 0;
struct btrfs_disk_key *found_key; struct btrfs_key found_key;
struct btrfs_leaf *leaf; struct extent_buffer *leaf;
key.objectid = dir; key.objectid = dir;
key.flags = 0;
btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
ret = btrfs_name_hash(name, name_len, &key.offset); ret = btrfs_name_hash(name, name_len, &key.offset);
BUG_ON(ret); BUG_ON(ret);
ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow); ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
if (ret < 0) if (ret < 0)
return ERR_PTR(ret); return ERR_PTR(ret);
...@@ -152,12 +158,13 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, ...@@ -152,12 +158,13 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
return NULL; return NULL;
path->slots[0]--; path->slots[0]--;
} }
leaf = btrfs_buffer_leaf(path->nodes[0]);
found_key = &leaf->items[path->slots[0]].key;
if (btrfs_disk_key_objectid(found_key) != dir || leaf = path->nodes[0];
btrfs_disk_key_type(found_key) != BTRFS_DIR_ITEM_KEY || btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
btrfs_disk_key_offset(found_key) != key.offset)
if (found_key.objectid != dir ||
btrfs_key_type(&found_key) != BTRFS_DIR_ITEM_KEY ||
found_key.offset != key.offset)
return NULL; return NULL;
return btrfs_match_dir_item_name(root, path, name, name_len); return btrfs_match_dir_item_name(root, path, name, name_len);
...@@ -176,7 +183,6 @@ btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans, ...@@ -176,7 +183,6 @@ btrfs_lookup_dir_index_item(struct btrfs_trans_handle *trans,
int cow = mod != 0; int cow = mod != 0;
key.objectid = dir; key.objectid = dir;
key.flags = 0;
btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY); btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY);
key.offset = objectid; key.offset = objectid;
...@@ -193,21 +199,22 @@ struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root, ...@@ -193,21 +199,22 @@ struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root,
const char *name, int name_len) const char *name, int name_len)
{ {
struct btrfs_dir_item *dir_item; struct btrfs_dir_item *dir_item;
char *name_ptr; unsigned long name_ptr;
u32 total_len; u32 total_len;
u32 cur = 0; u32 cur = 0;
u32 this_len; u32 this_len;
struct btrfs_leaf *leaf; struct extent_buffer *leaf;
leaf = btrfs_buffer_leaf(path->nodes[0]); leaf = path->nodes[0];
dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item); dir_item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item);
total_len = btrfs_item_size(leaf->items + path->slots[0]); total_len = btrfs_item_size_nr(leaf, path->slots[0]);
while(cur < total_len) { while(cur < total_len) {
this_len = sizeof(*dir_item) + btrfs_dir_name_len(dir_item); this_len = sizeof(*dir_item) +
name_ptr = (char *)(dir_item + 1); btrfs_dir_name_len(leaf, dir_item);
name_ptr = (unsigned long)(dir_item + 1);
if (btrfs_dir_name_len(dir_item) == name_len && if (btrfs_dir_name_len(leaf, dir_item) == name_len &&
memcmp(name_ptr, name, name_len) == 0) memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0)
return dir_item; return dir_item;
cur += this_len; cur += this_len;
...@@ -223,20 +230,23 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans, ...@@ -223,20 +230,23 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans,
struct btrfs_dir_item *di) struct btrfs_dir_item *di)
{ {
struct btrfs_leaf *leaf; struct extent_buffer *leaf;
u32 sub_item_len; u32 sub_item_len;
u32 item_len; u32 item_len;
int ret = 0; int ret = 0;
leaf = btrfs_buffer_leaf(path->nodes[0]); leaf = path->nodes[0];
sub_item_len = sizeof(*di) + btrfs_dir_name_len(di); sub_item_len = sizeof(*di) + btrfs_dir_name_len(leaf, di);
item_len = btrfs_item_size(leaf->items + path->slots[0]); item_len = btrfs_item_size_nr(leaf, path->slots[0]);
if (sub_item_len == btrfs_item_size(leaf->items + path->slots[0])) { if (sub_item_len == item_len) {
ret = btrfs_del_item(trans, root, path); ret = btrfs_del_item(trans, root, path);
} else { } else {
char *ptr = (char *)di; /* MARKER */
char *start = btrfs_item_ptr(leaf, path->slots[0], char); unsigned long ptr = (unsigned long)di;
btrfs_memmove(root, leaf, ptr, ptr + sub_item_len, unsigned long start;
start = btrfs_item_ptr_offset(leaf, path->slots[0]);
memmove_extent_buffer(leaf, ptr, ptr + sub_item_len,
item_len - (ptr + sub_item_len - start)); item_len - (ptr + sub_item_len - start));
ret = btrfs_truncate_item(trans, root, path, ret = btrfs_truncate_item(trans, root, path,
item_len - sub_item_len); item_len - sub_item_len);
......
...@@ -23,138 +23,132 @@ ...@@ -23,138 +23,132 @@
#include <linux/swap.h> #include <linux/swap.h>
#include <linux/radix-tree.h> #include <linux/radix-tree.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/buffer_head.h> // for block_sync_page
#include "ctree.h" #include "ctree.h"
#include "disk-io.h" #include "disk-io.h"
#include "transaction.h" #include "transaction.h"
#include "btrfs_inode.h" #include "btrfs_inode.h"
u64 bh_blocknr(struct buffer_head *bh) #if 0
static int check_tree_block(struct btrfs_root *root, struct extent_buffer *buf)
{ {
return bh->b_blocknr; if (extent_buffer_blocknr(buf) != btrfs_header_blocknr(buf)) {
} printk(KERN_CRIT "buf blocknr(buf) is %llu, header is %llu\n",
(unsigned long long)extent_buffer_blocknr(buf),
static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf) (unsigned long long)btrfs_header_blocknr(buf));
{
struct btrfs_node *node = btrfs_buffer_node(buf);
if (bh_blocknr(buf) != btrfs_header_blocknr(&node->header)) {
printk(KERN_CRIT "bh_blocknr(buf) is %llu, header is %llu\n",
(unsigned long long)bh_blocknr(buf),
(unsigned long long)btrfs_header_blocknr(&node->header));
return 1; return 1;
} }
return 0; return 0;
} }
#endif
struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr) struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root,
u64 blocknr)
{ {
struct address_space *mapping = root->fs_info->btree_inode->i_mapping; struct inode *btree_inode = root->fs_info->btree_inode;
int blockbits = root->fs_info->sb->s_blocksize_bits; return find_extent_buffer(&BTRFS_I(btree_inode)->extent_tree,
unsigned long index = blocknr >> (PAGE_CACHE_SHIFT - blockbits); blocknr * root->sectorsize,
struct page *page; root->sectorsize, GFP_NOFS);
struct buffer_head *bh; }
struct buffer_head *head;
struct buffer_head *ret = NULL;
page = find_lock_page(mapping, index);
if (!page)
return NULL;
if (!page_has_buffers(page))
goto out_unlock;
head = page_buffers(page); struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
bh = head; u64 blocknr)
do { {
if (buffer_mapped(bh) && bh_blocknr(bh) == blocknr) { struct inode *btree_inode = root->fs_info->btree_inode;
ret = bh; return alloc_extent_buffer(&BTRFS_I(btree_inode)->extent_tree,
get_bh(bh); blocknr * root->sectorsize,
goto out_unlock; root->sectorsize, GFP_NOFS);
}
bh = bh->b_this_page;
} while (bh != head);
out_unlock:
unlock_page(page);
page_cache_release(page);
return ret;
} }
int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh, struct extent_map *btree_get_extent(struct inode *inode, struct page *page,
u64 logical) size_t page_offset, u64 start, u64 end,
int create)
{ {
if (logical == 0) { struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
bh->b_bdev = NULL; struct extent_map *em;
bh->b_blocknr = 0; int ret;
set_buffer_mapped(bh);
} else { again:
map_bh(bh, root->fs_info->sb, logical); em = lookup_extent_mapping(em_tree, start, end);
if (em) {
goto out;
} }
return 0; em = alloc_extent_map(GFP_NOFS);
if (!em) {
em = ERR_PTR(-ENOMEM);
goto out;
}
em->start = 0;
em->end = (i_size_read(inode) & ~((u64)PAGE_CACHE_SIZE -1)) - 1;
em->block_start = 0;
em->block_end = em->end;
em->bdev = inode->i_sb->s_bdev;
ret = add_extent_mapping(em_tree, em);
if (ret == -EEXIST) {
free_extent_map(em);
em = NULL;
goto again;
} else if (ret) {
em = ERR_PTR(ret);
}
out:
return em;
} }
struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, static int btree_writepage(struct page *page, struct writeback_control *wbc)
u64 blocknr)
{ {
struct address_space *mapping = root->fs_info->btree_inode->i_mapping; struct extent_map_tree *tree;
int blockbits = root->fs_info->sb->s_blocksize_bits; tree = &BTRFS_I(page->mapping->host)->extent_tree;
unsigned long index = blocknr >> (PAGE_CACHE_SHIFT - blockbits); return extent_write_full_page(tree, page, btree_get_extent, wbc);
struct page *page; }
struct buffer_head *bh; int btree_readpage(struct file *file, struct page *page)
struct buffer_head *head; {
struct buffer_head *ret = NULL; struct extent_map_tree *tree;
int err; tree = &BTRFS_I(page->mapping->host)->extent_tree;
u64 first_block = index << (PAGE_CACHE_SHIFT - blockbits); return extent_read_full_page(tree, page, btree_get_extent);
}
page = find_or_create_page(mapping, index, GFP_NOFS); static int btree_releasepage(struct page *page, gfp_t unused_gfp_flags)
if (!page) {
return NULL; struct extent_map_tree *tree;
int ret;
if (!page_has_buffers(page)) BUG_ON(page->private != 1);
create_empty_buffers(page, root->fs_info->sb->s_blocksize, 0); tree = &BTRFS_I(page->mapping->host)->extent_tree;
head = page_buffers(page); ret = try_release_extent_mapping(tree, page);
bh = head; if (ret == 1) {
do { ClearPagePrivate(page);
if (!buffer_mapped(bh)) { set_page_private(page, 0);
err = btrfs_map_bh_to_logical(root, bh, first_block); page_cache_release(page);
BUG_ON(err); }
}
if (bh_blocknr(bh) == blocknr) {
ret = bh;
get_bh(bh);
goto out_unlock;
}
bh = bh->b_this_page;
first_block++;
} while (bh != head);
out_unlock:
unlock_page(page);
if (ret)
touch_buffer(ret);
page_cache_release(page);
return ret; return ret;
} }
static int btree_get_block(struct inode *inode, sector_t iblock, static void btree_invalidatepage(struct page *page, unsigned long offset)
struct buffer_head *bh, int create)
{ {
int err; struct extent_map_tree *tree;
struct btrfs_root *root = BTRFS_I(bh->b_page->mapping->host)->root; tree = &BTRFS_I(page->mapping->host)->extent_tree;
err = btrfs_map_bh_to_logical(root, bh, iblock); extent_invalidatepage(tree, page, offset);
return err; btree_releasepage(page, GFP_NOFS);
} }
int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len, int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len,
char *result) char *result)
{ {
return 0;
#if 0
u32 crc; u32 crc;
crc = crc32c(0, data, len); crc = crc32c(0, data, len);
memcpy(result, &crc, BTRFS_CRC32_SIZE); memcpy(result, &crc, BTRFS_CRC32_SIZE);
return 0; return 0;
#endif
} }
static int csum_tree_block(struct btrfs_root *root, struct buffer_head *bh, #if 0
static int csum_tree_block(struct btrfs_root *root, struct extent_buffer *buf,
int verify) int verify)
{ {
return 0;
char result[BTRFS_CRC32_SIZE]; char result[BTRFS_CRC32_SIZE];
int ret; int ret;
struct btrfs_node *node; struct btrfs_node *node;
...@@ -176,7 +170,9 @@ static int csum_tree_block(struct btrfs_root *root, struct buffer_head *bh, ...@@ -176,7 +170,9 @@ static int csum_tree_block(struct btrfs_root *root, struct buffer_head *bh,
} }
return 0; return 0;
} }
#endif
#if 0
static int btree_writepage(struct page *page, struct writeback_control *wbc) static int btree_writepage(struct page *page, struct writeback_control *wbc)
{ {
struct buffer_head *bh; struct buffer_head *bh;
...@@ -195,87 +191,65 @@ static int btree_writepage(struct page *page, struct writeback_control *wbc) ...@@ -195,87 +191,65 @@ static int btree_writepage(struct page *page, struct writeback_control *wbc)
} while (bh != head); } while (bh != head);
return block_write_full_page(page, btree_get_block, wbc); return block_write_full_page(page, btree_get_block, wbc);
} }
#endif
static int btree_readpage(struct file * file, struct page * page)
{
return block_read_full_page(page, btree_get_block);
}
static struct address_space_operations btree_aops = { static struct address_space_operations btree_aops = {
.readpage = btree_readpage, .readpage = btree_readpage,
.writepage = btree_writepage, .writepage = btree_writepage,
.releasepage = btree_releasepage,
.invalidatepage = btree_invalidatepage,
.sync_page = block_sync_page, .sync_page = block_sync_page,
}; };
int readahead_tree_block(struct btrfs_root *root, u64 blocknr) int readahead_tree_block(struct btrfs_root *root, u64 blocknr)
{ {
struct buffer_head *bh = NULL; struct extent_buffer *buf = NULL;
struct inode *btree_inode = root->fs_info->btree_inode;
int ret = 0; int ret = 0;
bh = btrfs_find_create_tree_block(root, blocknr); buf = btrfs_find_create_tree_block(root, blocknr);
if (!bh) if (!buf)
return 0; return 0;
if (buffer_uptodate(bh)) { read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree,
ret = 1; buf, 0);
goto done; free_extent_buffer(buf);
}
if (test_set_buffer_locked(bh)) {
ret = 1;
goto done;
}
if (!buffer_uptodate(bh)) {
get_bh(bh);
bh->b_end_io = end_buffer_read_sync;
submit_bh(READ, bh);
} else {
unlock_buffer(bh);
ret = 1;
}
done:
brelse(bh);
return ret; return ret;
} }
struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr)
{ {
struct buffer_head *bh = NULL; struct extent_buffer *buf = NULL;
struct inode *btree_inode = root->fs_info->btree_inode;
bh = btrfs_find_create_tree_block(root, blocknr);
if (!bh) buf = btrfs_find_create_tree_block(root, blocknr);
return bh; if (!buf)
if (buffer_uptodate(bh)) return NULL;
goto uptodate; read_extent_buffer_pages(&BTRFS_I(btree_inode)->extent_tree,
lock_buffer(bh); buf, 1);
if (!buffer_uptodate(bh)) { return buf;
get_bh(bh);
bh->b_end_io = end_buffer_read_sync;
submit_bh(READ, bh);
wait_on_buffer(bh);
if (!buffer_uptodate(bh))
goto fail;
} else {
unlock_buffer(bh);
}
uptodate:
if (!buffer_checked(bh)) {
csum_tree_block(root, bh, 1);
set_buffer_checked(bh);
}
if (check_tree_block(root, bh))
goto fail;
return bh;
fail:
brelse(bh);
return NULL;
} }
int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct buffer_head *buf) struct extent_buffer *buf)
{ {
WARN_ON(atomic_read(&buf->b_count) == 0); struct inode *btree_inode = root->fs_info->btree_inode;
lock_buffer(buf); clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree, buf);
clear_buffer_dirty(buf); return 0;
unlock_buffer(buf); }
int wait_on_tree_block_writeback(struct btrfs_root *root,
struct extent_buffer *buf)
{
struct inode *btree_inode = root->fs_info->btree_inode;
wait_on_extent_buffer_writeback(&BTRFS_I(btree_inode)->extent_tree,
buf);
return 0;
}
int set_tree_block_dirty(struct btrfs_root *root, struct extent_buffer *buf)
{
struct inode *btree_inode = root->fs_info->btree_inode;
set_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree, buf);
return 0; return 0;
} }
...@@ -287,7 +261,9 @@ static int __setup_root(int blocksize, ...@@ -287,7 +261,9 @@ static int __setup_root(int blocksize,
root->node = NULL; root->node = NULL;
root->inode = NULL; root->inode = NULL;
root->commit_root = NULL; root->commit_root = NULL;
root->blocksize = blocksize; root->sectorsize = blocksize;
root->nodesize = blocksize;
root->leafsize = blocksize;
root->ref_cows = 0; root->ref_cows = 0;
root->fs_info = fs_info; root->fs_info = fs_info;
root->objectid = objectid; root->objectid = objectid;
...@@ -332,7 +308,7 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info, ...@@ -332,7 +308,7 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info,
struct btrfs_root *root; struct btrfs_root *root;
struct btrfs_root *tree_root = fs_info->tree_root; struct btrfs_root *tree_root = fs_info->tree_root;
struct btrfs_path *path; struct btrfs_path *path;
struct btrfs_leaf *l; struct extent_buffer *l;
u64 highest_inode; u64 highest_inode;
int ret = 0; int ret = 0;
...@@ -361,11 +337,10 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info, ...@@ -361,11 +337,10 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info,
ret = -ENOENT; ret = -ENOENT;
goto out; goto out;
} }
l = btrfs_buffer_leaf(path->nodes[0]); l = path->nodes[0];
memcpy(&root->root_item, read_extent_buffer(l, &root->root_item,
btrfs_item_ptr(l, path->slots[0], struct btrfs_root_item), btrfs_item_ptr_offset(l, path->slots[0]),
sizeof(root->root_item)); sizeof(root->root_item));
memcpy(&root->root_key, location, sizeof(*location));
ret = 0; ret = 0;
out: out:
btrfs_release_path(root, path); btrfs_release_path(root, path);
...@@ -406,21 +381,21 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, ...@@ -406,21 +381,21 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
(unsigned long)root->root_key.objectid, (unsigned long)root->root_key.objectid,
root); root);
if (ret) { if (ret) {
brelse(root->node); free_extent_buffer(root->node);
kfree(root); kfree(root);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
ret = btrfs_set_root_name(root, name, namelen); ret = btrfs_set_root_name(root, name, namelen);
if (ret) { if (ret) {
brelse(root->node); free_extent_buffer(root->node);
kfree(root); kfree(root);
return ERR_PTR(ret); return ERR_PTR(ret);
} }
ret = btrfs_sysfs_add_root(root); ret = btrfs_sysfs_add_root(root);
if (ret) { if (ret) {
brelse(root->node); free_extent_buffer(root->node);
kfree(root->name); kfree(root->name);
kfree(root); kfree(root);
return ERR_PTR(ret); return ERR_PTR(ret);
...@@ -471,6 +446,9 @@ struct btrfs_root *open_ctree(struct super_block *sb) ...@@ -471,6 +446,9 @@ struct btrfs_root *open_ctree(struct super_block *sb)
fs_info->btree_inode->i_nlink = 1; fs_info->btree_inode->i_nlink = 1;
fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size; fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size;
fs_info->btree_inode->i_mapping->a_ops = &btree_aops; fs_info->btree_inode->i_mapping->a_ops = &btree_aops;
extent_map_tree_init(&BTRFS_I(fs_info->btree_inode)->extent_tree,
fs_info->btree_inode->i_mapping,
GFP_NOFS);
fs_info->do_barriers = 1; fs_info->do_barriers = 1;
fs_info->closing = 0; fs_info->closing = 0;
...@@ -493,10 +471,14 @@ struct btrfs_root *open_ctree(struct super_block *sb) ...@@ -493,10 +471,14 @@ struct btrfs_root *open_ctree(struct super_block *sb)
if (!fs_info->sb_buffer) if (!fs_info->sb_buffer)
goto fail_iput; goto fail_iput;
disk_super = (struct btrfs_super_block *)fs_info->sb_buffer->b_data;
fs_info->disk_super = disk_super;
memcpy(&fs_info->super_copy, disk_super, sizeof(fs_info->super_copy));
read_extent_buffer(fs_info->sb_buffer, &fs_info->super_copy, 0,
sizeof(fs_info->super_copy));
read_extent_buffer(fs_info->sb_buffer, fs_info->fsid,
(unsigned long)btrfs_super_fsid(fs_info->sb_buffer),
BTRFS_FSID_SIZE);
disk_super = &fs_info->super_copy;
if (!btrfs_super_root(disk_super)) if (!btrfs_super_root(disk_super))
goto fail_sb_buffer; goto fail_sb_buffer;
...@@ -530,9 +512,9 @@ struct btrfs_root *open_ctree(struct super_block *sb) ...@@ -530,9 +512,9 @@ struct btrfs_root *open_ctree(struct super_block *sb)
return tree_root; return tree_root;
fail_tree_root: fail_tree_root:
btrfs_block_release(tree_root, tree_root->node); free_extent_buffer(tree_root->node);
fail_sb_buffer: fail_sb_buffer:
btrfs_block_release(tree_root, fs_info->sb_buffer); free_extent_buffer(fs_info->sb_buffer);
fail_iput: fail_iput:
iput(fs_info->btree_inode); iput(fs_info->btree_inode);
fail: fail:
...@@ -546,31 +528,13 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -546,31 +528,13 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root
*root) *root)
{ {
int ret; int ret;
struct buffer_head *bh = root->fs_info->sb_buffer; struct extent_buffer *super = root->fs_info->sb_buffer;
struct inode *btree_inode = root->fs_info->btree_inode;
lock_buffer(bh);
WARN_ON(atomic_read(&bh->b_count) < 1); set_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree, super);
clear_buffer_dirty(bh); ret = sync_page_range_nolock(btree_inode, btree_inode->i_mapping,
csum_tree_block(root, bh, 0); super->start, super->len);
bh->b_end_io = end_buffer_write_sync; return ret;
get_bh(bh);
if (root->fs_info->do_barriers)
ret = submit_bh(WRITE_BARRIER, bh);
else
ret = submit_bh(WRITE, bh);
if (ret == -EOPNOTSUPP) {
get_bh(bh);
lock_buffer(bh);
set_buffer_uptodate(bh);
root->fs_info->do_barriers = 0;
ret = submit_bh(WRITE, bh);
}
wait_on_buffer(bh);
if (!buffer_uptodate(bh)) {
WARN_ON(1);
return -EIO;
}
return 0;
} }
int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root)
...@@ -581,9 +545,9 @@ int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root) ...@@ -581,9 +545,9 @@ int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root)
if (root->inode) if (root->inode)
iput(root->inode); iput(root->inode);
if (root->node) if (root->node)
brelse(root->node); free_extent_buffer(root->node);
if (root->commit_root) if (root->commit_root)
brelse(root->commit_root); free_extent_buffer(root->commit_root);
if (root->name) if (root->name)
kfree(root->name); kfree(root->name);
kfree(root); kfree(root);
...@@ -629,12 +593,10 @@ int close_ctree(struct btrfs_root *root) ...@@ -629,12 +593,10 @@ int close_ctree(struct btrfs_root *root)
mutex_unlock(&fs_info->fs_mutex); mutex_unlock(&fs_info->fs_mutex);
if (fs_info->extent_root->node) if (fs_info->extent_root->node)
btrfs_block_release(fs_info->extent_root, free_extent_buffer(fs_info->extent_root->node);
fs_info->extent_root->node);
if (fs_info->tree_root->node) if (fs_info->tree_root->node)
btrfs_block_release(fs_info->tree_root, free_extent_buffer(fs_info->tree_root->node);
fs_info->tree_root->node); free_extent_buffer(fs_info->sb_buffer);
btrfs_block_release(root, fs_info->sb_buffer);
truncate_inode_pages(fs_info->btree_inode->i_mapping, 0); truncate_inode_pages(fs_info->btree_inode->i_mapping, 0);
iput(fs_info->btree_inode); iput(fs_info->btree_inode);
...@@ -645,25 +607,32 @@ int close_ctree(struct btrfs_root *root) ...@@ -645,25 +607,32 @@ int close_ctree(struct btrfs_root *root)
return 0; return 0;
} }
void btrfs_mark_buffer_dirty(struct buffer_head *bh) int btrfs_buffer_uptodate(struct extent_buffer *buf)
{
struct inode *btree_inode = buf->pages[0]->mapping->host;
return extent_buffer_uptodate(&BTRFS_I(btree_inode)->extent_tree, buf);
}
int btrfs_set_buffer_uptodate(struct extent_buffer *buf)
{ {
struct btrfs_root *root = BTRFS_I(bh->b_page->mapping->host)->root; struct inode *btree_inode = buf->pages[0]->mapping->host;
u64 transid = btrfs_header_generation(btrfs_buffer_header(bh)); return set_extent_buffer_uptodate(&BTRFS_I(btree_inode)->extent_tree,
buf);
}
WARN_ON(!atomic_read(&bh->b_count)); void btrfs_mark_buffer_dirty(struct extent_buffer *buf)
{
struct btrfs_root *root = BTRFS_I(buf->pages[0]->mapping->host)->root;
u64 transid = btrfs_header_generation(buf);
struct inode *btree_inode = root->fs_info->btree_inode;
if (transid != root->fs_info->generation) { if (transid != root->fs_info->generation) {
printk(KERN_CRIT "transid mismatch buffer %llu, found %Lu running %Lu\n", printk(KERN_CRIT "transid mismatch buffer %llu, found %Lu running %Lu\n",
(unsigned long long)bh->b_blocknr, (unsigned long long)extent_buffer_blocknr(buf),
transid, root->fs_info->generation); transid, root->fs_info->generation);
WARN_ON(1); WARN_ON(1);
} }
mark_buffer_dirty(bh); set_extent_buffer_dirty(&BTRFS_I(btree_inode)->extent_tree, buf);
}
void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf)
{
brelse(buf);
} }
void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr)
......
...@@ -19,68 +19,35 @@ ...@@ -19,68 +19,35 @@
#ifndef __DISKIO__ #ifndef __DISKIO__
#define __DISKIO__ #define __DISKIO__
#include <linux/buffer_head.h>
#define BTRFS_SUPER_INFO_OFFSET (16 * 1024) #define BTRFS_SUPER_INFO_OFFSET (16 * 1024)
enum btrfs_bh_state_bits { struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr);
BH_Checked = BH_PrivateStart,
BH_Defrag,
BH_DefragDone,
};
BUFFER_FNS(Checked, checked);
BUFFER_FNS(Defrag, defrag);
BUFFER_FNS(DefragDone, defrag_done);
static inline struct btrfs_node *btrfs_buffer_node(struct buffer_head *bh)
{
return (struct btrfs_node *)bh->b_data;
}
static inline struct btrfs_leaf *btrfs_buffer_leaf(struct buffer_head *bh)
{
return (struct btrfs_leaf *)bh->b_data;
}
static inline struct btrfs_header *btrfs_buffer_header(struct buffer_head *bh)
{
return &((struct btrfs_node *)bh->b_data)->header;
}
struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr);
int readahead_tree_block(struct btrfs_root *root, u64 blocknr); int readahead_tree_block(struct btrfs_root *root, u64 blocknr);
struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
u64 blocknr); u64 blocknr);
int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct buffer_head *buf);
int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct buffer_head *buf);
int clean_tree_block(struct btrfs_trans_handle *trans, int clean_tree_block(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct buffer_head *buf); struct btrfs_root *root, struct extent_buffer *buf);
int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
struct btrfs_root *root);
struct btrfs_root *open_ctree(struct super_block *sb); struct btrfs_root *open_ctree(struct super_block *sb);
int close_ctree(struct btrfs_root *root); int close_ctree(struct btrfs_root *root);
void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf);
int write_ctree_super(struct btrfs_trans_handle *trans, int write_ctree_super(struct btrfs_trans_handle *trans,
struct btrfs_root *root); struct btrfs_root *root);
struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr); struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root,
int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len, u64 blocknr);
char *result);
struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
struct btrfs_key *location, struct btrfs_key *location,
const char *name, int namelen); const char *name, int namelen);
struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info, struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info,
struct btrfs_key *location); struct btrfs_key *location);
u64 bh_blocknr(struct buffer_head *bh);
int btrfs_insert_dev_radix(struct btrfs_root *root, int btrfs_insert_dev_radix(struct btrfs_root *root,
struct block_device *bdev, struct block_device *bdev,
u64 device_id, u64 device_id,
u64 block_start, u64 block_start,
u64 num_blocks); u64 num_blocks);
int btrfs_map_bh_to_logical(struct btrfs_root *root, struct buffer_head *bh,
u64 logical);
void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr); void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr);
int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root); int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root);
void btrfs_mark_buffer_dirty(struct buffer_head *bh); void btrfs_mark_buffer_dirty(struct extent_buffer *buf);
int btrfs_buffer_uptodate(struct extent_buffer *buf);
int btrfs_set_buffer_uptodate(struct extent_buffer *buf);
int wait_on_tree_block_writeback(struct btrfs_root *root,
struct extent_buffer *buf);
#endif #endif
此差异已折叠。
此差异已折叠。
...@@ -3,9 +3,20 @@ ...@@ -3,9 +3,20 @@
#include <linux/rbtree.h> #include <linux/rbtree.h>
#define EXTENT_MAP_HOLE (u64)-3
#define EXTENT_MAP_INLINE (u64)-2 #define EXTENT_MAP_INLINE (u64)-2
#define EXTENT_MAP_DELALLOC (u64)-1 #define EXTENT_MAP_DELALLOC (u64)-1
/* bits for the extent state */
#define EXTENT_DIRTY 1
#define EXTENT_WRITEBACK (1 << 1)
#define EXTENT_UPTODATE (1 << 2)
#define EXTENT_LOCKED (1 << 3)
#define EXTENT_NEW (1 << 4)
#define EXTENT_DELALLOC (1 << 5)
#define EXTENT_IOBITS (EXTENT_LOCKED | EXTENT_WRITEBACK)
struct extent_map_ops { struct extent_map_ops {
int (*fill_delalloc)(struct inode *inode, u64 start, u64 end); int (*fill_delalloc)(struct inode *inode, u64 start, u64 end);
int (*writepage_io_hook)(struct page *page, u64 start, u64 end); int (*writepage_io_hook)(struct page *page, u64 start, u64 end);
...@@ -51,10 +62,13 @@ struct extent_state { ...@@ -51,10 +62,13 @@ struct extent_state {
struct list_head list; struct list_head list;
}; };
#define EXTENT_BUFFER_SIZE(nr) (sizeof(struct extent_buffer) + \
(nr - 1) * sizeof(struct page *))
struct extent_buffer { struct extent_buffer {
u64 start; u64 start;
u64 end; /* inclusive */ unsigned long len;
char *addr; atomic_t refs;
int flags;
struct page *pages[]; struct page *pages[];
}; };
...@@ -87,8 +101,12 @@ int set_extent_new(struct extent_map_tree *tree, u64 start, u64 end, ...@@ -87,8 +101,12 @@ int set_extent_new(struct extent_map_tree *tree, u64 start, u64 end,
gfp_t mask); gfp_t mask);
int set_extent_dirty(struct extent_map_tree *tree, u64 start, u64 end, int set_extent_dirty(struct extent_map_tree *tree, u64 start, u64 end,
gfp_t mask); gfp_t mask);
int clear_extent_dirty(struct extent_map_tree *tree, u64 start, u64 end,
gfp_t mask);
int set_extent_delalloc(struct extent_map_tree *tree, u64 start, u64 end, int set_extent_delalloc(struct extent_map_tree *tree, u64 start, u64 end,
gfp_t mask); gfp_t mask);
int find_first_extent_bit(struct extent_map_tree *tree, u64 start,
u64 *start_ret, u64 *end_ret, int bits);
int extent_invalidatepage(struct extent_map_tree *tree, int extent_invalidatepage(struct extent_map_tree *tree,
struct page *page, unsigned long offset); struct page *page, unsigned long offset);
int extent_write_full_page(struct extent_map_tree *tree, struct page *page, int extent_write_full_page(struct extent_map_tree *tree, struct page *page,
...@@ -106,4 +124,57 @@ int set_range_dirty(struct extent_map_tree *tree, u64 start, u64 end); ...@@ -106,4 +124,57 @@ int set_range_dirty(struct extent_map_tree *tree, u64 start, u64 end);
int set_state_private(struct extent_map_tree *tree, u64 start, u64 private); int set_state_private(struct extent_map_tree *tree, u64 start, u64 private);
int get_state_private(struct extent_map_tree *tree, u64 start, u64 *private); int get_state_private(struct extent_map_tree *tree, u64 start, u64 *private);
void set_page_extent_mapped(struct page *page); void set_page_extent_mapped(struct page *page);
struct extent_buffer *alloc_extent_buffer(struct extent_map_tree *tree,
u64 start, unsigned long len,
gfp_t mask);
struct extent_buffer *find_extent_buffer(struct extent_map_tree *tree,
u64 start, unsigned long len,
gfp_t mask);
void free_extent_buffer(struct extent_buffer *eb);
int read_extent_buffer_pages(struct extent_map_tree *tree,
struct extent_buffer *eb, int wait);
static inline void extent_buffer_get(struct extent_buffer *eb)
{
atomic_inc(&eb->refs);
}
static inline u64 extent_buffer_blocknr(struct extent_buffer *eb)
{
return eb->start / 4096;
}
int memcmp_extent_buffer(struct extent_buffer *eb, const void *ptrv,
unsigned long start,
unsigned long len);
void read_extent_buffer(struct extent_buffer *eb, void *dst,
unsigned long start,
unsigned long len);
void write_extent_buffer(struct extent_buffer *eb, const void *src,
unsigned long start, unsigned long len);
void copy_extent_buffer(struct extent_buffer *dst, struct extent_buffer *src,
unsigned long dst_offset, unsigned long src_offset,
unsigned long len);
void memcpy_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
unsigned long src_offset, unsigned long len);
void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
unsigned long src_offset, unsigned long len);
void memset_extent_buffer(struct extent_buffer *eb, char c,
unsigned long start, unsigned long len);
int wait_on_extent_buffer_writeback(struct extent_map_tree *tree,
struct extent_buffer *eb);
int clear_extent_buffer_dirty(struct extent_map_tree *tree,
struct extent_buffer *eb);
int set_extent_buffer_dirty(struct extent_map_tree *tree,
struct extent_buffer *eb);
int set_extent_buffer_uptodate(struct extent_map_tree *tree,
struct extent_buffer *eb);
int extent_buffer_uptodate(struct extent_map_tree *tree,
struct extent_buffer *eb);
int map_extent_buffer(struct extent_buffer *eb, unsigned long offset,
char **token, char **map,
unsigned long *map_start,
unsigned long *map_len, int km);
void unmap_extent_buffer(struct extent_buffer *eb, char *token, int km);
#endif #endif
...@@ -34,12 +34,12 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, ...@@ -34,12 +34,12 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
struct btrfs_file_extent_item *item; struct btrfs_file_extent_item *item;
struct btrfs_key file_key; struct btrfs_key file_key;
struct btrfs_path *path; struct btrfs_path *path;
struct extent_buffer *leaf;
path = btrfs_alloc_path(); path = btrfs_alloc_path();
BUG_ON(!path); BUG_ON(!path);
file_key.objectid = objectid; file_key.objectid = objectid;
file_key.offset = pos; file_key.offset = pos;
file_key.flags = 0;
btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY);
ret = btrfs_insert_empty_item(trans, root, path, &file_key, ret = btrfs_insert_empty_item(trans, root, path, &file_key,
...@@ -47,15 +47,16 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, ...@@ -47,15 +47,16 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
if (ret < 0) if (ret < 0)
goto out; goto out;
BUG_ON(ret); BUG_ON(ret);
item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], leaf = path->nodes[0];
item = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_file_extent_item); struct btrfs_file_extent_item);
btrfs_set_file_extent_disk_blocknr(item, offset); btrfs_set_file_extent_disk_blocknr(leaf, item, offset);
btrfs_set_file_extent_disk_num_blocks(item, disk_num_blocks); btrfs_set_file_extent_disk_num_blocks(leaf, item, disk_num_blocks);
btrfs_set_file_extent_offset(item, 0); btrfs_set_file_extent_offset(leaf, item, 0);
btrfs_set_file_extent_num_blocks(item, num_blocks); btrfs_set_file_extent_num_blocks(leaf, item, num_blocks);
btrfs_set_file_extent_generation(item, trans->transid); btrfs_set_file_extent_generation(leaf, item, trans->transid);
btrfs_set_file_extent_type(item, BTRFS_FILE_EXTENT_REG); btrfs_set_file_extent_type(leaf, item, BTRFS_FILE_EXTENT_REG);
btrfs_mark_buffer_dirty(path->nodes[0]); btrfs_mark_buffer_dirty(leaf);
out: out:
btrfs_free_path(path); btrfs_free_path(path);
return ret; return ret;
...@@ -71,32 +72,30 @@ struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, ...@@ -71,32 +72,30 @@ struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans,
struct btrfs_key file_key; struct btrfs_key file_key;
struct btrfs_key found_key; struct btrfs_key found_key;
struct btrfs_csum_item *item; struct btrfs_csum_item *item;
struct btrfs_leaf *leaf; struct extent_buffer *leaf;
u64 csum_offset = 0; u64 csum_offset = 0;
int csums_in_item; int csums_in_item;
file_key.objectid = objectid; file_key.objectid = objectid;
file_key.offset = offset; file_key.offset = offset;
file_key.flags = 0;
btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY);
ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow); ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow);
if (ret < 0) if (ret < 0)
goto fail; goto fail;
leaf = btrfs_buffer_leaf(path->nodes[0]); leaf = path->nodes[0];
if (ret > 0) { if (ret > 0) {
ret = 1; ret = 1;
if (path->slots[0] == 0) if (path->slots[0] == 0)
goto fail; goto fail;
path->slots[0]--; path->slots[0]--;
btrfs_disk_key_to_cpu(&found_key, btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
&leaf->items[path->slots[0]].key);
if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY || if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY ||
found_key.objectid != objectid) { found_key.objectid != objectid) {
goto fail; goto fail;
} }
csum_offset = (offset - found_key.offset) >> csum_offset = (offset - found_key.offset) >>
root->fs_info->sb->s_blocksize_bits; root->fs_info->sb->s_blocksize_bits;
csums_in_item = btrfs_item_size(leaf->items + path->slots[0]); csums_in_item = btrfs_item_size_nr(leaf, path->slots[0]);
csums_in_item /= BTRFS_CRC32_SIZE; csums_in_item /= BTRFS_CRC32_SIZE;
if (csum_offset >= csums_in_item) { if (csum_offset >= csums_in_item) {
...@@ -127,7 +126,6 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, ...@@ -127,7 +126,6 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,
file_key.objectid = objectid; file_key.objectid = objectid;
file_key.offset = offset; file_key.offset = offset;
file_key.flags = 0;
btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY); btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY);
ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow); ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow);
return ret; return ret;
...@@ -138,12 +136,14 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, ...@@ -138,12 +136,14 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
u64 objectid, u64 offset, u64 objectid, u64 offset,
char *data, size_t len) char *data, size_t len)
{ {
return 0;
#if 0
int ret; int ret;
struct btrfs_key file_key; struct btrfs_key file_key;
struct btrfs_key found_key; struct btrfs_key found_key;
struct btrfs_path *path; struct btrfs_path *path;
struct btrfs_csum_item *item; struct btrfs_csum_item *item;
struct btrfs_leaf *leaf; struct extent_buffer *leaf;
u64 csum_offset; u64 csum_offset;
path = btrfs_alloc_path(); path = btrfs_alloc_path();
...@@ -161,8 +161,8 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, ...@@ -161,8 +161,8 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
if (ret == -EFBIG) { if (ret == -EFBIG) {
u32 item_size; u32 item_size;
/* we found one, but it isn't big enough yet */ /* we found one, but it isn't big enough yet */
leaf = btrfs_buffer_leaf(path->nodes[0]); leaf = path->nodes[0];
item_size = btrfs_item_size(leaf->items + path->slots[0]); item_size = btrfs_item_size_nr(leaf, path->slots[0]);
if ((item_size / BTRFS_CRC32_SIZE) >= MAX_CSUM_ITEMS(root)) { if ((item_size / BTRFS_CRC32_SIZE) >= MAX_CSUM_ITEMS(root)) {
/* already at max size, make a new one */ /* already at max size, make a new one */
goto insert; goto insert;
...@@ -188,8 +188,8 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, ...@@ -188,8 +188,8 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
goto insert; goto insert;
} }
path->slots[0]--; path->slots[0]--;
leaf = btrfs_buffer_leaf(path->nodes[0]); leaf = path->nodes[0];
btrfs_disk_key_to_cpu(&found_key, &leaf->items[path->slots[0]].key); btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
csum_offset = (offset - found_key.offset) >> csum_offset = (offset - found_key.offset) >>
root->fs_info->sb->s_blocksize_bits; root->fs_info->sb->s_blocksize_bits;
if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY || if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY ||
...@@ -197,10 +197,10 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, ...@@ -197,10 +197,10 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
csum_offset >= MAX_CSUM_ITEMS(root)) { csum_offset >= MAX_CSUM_ITEMS(root)) {
goto insert; goto insert;
} }
if (csum_offset >= btrfs_item_size(leaf->items + path->slots[0]) / if (csum_offset >= btrfs_item_size_nr(leaf, path->slots[0]) /
BTRFS_CRC32_SIZE) { BTRFS_CRC32_SIZE) {
u32 diff = (csum_offset + 1) * BTRFS_CRC32_SIZE; u32 diff = (csum_offset + 1) * BTRFS_CRC32_SIZE;
diff = diff - btrfs_item_size(leaf->items + path->slots[0]); diff = diff - btrfs_item_size_nr(leaf, path->slots[0]);
if (diff != BTRFS_CRC32_SIZE) if (diff != BTRFS_CRC32_SIZE)
goto insert; goto insert;
ret = btrfs_extend_item(trans, root, path, diff); ret = btrfs_extend_item(trans, root, path, diff);
...@@ -220,21 +220,20 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, ...@@ -220,21 +220,20 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
goto fail; goto fail;
} }
csum: csum:
item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], leaf = path->nodes[0];
struct btrfs_csum_item); item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
ret = 0; ret = 0;
item = (struct btrfs_csum_item *)((unsigned char *)item + item = (struct btrfs_csum_item *)((unsigned char *)item +
csum_offset * BTRFS_CRC32_SIZE); csum_offset * BTRFS_CRC32_SIZE);
found: found:
btrfs_check_bounds(&item->csum, BTRFS_CRC32_SIZE, /* FIXME!!!!!!!!!!!! */
path->nodes[0]->b_data,
root->fs_info->sb->s_blocksize);
ret = btrfs_csum_data(root, data, len, &item->csum); ret = btrfs_csum_data(root, data, len, &item->csum);
btrfs_mark_buffer_dirty(path->nodes[0]); btrfs_mark_buffer_dirty(path->nodes[0]);
fail: fail:
btrfs_release_path(root, path); btrfs_release_path(root, path);
btrfs_free_path(path); btrfs_free_path(path);
return ret; return ret;
#endif
} }
int btrfs_csum_truncate(struct btrfs_trans_handle *trans, int btrfs_csum_truncate(struct btrfs_trans_handle *trans,
...@@ -242,21 +241,21 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans, ...@@ -242,21 +241,21 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans,
u64 isize) u64 isize)
{ {
struct btrfs_key key; struct btrfs_key key;
struct btrfs_leaf *leaf = btrfs_buffer_leaf(path->nodes[0]); struct extent_buffer *leaf = path->nodes[0];
int slot = path->slots[0]; int slot = path->slots[0];
int ret; int ret;
u32 new_item_size; u32 new_item_size;
u64 new_item_span; u64 new_item_span;
u64 blocks; u64 blocks;
btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); btrfs_item_key_to_cpu(leaf, &key, slot);
if (isize <= key.offset) if (isize <= key.offset)
return 0; return 0;
new_item_span = isize - key.offset; new_item_span = isize - key.offset;
blocks = (new_item_span + root->blocksize - 1) >> blocks = (new_item_span + root->sectorsize - 1) >>
root->fs_info->sb->s_blocksize_bits; root->fs_info->sb->s_blocksize_bits;
new_item_size = blocks * BTRFS_CRC32_SIZE; new_item_size = blocks * BTRFS_CRC32_SIZE;
if (new_item_size >= btrfs_item_size(leaf->items + slot)) if (new_item_size >= btrfs_item_size_nr(leaf, slot))
return 0; return 0;
ret = btrfs_truncate_item(trans, root, path, new_item_size); ret = btrfs_truncate_item(trans, root, path, new_item_size);
BUG_ON(ret); BUG_ON(ret);
......
此差异已折叠。
...@@ -20,24 +20,18 @@ ...@@ -20,24 +20,18 @@
#include "disk-io.h" #include "disk-io.h"
#include "transaction.h" #include "transaction.h"
int btrfs_insert_inode(struct btrfs_trans_handle *trans, struct btrfs_root int btrfs_insert_empty_inode(struct btrfs_trans_handle *trans,
*root, u64 objectid, struct btrfs_inode_item struct btrfs_root *root,
*inode_item) struct btrfs_path *path, u64 objectid)
{ {
struct btrfs_path *path;
struct btrfs_key key; struct btrfs_key key;
int ret; int ret;
key.objectid = objectid; key.objectid = objectid;
key.flags = 0;
btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY);
key.offset = 0; key.offset = 0;
path = btrfs_alloc_path(); ret = btrfs_insert_empty_item(trans, root, path, &key,
BUG_ON(!path); sizeof(struct btrfs_inode_item));
ret = btrfs_insert_item(trans, root, &key, inode_item,
sizeof(*inode_item));
btrfs_release_path(root, path);
btrfs_free_path(path);
if (ret == 0 && objectid > root->highest_inode) if (ret == 0 && objectid > root->highest_inode)
root->highest_inode = objectid; root->highest_inode = objectid;
return ret; return ret;
...@@ -51,15 +45,15 @@ int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -51,15 +45,15 @@ int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root
int cow = mod != 0; int cow = mod != 0;
int ret; int ret;
int slot; int slot;
struct btrfs_leaf *leaf; struct extent_buffer *leaf;
struct btrfs_key found_key; struct btrfs_key found_key;
ret = btrfs_search_slot(trans, root, location, path, ins_len, cow); ret = btrfs_search_slot(trans, root, location, path, ins_len, cow);
if (ret > 0 && btrfs_key_type(location) == BTRFS_ROOT_ITEM_KEY && if (ret > 0 && btrfs_key_type(location) == BTRFS_ROOT_ITEM_KEY &&
location->offset == (u64)-1 && path->slots[0] != 0) { location->offset == (u64)-1 && path->slots[0] != 0) {
slot = path->slots[0] - 1; slot = path->slots[0] - 1;
leaf = btrfs_buffer_leaf(path->nodes[0]); leaf = path->nodes[0];
btrfs_disk_key_to_cpu(&found_key, &leaf->items[slot].key); btrfs_item_key_to_cpu(leaf, &found_key, slot);
if (found_key.objectid == location->objectid && if (found_key.objectid == location->objectid &&
btrfs_key_type(&found_key) == btrfs_key_type(location)) { btrfs_key_type(&found_key) == btrfs_key_type(location)) {
path->slots[0]--; path->slots[0]--;
......
...@@ -24,8 +24,9 @@ int btrfs_find_highest_inode(struct btrfs_root *root, u64 *objectid) ...@@ -24,8 +24,9 @@ int btrfs_find_highest_inode(struct btrfs_root *root, u64 *objectid)
{ {
struct btrfs_path *path; struct btrfs_path *path;
int ret; int ret;
struct btrfs_leaf *l; struct extent_buffer *l;
struct btrfs_key search_key; struct btrfs_key search_key;
struct btrfs_key found_key;
int slot; int slot;
path = btrfs_alloc_path(); path = btrfs_alloc_path();
...@@ -39,8 +40,9 @@ int btrfs_find_highest_inode(struct btrfs_root *root, u64 *objectid) ...@@ -39,8 +40,9 @@ int btrfs_find_highest_inode(struct btrfs_root *root, u64 *objectid)
BUG_ON(ret == 0); BUG_ON(ret == 0);
if (path->slots[0] > 0) { if (path->slots[0] > 0) {
slot = path->slots[0] - 1; slot = path->slots[0] - 1;
l = btrfs_buffer_leaf(path->nodes[0]); l = path->nodes[0];
*objectid = btrfs_disk_key_objectid(&l->items[slot].key); btrfs_item_key_to_cpu(l, &found_key, slot);
*objectid = found_key.objectid;
} else { } else {
*objectid = BTRFS_FIRST_FREE_OBJECTID; *objectid = BTRFS_FIRST_FREE_OBJECTID;
} }
...@@ -64,13 +66,12 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, ...@@ -64,13 +66,12 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
int slot = 0; int slot = 0;
u64 last_ino = 0; u64 last_ino = 0;
int start_found; int start_found;
struct btrfs_leaf *l; struct extent_buffer *l;
struct btrfs_key search_key; struct btrfs_key search_key;
u64 search_start = dirid; u64 search_start = dirid;
path = btrfs_alloc_path(); path = btrfs_alloc_path();
BUG_ON(!path); BUG_ON(!path);
search_key.flags = 0;
search_start = root->last_inode_alloc; search_start = root->last_inode_alloc;
search_start = max(search_start, BTRFS_FIRST_FREE_OBJECTID); search_start = max(search_start, BTRFS_FIRST_FREE_OBJECTID);
search_key.objectid = search_start; search_key.objectid = search_start;
...@@ -86,9 +87,9 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, ...@@ -86,9 +87,9 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
path->slots[0]--; path->slots[0]--;
while (1) { while (1) {
l = btrfs_buffer_leaf(path->nodes[0]); l = path->nodes[0];
slot = path->slots[0]; slot = path->slots[0];
if (slot >= btrfs_header_nritems(&l->header)) { if (slot >= btrfs_header_nritems(l)) {
ret = btrfs_next_leaf(root, path); ret = btrfs_next_leaf(root, path);
if (ret == 0) if (ret == 0)
continue; continue;
...@@ -103,7 +104,7 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, ...@@ -103,7 +104,7 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
last_ino : search_start; last_ino : search_start;
goto found; goto found;
} }
btrfs_disk_key_to_cpu(&key, &l->items[slot].key); btrfs_item_key_to_cpu(l, &key, slot);
if (key.objectid >= search_start) { if (key.objectid >= search_start) {
if (start_found) { if (start_found) {
if (last_ino < search_start) if (last_ino < search_start)
......
此差异已折叠。
此差异已折叠。
...@@ -18,6 +18,6 @@ ...@@ -18,6 +18,6 @@
#ifndef __PRINT_TREE_ #ifndef __PRINT_TREE_
#define __PRINT_TREE_ #define __PRINT_TREE_
void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l); void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l);
void btrfs_print_tree(struct btrfs_root *root, struct buffer_head *t); void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *t);
#endif #endif
此差异已折叠。
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
#include "ioctl.h" #include "ioctl.h"
#include "print-tree.h" #include "print-tree.h"
#define BTRFS_SUPER_MAGIC 0x9123682E #define BTRFS_SUPER_MAGIC 0x9123683E
static struct super_operations btrfs_super_ops; static struct super_operations btrfs_super_ops;
...@@ -115,13 +115,12 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent) ...@@ -115,13 +115,12 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent)
return -EIO; return -EIO;
} }
sb->s_fs_info = tree_root; sb->s_fs_info = tree_root;
disk_super = tree_root->fs_info->disk_super; disk_super = &tree_root->fs_info->super_copy;
inode = btrfs_iget_locked(sb, btrfs_super_root_dir(disk_super), inode = btrfs_iget_locked(sb, btrfs_super_root_dir(disk_super),
tree_root); tree_root);
bi = BTRFS_I(inode); bi = BTRFS_I(inode);
bi->location.objectid = inode->i_ino; bi->location.objectid = inode->i_ino;
bi->location.offset = 0; bi->location.offset = 0;
bi->location.flags = 0;
bi->root = tree_root; bi->root = tree_root;
btrfs_set_key_type(&bi->location, BTRFS_INODE_ITEM_KEY); btrfs_set_key_type(&bi->location, BTRFS_INODE_ITEM_KEY);
...@@ -281,6 +280,7 @@ int btrfs_get_sb_bdev(struct file_system_type *fs_type, ...@@ -281,6 +280,7 @@ int btrfs_get_sb_bdev(struct file_system_type *fs_type,
error_bdev: error_bdev:
close_bdev_excl(bdev); close_bdev_excl(bdev);
error: error:
printk("get_sb failed\n");
return error; return error;
} }
/* end copy & paste */ /* end copy & paste */
...@@ -295,6 +295,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type, ...@@ -295,6 +295,7 @@ static int btrfs_get_sb(struct file_system_type *fs_type,
ret = btrfs_get_sb_bdev(fs_type, flags, dev_name, data, ret = btrfs_get_sb_bdev(fs_type, flags, dev_name, data,
btrfs_fill_super, mnt, btrfs_fill_super, mnt,
subvol_name ? subvol_name : "default"); subvol_name ? subvol_name : "default");
printk("btrfs_get_sb returns %d\n", ret);
return ret; return ret;
} }
......
...@@ -31,31 +31,31 @@ ...@@ -31,31 +31,31 @@
static ssize_t root_blocks_used_show(struct btrfs_root *root, char *buf) static ssize_t root_blocks_used_show(struct btrfs_root *root, char *buf)
{ {
return snprintf(buf, PAGE_SIZE, "%llu\n", return snprintf(buf, PAGE_SIZE, "%llu\n",
(unsigned long long)btrfs_root_blocks_used(&root->root_item)); (unsigned long long)btrfs_root_used(&root->root_item));
} }
static ssize_t root_block_limit_show(struct btrfs_root *root, char *buf) static ssize_t root_block_limit_show(struct btrfs_root *root, char *buf)
{ {
return snprintf(buf, PAGE_SIZE, "%llu\n", return snprintf(buf, PAGE_SIZE, "%llu\n",
(unsigned long long)btrfs_root_block_limit(&root->root_item)); (unsigned long long)btrfs_root_limit(&root->root_item));
} }
static ssize_t super_blocks_used_show(struct btrfs_fs_info *fs, char *buf) static ssize_t super_blocks_used_show(struct btrfs_fs_info *fs, char *buf)
{ {
return snprintf(buf, PAGE_SIZE, "%llu\n", return snprintf(buf, PAGE_SIZE, "%llu\n",
(unsigned long long)btrfs_super_blocks_used(fs->disk_super)); (unsigned long long)btrfs_super_blocks_used(&fs->super_copy));
} }
static ssize_t super_total_blocks_show(struct btrfs_fs_info *fs, char *buf) static ssize_t super_total_blocks_show(struct btrfs_fs_info *fs, char *buf)
{ {
return snprintf(buf, PAGE_SIZE, "%llu\n", return snprintf(buf, PAGE_SIZE, "%llu\n",
(unsigned long long)btrfs_super_total_blocks(fs->disk_super)); (unsigned long long)btrfs_super_total_blocks(&fs->super_copy));
} }
static ssize_t super_blocksize_show(struct btrfs_fs_info *fs, char *buf) static ssize_t super_blocksize_show(struct btrfs_fs_info *fs, char *buf)
{ {
return snprintf(buf, PAGE_SIZE, "%llu\n", return snprintf(buf, PAGE_SIZE, "%llu\n",
(unsigned long long)btrfs_super_blocksize(fs->disk_super)); (unsigned long long)btrfs_super_sectorsize(&fs->super_copy));
} }
/* this is for root attrs (subvols/snapshots) */ /* this is for root attrs (subvols/snapshots) */
......
此差异已折叠。
...@@ -28,7 +28,7 @@ struct btrfs_transaction { ...@@ -28,7 +28,7 @@ struct btrfs_transaction {
int use_count; int use_count;
int commit_done; int commit_done;
struct list_head list; struct list_head list;
struct radix_tree_root dirty_pages; struct extent_map_tree dirty_pages;
unsigned long start_time; unsigned long start_time;
wait_queue_head_t writer_wait; wait_queue_head_t writer_wait;
wait_queue_head_t commit_wait; wait_queue_head_t commit_wait;
...@@ -83,5 +83,6 @@ int btrfs_add_dead_root(struct btrfs_root *root, struct btrfs_root *latest, ...@@ -83,5 +83,6 @@ int btrfs_add_dead_root(struct btrfs_root *root, struct btrfs_root *latest,
int btrfs_defrag_dirty_roots(struct btrfs_fs_info *info); int btrfs_defrag_dirty_roots(struct btrfs_fs_info *info);
int btrfs_defrag_root(struct btrfs_root *root, int cacheonly); int btrfs_defrag_root(struct btrfs_root *root, int cacheonly);
int btrfs_clean_old_snapshots(struct btrfs_root *root); int btrfs_clean_old_snapshots(struct btrfs_root *root);
int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
struct btrfs_root *root);
#endif #endif
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册