mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Btrfs: Create extent_buffer interface for large blocksizes
Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
@@ -23,4 +23,6 @@ modules_install:
|
||||
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
|
||||
|
||||
+825
-675
File diff suppressed because it is too large
Load Diff
+326
-545
File diff suppressed because it is too large
Load Diff
+56
-46
@@ -33,7 +33,7 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle
|
||||
int ret;
|
||||
char *ptr;
|
||||
struct btrfs_item *item;
|
||||
struct btrfs_leaf *leaf;
|
||||
struct extent_buffer *leaf;
|
||||
|
||||
ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
|
||||
if (ret == -EEXIST) {
|
||||
@@ -49,11 +49,11 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle
|
||||
if (ret < 0)
|
||||
return ERR_PTR(ret);
|
||||
WARN_ON(ret > 0);
|
||||
leaf = btrfs_buffer_leaf(path->nodes[0]);
|
||||
item = leaf->items + path->slots[0];
|
||||
leaf = path->nodes[0];
|
||||
item = btrfs_item_nr(leaf, path->slots[0]);
|
||||
ptr = btrfs_item_ptr(leaf, path->slots[0], char);
|
||||
BUG_ON(data_size > btrfs_item_size(item));
|
||||
ptr += btrfs_item_size(item) - data_size;
|
||||
BUG_ON(data_size > btrfs_item_size(leaf, item));
|
||||
ptr += btrfs_item_size(leaf, item) - data_size;
|
||||
return (struct btrfs_dir_item *)ptr;
|
||||
}
|
||||
|
||||
@@ -65,12 +65,13 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||
int ret2 = 0;
|
||||
struct btrfs_path *path;
|
||||
struct btrfs_dir_item *dir_item;
|
||||
char *name_ptr;
|
||||
struct extent_buffer *leaf;
|
||||
unsigned long name_ptr;
|
||||
struct btrfs_key key;
|
||||
struct btrfs_disk_key disk_key;
|
||||
u32 data_size;
|
||||
|
||||
key.objectid = dir;
|
||||
key.flags = 0;
|
||||
btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
|
||||
ret = btrfs_name_hash(name, name_len, &key.offset);
|
||||
BUG_ON(ret);
|
||||
@@ -85,14 +86,16 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||
goto out;
|
||||
}
|
||||
|
||||
btrfs_cpu_key_to_disk(&dir_item->location, location);
|
||||
btrfs_set_dir_type(dir_item, type);
|
||||
btrfs_set_dir_flags(dir_item, 0);
|
||||
btrfs_set_dir_name_len(dir_item, name_len);
|
||||
name_ptr = (char *)(dir_item + 1);
|
||||
leaf = path->nodes[0];
|
||||
btrfs_cpu_key_to_disk(&disk_key, location);
|
||||
btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
|
||||
btrfs_set_dir_type(leaf, dir_item, type);
|
||||
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);
|
||||
btrfs_mark_buffer_dirty(path->nodes[0]);
|
||||
write_extent_buffer(leaf, name, name_ptr, name_len);
|
||||
btrfs_mark_buffer_dirty(leaf);
|
||||
|
||||
second_insert:
|
||||
/* FIXME, use some real flag for selecting the extra index */
|
||||
@@ -110,13 +113,15 @@ second_insert:
|
||||
ret2 = PTR_ERR(dir_item);
|
||||
goto out;
|
||||
}
|
||||
btrfs_cpu_key_to_disk(&dir_item->location, location);
|
||||
btrfs_set_dir_type(dir_item, type);
|
||||
btrfs_set_dir_flags(dir_item, 0);
|
||||
btrfs_set_dir_name_len(dir_item, name_len);
|
||||
name_ptr = (char *)(dir_item + 1);
|
||||
btrfs_memcpy(root, path->nodes[0]->b_data, name_ptr, name, name_len);
|
||||
btrfs_mark_buffer_dirty(path->nodes[0]);
|
||||
leaf = path->nodes[0];
|
||||
btrfs_cpu_key_to_disk(&disk_key, location);
|
||||
btrfs_set_dir_item_key(leaf, dir_item, &disk_key);
|
||||
btrfs_set_dir_type(leaf, dir_item, type);
|
||||
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);
|
||||
write_extent_buffer(leaf, name, name_ptr, name_len);
|
||||
btrfs_mark_buffer_dirty(leaf);
|
||||
out:
|
||||
btrfs_free_path(path);
|
||||
if (ret)
|
||||
@@ -136,14 +141,15 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_key key;
|
||||
int ins_len = mod < 0 ? -1 : 0;
|
||||
int cow = mod != 0;
|
||||
struct btrfs_disk_key *found_key;
|
||||
struct btrfs_leaf *leaf;
|
||||
struct btrfs_key found_key;
|
||||
struct extent_buffer *leaf;
|
||||
|
||||
key.objectid = dir;
|
||||
key.flags = 0;
|
||||
btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
|
||||
|
||||
ret = btrfs_name_hash(name, name_len, &key.offset);
|
||||
BUG_ON(ret);
|
||||
|
||||
ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
|
||||
if (ret < 0)
|
||||
return ERR_PTR(ret);
|
||||
@@ -152,12 +158,13 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
|
||||
return NULL;
|
||||
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 ||
|
||||
btrfs_disk_key_type(found_key) != BTRFS_DIR_ITEM_KEY ||
|
||||
btrfs_disk_key_offset(found_key) != key.offset)
|
||||
leaf = path->nodes[0];
|
||||
btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
|
||||
|
||||
if (found_key.objectid != dir ||
|
||||
btrfs_key_type(&found_key) != BTRFS_DIR_ITEM_KEY ||
|
||||
found_key.offset != key.offset)
|
||||
return NULL;
|
||||
|
||||
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,
|
||||
int cow = mod != 0;
|
||||
|
||||
key.objectid = dir;
|
||||
key.flags = 0;
|
||||
btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY);
|
||||
key.offset = objectid;
|
||||
|
||||
@@ -193,21 +199,22 @@ struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root,
|
||||
const char *name, int name_len)
|
||||
{
|
||||
struct btrfs_dir_item *dir_item;
|
||||
char *name_ptr;
|
||||
unsigned long name_ptr;
|
||||
u32 total_len;
|
||||
u32 cur = 0;
|
||||
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);
|
||||
total_len = btrfs_item_size(leaf->items + path->slots[0]);
|
||||
total_len = btrfs_item_size_nr(leaf, path->slots[0]);
|
||||
while(cur < total_len) {
|
||||
this_len = sizeof(*dir_item) + btrfs_dir_name_len(dir_item);
|
||||
name_ptr = (char *)(dir_item + 1);
|
||||
this_len = sizeof(*dir_item) +
|
||||
btrfs_dir_name_len(leaf, dir_item);
|
||||
name_ptr = (unsigned long)(dir_item + 1);
|
||||
|
||||
if (btrfs_dir_name_len(dir_item) == name_len &&
|
||||
memcmp(name_ptr, name, name_len) == 0)
|
||||
if (btrfs_dir_name_len(leaf, dir_item) == name_len &&
|
||||
memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0)
|
||||
return dir_item;
|
||||
|
||||
cur += this_len;
|
||||
@@ -223,20 +230,23 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_dir_item *di)
|
||||
{
|
||||
|
||||
struct btrfs_leaf *leaf;
|
||||
struct extent_buffer *leaf;
|
||||
u32 sub_item_len;
|
||||
u32 item_len;
|
||||
int ret = 0;
|
||||
|
||||
leaf = btrfs_buffer_leaf(path->nodes[0]);
|
||||
sub_item_len = sizeof(*di) + btrfs_dir_name_len(di);
|
||||
item_len = btrfs_item_size(leaf->items + path->slots[0]);
|
||||
if (sub_item_len == btrfs_item_size(leaf->items + path->slots[0])) {
|
||||
leaf = path->nodes[0];
|
||||
sub_item_len = sizeof(*di) + btrfs_dir_name_len(leaf, di);
|
||||
item_len = btrfs_item_size_nr(leaf, path->slots[0]);
|
||||
if (sub_item_len == item_len) {
|
||||
ret = btrfs_del_item(trans, root, path);
|
||||
} else {
|
||||
char *ptr = (char *)di;
|
||||
char *start = btrfs_item_ptr(leaf, path->slots[0], char);
|
||||
btrfs_memmove(root, leaf, ptr, ptr + sub_item_len,
|
||||
/* MARKER */
|
||||
unsigned long ptr = (unsigned long)di;
|
||||
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));
|
||||
ret = btrfs_truncate_item(trans, root, path,
|
||||
item_len - sub_item_len);
|
||||
|
||||
+182
-213
File diff suppressed because it is too large
Load Diff
+11
-44
@@ -19,68 +19,35 @@
|
||||
#ifndef __DISKIO__
|
||||
#define __DISKIO__
|
||||
|
||||
#include <linux/buffer_head.h>
|
||||
|
||||
#define BTRFS_SUPER_INFO_OFFSET (16 * 1024)
|
||||
|
||||
enum btrfs_bh_state_bits {
|
||||
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);
|
||||
struct extent_buffer *read_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,
|
||||
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);
|
||||
struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
|
||||
u64 blocknr);
|
||||
int clean_tree_block(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root, struct buffer_head *buf);
|
||||
int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root);
|
||||
struct btrfs_root *root, struct extent_buffer *buf);
|
||||
struct btrfs_root *open_ctree(struct super_block *sb);
|
||||
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,
|
||||
struct btrfs_root *root);
|
||||
struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr);
|
||||
int btrfs_csum_data(struct btrfs_root * root, char *data, size_t len,
|
||||
char *result);
|
||||
struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root,
|
||||
u64 blocknr);
|
||||
struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_key *location,
|
||||
const char *name, int namelen);
|
||||
struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_key *location);
|
||||
u64 bh_blocknr(struct buffer_head *bh);
|
||||
int btrfs_insert_dev_radix(struct btrfs_root *root,
|
||||
struct block_device *bdev,
|
||||
u64 device_id,
|
||||
u64 block_start,
|
||||
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);
|
||||
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
|
||||
|
||||
+150
-144
File diff suppressed because it is too large
Load Diff
+656
-16
File diff suppressed because it is too large
Load Diff
+73
-2
@@ -3,9 +3,20 @@
|
||||
|
||||
#include <linux/rbtree.h>
|
||||
|
||||
#define EXTENT_MAP_HOLE (u64)-3
|
||||
#define EXTENT_MAP_INLINE (u64)-2
|
||||
#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 {
|
||||
int (*fill_delalloc)(struct inode *inode, u64 start, u64 end);
|
||||
int (*writepage_io_hook)(struct page *page, u64 start, u64 end);
|
||||
@@ -51,10 +62,13 @@ struct extent_state {
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
#define EXTENT_BUFFER_SIZE(nr) (sizeof(struct extent_buffer) + \
|
||||
(nr - 1) * sizeof(struct page *))
|
||||
struct extent_buffer {
|
||||
u64 start;
|
||||
u64 end; /* inclusive */
|
||||
char *addr;
|
||||
unsigned long len;
|
||||
atomic_t refs;
|
||||
int flags;
|
||||
struct page *pages[];
|
||||
};
|
||||
|
||||
@@ -87,8 +101,12 @@ int set_extent_new(struct extent_map_tree *tree, u64 start, u64 end,
|
||||
gfp_t mask);
|
||||
int set_extent_dirty(struct extent_map_tree *tree, u64 start, u64 end,
|
||||
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,
|
||||
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,
|
||||
struct page *page, unsigned long offset);
|
||||
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);
|
||||
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);
|
||||
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
|
||||
|
||||
+31
-32
@@ -34,12 +34,12 @@ int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_file_extent_item *item;
|
||||
struct btrfs_key file_key;
|
||||
struct btrfs_path *path;
|
||||
struct extent_buffer *leaf;
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
BUG_ON(!path);
|
||||
file_key.objectid = objectid;
|
||||
file_key.offset = pos;
|
||||
file_key.flags = 0;
|
||||
btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_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,
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
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);
|
||||
btrfs_set_file_extent_disk_blocknr(item, offset);
|
||||
btrfs_set_file_extent_disk_num_blocks(item, disk_num_blocks);
|
||||
btrfs_set_file_extent_offset(item, 0);
|
||||
btrfs_set_file_extent_num_blocks(item, num_blocks);
|
||||
btrfs_set_file_extent_generation(item, trans->transid);
|
||||
btrfs_set_file_extent_type(item, BTRFS_FILE_EXTENT_REG);
|
||||
btrfs_mark_buffer_dirty(path->nodes[0]);
|
||||
btrfs_set_file_extent_disk_blocknr(leaf, item, offset);
|
||||
btrfs_set_file_extent_disk_num_blocks(leaf, item, disk_num_blocks);
|
||||
btrfs_set_file_extent_offset(leaf, item, 0);
|
||||
btrfs_set_file_extent_num_blocks(leaf, item, num_blocks);
|
||||
btrfs_set_file_extent_generation(leaf, item, trans->transid);
|
||||
btrfs_set_file_extent_type(leaf, item, BTRFS_FILE_EXTENT_REG);
|
||||
btrfs_mark_buffer_dirty(leaf);
|
||||
out:
|
||||
btrfs_free_path(path);
|
||||
return ret;
|
||||
@@ -71,32 +72,30 @@ struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_key file_key;
|
||||
struct btrfs_key found_key;
|
||||
struct btrfs_csum_item *item;
|
||||
struct btrfs_leaf *leaf;
|
||||
struct extent_buffer *leaf;
|
||||
u64 csum_offset = 0;
|
||||
int csums_in_item;
|
||||
|
||||
file_key.objectid = objectid;
|
||||
file_key.offset = offset;
|
||||
file_key.flags = 0;
|
||||
btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY);
|
||||
ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow);
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
leaf = btrfs_buffer_leaf(path->nodes[0]);
|
||||
leaf = path->nodes[0];
|
||||
if (ret > 0) {
|
||||
ret = 1;
|
||||
if (path->slots[0] == 0)
|
||||
goto fail;
|
||||
path->slots[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]);
|
||||
if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY ||
|
||||
found_key.objectid != objectid) {
|
||||
goto fail;
|
||||
}
|
||||
csum_offset = (offset - found_key.offset) >>
|
||||
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;
|
||||
|
||||
if (csum_offset >= csums_in_item) {
|
||||
@@ -127,7 +126,6 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans,
|
||||
|
||||
file_key.objectid = objectid;
|
||||
file_key.offset = offset;
|
||||
file_key.flags = 0;
|
||||
btrfs_set_key_type(&file_key, BTRFS_EXTENT_DATA_KEY);
|
||||
ret = btrfs_search_slot(trans, root, &file_key, path, ins_len, cow);
|
||||
return ret;
|
||||
@@ -138,12 +136,14 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
|
||||
u64 objectid, u64 offset,
|
||||
char *data, size_t len)
|
||||
{
|
||||
return 0;
|
||||
#if 0
|
||||
int ret;
|
||||
struct btrfs_key file_key;
|
||||
struct btrfs_key found_key;
|
||||
struct btrfs_path *path;
|
||||
struct btrfs_csum_item *item;
|
||||
struct btrfs_leaf *leaf;
|
||||
struct extent_buffer *leaf;
|
||||
u64 csum_offset;
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
@@ -161,8 +161,8 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
|
||||
if (ret == -EFBIG) {
|
||||
u32 item_size;
|
||||
/* we found one, but it isn't big enough yet */
|
||||
leaf = btrfs_buffer_leaf(path->nodes[0]);
|
||||
item_size = btrfs_item_size(leaf->items + path->slots[0]);
|
||||
leaf = path->nodes[0];
|
||||
item_size = btrfs_item_size_nr(leaf, path->slots[0]);
|
||||
if ((item_size / BTRFS_CRC32_SIZE) >= MAX_CSUM_ITEMS(root)) {
|
||||
/* already at max size, make a new one */
|
||||
goto insert;
|
||||
@@ -188,8 +188,8 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
|
||||
goto insert;
|
||||
}
|
||||
path->slots[0]--;
|
||||
leaf = btrfs_buffer_leaf(path->nodes[0]);
|
||||
btrfs_disk_key_to_cpu(&found_key, &leaf->items[path->slots[0]].key);
|
||||
leaf = path->nodes[0];
|
||||
btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
|
||||
csum_offset = (offset - found_key.offset) >>
|
||||
root->fs_info->sb->s_blocksize_bits;
|
||||
if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY ||
|
||||
@@ -197,10 +197,10 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
|
||||
csum_offset >= MAX_CSUM_ITEMS(root)) {
|
||||
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) {
|
||||
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)
|
||||
goto insert;
|
||||
ret = btrfs_extend_item(trans, root, path, diff);
|
||||
@@ -220,21 +220,20 @@ insert:
|
||||
goto fail;
|
||||
}
|
||||
csum:
|
||||
item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0],
|
||||
struct btrfs_csum_item);
|
||||
leaf = path->nodes[0];
|
||||
item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
|
||||
ret = 0;
|
||||
item = (struct btrfs_csum_item *)((unsigned char *)item +
|
||||
csum_offset * BTRFS_CRC32_SIZE);
|
||||
found:
|
||||
btrfs_check_bounds(&item->csum, BTRFS_CRC32_SIZE,
|
||||
path->nodes[0]->b_data,
|
||||
root->fs_info->sb->s_blocksize);
|
||||
/* FIXME!!!!!!!!!!!! */
|
||||
ret = btrfs_csum_data(root, data, len, &item->csum);
|
||||
btrfs_mark_buffer_dirty(path->nodes[0]);
|
||||
fail:
|
||||
btrfs_release_path(root, path);
|
||||
btrfs_free_path(path);
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
int btrfs_csum_truncate(struct btrfs_trans_handle *trans,
|
||||
@@ -242,21 +241,21 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans,
|
||||
u64 isize)
|
||||
{
|
||||
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 ret;
|
||||
u32 new_item_size;
|
||||
u64 new_item_span;
|
||||
u64 blocks;
|
||||
|
||||
btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key);
|
||||
btrfs_item_key_to_cpu(leaf, &key, slot);
|
||||
if (isize <= key.offset)
|
||||
return 0;
|
||||
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;
|
||||
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;
|
||||
ret = btrfs_truncate_item(trans, root, path, new_item_size);
|
||||
BUG_ON(ret);
|
||||
|
||||
+66
-61
@@ -16,7 +16,6 @@
|
||||
* Boston, MA 021110-1307, USA.
|
||||
*/
|
||||
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/highmem.h>
|
||||
@@ -88,7 +87,9 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
|
||||
{
|
||||
struct btrfs_key key;
|
||||
struct btrfs_path *path;
|
||||
char *ptr, *kaddr;
|
||||
struct extent_buffer *leaf;
|
||||
char *kaddr;
|
||||
unsigned long ptr;
|
||||
struct btrfs_file_extent_item *ei;
|
||||
u32 datasize;
|
||||
int err = 0;
|
||||
@@ -102,7 +103,6 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
|
||||
|
||||
key.objectid = inode->i_ino;
|
||||
key.offset = offset;
|
||||
key.flags = 0;
|
||||
btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY);
|
||||
BUG_ON(size >= PAGE_CACHE_SIZE);
|
||||
datasize = btrfs_file_extent_calc_inline_size(size);
|
||||
@@ -113,18 +113,17 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
|
||||
err = ret;
|
||||
goto fail;
|
||||
}
|
||||
ei = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]),
|
||||
path->slots[0], struct btrfs_file_extent_item);
|
||||
btrfs_set_file_extent_generation(ei, trans->transid);
|
||||
btrfs_set_file_extent_type(ei,
|
||||
BTRFS_FILE_EXTENT_INLINE);
|
||||
leaf = path->nodes[0];
|
||||
ei = btrfs_item_ptr(leaf, path->slots[0],
|
||||
struct btrfs_file_extent_item);
|
||||
btrfs_set_file_extent_generation(leaf, ei, trans->transid);
|
||||
btrfs_set_file_extent_type(leaf, ei, BTRFS_FILE_EXTENT_INLINE);
|
||||
ptr = btrfs_file_extent_inline_start(ei);
|
||||
|
||||
kaddr = kmap_atomic(page, KM_USER0);
|
||||
btrfs_memcpy(root, path->nodes[0]->b_data,
|
||||
ptr, kaddr + page_offset, size);
|
||||
write_extent_buffer(leaf, kaddr + page_offset, ptr, size);
|
||||
kunmap_atomic(kaddr, KM_USER0);
|
||||
btrfs_mark_buffer_dirty(path->nodes[0]);
|
||||
btrfs_mark_buffer_dirty(leaf);
|
||||
fail:
|
||||
btrfs_free_path(path);
|
||||
return err;
|
||||
@@ -156,8 +155,8 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
|
||||
|
||||
em->bdev = inode->i_sb->s_bdev;
|
||||
|
||||
start_pos = pos & ~((u64)root->blocksize - 1);
|
||||
num_blocks = (write_bytes + pos - start_pos + root->blocksize - 1) >>
|
||||
start_pos = pos & ~((u64)root->sectorsize - 1);
|
||||
num_blocks = (write_bytes + pos - start_pos + root->sectorsize - 1) >>
|
||||
inode->i_blkbits;
|
||||
|
||||
down_read(&BTRFS_I(inode)->root->snap_sem);
|
||||
@@ -184,7 +183,7 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
|
||||
if (inode->i_size < start_pos) {
|
||||
u64 last_pos_in_file;
|
||||
u64 hole_size;
|
||||
u64 mask = root->blocksize - 1;
|
||||
u64 mask = root->sectorsize - 1;
|
||||
last_pos_in_file = (isize + mask) & ~mask;
|
||||
hole_size = (start_pos - last_pos_in_file + mask) & ~mask;
|
||||
|
||||
@@ -227,8 +226,8 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
|
||||
/* step one, delete the existing extents in this range */
|
||||
/* FIXME blocksize != pagesize */
|
||||
err = btrfs_drop_extents(trans, root, inode, start_pos,
|
||||
(pos + write_bytes + root->blocksize -1) &
|
||||
~((u64)root->blocksize - 1), &hint_block);
|
||||
(pos + write_bytes + root->sectorsize -1) &
|
||||
~((u64)root->sectorsize - 1), &hint_block);
|
||||
if (err)
|
||||
goto failed;
|
||||
|
||||
@@ -288,7 +287,7 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
|
||||
{
|
||||
int ret;
|
||||
struct btrfs_key key;
|
||||
struct btrfs_leaf *leaf;
|
||||
struct extent_buffer *leaf;
|
||||
int slot;
|
||||
struct btrfs_file_extent_item *extent;
|
||||
u64 extent_end = 0;
|
||||
@@ -327,10 +326,10 @@ next_slot:
|
||||
found_extent = 0;
|
||||
found_inline = 0;
|
||||
extent = NULL;
|
||||
leaf = btrfs_buffer_leaf(path->nodes[0]);
|
||||
leaf = path->nodes[0];
|
||||
slot = path->slots[0];
|
||||
ret = 0;
|
||||
btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key);
|
||||
btrfs_item_key_to_cpu(leaf, &key, slot);
|
||||
if (key.offset >= end || key.objectid != inode->i_ino) {
|
||||
goto out;
|
||||
}
|
||||
@@ -344,17 +343,18 @@ next_slot:
|
||||
if (btrfs_key_type(&key) == BTRFS_EXTENT_DATA_KEY) {
|
||||
extent = btrfs_item_ptr(leaf, slot,
|
||||
struct btrfs_file_extent_item);
|
||||
found_type = btrfs_file_extent_type(extent);
|
||||
found_type = btrfs_file_extent_type(leaf, extent);
|
||||
if (found_type == BTRFS_FILE_EXTENT_REG) {
|
||||
extent_end = key.offset +
|
||||
(btrfs_file_extent_num_blocks(extent) <<
|
||||
(btrfs_file_extent_num_blocks(leaf, extent) <<
|
||||
inode->i_blkbits);
|
||||
found_extent = 1;
|
||||
} else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
|
||||
struct btrfs_item *item;
|
||||
item = btrfs_item_nr(leaf, slot);
|
||||
found_inline = 1;
|
||||
extent_end = key.offset +
|
||||
btrfs_file_extent_inline_len(leaf->items +
|
||||
slot);
|
||||
btrfs_file_extent_inline_len(leaf, item);
|
||||
}
|
||||
} else {
|
||||
extent_end = search_start;
|
||||
@@ -365,8 +365,7 @@ next_slot:
|
||||
search_start >= extent_end) {
|
||||
int nextret;
|
||||
u32 nritems;
|
||||
nritems = btrfs_header_nritems(
|
||||
btrfs_buffer_header(path->nodes[0]));
|
||||
nritems = btrfs_header_nritems(leaf);
|
||||
if (slot >= nritems - 1) {
|
||||
nextret = btrfs_next_leaf(root, path);
|
||||
if (nextret)
|
||||
@@ -380,7 +379,7 @@ next_slot:
|
||||
|
||||
/* FIXME, there's only one inline extent allowed right now */
|
||||
if (found_inline) {
|
||||
u64 mask = root->blocksize - 1;
|
||||
u64 mask = root->sectorsize - 1;
|
||||
search_start = (extent_end + mask) & ~mask;
|
||||
} else
|
||||
search_start = extent_end;
|
||||
@@ -388,10 +387,13 @@ next_slot:
|
||||
if (end < extent_end && end >= key.offset) {
|
||||
if (found_extent) {
|
||||
u64 disk_blocknr =
|
||||
btrfs_file_extent_disk_blocknr(extent);
|
||||
btrfs_file_extent_disk_blocknr(leaf,extent);
|
||||
u64 disk_num_blocks =
|
||||
btrfs_file_extent_disk_num_blocks(extent);
|
||||
memcpy(&old, extent, sizeof(old));
|
||||
btrfs_file_extent_disk_num_blocks(leaf,
|
||||
extent);
|
||||
read_extent_buffer(leaf, &old,
|
||||
(unsigned long)extent,
|
||||
sizeof(old));
|
||||
if (disk_blocknr != 0) {
|
||||
ret = btrfs_inc_extent_ref(trans, root,
|
||||
disk_blocknr, disk_num_blocks);
|
||||
@@ -406,20 +408,24 @@ next_slot:
|
||||
u64 new_num;
|
||||
u64 old_num;
|
||||
keep = 1;
|
||||
WARN_ON(start & (root->blocksize - 1));
|
||||
WARN_ON(start & (root->sectorsize - 1));
|
||||
if (found_extent) {
|
||||
new_num = (start - key.offset) >>
|
||||
inode->i_blkbits;
|
||||
old_num = btrfs_file_extent_num_blocks(extent);
|
||||
old_num = btrfs_file_extent_num_blocks(leaf,
|
||||
extent);
|
||||
*hint_block =
|
||||
btrfs_file_extent_disk_blocknr(extent);
|
||||
if (btrfs_file_extent_disk_blocknr(extent)) {
|
||||
btrfs_file_extent_disk_blocknr(leaf,
|
||||
extent);
|
||||
if (btrfs_file_extent_disk_blocknr(leaf,
|
||||
extent)) {
|
||||
inode->i_blocks -=
|
||||
(old_num - new_num) << 3;
|
||||
}
|
||||
btrfs_set_file_extent_num_blocks(extent,
|
||||
btrfs_set_file_extent_num_blocks(leaf,
|
||||
extent,
|
||||
new_num);
|
||||
btrfs_mark_buffer_dirty(path->nodes[0]);
|
||||
btrfs_mark_buffer_dirty(leaf);
|
||||
} else {
|
||||
WARN_ON(1);
|
||||
}
|
||||
@@ -431,13 +437,17 @@ next_slot:
|
||||
u64 extent_num_blocks = 0;
|
||||
if (found_extent) {
|
||||
disk_blocknr =
|
||||
btrfs_file_extent_disk_blocknr(extent);
|
||||
btrfs_file_extent_disk_blocknr(leaf,
|
||||
extent);
|
||||
disk_num_blocks =
|
||||
btrfs_file_extent_disk_num_blocks(extent);
|
||||
btrfs_file_extent_disk_num_blocks(leaf,
|
||||
extent);
|
||||
extent_num_blocks =
|
||||
btrfs_file_extent_num_blocks(extent);
|
||||
btrfs_file_extent_num_blocks(leaf,
|
||||
extent);
|
||||
*hint_block =
|
||||
btrfs_file_extent_disk_blocknr(extent);
|
||||
btrfs_file_extent_disk_blocknr(leaf,
|
||||
extent);
|
||||
}
|
||||
ret = btrfs_del_item(trans, root, path);
|
||||
/* TODO update progress marker and return */
|
||||
@@ -464,42 +474,37 @@ next_slot:
|
||||
struct btrfs_key ins;
|
||||
ins.objectid = inode->i_ino;
|
||||
ins.offset = end;
|
||||
ins.flags = 0;
|
||||
btrfs_set_key_type(&ins, BTRFS_EXTENT_DATA_KEY);
|
||||
btrfs_release_path(root, path);
|
||||
ret = btrfs_insert_empty_item(trans, root, path, &ins,
|
||||
sizeof(*extent));
|
||||
|
||||
leaf = path->nodes[0];
|
||||
if (ret) {
|
||||
btrfs_print_leaf(root, btrfs_buffer_leaf(path->nodes[0]));
|
||||
printk("got %d on inserting %Lu %u %Lu start %Lu end %Lu found %Lu %Lu keep was %d\n", ret , ins.objectid, ins.flags, ins.offset, start, end, key.offset, extent_end, keep);
|
||||
btrfs_print_leaf(root, leaf);
|
||||
printk("got %d on inserting %Lu %u %Lu start %Lu end %Lu found %Lu %Lu keep was %d\n", ret , ins.objectid, ins.type, ins.offset, start, end, key.offset, extent_end, keep);
|
||||
}
|
||||
BUG_ON(ret);
|
||||
extent = btrfs_item_ptr(
|
||||
btrfs_buffer_leaf(path->nodes[0]),
|
||||
path->slots[0],
|
||||
struct btrfs_file_extent_item);
|
||||
btrfs_set_file_extent_disk_blocknr(extent,
|
||||
btrfs_file_extent_disk_blocknr(&old));
|
||||
btrfs_set_file_extent_disk_num_blocks(extent,
|
||||
btrfs_file_extent_disk_num_blocks(&old));
|
||||
extent = btrfs_item_ptr(leaf, path->slots[0],
|
||||
struct btrfs_file_extent_item);
|
||||
write_extent_buffer(leaf, &old,
|
||||
(unsigned long)extent, sizeof(old));
|
||||
|
||||
btrfs_set_file_extent_offset(extent,
|
||||
btrfs_file_extent_offset(&old) +
|
||||
btrfs_set_file_extent_offset(leaf, extent,
|
||||
le64_to_cpu(old.offset) +
|
||||
((end - key.offset) >> inode->i_blkbits));
|
||||
WARN_ON(btrfs_file_extent_num_blocks(&old) <
|
||||
WARN_ON(le64_to_cpu(old.num_blocks) <
|
||||
(extent_end - end) >> inode->i_blkbits);
|
||||
btrfs_set_file_extent_num_blocks(extent,
|
||||
btrfs_set_file_extent_num_blocks(leaf, extent,
|
||||
(extent_end - end) >> inode->i_blkbits);
|
||||
|
||||
btrfs_set_file_extent_type(extent,
|
||||
btrfs_set_file_extent_type(leaf, extent,
|
||||
BTRFS_FILE_EXTENT_REG);
|
||||
btrfs_set_file_extent_generation(extent,
|
||||
btrfs_file_extent_generation(&old));
|
||||
btrfs_mark_buffer_dirty(path->nodes[0]);
|
||||
if (btrfs_file_extent_disk_blocknr(&old) != 0) {
|
||||
if (le64_to_cpu(old.disk_blocknr) != 0) {
|
||||
inode->i_blocks +=
|
||||
btrfs_file_extent_num_blocks(extent) << 3;
|
||||
btrfs_file_extent_num_blocks(leaf,
|
||||
extent) << 3;
|
||||
}
|
||||
ret = 0;
|
||||
goto out;
|
||||
@@ -529,8 +534,8 @@ static int prepare_pages(struct btrfs_root *root,
|
||||
u64 num_blocks;
|
||||
u64 start_pos;
|
||||
|
||||
start_pos = pos & ~((u64)root->blocksize - 1);
|
||||
num_blocks = (write_bytes + pos - start_pos + root->blocksize - 1) >>
|
||||
start_pos = pos & ~((u64)root->sectorsize - 1);
|
||||
num_blocks = (write_bytes + pos - start_pos + root->sectorsize - 1) >>
|
||||
inode->i_blkbits;
|
||||
|
||||
memset(pages, 0, num_pages * sizeof(struct page *));
|
||||
|
||||
+8
-14
@@ -20,24 +20,18 @@
|
||||
#include "disk-io.h"
|
||||
#include "transaction.h"
|
||||
|
||||
int btrfs_insert_inode(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||
*root, u64 objectid, struct btrfs_inode_item
|
||||
*inode_item)
|
||||
int btrfs_insert_empty_inode(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root,
|
||||
struct btrfs_path *path, u64 objectid)
|
||||
{
|
||||
struct btrfs_path *path;
|
||||
struct btrfs_key key;
|
||||
int ret;
|
||||
key.objectid = objectid;
|
||||
key.flags = 0;
|
||||
btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY);
|
||||
key.offset = 0;
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
BUG_ON(!path);
|
||||
ret = btrfs_insert_item(trans, root, &key, inode_item,
|
||||
sizeof(*inode_item));
|
||||
btrfs_release_path(root, path);
|
||||
btrfs_free_path(path);
|
||||
ret = btrfs_insert_empty_item(trans, root, path, &key,
|
||||
sizeof(struct btrfs_inode_item));
|
||||
if (ret == 0 && objectid > root->highest_inode)
|
||||
root->highest_inode = objectid;
|
||||
return ret;
|
||||
@@ -51,15 +45,15 @@ int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||
int cow = mod != 0;
|
||||
int ret;
|
||||
int slot;
|
||||
struct btrfs_leaf *leaf;
|
||||
struct extent_buffer *leaf;
|
||||
struct btrfs_key found_key;
|
||||
|
||||
ret = btrfs_search_slot(trans, root, location, path, ins_len, cow);
|
||||
if (ret > 0 && btrfs_key_type(location) == BTRFS_ROOT_ITEM_KEY &&
|
||||
location->offset == (u64)-1 && path->slots[0] != 0) {
|
||||
slot = path->slots[0] - 1;
|
||||
leaf = btrfs_buffer_leaf(path->nodes[0]);
|
||||
btrfs_disk_key_to_cpu(&found_key, &leaf->items[slot].key);
|
||||
leaf = path->nodes[0];
|
||||
btrfs_item_key_to_cpu(leaf, &found_key, slot);
|
||||
if (found_key.objectid == location->objectid &&
|
||||
btrfs_key_type(&found_key) == btrfs_key_type(location)) {
|
||||
path->slots[0]--;
|
||||
|
||||
@@ -24,8 +24,9 @@ int btrfs_find_highest_inode(struct btrfs_root *root, u64 *objectid)
|
||||
{
|
||||
struct btrfs_path *path;
|
||||
int ret;
|
||||
struct btrfs_leaf *l;
|
||||
struct extent_buffer *l;
|
||||
struct btrfs_key search_key;
|
||||
struct btrfs_key found_key;
|
||||
int slot;
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
@@ -39,8 +40,9 @@ int btrfs_find_highest_inode(struct btrfs_root *root, u64 *objectid)
|
||||
BUG_ON(ret == 0);
|
||||
if (path->slots[0] > 0) {
|
||||
slot = path->slots[0] - 1;
|
||||
l = btrfs_buffer_leaf(path->nodes[0]);
|
||||
*objectid = btrfs_disk_key_objectid(&l->items[slot].key);
|
||||
l = path->nodes[0];
|
||||
btrfs_item_key_to_cpu(l, &found_key, slot);
|
||||
*objectid = found_key.objectid;
|
||||
} else {
|
||||
*objectid = BTRFS_FIRST_FREE_OBJECTID;
|
||||
}
|
||||
@@ -64,13 +66,12 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
|
||||
int slot = 0;
|
||||
u64 last_ino = 0;
|
||||
int start_found;
|
||||
struct btrfs_leaf *l;
|
||||
struct extent_buffer *l;
|
||||
struct btrfs_key search_key;
|
||||
u64 search_start = dirid;
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
BUG_ON(!path);
|
||||
search_key.flags = 0;
|
||||
search_start = root->last_inode_alloc;
|
||||
search_start = max(search_start, BTRFS_FIRST_FREE_OBJECTID);
|
||||
search_key.objectid = search_start;
|
||||
@@ -86,9 +87,9 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
|
||||
path->slots[0]--;
|
||||
|
||||
while (1) {
|
||||
l = btrfs_buffer_leaf(path->nodes[0]);
|
||||
l = path->nodes[0];
|
||||
slot = path->slots[0];
|
||||
if (slot >= btrfs_header_nritems(&l->header)) {
|
||||
if (slot >= btrfs_header_nritems(l)) {
|
||||
ret = btrfs_next_leaf(root, path);
|
||||
if (ret == 0)
|
||||
continue;
|
||||
@@ -103,7 +104,7 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
|
||||
last_ino : search_start;
|
||||
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 (start_found) {
|
||||
if (last_ino < search_start)
|
||||
|
||||
+267
-168
File diff suppressed because it is too large
Load Diff
+45
-51
@@ -20,10 +20,10 @@
|
||||
#include "disk-io.h"
|
||||
#include "print-tree.h"
|
||||
|
||||
void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l)
|
||||
void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
|
||||
{
|
||||
int i;
|
||||
u32 nr = btrfs_header_nritems(&l->header);
|
||||
u32 nr = btrfs_header_nritems(l);
|
||||
struct btrfs_item *item;
|
||||
struct btrfs_extent_item *ei;
|
||||
struct btrfs_root_item *ri;
|
||||
@@ -31,119 +31,113 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l)
|
||||
struct btrfs_inode_item *ii;
|
||||
struct btrfs_block_group_item *bi;
|
||||
struct btrfs_file_extent_item *fi;
|
||||
struct btrfs_key key;
|
||||
struct btrfs_key found_key;
|
||||
u32 type;
|
||||
|
||||
printk("leaf %llu total ptrs %d free space %d\n",
|
||||
(unsigned long long)btrfs_header_blocknr(&l->header), nr,
|
||||
(unsigned long long)btrfs_header_blocknr(l), nr,
|
||||
btrfs_leaf_free_space(root, l));
|
||||
for (i = 0 ; i < nr ; i++) {
|
||||
item = l->items + i;
|
||||
type = btrfs_disk_key_type(&item->key);
|
||||
item = btrfs_item_nr(l, i);
|
||||
btrfs_item_key_to_cpu(l, &key, i);
|
||||
type = btrfs_key_type(&key);
|
||||
printk("\titem %d key (%llu %x %llu) itemoff %d itemsize %d\n",
|
||||
i,
|
||||
(unsigned long long)btrfs_disk_key_objectid(&item->key),
|
||||
btrfs_disk_key_flags(&item->key),
|
||||
(unsigned long long)btrfs_disk_key_offset(&item->key),
|
||||
btrfs_item_offset(item),
|
||||
btrfs_item_size(item));
|
||||
(unsigned long long)key.objectid, type,
|
||||
(unsigned long long)key.offset,
|
||||
btrfs_item_offset(l, item), btrfs_item_size(l, item));
|
||||
switch (type) {
|
||||
case BTRFS_INODE_ITEM_KEY:
|
||||
ii = btrfs_item_ptr(l, i, struct btrfs_inode_item);
|
||||
printk("\t\tinode generation %llu size %llu mode %o\n",
|
||||
(unsigned long long)btrfs_inode_generation(ii),
|
||||
(unsigned long long)btrfs_inode_size(ii),
|
||||
btrfs_inode_mode(ii));
|
||||
(unsigned long long)btrfs_inode_generation(l, ii),
|
||||
(unsigned long long)btrfs_inode_size(l, ii),
|
||||
btrfs_inode_mode(l, ii));
|
||||
break;
|
||||
case BTRFS_DIR_ITEM_KEY:
|
||||
di = btrfs_item_ptr(l, i, struct btrfs_dir_item);
|
||||
btrfs_dir_item_key_to_cpu(l, di, &found_key);
|
||||
printk("\t\tdir oid %llu flags %u type %u\n",
|
||||
(unsigned long long)btrfs_disk_key_objectid(
|
||||
&di->location),
|
||||
btrfs_dir_flags(di),
|
||||
btrfs_dir_type(di));
|
||||
printk("\t\tname %.*s\n",
|
||||
btrfs_dir_name_len(di),(char *)(di + 1));
|
||||
(unsigned long long)found_key.objectid,
|
||||
btrfs_dir_flags(l, di),
|
||||
btrfs_dir_type(l, di));
|
||||
break;
|
||||
case BTRFS_ROOT_ITEM_KEY:
|
||||
ri = btrfs_item_ptr(l, i, struct btrfs_root_item);
|
||||
printk("\t\troot data blocknr %llu refs %u\n",
|
||||
(unsigned long long)btrfs_root_blocknr(ri),
|
||||
btrfs_root_refs(ri));
|
||||
(unsigned long long)btrfs_disk_root_blocknr(l, ri),
|
||||
btrfs_disk_root_refs(l, ri));
|
||||
break;
|
||||
case BTRFS_EXTENT_ITEM_KEY:
|
||||
ei = btrfs_item_ptr(l, i, struct btrfs_extent_item);
|
||||
printk("\t\textent data refs %u\n",
|
||||
btrfs_extent_refs(ei));
|
||||
btrfs_extent_refs(l, ei));
|
||||
break;
|
||||
|
||||
case BTRFS_EXTENT_DATA_KEY:
|
||||
fi = btrfs_item_ptr(l, i,
|
||||
struct btrfs_file_extent_item);
|
||||
if (btrfs_file_extent_type(fi) ==
|
||||
if (btrfs_file_extent_type(l, fi) ==
|
||||
BTRFS_FILE_EXTENT_INLINE) {
|
||||
printk("\t\tinline extent data size %u\n",
|
||||
btrfs_file_extent_inline_len(l->items + i));
|
||||
btrfs_file_extent_inline_len(l, item));
|
||||
break;
|
||||
}
|
||||
printk("\t\textent data disk block %llu nr %llu\n",
|
||||
(unsigned long long)btrfs_file_extent_disk_blocknr(fi),
|
||||
(unsigned long long)btrfs_file_extent_disk_num_blocks(fi));
|
||||
(unsigned long long)btrfs_file_extent_disk_blocknr(l, fi),
|
||||
(unsigned long long)btrfs_file_extent_disk_num_blocks(l, fi));
|
||||
printk("\t\textent data offset %llu nr %llu\n",
|
||||
(unsigned long long)btrfs_file_extent_offset(fi),
|
||||
(unsigned long long)btrfs_file_extent_num_blocks(fi));
|
||||
(unsigned long long)btrfs_file_extent_offset(l, fi),
|
||||
(unsigned long long)btrfs_file_extent_num_blocks(l, fi));
|
||||
break;
|
||||
case BTRFS_BLOCK_GROUP_ITEM_KEY:
|
||||
bi = btrfs_item_ptr(l, i,
|
||||
struct btrfs_block_group_item);
|
||||
printk("\t\tblock group used %llu\n",
|
||||
(unsigned long long)btrfs_block_group_used(bi));
|
||||
break;
|
||||
case BTRFS_STRING_ITEM_KEY:
|
||||
printk("\t\titem data %.*s\n", btrfs_item_size(item),
|
||||
btrfs_leaf_data(l) + btrfs_item_offset(item));
|
||||
(unsigned long long)btrfs_disk_block_group_used(l, bi));
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void btrfs_print_tree(struct btrfs_root *root, struct buffer_head *t)
|
||||
void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *c)
|
||||
{
|
||||
int i;
|
||||
u32 nr;
|
||||
struct btrfs_node *c;
|
||||
struct btrfs_key key;
|
||||
|
||||
if (!t)
|
||||
if (!c)
|
||||
return;
|
||||
c = btrfs_buffer_node(t);
|
||||
nr = btrfs_header_nritems(&c->header);
|
||||
nr = btrfs_header_nritems(c);
|
||||
if (btrfs_is_leaf(c)) {
|
||||
btrfs_print_leaf(root, (struct btrfs_leaf *)c);
|
||||
btrfs_print_leaf(root, c);
|
||||
return;
|
||||
}
|
||||
printk("node %llu level %d total ptrs %d free spc %u\n",
|
||||
(unsigned long long)btrfs_header_blocknr(&c->header),
|
||||
btrfs_header_level(&c->header), nr,
|
||||
(unsigned long long)btrfs_header_blocknr(c),
|
||||
btrfs_header_level(c), nr,
|
||||
(u32)BTRFS_NODEPTRS_PER_BLOCK(root) - nr);
|
||||
for (i = 0; i < nr; i++) {
|
||||
btrfs_node_key_to_cpu(c, &key, i);
|
||||
printk("\tkey %d (%llu %u %llu) block %llu\n",
|
||||
i,
|
||||
(unsigned long long)c->ptrs[i].key.objectid,
|
||||
c->ptrs[i].key.flags,
|
||||
(unsigned long long)c->ptrs[i].key.offset,
|
||||
(unsigned long long)key.objectid,
|
||||
key.type,
|
||||
(unsigned long long)key.offset,
|
||||
(unsigned long long)btrfs_node_blockptr(c, i));
|
||||
}
|
||||
for (i = 0; i < nr; i++) {
|
||||
struct buffer_head *next_buf = read_tree_block(root,
|
||||
struct extent_buffer *next = read_tree_block(root,
|
||||
btrfs_node_blockptr(c, i));
|
||||
struct btrfs_node *next = btrfs_buffer_node(next_buf);
|
||||
if (btrfs_is_leaf(next) &&
|
||||
btrfs_header_level(&c->header) != 1)
|
||||
btrfs_header_level(c) != 1)
|
||||
BUG();
|
||||
if (btrfs_header_level(&next->header) !=
|
||||
btrfs_header_level(&c->header) - 1)
|
||||
if (btrfs_header_level(next) !=
|
||||
btrfs_header_level(c) - 1)
|
||||
BUG();
|
||||
btrfs_print_tree(root, next_buf);
|
||||
btrfs_block_release(root, next_buf);
|
||||
btrfs_print_tree(root, next);
|
||||
free_extent_buffer(next);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,6 @@
|
||||
|
||||
#ifndef __PRINT_TREE_
|
||||
#define __PRINT_TREE_
|
||||
void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l);
|
||||
void btrfs_print_tree(struct btrfs_root *root, struct buffer_head *t);
|
||||
void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l);
|
||||
void btrfs_print_tree(struct btrfs_root *root, struct extent_buffer *t);
|
||||
#endif
|
||||
|
||||
+27
-24
@@ -26,12 +26,13 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
|
||||
{
|
||||
struct btrfs_path *path;
|
||||
struct btrfs_key search_key;
|
||||
struct btrfs_leaf *l;
|
||||
struct btrfs_key found_key;
|
||||
struct extent_buffer *l;
|
||||
int ret;
|
||||
int slot;
|
||||
|
||||
search_key.objectid = objectid;
|
||||
search_key.flags = (u32)-1;
|
||||
search_key.type = (u8)-1;
|
||||
search_key.offset = (u64)-1;
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
@@ -39,17 +40,19 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid,
|
||||
ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
BUG_ON(ret == 0);
|
||||
l = btrfs_buffer_leaf(path->nodes[0]);
|
||||
l = path->nodes[0];
|
||||
BUG_ON(path->slots[0] == 0);
|
||||
slot = path->slots[0] - 1;
|
||||
if (btrfs_disk_key_objectid(&l->items[slot].key) != objectid) {
|
||||
btrfs_item_key_to_cpu(l, &found_key, slot);
|
||||
if (found_key.objectid != objectid) {
|
||||
ret = 1;
|
||||
goto out;
|
||||
}
|
||||
memcpy(item, btrfs_item_ptr(l, slot, struct btrfs_root_item),
|
||||
sizeof(*item));
|
||||
btrfs_disk_key_to_cpu(key, &l->items[slot].key);
|
||||
read_extent_buffer(l, item, btrfs_item_ptr_offset(l, slot),
|
||||
sizeof(*item));
|
||||
memcpy(key, &found_key, sizeof(found_key));
|
||||
ret = 0;
|
||||
out:
|
||||
btrfs_release_path(root, path);
|
||||
@@ -62,10 +65,10 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||
*item)
|
||||
{
|
||||
struct btrfs_path *path;
|
||||
struct btrfs_leaf *l;
|
||||
struct extent_buffer *l;
|
||||
int ret;
|
||||
int slot;
|
||||
struct btrfs_root_item *update_item;
|
||||
unsigned long ptr;
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
BUG_ON(!path);
|
||||
@@ -73,10 +76,10 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
BUG_ON(ret != 0);
|
||||
l = btrfs_buffer_leaf(path->nodes[0]);
|
||||
l = path->nodes[0];
|
||||
slot = path->slots[0];
|
||||
update_item = btrfs_item_ptr(l, slot, struct btrfs_root_item);
|
||||
btrfs_memcpy(root, l, update_item, item, sizeof(*item));
|
||||
ptr = btrfs_item_ptr_offset(l, slot);
|
||||
write_extent_buffer(l, item, ptr, sizeof(*item));
|
||||
btrfs_mark_buffer_dirty(path->nodes[0]);
|
||||
out:
|
||||
btrfs_release_path(root, path);
|
||||
@@ -103,11 +106,10 @@ int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid,
|
||||
struct btrfs_path *path;
|
||||
int ret;
|
||||
u32 nritems;
|
||||
struct btrfs_leaf *leaf;
|
||||
struct extent_buffer *leaf;
|
||||
int slot;
|
||||
|
||||
key.objectid = objectid;
|
||||
key.flags = 0;
|
||||
btrfs_set_key_type(&key, BTRFS_ROOT_ITEM_KEY);
|
||||
key.offset = 0;
|
||||
path = btrfs_alloc_path();
|
||||
@@ -117,19 +119,19 @@ int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid,
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
while(1) {
|
||||
leaf = btrfs_buffer_leaf(path->nodes[0]);
|
||||
nritems = btrfs_header_nritems(&leaf->header);
|
||||
leaf = path->nodes[0];
|
||||
nritems = btrfs_header_nritems(leaf);
|
||||
slot = path->slots[0];
|
||||
if (slot >= nritems) {
|
||||
ret = btrfs_next_leaf(root, path);
|
||||
if (ret)
|
||||
break;
|
||||
leaf = btrfs_buffer_leaf(path->nodes[0]);
|
||||
nritems = btrfs_header_nritems(&leaf->header);
|
||||
leaf = path->nodes[0];
|
||||
nritems = btrfs_header_nritems(leaf);
|
||||
slot = path->slots[0];
|
||||
}
|
||||
item = leaf->items + slot;
|
||||
btrfs_disk_key_to_cpu(&key, &item->key);
|
||||
item = btrfs_item_nr(leaf, slot);
|
||||
btrfs_item_key_to_cpu(leaf, &key, slot);
|
||||
if (btrfs_key_type(&key) != BTRFS_ROOT_ITEM_KEY)
|
||||
goto next;
|
||||
|
||||
@@ -140,7 +142,7 @@ int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid,
|
||||
break;
|
||||
|
||||
ri = btrfs_item_ptr(leaf, slot, struct btrfs_root_item);
|
||||
if (btrfs_root_refs(ri) != 0)
|
||||
if (btrfs_disk_root_refs(leaf, ri) != 0)
|
||||
goto next;
|
||||
|
||||
dead_root = btrfs_read_fs_root_no_radix(root->fs_info, &key);
|
||||
@@ -170,6 +172,7 @@ int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||
int ret;
|
||||
u32 refs;
|
||||
struct btrfs_root_item *ri;
|
||||
struct extent_buffer *leaf;
|
||||
|
||||
path = btrfs_alloc_path();
|
||||
BUG_ON(!path);
|
||||
@@ -177,10 +180,10 @@ int btrfs_del_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
BUG_ON(ret != 0);
|
||||
ri = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]),
|
||||
path->slots[0], struct btrfs_root_item);
|
||||
leaf = path->nodes[0];
|
||||
ri = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_item);
|
||||
|
||||
refs = btrfs_root_refs(ri);
|
||||
refs = btrfs_disk_root_refs(leaf, ri);
|
||||
BUG_ON(refs != 0);
|
||||
ret = btrfs_del_item(trans, root, path);
|
||||
out:
|
||||
|
||||
+4
-3
@@ -41,7 +41,7 @@
|
||||
#include "ioctl.h"
|
||||
#include "print-tree.h"
|
||||
|
||||
#define BTRFS_SUPER_MAGIC 0x9123682E
|
||||
#define BTRFS_SUPER_MAGIC 0x9123683E
|
||||
|
||||
static struct super_operations btrfs_super_ops;
|
||||
|
||||
@@ -115,13 +115,12 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent)
|
||||
return -EIO;
|
||||
}
|
||||
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),
|
||||
tree_root);
|
||||
bi = BTRFS_I(inode);
|
||||
bi->location.objectid = inode->i_ino;
|
||||
bi->location.offset = 0;
|
||||
bi->location.flags = 0;
|
||||
bi->root = tree_root;
|
||||
|
||||
btrfs_set_key_type(&bi->location, BTRFS_INODE_ITEM_KEY);
|
||||
@@ -281,6 +280,7 @@ error_s:
|
||||
error_bdev:
|
||||
close_bdev_excl(bdev);
|
||||
error:
|
||||
printk("get_sb failed\n");
|
||||
return error;
|
||||
}
|
||||
/* end copy & paste */
|
||||
@@ -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,
|
||||
btrfs_fill_super, mnt,
|
||||
subvol_name ? subvol_name : "default");
|
||||
printk("btrfs_get_sb returns %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -31,31 +31,31 @@
|
||||
static ssize_t root_blocks_used_show(struct btrfs_root *root, char *buf)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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) */
|
||||
|
||||
+34
-27
@@ -19,6 +19,7 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include "ctree.h"
|
||||
#include "disk-io.h"
|
||||
#include "transaction.h"
|
||||
@@ -66,7 +67,9 @@ static int join_transaction(struct btrfs_root *root)
|
||||
cur_trans->commit_done = 0;
|
||||
cur_trans->start_time = get_seconds();
|
||||
list_add_tail(&cur_trans->list, &root->fs_info->trans_list);
|
||||
init_bit_radix(&cur_trans->dirty_pages);
|
||||
extent_map_tree_init(&cur_trans->dirty_pages,
|
||||
root->fs_info->btree_inode->i_mapping,
|
||||
GFP_NOFS);
|
||||
} else {
|
||||
cur_trans->num_writers++;
|
||||
cur_trans->num_joined++;
|
||||
@@ -88,7 +91,7 @@ static int record_root_in_trans(struct btrfs_root *root)
|
||||
(unsigned long)root->root_key.objectid,
|
||||
BTRFS_ROOT_DEFRAG_TAG);
|
||||
root->commit_root = root->node;
|
||||
get_bh(root->node);
|
||||
extent_buffer_get(root->node);
|
||||
} else {
|
||||
WARN_ON(1);
|
||||
}
|
||||
@@ -144,29 +147,30 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans,
|
||||
int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_root *root)
|
||||
{
|
||||
unsigned long gang[16];
|
||||
int ret;
|
||||
int i;
|
||||
int err;
|
||||
int werr = 0;
|
||||
struct extent_map_tree *dirty_pages;
|
||||
struct page *page;
|
||||
struct radix_tree_root *dirty_pages;
|
||||
struct inode *btree_inode = root->fs_info->btree_inode;
|
||||
u64 start;
|
||||
u64 end;
|
||||
unsigned long index;
|
||||
|
||||
if (!trans || !trans->transaction) {
|
||||
return filemap_write_and_wait(btree_inode->i_mapping);
|
||||
}
|
||||
dirty_pages = &trans->transaction->dirty_pages;
|
||||
while(1) {
|
||||
ret = find_first_radix_bit(dirty_pages, gang,
|
||||
0, ARRAY_SIZE(gang));
|
||||
if (!ret)
|
||||
ret = find_first_extent_bit(dirty_pages, 0, &start, &end,
|
||||
EXTENT_DIRTY);
|
||||
if (ret)
|
||||
break;
|
||||
for (i = 0; i < ret; i++) {
|
||||
/* FIXME EIO */
|
||||
clear_radix_bit(dirty_pages, gang[i]);
|
||||
page = find_lock_page(btree_inode->i_mapping,
|
||||
gang[i]);
|
||||
clear_extent_dirty(dirty_pages, start, end, GFP_NOFS);
|
||||
while(start <= end) {
|
||||
index = start >> PAGE_CACHE_SHIFT;
|
||||
start = (index + 1) << PAGE_CACHE_SHIFT;
|
||||
page = find_lock_page(btree_inode->i_mapping, index);
|
||||
if (!page)
|
||||
continue;
|
||||
if (PageWriteback(page)) {
|
||||
@@ -202,10 +206,11 @@ int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans,
|
||||
btrfs_write_dirty_block_groups(trans, extent_root);
|
||||
while(1) {
|
||||
old_extent_block = btrfs_root_blocknr(&extent_root->root_item);
|
||||
if (old_extent_block == bh_blocknr(extent_root->node))
|
||||
if (old_extent_block ==
|
||||
extent_buffer_blocknr(extent_root->node))
|
||||
break;
|
||||
btrfs_set_root_blocknr(&extent_root->root_item,
|
||||
bh_blocknr(extent_root->node));
|
||||
extent_buffer_blocknr(extent_root->node));
|
||||
ret = btrfs_update_root(trans, tree_root,
|
||||
&extent_root->root_key,
|
||||
&extent_root->root_item);
|
||||
@@ -279,9 +284,9 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans,
|
||||
(unsigned long)root->root_key.objectid,
|
||||
BTRFS_ROOT_TRANS_TAG);
|
||||
if (root->commit_root == root->node) {
|
||||
WARN_ON(bh_blocknr(root->node) !=
|
||||
WARN_ON(extent_buffer_blocknr(root->node) !=
|
||||
btrfs_root_blocknr(&root->root_item));
|
||||
brelse(root->commit_root);
|
||||
free_extent_buffer(root->commit_root);
|
||||
root->commit_root = NULL;
|
||||
|
||||
/* make sure to update the root on disk
|
||||
@@ -310,7 +315,7 @@ static int add_dirty_roots(struct btrfs_trans_handle *trans,
|
||||
|
||||
root->root_key.offset = root->fs_info->generation;
|
||||
btrfs_set_root_blocknr(&root->root_item,
|
||||
bh_blocknr(root->node));
|
||||
extent_buffer_blocknr(root->node));
|
||||
err = btrfs_insert_root(trans, root->fs_info->tree_root,
|
||||
&root->root_key,
|
||||
&root->root_item);
|
||||
@@ -389,10 +394,10 @@ int btrfs_defrag_dirty_roots(struct btrfs_fs_info *info)
|
||||
for (i = 0; i < ret; i++) {
|
||||
root = gang[i];
|
||||
last = root->root_key.objectid + 1;
|
||||
btrfs_defrag_root(root, 1);
|
||||
// btrfs_defrag_root(root, 1);
|
||||
}
|
||||
}
|
||||
btrfs_defrag_root(info->extent_root, 1);
|
||||
// btrfs_defrag_root(info->extent_root, 1);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -414,7 +419,7 @@ static int drop_dirty_roots(struct btrfs_root *tree_root,
|
||||
dirty = list_entry(list->next, struct dirty_root, list);
|
||||
list_del_init(&dirty->list);
|
||||
|
||||
num_blocks = btrfs_root_blocks_used(&dirty->root->root_item);
|
||||
num_blocks = btrfs_root_used(&dirty->root->root_item);
|
||||
root = dirty->latest_root;
|
||||
|
||||
while(1) {
|
||||
@@ -441,11 +446,11 @@ static int drop_dirty_roots(struct btrfs_root *tree_root,
|
||||
}
|
||||
BUG_ON(ret);
|
||||
|
||||
num_blocks -= btrfs_root_blocks_used(&dirty->root->root_item);
|
||||
blocks_used = btrfs_root_blocks_used(&root->root_item);
|
||||
num_blocks -= btrfs_root_used(&dirty->root->root_item);
|
||||
blocks_used = btrfs_root_used(&root->root_item);
|
||||
if (num_blocks) {
|
||||
record_root_in_trans(root);
|
||||
btrfs_set_root_blocks_used(&root->root_item,
|
||||
btrfs_set_root_used(&root->root_item,
|
||||
blocks_used - num_blocks);
|
||||
}
|
||||
ret = btrfs_del_root(trans, tree_root, &dirty->root->root_key);
|
||||
@@ -553,9 +558,11 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
|
||||
btrfs_set_super_generation(&root->fs_info->super_copy,
|
||||
cur_trans->transid);
|
||||
btrfs_set_super_root(&root->fs_info->super_copy,
|
||||
bh_blocknr(root->fs_info->tree_root->node));
|
||||
memcpy(root->fs_info->disk_super, &root->fs_info->super_copy,
|
||||
sizeof(root->fs_info->super_copy));
|
||||
extent_buffer_blocknr(root->fs_info->tree_root->node));
|
||||
|
||||
write_extent_buffer(root->fs_info->sb_buffer,
|
||||
&root->fs_info->super_copy, 0,
|
||||
sizeof(root->fs_info->super_copy));
|
||||
|
||||
btrfs_copy_pinned(root, &pinned_copy);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user