提交 0b86a832 编写于 作者: C Chris Mason

Btrfs: Add support for multiple devices per filesystem

Signed-off-by: NChris Mason <chris.mason@oracle.com>
上级 7f93bf8d
...@@ -6,7 +6,7 @@ btrfs-y := super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \ ...@@ -6,7 +6,7 @@ btrfs-y := super.o ctree.o extent-tree.o print-tree.o root-tree.o dir-item.o \
hash.o file-item.o inode-item.o inode-map.o disk-io.o \ hash.o file-item.o inode-item.o inode-map.o disk-io.o \
transaction.o bit-radix.o inode.o file.o tree-defrag.o \ transaction.o bit-radix.o inode.o file.o tree-defrag.o \
extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \ extent_map.o sysfs.o struct-funcs.o xattr.o ordered-data.o \
extent_io.o extent_io.o volumes.o
ifeq ($(CONFIG_FS_POSIX_ACL),y) ifeq ($(CONFIG_FS_POSIX_ACL),y)
btrfs-y += acl.o btrfs-y += acl.o
......
...@@ -70,6 +70,14 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p) ...@@ -70,6 +70,14 @@ void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p)
memset(p, 0, sizeof(*p)); memset(p, 0, sizeof(*p));
} }
static void add_root_to_dirty_list(struct btrfs_root *root)
{
if (root->track_dirty && list_empty(&root->dirty_list)) {
list_add(&root->dirty_list,
&root->fs_info->dirty_cowonly_roots);
}
}
int btrfs_copy_root(struct btrfs_trans_handle *trans, int btrfs_copy_root(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct btrfs_root *root,
struct extent_buffer *buf, struct extent_buffer *buf,
...@@ -196,6 +204,7 @@ int __btrfs_cow_block(struct btrfs_trans_handle *trans, ...@@ -196,6 +204,7 @@ int __btrfs_cow_block(struct btrfs_trans_handle *trans,
root_gen, 0, 0, 1); root_gen, 0, 0, 1);
} }
free_extent_buffer(buf); free_extent_buffer(buf);
add_root_to_dirty_list(root);
} else { } else {
root_gen = btrfs_header_generation(parent); root_gen = btrfs_header_generation(parent);
btrfs_set_node_blockptr(parent, parent_slot, btrfs_set_node_blockptr(parent, parent_slot,
...@@ -241,7 +250,7 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans, ...@@ -241,7 +250,7 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans,
return 0; return 0;
} }
search_start = buf->start & ~((u64)BTRFS_BLOCK_GROUP_SIZE - 1); search_start = buf->start & ~((u64)(1024 * 1024 * 1024) - 1);
ret = __btrfs_cow_block(trans, root, buf, parent, ret = __btrfs_cow_block(trans, root, buf, parent,
parent_slot, cow_ret, search_start, 0); parent_slot, cow_ret, search_start, 0);
return ret; return ret;
...@@ -724,6 +733,7 @@ static int balance_level(struct btrfs_trans_handle *trans, ...@@ -724,6 +733,7 @@ static int balance_level(struct btrfs_trans_handle *trans,
BUG_ON(ret); BUG_ON(ret);
root->node = child; root->node = child;
add_root_to_dirty_list(root);
path->nodes[level] = NULL; path->nodes[level] = NULL;
clean_tree_block(trans, root, mid); clean_tree_block(trans, root, mid);
wait_on_tree_block_writeback(root, mid); wait_on_tree_block_writeback(root, mid);
...@@ -1369,6 +1379,7 @@ static int noinline insert_new_root(struct btrfs_trans_handle *trans, ...@@ -1369,6 +1379,7 @@ static int noinline insert_new_root(struct btrfs_trans_handle *trans,
/* the super has an extra ref to root->node */ /* the super has an extra ref to root->node */
free_extent_buffer(root->node); free_extent_buffer(root->node);
root->node = c; root->node = c;
add_root_to_dirty_list(root);
extent_buffer_get(c); extent_buffer_get(c);
path->nodes[level] = c; path->nodes[level] = c;
path->slots[level] = 0; path->slots[level] = 0;
...@@ -2777,3 +2788,28 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path) ...@@ -2777,3 +2788,28 @@ int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path)
} }
return 0; return 0;
} }
int btrfs_previous_item(struct btrfs_root *root,
struct btrfs_path *path, u64 min_objectid,
int type)
{
struct btrfs_key found_key;
struct extent_buffer *leaf;
int ret;
while(1) {
if (path->slots[0] == 0) {
ret = btrfs_prev_leaf(root, path);
if (ret != 0)
return ret;
} else {
path->slots[0]--;
}
leaf = path->nodes[0];
btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
if (found_key.type == type)
return 0;
}
return 1;
}
...@@ -40,12 +40,44 @@ extern struct kmem_cache *btrfs_path_cachep; ...@@ -40,12 +40,44 @@ extern struct kmem_cache *btrfs_path_cachep;
#define BTRFS_MAGIC "_B4RfS_M" #define BTRFS_MAGIC "_B4RfS_M"
#define BTRFS_MAX_LEVEL 8 #define BTRFS_MAX_LEVEL 8
/* holds pointers to all of the tree roots */
#define BTRFS_ROOT_TREE_OBJECTID 1ULL #define BTRFS_ROOT_TREE_OBJECTID 1ULL
/* stores information about which extents are in use, and reference counts */
#define BTRFS_EXTENT_TREE_OBJECTID 2ULL #define BTRFS_EXTENT_TREE_OBJECTID 2ULL
/* one per subvolume, storing files and directories */
#define BTRFS_FS_TREE_OBJECTID 3ULL #define BTRFS_FS_TREE_OBJECTID 3ULL
/* directory objectid inside the root tree */
#define BTRFS_ROOT_TREE_DIR_OBJECTID 4ULL #define BTRFS_ROOT_TREE_DIR_OBJECTID 4ULL
/*
* chunk tree stores translations from logical -> physical block numbering
* the super block points to the chunk tree
*/
#define BTRFS_CHUNK_TREE_OBJECTID 5ULL
/*
* stores information about which areas of a given device are in use.
* one per device. The tree of tree roots points to the device tree
*/
#define BTRFS_DEV_TREE_OBJECTID 6ULL
/*
* All files have objectids higher than this.
*/
#define BTRFS_FIRST_FREE_OBJECTID 256ULL #define BTRFS_FIRST_FREE_OBJECTID 256ULL
/*
* the device items go into the chunk tree. The key is in the form
* [ 1 BTRFS_DEV_ITEM_KEY device_id ]
*/
#define BTRFS_DEV_ITEMS_OBJECTID 1ULL
/* /*
* we can actually store much bigger names, but lets not confuse the rest * we can actually store much bigger names, but lets not confuse the rest
* of linux * of linux
...@@ -95,6 +127,81 @@ struct btrfs_key { ...@@ -95,6 +127,81 @@ struct btrfs_key {
u64 offset; u64 offset;
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
struct btrfs_mapping_tree {
struct extent_map_tree map_tree;
};
#define BTRFS_DEV_UUID_SIZE 16
struct btrfs_dev_item {
/* the internal btrfs device id */
__le64 devid;
/* size of the device */
__le64 total_bytes;
/* bytes used */
__le64 bytes_used;
/* optimal io alignment for this device */
__le32 io_align;
/* optimal io width for this device */
__le32 io_width;
/* minimal io size for this device */
__le32 sector_size;
/* the kernel device number */
__le64 rdev;
/* type and info about this device */
__le64 type;
/* partition number, 0 for whole dev */
__le32 partition;
/* length of the name data at the end of the item */
__le16 name_len;
/* physical drive uuid (or lvm uuid) */
u8 uuid[BTRFS_DEV_UUID_SIZE];
/* name goes here */
} __attribute__ ((__packed__));
struct btrfs_stripe {
__le64 devid;
__le64 offset;
} __attribute__ ((__packed__));
struct btrfs_chunk {
__le64 owner;
__le64 stripe_len;
__le64 type;
/* optimal io alignment for this chunk */
__le32 io_align;
/* optimal io width for this chunk */
__le32 io_width;
/* minimal io size for this chunk */
__le32 sector_size;
/* 2^16 stripes is quite a lot, a second limit is the size of a single
* item in the btree
*/
__le16 num_stripes;
struct btrfs_stripe stripe;
/* additional stripes go here */
} __attribute__ ((__packed__));
static inline unsigned long btrfs_chunk_item_size(int num_stripes)
{
BUG_ON(num_stripes == 0);
return sizeof(struct btrfs_chunk) +
sizeof(struct btrfs_stripe) * (num_stripes - 1);
}
#define BTRFS_FSID_SIZE 16 #define BTRFS_FSID_SIZE 16
/* /*
* every tree block (leaf or node) starts with this header. * every tree block (leaf or node) starts with this header.
...@@ -119,6 +226,13 @@ struct btrfs_header { ...@@ -119,6 +226,13 @@ struct btrfs_header {
sizeof(struct btrfs_item) - \ sizeof(struct btrfs_item) - \
sizeof(struct btrfs_file_extent_item)) sizeof(struct btrfs_file_extent_item))
/*
* this is a very generous portion of the super block, giving us
* room to translate 14 chunks with 3 stripes each.
*/
#define BTRFS_SYSTEM_CHUNK_ARRAY_SIZE 2048
/* /*
* the super block basically lists the main trees of the FS * the super block basically lists the main trees of the FS
* it currently lacks any block count etc etc * it currently lacks any block count etc etc
...@@ -131,6 +245,7 @@ struct btrfs_super_block { ...@@ -131,6 +245,7 @@ struct btrfs_super_block {
__le64 magic; __le64 magic;
__le64 generation; __le64 generation;
__le64 root; __le64 root;
__le64 chunk_root;
__le64 total_bytes; __le64 total_bytes;
__le64 bytes_used; __le64 bytes_used;
__le64 root_dir_objectid; __le64 root_dir_objectid;
...@@ -138,7 +253,10 @@ struct btrfs_super_block { ...@@ -138,7 +253,10 @@ struct btrfs_super_block {
__le32 nodesize; __le32 nodesize;
__le32 leafsize; __le32 leafsize;
__le32 stripesize; __le32 stripesize;
__le32 sys_chunk_array_size;
u8 root_level; u8 root_level;
u8 chunk_root_level;
u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE];
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
/* /*
...@@ -208,12 +326,22 @@ struct btrfs_extent_ref { ...@@ -208,12 +326,22 @@ struct btrfs_extent_ref {
__le64 offset; __le64 offset;
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
/* dev extents record free space on individual devices. The owner
* field points back to the chunk allocation mapping tree that allocated
* the extent
*/
struct btrfs_dev_extent {
__le64 owner;
__le64 length;
} __attribute__ ((__packed__));
struct btrfs_inode_ref { struct btrfs_inode_ref {
__le16 name_len; __le16 name_len;
/* name goes here */ /* name goes here */
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
struct btrfs_inode_timespec { struct btrfs_timespec {
__le64 sec; __le64 sec;
__le32 nsec; __le32 nsec;
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
...@@ -231,13 +359,13 @@ struct btrfs_inode_item { ...@@ -231,13 +359,13 @@ struct btrfs_inode_item {
__le32 uid; __le32 uid;
__le32 gid; __le32 gid;
__le32 mode; __le32 mode;
__le32 rdev; __le64 rdev;
__le16 flags; __le16 flags;
__le16 compat_flags; __le16 compat_flags;
struct btrfs_inode_timespec atime; struct btrfs_timespec atime;
struct btrfs_inode_timespec ctime; struct btrfs_timespec ctime;
struct btrfs_inode_timespec mtime; struct btrfs_timespec mtime;
struct btrfs_inode_timespec otime; struct btrfs_timespec otime;
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
struct btrfs_dir_item { struct btrfs_dir_item {
...@@ -290,29 +418,34 @@ struct btrfs_csum_item { ...@@ -290,29 +418,34 @@ struct btrfs_csum_item {
u8 csum; u8 csum;
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
/* tag for the radix tree of block groups in ram */ /* different types of block groups (and chunks) */
#define BTRFS_BLOCK_GROUP_SIZE (256 * 1024 * 1024) #define BTRFS_BLOCK_GROUP_DATA (1 << 0)
#define BTRFS_BLOCK_GROUP_SYSTEM (1 << 1)
#define BTRFS_BLOCK_GROUP_METADATA (1 << 2)
#define BTRFS_BLOCK_GROUP_DATA 1
#define BTRFS_BLOCK_GROUP_MIXED 2
struct btrfs_block_group_item { struct btrfs_block_group_item {
__le64 used; __le64 used;
u8 flags; __le64 chunk_tree;
__le64 chunk_objectid;
__le64 flags;
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
struct btrfs_block_group_cache { struct btrfs_block_group_cache {
struct btrfs_key key; struct btrfs_key key;
struct btrfs_block_group_item item; struct btrfs_block_group_item item;
int data;
int cached;
u64 pinned; u64 pinned;
u64 flags;
int cached;
}; };
struct btrfs_device;
struct btrfs_fs_info { struct btrfs_fs_info {
u8 fsid[BTRFS_FSID_SIZE]; u8 fsid[BTRFS_FSID_SIZE];
struct btrfs_root *extent_root; struct btrfs_root *extent_root;
struct btrfs_root *tree_root; struct btrfs_root *tree_root;
struct btrfs_root *chunk_root;
struct btrfs_root *dev_root;
struct radix_tree_root fs_roots_radix; struct radix_tree_root fs_roots_radix;
struct extent_io_tree free_space_cache; struct extent_io_tree free_space_cache;
...@@ -321,6 +454,9 @@ struct btrfs_fs_info { ...@@ -321,6 +454,9 @@ struct btrfs_fs_info {
struct extent_io_tree pending_del; struct extent_io_tree pending_del;
struct extent_io_tree extent_ins; struct extent_io_tree extent_ins;
/* logical->physical extent mapping */
struct btrfs_mapping_tree mapping_tree;
u64 generation; u64 generation;
u64 last_trans_committed; u64 last_trans_committed;
unsigned long mount_opt; unsigned long mount_opt;
...@@ -330,6 +466,7 @@ struct btrfs_fs_info { ...@@ -330,6 +466,7 @@ struct btrfs_fs_info {
struct btrfs_transaction *running_transaction; struct btrfs_transaction *running_transaction;
struct btrfs_super_block super_copy; struct btrfs_super_block super_copy;
struct extent_buffer *sb_buffer; struct extent_buffer *sb_buffer;
struct block_device *__bdev;
struct super_block *sb; struct super_block *sb;
struct inode *btree_inode; struct inode *btree_inode;
spinlock_t hash_lock; spinlock_t hash_lock;
...@@ -350,12 +487,17 @@ struct btrfs_fs_info { ...@@ -350,12 +487,17 @@ struct btrfs_fs_info {
unsigned long throttles; unsigned long throttles;
u64 total_pinned; u64 total_pinned;
struct list_head dirty_cowonly_roots;
struct list_head devices;
struct list_head *last_device;
spinlock_t delalloc_lock; spinlock_t delalloc_lock;
spinlock_t new_trans_lock; spinlock_t new_trans_lock;
u64 delalloc_bytes; u64 delalloc_bytes;
u64 last_alloc; u64 last_alloc;
u64 last_data_alloc; u64 last_data_alloc;
}; };
/* /*
* in ram representation of the tree. extent_root is used for all allocations * in ram representation of the tree. extent_root is used for all allocations
* and for the extent tree extent_root root. * and for the extent tree extent_root root.
...@@ -387,14 +529,19 @@ struct btrfs_root { ...@@ -387,14 +529,19 @@ struct btrfs_root {
u64 highest_inode; u64 highest_inode;
u64 last_inode_alloc; u64 last_inode_alloc;
int ref_cows; int ref_cows;
int track_dirty;
struct btrfs_key defrag_progress; struct btrfs_key defrag_progress;
int defrag_running; int defrag_running;
int defrag_level; int defrag_level;
char *name; char *name;
int in_sysfs; int in_sysfs;
/* the dirty list is only used by non-reference counted roots */
struct list_head dirty_list;
}; };
/* /*
* inode items have the data typically returned from stat and store other * inode items have the data typically returned from stat and store other
* info about object characteristics. There is one for every file and dir in * info about object characteristics. There is one for every file and dir in
* the FS * the FS
...@@ -439,6 +586,10 @@ struct btrfs_root { ...@@ -439,6 +586,10 @@ struct btrfs_root {
*/ */
#define BTRFS_BLOCK_GROUP_ITEM_KEY 50 #define BTRFS_BLOCK_GROUP_ITEM_KEY 50
#define BTRFS_DEV_EXTENT_KEY 75
#define BTRFS_DEV_ITEM_KEY 76
#define BTRFS_CHUNK_ITEM_KEY 77
/* /*
* string items are for debugging. They just store a short string of * string items are for debugging. They just store a short string of
* data in the FS * data in the FS
...@@ -518,13 +669,104 @@ static inline void btrfs_set_##name(type *s, u##bits val) \ ...@@ -518,13 +669,104 @@ static inline void btrfs_set_##name(type *s, u##bits val) \
s->member = cpu_to_le##bits(val); \ s->member = cpu_to_le##bits(val); \
} }
BTRFS_SETGET_FUNCS(device_type, struct btrfs_dev_item, type, 64);
BTRFS_SETGET_FUNCS(device_total_bytes, struct btrfs_dev_item, total_bytes, 64);
BTRFS_SETGET_FUNCS(device_bytes_used, struct btrfs_dev_item, bytes_used, 64);
BTRFS_SETGET_FUNCS(device_io_align, struct btrfs_dev_item, io_align, 32);
BTRFS_SETGET_FUNCS(device_io_width, struct btrfs_dev_item, io_width, 32);
BTRFS_SETGET_FUNCS(device_sector_size, struct btrfs_dev_item, sector_size, 32);
BTRFS_SETGET_FUNCS(device_id, struct btrfs_dev_item, devid, 64);
BTRFS_SETGET_FUNCS(device_rdev, struct btrfs_dev_item, rdev, 64);
BTRFS_SETGET_FUNCS(device_partition, struct btrfs_dev_item, partition, 32);
BTRFS_SETGET_FUNCS(device_name_len, struct btrfs_dev_item, name_len, 16);
static inline char *btrfs_device_uuid(struct btrfs_dev_item *d)
{
return (char *)d + offsetof(struct btrfs_dev_item, uuid);
}
static inline char *btrfs_device_name(struct btrfs_dev_item *d)
{
return (char *)(d + 1);
}
BTRFS_SETGET_FUNCS(chunk_owner, struct btrfs_chunk, owner, 64);
BTRFS_SETGET_FUNCS(chunk_stripe_len, struct btrfs_chunk, stripe_len, 64);
BTRFS_SETGET_FUNCS(chunk_io_align, struct btrfs_chunk, io_align, 32);
BTRFS_SETGET_FUNCS(chunk_io_width, struct btrfs_chunk, io_width, 32);
BTRFS_SETGET_FUNCS(chunk_sector_size, struct btrfs_chunk, sector_size, 32);
BTRFS_SETGET_FUNCS(chunk_type, struct btrfs_chunk, type, 64);
BTRFS_SETGET_FUNCS(chunk_num_stripes, struct btrfs_chunk, num_stripes, 16);
BTRFS_SETGET_FUNCS(stripe_devid, struct btrfs_stripe, devid, 64);
BTRFS_SETGET_FUNCS(stripe_offset, struct btrfs_stripe, offset, 64);
BTRFS_SETGET_STACK_FUNCS(stack_chunk_owner, struct btrfs_chunk, owner, 64);
BTRFS_SETGET_STACK_FUNCS(stack_chunk_stripe_len, struct btrfs_chunk,
stripe_len, 64);
BTRFS_SETGET_STACK_FUNCS(stack_chunk_io_align, struct btrfs_chunk,
io_align, 32);
BTRFS_SETGET_STACK_FUNCS(stack_chunk_io_width, struct btrfs_chunk,
io_width, 32);
BTRFS_SETGET_STACK_FUNCS(stack_chunk_sector_size, struct btrfs_chunk,
sector_size, 32);
BTRFS_SETGET_STACK_FUNCS(stack_chunk_type, struct btrfs_chunk, type, 64);
BTRFS_SETGET_STACK_FUNCS(stack_chunk_num_stripes, struct btrfs_chunk,
num_stripes, 16);
BTRFS_SETGET_STACK_FUNCS(stack_stripe_devid, struct btrfs_stripe, devid, 64);
BTRFS_SETGET_STACK_FUNCS(stack_stripe_offset, struct btrfs_stripe, offset, 64);
static inline struct btrfs_stripe *btrfs_stripe_nr(struct btrfs_chunk *c,
int nr)
{
unsigned long offset = (unsigned long)c;
offset += offsetof(struct btrfs_chunk, stripe);
offset += nr * sizeof(struct btrfs_stripe);
return (struct btrfs_stripe *)offset;
}
static inline u64 btrfs_stripe_offset_nr(struct extent_buffer *eb,
struct btrfs_chunk *c, int nr)
{
return btrfs_stripe_offset(eb, btrfs_stripe_nr(c, nr));
}
static inline void btrfs_set_stripe_offset_nr(struct extent_buffer *eb,
struct btrfs_chunk *c, int nr,
u64 val)
{
btrfs_set_stripe_offset(eb, btrfs_stripe_nr(c, nr), val);
}
static inline u64 btrfs_stripe_devid_nr(struct extent_buffer *eb,
struct btrfs_chunk *c, int nr)
{
return btrfs_stripe_devid(eb, btrfs_stripe_nr(c, nr));
}
static inline void btrfs_set_stripe_devid_nr(struct extent_buffer *eb,
struct btrfs_chunk *c, int nr,
u64 val)
{
btrfs_set_stripe_devid(eb, btrfs_stripe_nr(c, nr), val);
}
/* struct btrfs_block_group_item */ /* struct btrfs_block_group_item */
BTRFS_SETGET_STACK_FUNCS(block_group_used, struct btrfs_block_group_item, BTRFS_SETGET_STACK_FUNCS(block_group_used, struct btrfs_block_group_item,
used, 64); used, 64);
BTRFS_SETGET_FUNCS(disk_block_group_used, struct btrfs_block_group_item, BTRFS_SETGET_FUNCS(disk_block_group_used, struct btrfs_block_group_item,
used, 64); used, 64);
BTRFS_SETGET_FUNCS(disk_block_group_flags, struct btrfs_block_group_item, BTRFS_SETGET_STACK_FUNCS(block_group_chunk_tree, struct btrfs_block_group_item,
flags, 8); chunk_tree, 64);
BTRFS_SETGET_FUNCS(disk_block_group_chunk_tree, struct btrfs_block_group_item,
chunk_tree, 64);
BTRFS_SETGET_STACK_FUNCS(block_group_chunk_objectid,
struct btrfs_block_group_item, chunk_objectid, 64);
BTRFS_SETGET_FUNCS(disk_block_group_chunk_objecitd,
struct btrfs_block_group_item, chunk_objectid, 64);
BTRFS_SETGET_FUNCS(disk_block_group_flags,
struct btrfs_block_group_item, flags, 64);
BTRFS_SETGET_STACK_FUNCS(block_group_flags,
struct btrfs_block_group_item, flags, 64);
/* struct btrfs_inode_ref */ /* struct btrfs_inode_ref */
BTRFS_SETGET_FUNCS(inode_ref_name_len, struct btrfs_inode_ref, name_len, 16); BTRFS_SETGET_FUNCS(inode_ref_name_len, struct btrfs_inode_ref, name_len, 16);
...@@ -538,49 +780,53 @@ BTRFS_SETGET_FUNCS(inode_nlink, struct btrfs_inode_item, nlink, 32); ...@@ -538,49 +780,53 @@ BTRFS_SETGET_FUNCS(inode_nlink, struct btrfs_inode_item, nlink, 32);
BTRFS_SETGET_FUNCS(inode_uid, struct btrfs_inode_item, uid, 32); BTRFS_SETGET_FUNCS(inode_uid, struct btrfs_inode_item, uid, 32);
BTRFS_SETGET_FUNCS(inode_gid, struct btrfs_inode_item, gid, 32); BTRFS_SETGET_FUNCS(inode_gid, struct btrfs_inode_item, gid, 32);
BTRFS_SETGET_FUNCS(inode_mode, struct btrfs_inode_item, mode, 32); BTRFS_SETGET_FUNCS(inode_mode, struct btrfs_inode_item, mode, 32);
BTRFS_SETGET_FUNCS(inode_rdev, struct btrfs_inode_item, rdev, 32); BTRFS_SETGET_FUNCS(inode_rdev, struct btrfs_inode_item, rdev, 64);
BTRFS_SETGET_FUNCS(inode_flags, struct btrfs_inode_item, flags, 16); BTRFS_SETGET_FUNCS(inode_flags, struct btrfs_inode_item, flags, 16);
BTRFS_SETGET_FUNCS(inode_compat_flags, struct btrfs_inode_item, BTRFS_SETGET_FUNCS(inode_compat_flags, struct btrfs_inode_item,
compat_flags, 16); compat_flags, 16);
static inline struct btrfs_inode_timespec * static inline struct btrfs_timespec *
btrfs_inode_atime(struct btrfs_inode_item *inode_item) btrfs_inode_atime(struct btrfs_inode_item *inode_item)
{ {
unsigned long ptr = (unsigned long)inode_item; unsigned long ptr = (unsigned long)inode_item;
ptr += offsetof(struct btrfs_inode_item, atime); ptr += offsetof(struct btrfs_inode_item, atime);
return (struct btrfs_inode_timespec *)ptr; return (struct btrfs_timespec *)ptr;
} }
static inline struct btrfs_inode_timespec * static inline struct btrfs_timespec *
btrfs_inode_mtime(struct btrfs_inode_item *inode_item) btrfs_inode_mtime(struct btrfs_inode_item *inode_item)
{ {
unsigned long ptr = (unsigned long)inode_item; unsigned long ptr = (unsigned long)inode_item;
ptr += offsetof(struct btrfs_inode_item, mtime); ptr += offsetof(struct btrfs_inode_item, mtime);
return (struct btrfs_inode_timespec *)ptr; return (struct btrfs_timespec *)ptr;
} }
static inline struct btrfs_inode_timespec * static inline struct btrfs_timespec *
btrfs_inode_ctime(struct btrfs_inode_item *inode_item) btrfs_inode_ctime(struct btrfs_inode_item *inode_item)
{ {
unsigned long ptr = (unsigned long)inode_item; unsigned long ptr = (unsigned long)inode_item;
ptr += offsetof(struct btrfs_inode_item, ctime); ptr += offsetof(struct btrfs_inode_item, ctime);
return (struct btrfs_inode_timespec *)ptr; return (struct btrfs_timespec *)ptr;
} }
static inline struct btrfs_inode_timespec * static inline struct btrfs_timespec *
btrfs_inode_otime(struct btrfs_inode_item *inode_item) btrfs_inode_otime(struct btrfs_inode_item *inode_item)
{ {
unsigned long ptr = (unsigned long)inode_item; unsigned long ptr = (unsigned long)inode_item;
ptr += offsetof(struct btrfs_inode_item, otime); ptr += offsetof(struct btrfs_inode_item, otime);
return (struct btrfs_inode_timespec *)ptr; return (struct btrfs_timespec *)ptr;
} }
BTRFS_SETGET_FUNCS(timespec_sec, struct btrfs_inode_timespec, sec, 64); BTRFS_SETGET_FUNCS(timespec_sec, struct btrfs_timespec, sec, 64);
BTRFS_SETGET_FUNCS(timespec_nsec, struct btrfs_inode_timespec, nsec, 32); BTRFS_SETGET_FUNCS(timespec_nsec, struct btrfs_timespec, nsec, 32);
/* struct btrfs_extent_item */ /* struct btrfs_extent_item */
BTRFS_SETGET_FUNCS(extent_refs, struct btrfs_extent_item, refs, 32); BTRFS_SETGET_FUNCS(extent_refs, struct btrfs_extent_item, refs, 32);
/* struct btrfs_dev_extent */
BTRFS_SETGET_FUNCS(dev_extent_owner, struct btrfs_dev_extent, owner, 64);
BTRFS_SETGET_FUNCS(dev_extent_length, struct btrfs_dev_extent, length, 64);
/* struct btrfs_extent_ref */ /* struct btrfs_extent_ref */
BTRFS_SETGET_FUNCS(ref_root, struct btrfs_extent_ref, root, 64); BTRFS_SETGET_FUNCS(ref_root, struct btrfs_extent_ref, root, 64);
BTRFS_SETGET_FUNCS(ref_generation, struct btrfs_extent_ref, generation, 64); BTRFS_SETGET_FUNCS(ref_generation, struct btrfs_extent_ref, generation, 64);
...@@ -846,8 +1092,14 @@ BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64); ...@@ -846,8 +1092,14 @@ BTRFS_SETGET_STACK_FUNCS(super_bytenr, struct btrfs_super_block, bytenr, 64);
BTRFS_SETGET_STACK_FUNCS(super_generation, struct btrfs_super_block, BTRFS_SETGET_STACK_FUNCS(super_generation, struct btrfs_super_block,
generation, 64); generation, 64);
BTRFS_SETGET_STACK_FUNCS(super_root, struct btrfs_super_block, root, 64); BTRFS_SETGET_STACK_FUNCS(super_root, struct btrfs_super_block, root, 64);
BTRFS_SETGET_STACK_FUNCS(super_sys_array_size,
struct btrfs_super_block, sys_chunk_array_size, 32);
BTRFS_SETGET_STACK_FUNCS(super_root_level, struct btrfs_super_block, BTRFS_SETGET_STACK_FUNCS(super_root_level, struct btrfs_super_block,
root_level, 8); root_level, 8);
BTRFS_SETGET_STACK_FUNCS(super_chunk_root, struct btrfs_super_block,
chunk_root, 64);
BTRFS_SETGET_STACK_FUNCS(super_chunk_root_level, struct btrfs_super_block,
chunk_root_level, 64);
BTRFS_SETGET_STACK_FUNCS(super_total_bytes, struct btrfs_super_block, BTRFS_SETGET_STACK_FUNCS(super_total_bytes, struct btrfs_super_block,
total_bytes, 64); total_bytes, 64);
BTRFS_SETGET_STACK_FUNCS(super_bytes_used, struct btrfs_super_block, BTRFS_SETGET_STACK_FUNCS(super_bytes_used, struct btrfs_super_block,
...@@ -1009,7 +1261,14 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, ...@@ -1009,7 +1261,14 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
struct btrfs_root *root); struct btrfs_root *root);
int btrfs_free_block_groups(struct btrfs_fs_info *info); int btrfs_free_block_groups(struct btrfs_fs_info *info);
int btrfs_read_block_groups(struct btrfs_root *root); int btrfs_read_block_groups(struct btrfs_root *root);
int btrfs_make_block_group(struct btrfs_trans_handle *trans,
struct btrfs_root *root, u64 bytes_used,
u64 type, u64 chunk_tree, u64 chunk_objectid,
u64 size);
/* ctree.c */ /* ctree.c */
int btrfs_previous_item(struct btrfs_root *root,
struct btrfs_path *path, u64 min_objectid,
int type);
int btrfs_cow_block(struct btrfs_trans_handle *trans, int btrfs_cow_block(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct extent_buffer *buf, struct btrfs_root *root, struct extent_buffer *buf,
struct extent_buffer *parent, int parent_slot, struct extent_buffer *parent, int parent_slot,
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "disk-io.h" #include "disk-io.h"
#include "transaction.h" #include "transaction.h"
#include "btrfs_inode.h" #include "btrfs_inode.h"
#include "volumes.h"
#include "print-tree.h" #include "print-tree.h"
#if 0 #if 0
...@@ -234,6 +235,19 @@ static int btree_writepage_io_hook(struct page *page, u64 start, u64 end) ...@@ -234,6 +235,19 @@ static int btree_writepage_io_hook(struct page *page, u64 start, u64 end)
return 0; return 0;
} }
static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio)
{
struct btrfs_root *root = BTRFS_I(inode)->root;
u64 offset;
offset = bio->bi_sector << 9;
if (offset == BTRFS_SUPER_INFO_OFFSET) {
bio->bi_bdev = root->fs_info->sb->s_bdev;
submit_bio(rw, bio);
return 0;
}
return btrfs_map_bio(BTRFS_I(inode)->root, rw, bio);
}
static int btree_writepage(struct page *page, struct writeback_control *wbc) static int btree_writepage(struct page *page, struct writeback_control *wbc)
{ {
struct extent_io_tree *tree; struct extent_io_tree *tree;
...@@ -345,6 +359,23 @@ int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize) ...@@ -345,6 +359,23 @@ int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize)
return ret; return ret;
} }
static int close_all_devices(struct btrfs_fs_info *fs_info)
{
struct list_head *list;
struct list_head *next;
struct btrfs_device *device;
list = &fs_info->devices;
while(!list_empty(list)) {
next = list->next;
list_del(next);
device = list_entry(next, struct btrfs_device, dev_list);
kfree(device->name);
kfree(device);
}
return 0;
}
struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
u32 blocksize) u32 blocksize)
{ {
...@@ -420,6 +451,8 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, ...@@ -420,6 +451,8 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
root->leafsize = leafsize; root->leafsize = leafsize;
root->stripesize = stripesize; root->stripesize = stripesize;
root->ref_cows = 0; root->ref_cows = 0;
root->track_dirty = 0;
root->fs_info = fs_info; root->fs_info = fs_info;
root->objectid = objectid; root->objectid = objectid;
root->last_trans = 0; root->last_trans = 0;
...@@ -427,6 +460,8 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, ...@@ -427,6 +460,8 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
root->last_inode_alloc = 0; root->last_inode_alloc = 0;
root->name = NULL; root->name = NULL;
root->in_sysfs = 0; root->in_sysfs = 0;
INIT_LIST_HEAD(&root->dirty_list);
memset(&root->root_key, 0, sizeof(root->root_key)); memset(&root->root_key, 0, sizeof(root->root_key));
memset(&root->root_item, 0, sizeof(root->root_item)); memset(&root->root_item, 0, sizeof(root->root_item));
memset(&root->defrag_progress, 0, sizeof(root->defrag_progress)); memset(&root->defrag_progress, 0, sizeof(root->defrag_progress));
...@@ -634,6 +669,10 @@ struct btrfs_root *open_ctree(struct super_block *sb) ...@@ -634,6 +669,10 @@ struct btrfs_root *open_ctree(struct super_block *sb)
GFP_NOFS); GFP_NOFS);
struct btrfs_fs_info *fs_info = kmalloc(sizeof(*fs_info), struct btrfs_fs_info *fs_info = kmalloc(sizeof(*fs_info),
GFP_NOFS); GFP_NOFS);
struct btrfs_root *chunk_root = kmalloc(sizeof(struct btrfs_root),
GFP_NOFS);
struct btrfs_root *dev_root = kmalloc(sizeof(struct btrfs_root),
GFP_NOFS);
int ret; int ret;
int err = -EIO; int err = -EIO;
struct btrfs_super_block *disk_super; struct btrfs_super_block *disk_super;
...@@ -657,6 +696,12 @@ struct btrfs_root *open_ctree(struct super_block *sb) ...@@ -657,6 +696,12 @@ struct btrfs_root *open_ctree(struct super_block *sb)
fs_info->last_trans_committed = 0; fs_info->last_trans_committed = 0;
fs_info->tree_root = tree_root; fs_info->tree_root = tree_root;
fs_info->extent_root = extent_root; fs_info->extent_root = extent_root;
fs_info->chunk_root = chunk_root;
fs_info->dev_root = dev_root;
INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots);
INIT_LIST_HEAD(&fs_info->devices);
btrfs_mapping_init(&fs_info->mapping_tree);
fs_info->last_device = &fs_info->devices;
fs_info->sb = sb; fs_info->sb = sb;
fs_info->throttles = 0; fs_info->throttles = 0;
fs_info->mount_opt = 0; fs_info->mount_opt = 0;
...@@ -714,12 +759,12 @@ struct btrfs_root *open_ctree(struct super_block *sb) ...@@ -714,12 +759,12 @@ struct btrfs_root *open_ctree(struct super_block *sb)
goto fail_iput; goto fail_iput;
} }
#endif #endif
__setup_root(512, 512, 512, 512, tree_root, __setup_root(4096, 4096, 4096, 4096, tree_root,
fs_info, BTRFS_ROOT_TREE_OBJECTID); fs_info, BTRFS_ROOT_TREE_OBJECTID);
fs_info->sb_buffer = read_tree_block(tree_root, fs_info->sb_buffer = read_tree_block(tree_root,
BTRFS_SUPER_INFO_OFFSET, BTRFS_SUPER_INFO_OFFSET,
512); 4096);
if (!fs_info->sb_buffer) if (!fs_info->sb_buffer)
goto fail_iput; goto fail_iput;
...@@ -730,6 +775,7 @@ struct btrfs_root *open_ctree(struct super_block *sb) ...@@ -730,6 +775,7 @@ struct btrfs_root *open_ctree(struct super_block *sb)
read_extent_buffer(fs_info->sb_buffer, fs_info->fsid, read_extent_buffer(fs_info->sb_buffer, fs_info->fsid,
(unsigned long)btrfs_super_fsid(fs_info->sb_buffer), (unsigned long)btrfs_super_fsid(fs_info->sb_buffer),
BTRFS_FSID_SIZE); BTRFS_FSID_SIZE);
disk_super = &fs_info->super_copy; 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;
...@@ -753,23 +799,47 @@ struct btrfs_root *open_ctree(struct super_block *sb) ...@@ -753,23 +799,47 @@ struct btrfs_root *open_ctree(struct super_block *sb)
goto fail_sb_buffer; goto fail_sb_buffer;
} }
mutex_lock(&fs_info->fs_mutex);
ret = btrfs_read_sys_array(tree_root);
BUG_ON(ret);
blocksize = btrfs_level_size(tree_root,
btrfs_super_chunk_root_level(disk_super));
__setup_root(nodesize, leafsize, sectorsize, stripesize,
chunk_root, fs_info, BTRFS_CHUNK_TREE_OBJECTID);
chunk_root->node = read_tree_block(chunk_root,
btrfs_super_chunk_root(disk_super),
blocksize);
BUG_ON(!chunk_root->node);
ret = btrfs_read_chunk_tree(chunk_root);
BUG_ON(ret);
blocksize = btrfs_level_size(tree_root, blocksize = btrfs_level_size(tree_root,
btrfs_super_root_level(disk_super)); btrfs_super_root_level(disk_super));
tree_root->node = read_tree_block(tree_root, tree_root->node = read_tree_block(tree_root,
btrfs_super_root(disk_super), btrfs_super_root(disk_super),
blocksize); blocksize);
if (!tree_root->node) if (!tree_root->node)
goto fail_sb_buffer; goto fail_sb_buffer;
mutex_lock(&fs_info->fs_mutex);
ret = find_and_setup_root(tree_root, fs_info, ret = find_and_setup_root(tree_root, fs_info,
BTRFS_EXTENT_TREE_OBJECTID, extent_root); BTRFS_EXTENT_TREE_OBJECTID, extent_root);
if (ret) { if (ret)
mutex_unlock(&fs_info->fs_mutex);
goto fail_tree_root; goto fail_tree_root;
} extent_root->track_dirty = 1;
ret = find_and_setup_root(tree_root, fs_info,
BTRFS_DEV_TREE_OBJECTID, dev_root);
dev_root->track_dirty = 1;
if (ret)
goto fail_extent_root;
btrfs_read_block_groups(extent_root); btrfs_read_block_groups(extent_root);
...@@ -777,7 +847,10 @@ struct btrfs_root *open_ctree(struct super_block *sb) ...@@ -777,7 +847,10 @@ struct btrfs_root *open_ctree(struct super_block *sb)
mutex_unlock(&fs_info->fs_mutex); mutex_unlock(&fs_info->fs_mutex);
return tree_root; return tree_root;
fail_extent_root:
free_extent_buffer(extent_root->node);
fail_tree_root: fail_tree_root:
mutex_unlock(&fs_info->fs_mutex);
free_extent_buffer(tree_root->node); free_extent_buffer(tree_root->node);
fail_sb_buffer: fail_sb_buffer:
free_extent_buffer(fs_info->sb_buffer); free_extent_buffer(fs_info->sb_buffer);
...@@ -874,6 +947,12 @@ int close_ctree(struct btrfs_root *root) ...@@ -874,6 +947,12 @@ int close_ctree(struct btrfs_root *root)
if (fs_info->tree_root->node) if (fs_info->tree_root->node)
free_extent_buffer(fs_info->tree_root->node); free_extent_buffer(fs_info->tree_root->node);
if (root->fs_info->chunk_root->node);
free_extent_buffer(root->fs_info->chunk_root->node);
if (root->fs_info->dev_root->node);
free_extent_buffer(root->fs_info->dev_root->node);
free_extent_buffer(fs_info->sb_buffer); free_extent_buffer(fs_info->sb_buffer);
btrfs_free_block_groups(root->fs_info); btrfs_free_block_groups(root->fs_info);
...@@ -901,8 +980,13 @@ int close_ctree(struct btrfs_root *root) ...@@ -901,8 +980,13 @@ int close_ctree(struct btrfs_root *root)
kfree(hasher); kfree(hasher);
} }
#endif #endif
close_all_devices(fs_info);
btrfs_mapping_tree_free(&fs_info->mapping_tree);
kfree(fs_info->extent_root); kfree(fs_info->extent_root);
kfree(fs_info->tree_root); kfree(fs_info->tree_root);
kfree(fs_info->chunk_root);
kfree(fs_info->dev_root);
return 0; return 0;
} }
...@@ -1016,4 +1100,5 @@ int btrfs_read_buffer(struct extent_buffer *buf) ...@@ -1016,4 +1100,5 @@ int btrfs_read_buffer(struct extent_buffer *buf)
static struct extent_io_ops btree_extent_io_ops = { static struct extent_io_ops btree_extent_io_ops = {
.writepage_io_hook = btree_writepage_io_hook, .writepage_io_hook = btree_writepage_io_hook,
.submit_bio_hook = btree_submit_bio_hook,
}; };
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#define __DISKIO__ #define __DISKIO__
#define BTRFS_SUPER_INFO_OFFSET (16 * 1024) #define BTRFS_SUPER_INFO_OFFSET (16 * 1024)
struct btrfs_device;
struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
u32 blocksize); u32 blocksize);
...@@ -65,4 +66,5 @@ int btrfs_read_buffer(struct extent_buffer *buf); ...@@ -65,4 +66,5 @@ int btrfs_read_buffer(struct extent_buffer *buf);
u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len); u32 btrfs_csum_data(struct btrfs_root *root, char *data, u32 seed, size_t len);
void btrfs_csum_final(u32 crc, char *result); void btrfs_csum_final(u32 crc, char *result);
void btrfs_throttle(struct btrfs_root *root); void btrfs_throttle(struct btrfs_root *root);
int btrfs_open_device(struct btrfs_device *dev);
#endif #endif
此差异已折叠。
...@@ -1706,8 +1706,8 @@ static int submit_one_bio(int rw, struct bio *bio) ...@@ -1706,8 +1706,8 @@ static int submit_one_bio(int rw, struct bio *bio)
WARN_ON(1); WARN_ON(1);
} }
if (tree->ops && tree->ops->submit_bio_hook) if (tree->ops && tree->ops->submit_bio_hook)
tree->ops->submit_bio_hook(rw, bio); tree->ops->submit_bio_hook(page->mapping->host, rw, bio);
else
submit_bio(rw, bio); submit_bio(rw, bio);
if (bio_flagged(bio, BIO_EOPNOTSUPP)) if (bio_flagged(bio, BIO_EOPNOTSUPP))
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
......
...@@ -28,7 +28,7 @@ struct extent_state; ...@@ -28,7 +28,7 @@ struct extent_state;
struct extent_io_ops { struct extent_io_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);
int (*submit_bio_hook)(int rw, struct bio *bio); int (*submit_bio_hook)(struct inode *inode, int rw, struct bio *bio);
int (*readpage_io_hook)(struct page *page, u64 start, u64 end); int (*readpage_io_hook)(struct page *page, u64 start, u64 end);
int (*readpage_end_io_hook)(struct page *page, u64 start, u64 end, int (*readpage_end_io_hook)(struct page *page, u64 start, u64 end,
struct extent_state *state); struct extent_state *state);
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include "btrfs_inode.h" #include "btrfs_inode.h"
#include "ioctl.h" #include "ioctl.h"
#include "print-tree.h" #include "print-tree.h"
#include "volumes.h"
struct btrfs_iget_args { struct btrfs_iget_args {
u64 ino; u64 ino;
...@@ -295,20 +296,20 @@ int btrfs_clear_bit_hook(struct inode *inode, u64 start, u64 end, ...@@ -295,20 +296,20 @@ int btrfs_clear_bit_hook(struct inode *inode, u64 start, u64 end,
return 0; return 0;
} }
int btrfs_submit_bio_hook(int rw, struct bio *bio) int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio)
{ {
struct bio_vec *bvec = bio->bi_io_vec;
struct inode *inode = bvec->bv_page->mapping->host;
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_trans_handle *trans; struct btrfs_trans_handle *trans;
int ret = 0; int ret = 0;
if (rw != WRITE) if (rw != WRITE) {
return 0; goto mapit;
}
if (btrfs_test_opt(root, NODATASUM) || if (btrfs_test_opt(root, NODATASUM) ||
btrfs_test_flag(inode, NODATASUM)) btrfs_test_flag(inode, NODATASUM)) {
return 0; goto mapit;
}
mutex_lock(&root->fs_info->fs_mutex); mutex_lock(&root->fs_info->fs_mutex);
trans = btrfs_start_transaction(root, 1); trans = btrfs_start_transaction(root, 1);
...@@ -317,7 +318,8 @@ int btrfs_submit_bio_hook(int rw, struct bio *bio) ...@@ -317,7 +318,8 @@ int btrfs_submit_bio_hook(int rw, struct bio *bio)
ret = btrfs_end_transaction(trans, root); ret = btrfs_end_transaction(trans, root);
BUG_ON(ret); BUG_ON(ret);
mutex_unlock(&root->fs_info->fs_mutex); mutex_unlock(&root->fs_info->fs_mutex);
return ret; mapit:
return btrfs_map_bio(root, rw, bio);
} }
int btrfs_readpage_io_hook(struct page *page, u64 start, u64 end) int btrfs_readpage_io_hook(struct page *page, u64 start, u64 end)
...@@ -406,7 +408,7 @@ void btrfs_read_locked_inode(struct inode *inode) ...@@ -406,7 +408,7 @@ void btrfs_read_locked_inode(struct inode *inode)
struct btrfs_path *path; struct btrfs_path *path;
struct extent_buffer *leaf; struct extent_buffer *leaf;
struct btrfs_inode_item *inode_item; struct btrfs_inode_item *inode_item;
struct btrfs_inode_timespec *tspec; struct btrfs_timespec *tspec;
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_key location; struct btrfs_key location;
u64 alloc_group_block; u64 alloc_group_block;
...@@ -455,7 +457,8 @@ void btrfs_read_locked_inode(struct inode *inode) ...@@ -455,7 +457,8 @@ void btrfs_read_locked_inode(struct inode *inode)
BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item); BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item);
if (!BTRFS_I(inode)->block_group) { if (!BTRFS_I(inode)->block_group) {
BTRFS_I(inode)->block_group = btrfs_find_block_group(root, BTRFS_I(inode)->block_group = btrfs_find_block_group(root,
NULL, 0, 0, 0); NULL, 0,
BTRFS_BLOCK_GROUP_METADATA, 0);
} }
btrfs_free_path(path); btrfs_free_path(path);
inode_item = NULL; inode_item = NULL;
...@@ -1550,7 +1553,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, ...@@ -1550,7 +1553,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
owner = 0; owner = 0;
else else
owner = 1; owner = 1;
group = btrfs_find_block_group(root, group, 0, 0, owner); group = btrfs_find_block_group(root, group, 0,
BTRFS_BLOCK_GROUP_METADATA, owner);
BTRFS_I(inode)->block_group = group; BTRFS_I(inode)->block_group = group;
BTRFS_I(inode)->flags = 0; BTRFS_I(inode)->flags = 0;
......
...@@ -20,6 +20,40 @@ ...@@ -20,6 +20,40 @@
#include "disk-io.h" #include "disk-io.h"
#include "print-tree.h" #include "print-tree.h"
static void print_chunk(struct extent_buffer *eb, struct btrfs_chunk *chunk)
{
int num_stripes = btrfs_chunk_num_stripes(eb, chunk);
int i;
printk("\t\tchunk owner %llu type %llu num_stripes %d\n",
(unsigned long long)btrfs_chunk_owner(eb, chunk),
(unsigned long long)btrfs_chunk_type(eb, chunk),
num_stripes);
for (i = 0 ; i < num_stripes ; i++) {
printk("\t\t\tstripe %d devid %llu offset %llu\n", i,
(unsigned long long)btrfs_stripe_devid_nr(eb, chunk, i),
(unsigned long long)btrfs_stripe_offset_nr(eb, chunk, i));
}
}
static void print_dev_item(struct extent_buffer *eb,
struct btrfs_dev_item *dev_item)
{
char *name;
int name_len;
name_len = btrfs_device_name_len(eb, dev_item);
name = kmalloc(name_len, GFP_NOFS);
if (name) {
read_extent_buffer(eb, name,
(unsigned long)btrfs_device_name(dev_item),
name_len);
}
printk("\t\tdev item name %.*s devid %llu "
"total_bytes %llu bytes used %Lu\n", name_len, name,
(unsigned long long)btrfs_device_id(eb, dev_item),
(unsigned long long)btrfs_device_total_bytes(eb, dev_item),
(unsigned long long)btrfs_device_bytes_used(eb, dev_item));
kfree(name);
}
void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
{ {
int i; int i;
...@@ -34,6 +68,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) ...@@ -34,6 +68,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
struct btrfs_key key; struct btrfs_key key;
struct btrfs_key found_key; struct btrfs_key found_key;
struct btrfs_extent_ref *ref; struct btrfs_extent_ref *ref;
struct btrfs_dev_extent *dev_extent;
u32 type; u32 type;
printk("leaf %llu total ptrs %d free space %d\n", printk("leaf %llu total ptrs %d free space %d\n",
...@@ -106,6 +141,19 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l) ...@@ -106,6 +141,19 @@ void btrfs_print_leaf(struct btrfs_root *root, struct extent_buffer *l)
printk("\t\tblock group used %llu\n", printk("\t\tblock group used %llu\n",
(unsigned long long)btrfs_disk_block_group_used(l, bi)); (unsigned long long)btrfs_disk_block_group_used(l, bi));
break; break;
case BTRFS_CHUNK_ITEM_KEY:
print_chunk(l, btrfs_item_ptr(l, i, struct btrfs_chunk));
break;
case BTRFS_DEV_ITEM_KEY:
print_dev_item(l, btrfs_item_ptr(l, i,
struct btrfs_dev_item));
break;
case BTRFS_DEV_EXTENT_KEY:
dev_extent = btrfs_item_ptr(l, i,
struct btrfs_dev_extent);
printk("\t\tdev extent owner %llu length %llu\n",
(unsigned long long)btrfs_dev_extent_owner(l, dev_extent),
(unsigned long long)btrfs_dev_extent_length(l, dev_extent));
}; };
} }
} }
......
...@@ -198,29 +198,42 @@ int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans, ...@@ -198,29 +198,42 @@ int btrfs_write_and_wait_transaction(struct btrfs_trans_handle *trans,
return werr; return werr;
} }
int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans, static int update_cowonly_root(struct btrfs_trans_handle *trans,
struct btrfs_root *root) struct btrfs_root *root)
{ {
int ret; int ret;
u64 old_extent_block; u64 old_root_bytenr;
struct btrfs_fs_info *fs_info = root->fs_info; struct btrfs_root *tree_root = root->fs_info->tree_root;
struct btrfs_root *tree_root = fs_info->tree_root;
struct btrfs_root *extent_root = fs_info->extent_root;
btrfs_write_dirty_block_groups(trans, extent_root); btrfs_write_dirty_block_groups(trans, root);
while(1) { while(1) {
old_extent_block = btrfs_root_bytenr(&extent_root->root_item); old_root_bytenr = btrfs_root_bytenr(&root->root_item);
if (old_extent_block == extent_root->node->start) if (old_root_bytenr == root->node->start)
break; break;
btrfs_set_root_bytenr(&extent_root->root_item, btrfs_set_root_bytenr(&root->root_item,
extent_root->node->start); root->node->start);
btrfs_set_root_level(&extent_root->root_item, btrfs_set_root_level(&root->root_item,
btrfs_header_level(extent_root->node)); btrfs_header_level(root->node));
ret = btrfs_update_root(trans, tree_root, ret = btrfs_update_root(trans, tree_root,
&extent_root->root_key, &root->root_key,
&extent_root->root_item); &root->root_item);
BUG_ON(ret); BUG_ON(ret);
btrfs_write_dirty_block_groups(trans, extent_root); btrfs_write_dirty_block_groups(trans, root);
}
return 0;
}
int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans,
struct btrfs_root *root)
{
struct btrfs_fs_info *fs_info = root->fs_info;
struct list_head *next;
while(!list_empty(&fs_info->dirty_cowonly_roots)) {
next = fs_info->dirty_cowonly_roots.next;
list_del_init(next);
root = list_entry(next, struct btrfs_root, dirty_list);
update_cowonly_root(trans, root);
} }
return 0; return 0;
} }
...@@ -616,6 +629,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, ...@@ -616,6 +629,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
unsigned long timeout = 1; unsigned long timeout = 1;
struct btrfs_transaction *cur_trans; struct btrfs_transaction *cur_trans;
struct btrfs_transaction *prev_trans = NULL; struct btrfs_transaction *prev_trans = NULL;
struct btrfs_root *chunk_root = root->fs_info->chunk_root;
struct list_head dirty_fs_roots; struct list_head dirty_fs_roots;
struct extent_io_tree *pinned_copy; struct extent_io_tree *pinned_copy;
DEFINE_WAIT(wait); DEFINE_WAIT(wait);
...@@ -714,6 +728,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, ...@@ -714,6 +728,10 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
btrfs_set_super_root_level(&root->fs_info->super_copy, btrfs_set_super_root_level(&root->fs_info->super_copy,
btrfs_header_level(root->fs_info->tree_root->node)); btrfs_header_level(root->fs_info->tree_root->node));
btrfs_set_super_chunk_root(&root->fs_info->super_copy,
chunk_root->node->start);
btrfs_set_super_chunk_root_level(&root->fs_info->super_copy,
btrfs_header_level(chunk_root->node));
write_extent_buffer(root->fs_info->sb_buffer, write_extent_buffer(root->fs_info->sb_buffer,
&root->fs_info->super_copy, 0, &root->fs_info->super_copy, 0,
sizeof(root->fs_info->super_copy)); sizeof(root->fs_info->super_copy));
......
此差异已折叠。
/*
* Copyright (C) 2007 Oracle. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License v2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 021110-1307, USA.
*/
#ifndef __BTRFS_VOLUMES_
#define __BTRFS_VOLUMES_
struct btrfs_device {
struct list_head dev_list;
struct btrfs_root *dev_root;
struct btrfs_key dev_key;
struct block_device *bdev;
/* the internal btrfs device id */
u64 devid;
/* size of the device */
u64 total_bytes;
/* bytes used */
u64 bytes_used;
/* optimal io alignment for this device */
u32 io_align;
/* optimal io width for this device */
u32 io_width;
/* minimal io size for this device */
u32 sector_size;
/* the kernel device number */
u64 rdev;
/* type and info about this device */
u64 type;
/* partition number, 0 for whole dev */
int partition;
/* length of the name data at the end of the item */
int name_len;
/* physical drive uuid (or lvm uuid) */
u8 uuid[BTRFS_DEV_UUID_SIZE];
char *name;
};
int btrfs_alloc_dev_extent(struct btrfs_trans_handle *trans,
struct btrfs_device *device,
u64 owner, u64 num_bytes, u64 *start);
int btrfs_map_block(struct btrfs_mapping_tree *map_tree,
u64 logical, u64 *phys, u64 *length,
struct btrfs_device **dev);
int btrfs_read_sys_array(struct btrfs_root *root);
int btrfs_read_chunk_tree(struct btrfs_root *root);
int btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
struct btrfs_root *extent_root, u64 *start,
u64 *num_bytes, u32 type);
void btrfs_mapping_init(struct btrfs_mapping_tree *tree);
void btrfs_mapping_tree_free(struct btrfs_mapping_tree *tree);
int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio);
#endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册