Commit d6e4a428 authored by Chris Mason's avatar Chris Mason Committed by David Woodhouse

Btrfs: start of support for many FS volumes

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 3eb0314d
...@@ -19,3 +19,10 @@ ...@@ -19,3 +19,10 @@
* fsck * fsck
* Scrub & defrag * Scrub & defrag
---
metata FS ideas:
mount metadata FS on /sys/fs/btrfs/dev/
subvolumes in /sys/fs/btrfs/dev/fs/
snapshots in /sys/fs/btrfs/dev/fs/snapshots
mount -o bind
ioctl to create a snapshot
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
struct btrfs_inode { struct btrfs_inode {
u32 magic; u32 magic;
struct btrfs_root *root;
struct btrfs_key location;
struct inode vfs_inode; struct inode vfs_inode;
u32 magic2; u32 magic2;
}; };
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/kobject.h>
#include "bit-radix.h" #include "bit-radix.h"
struct btrfs_trans_handle; struct btrfs_trans_handle;
...@@ -183,13 +184,15 @@ struct btrfs_inline_data_item { ...@@ -183,13 +184,15 @@ struct btrfs_inline_data_item {
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
struct btrfs_dir_item { struct btrfs_dir_item {
__le64 objectid; struct btrfs_disk_key location;
__le16 flags; __le16 flags;
__le16 name_len; __le16 name_len;
u8 type; u8 type;
} __attribute__ ((__packed__)); } __attribute__ ((__packed__));
struct btrfs_root_item { struct btrfs_root_item {
struct btrfs_inode_item inode;
__le64 root_dirid;
__le64 blocknr; __le64 blocknr;
__le32 flags; __le32 flags;
__le64 block_limit; __le64 block_limit;
...@@ -249,6 +252,7 @@ struct btrfs_fs_info { ...@@ -249,6 +252,7 @@ struct btrfs_fs_info {
struct mutex fs_mutex; struct mutex fs_mutex;
struct crypto_hash *hash_tfm; struct crypto_hash *hash_tfm;
spinlock_t hash_lock; spinlock_t hash_lock;
struct kobject kobj;
}; };
/* /*
...@@ -504,16 +508,6 @@ static inline void btrfs_set_item_size(struct btrfs_item *item, u16 val) ...@@ -504,16 +508,6 @@ static inline void btrfs_set_item_size(struct btrfs_item *item, u16 val)
item->size = cpu_to_le16(val); item->size = cpu_to_le16(val);
} }
static inline u64 btrfs_dir_objectid(struct btrfs_dir_item *d)
{
return le64_to_cpu(d->objectid);
}
static inline void btrfs_set_dir_objectid(struct btrfs_dir_item *d, u64 val)
{
d->objectid = cpu_to_le64(val);
}
static inline u16 btrfs_dir_flags(struct btrfs_dir_item *d) static inline u16 btrfs_dir_flags(struct btrfs_dir_item *d)
{ {
return le16_to_cpu(d->flags); return le16_to_cpu(d->flags);
...@@ -724,6 +718,16 @@ static inline void btrfs_set_root_blocknr(struct btrfs_root_item *item, u64 val) ...@@ -724,6 +718,16 @@ static inline void btrfs_set_root_blocknr(struct btrfs_root_item *item, u64 val)
item->blocknr = cpu_to_le64(val); item->blocknr = cpu_to_le64(val);
} }
static inline u64 btrfs_root_dirid(struct btrfs_root_item *item)
{
return le64_to_cpu(item->root_dirid);
}
static inline void btrfs_set_root_dirid(struct btrfs_root_item *item, u64 val)
{
item->root_dirid = cpu_to_le64(val);
}
static inline u32 btrfs_root_refs(struct btrfs_root_item *item) static inline u32 btrfs_root_refs(struct btrfs_root_item *item)
{ {
return le32_to_cpu(item->refs); return le32_to_cpu(item->refs);
...@@ -950,8 +954,8 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct ...@@ -950,8 +954,8 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct
btrfs_root_item *item, struct btrfs_key *key); btrfs_root_item *item, struct btrfs_key *key);
/* dir-item.c */ /* dir-item.c */
int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
*root, const char *name, int name_len, u64 dir, u64 *root, const char *name, int name_len, u64 dir,
objectid, u8 type); struct btrfs_key *location, u8 type);
int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
*root, struct btrfs_path *path, u64 dir, *root, struct btrfs_path *path, u64 dir,
const char *name, int name_len, int mod); const char *name, int name_len, int mod);
...@@ -978,7 +982,8 @@ int btrfs_insert_inode(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -978,7 +982,8 @@ int btrfs_insert_inode(struct btrfs_trans_handle *trans, struct btrfs_root
*root, u64 objectid, struct btrfs_inode_item *root, u64 objectid, struct btrfs_inode_item
*inode_item); *inode_item);
int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root
*root, struct btrfs_path *path, u64 objectid, int mod); *root, struct btrfs_path *path,
struct btrfs_key *location, int mod);
/* file-item.c */ /* file-item.c */
int btrfs_alloc_file_extent(struct btrfs_trans_handle *trans, int btrfs_alloc_file_extent(struct btrfs_trans_handle *trans,
...@@ -997,4 +1002,7 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans, ...@@ -997,4 +1002,7 @@ int btrfs_csum_file_block(struct btrfs_trans_handle *trans,
int btrfs_csum_verify_file_block(struct btrfs_root *root, int btrfs_csum_verify_file_block(struct btrfs_root *root,
u64 objectid, u64 offset, u64 objectid, u64 offset,
char *data, size_t len); char *data, size_t len);
/* super.c */
extern struct subsystem btrfs_subsys;
#endif #endif
...@@ -25,8 +25,8 @@ int insert_with_overflow(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -25,8 +25,8 @@ int insert_with_overflow(struct btrfs_trans_handle *trans, struct btrfs_root
} }
int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
*root, const char *name, int name_len, u64 dir, u64 *root, const char *name, int name_len, u64 dir,
objectid, u8 type) struct btrfs_key *location, u8 type)
{ {
int ret = 0; int ret = 0;
struct btrfs_path *path; struct btrfs_path *path;
...@@ -50,17 +50,21 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -50,17 +50,21 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
dir_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), dir_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]),
path->slots[0], path->slots[0],
struct btrfs_dir_item); struct btrfs_dir_item);
btrfs_set_dir_objectid(dir_item, objectid); btrfs_cpu_key_to_disk(&dir_item->location, location);
btrfs_set_dir_type(dir_item, type); btrfs_set_dir_type(dir_item, type);
btrfs_set_dir_flags(dir_item, 0); btrfs_set_dir_flags(dir_item, 0);
btrfs_set_dir_name_len(dir_item, name_len); btrfs_set_dir_name_len(dir_item, name_len);
name_ptr = (char *)(dir_item + 1); name_ptr = (char *)(dir_item + 1);
/* FIXME, use some real flag for selecting the extra index */
if (root == root->fs_info->tree_root)
goto out;
btrfs_memcpy(root, path->nodes[0]->b_data, name_ptr, name, name_len); btrfs_memcpy(root, path->nodes[0]->b_data, name_ptr, name, name_len);
btrfs_mark_buffer_dirty(path->nodes[0]); btrfs_mark_buffer_dirty(path->nodes[0]);
btrfs_release_path(root, path); btrfs_release_path(root, path);
btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY); btrfs_set_key_type(&key, BTRFS_DIR_INDEX_KEY);
key.offset = objectid; key.offset = location->objectid;
ret = insert_with_overflow(trans, root, path, &key, data_size); ret = insert_with_overflow(trans, root, path, &key, data_size);
// FIXME clear the dirindex bit // FIXME clear the dirindex bit
if (ret) if (ret)
...@@ -69,7 +73,7 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -69,7 +73,7 @@ int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
dir_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), dir_item = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]),
path->slots[0], path->slots[0],
struct btrfs_dir_item); struct btrfs_dir_item);
btrfs_set_dir_objectid(dir_item, objectid); btrfs_cpu_key_to_disk(&dir_item->location, location);
btrfs_set_dir_type(dir_item, type); btrfs_set_dir_type(dir_item, type);
btrfs_set_dir_flags(dir_item, 0); btrfs_set_dir_flags(dir_item, 0);
btrfs_set_dir_name_len(dir_item, name_len); btrfs_set_dir_name_len(dir_item, name_len);
......
...@@ -338,7 +338,6 @@ struct btrfs_root *open_ctree(struct super_block *sb) ...@@ -338,7 +338,6 @@ struct btrfs_root *open_ctree(struct super_block *sb)
sb->s_blocksize); sb->s_blocksize);
if (!fs_info->sb_buffer) { if (!fs_info->sb_buffer) {
printk("failed2\n");
return NULL; return NULL;
} }
disk_super = (struct btrfs_super_block *)fs_info->sb_buffer->b_data; disk_super = (struct btrfs_super_block *)fs_info->sb_buffer->b_data;
...@@ -369,6 +368,10 @@ printk("failed2\n"); ...@@ -369,6 +368,10 @@ printk("failed2\n");
ret = btrfs_find_highest_inode(root, &root->fs_info->last_inode_alloc); ret = btrfs_find_highest_inode(root, &root->fs_info->last_inode_alloc);
if (ret == 0) if (ret == 0)
fs_info->highest_inode = fs_info->last_inode_alloc; fs_info->highest_inode = fs_info->last_inode_alloc;
memset(&fs_info->kobj, 0, sizeof(fs_info->kobj));
kobj_set_kset_s(fs_info, btrfs_subsys);
kobject_set_name(&fs_info->kobj, "%s", sb->s_id);
kobject_register(&fs_info->kobj);
mutex_unlock(&fs_info->fs_mutex); mutex_unlock(&fs_info->fs_mutex);
return root; return root;
} }
...@@ -430,7 +433,7 @@ int close_ctree(struct btrfs_root *root) ...@@ -430,7 +433,7 @@ int close_ctree(struct btrfs_root *root)
kfree(root->fs_info->extent_root); kfree(root->fs_info->extent_root);
kfree(root->fs_info->inode_root); kfree(root->fs_info->inode_root);
kfree(root->fs_info->tree_root); kfree(root->fs_info->tree_root);
kfree(root->fs_info); kobject_unregister(&root->fs_info->kobj);
kfree(root); kfree(root);
return 0; return 0;
} }
......
...@@ -26,15 +26,27 @@ int btrfs_insert_inode(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -26,15 +26,27 @@ int btrfs_insert_inode(struct btrfs_trans_handle *trans, struct btrfs_root
} }
int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root
*root, struct btrfs_path *path, u64 objectid, int mod) *root, struct btrfs_path *path,
struct btrfs_key *location, int mod)
{ {
struct btrfs_key key;
int ins_len = mod < 0 ? -1 : 0; int ins_len = mod < 0 ? -1 : 0;
int cow = mod != 0; int cow = mod != 0;
int ret;
int slot;
struct btrfs_leaf *leaf;
struct btrfs_key found_key;
key.objectid = objectid; ret = btrfs_search_slot(trans, root, location, path, ins_len, cow);
key.flags = 0; if (ret > 0 && btrfs_key_type(location) == BTRFS_ROOT_ITEM_KEY &&
btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY); location->offset == (u64)-1 && path->slots[0] != 0) {
key.offset = 0; slot = path->slots[0] - 1;
return btrfs_search_slot(trans, root, &key, path, ins_len, cow); leaf = btrfs_buffer_leaf(path->nodes[0]);
btrfs_disk_key_to_cpu(&found_key, &leaf->items[slot].key);
if (found_key.objectid == location->objectid &&
btrfs_key_type(&found_key) == btrfs_key_type(location)) {
path->slots[0]--;
return 0;
}
}
return ret;
} }
...@@ -38,7 +38,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) ...@@ -38,7 +38,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l)
case BTRFS_DIR_ITEM_KEY: case BTRFS_DIR_ITEM_KEY:
di = btrfs_item_ptr(l, i, struct btrfs_dir_item); di = btrfs_item_ptr(l, i, struct btrfs_dir_item);
printk("\t\tdir oid %Lu flags %u type %u\n", printk("\t\tdir oid %Lu flags %u type %u\n",
btrfs_dir_objectid(di), btrfs_disk_key_objectid(&di->location),
btrfs_dir_flags(di), btrfs_dir_flags(di),
btrfs_dir_type(di)); btrfs_dir_type(di));
printk("\t\tname %.*s\n", printk("\t\tname %.*s\n",
......
This diff is collapsed.
...@@ -52,6 +52,8 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root, ...@@ -52,6 +52,8 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS); kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS);
int ret; int ret;
/* FIXME, use the right root */
root = root->fs_info->fs_root;
mutex_lock(&root->fs_info->trans_mutex); mutex_lock(&root->fs_info->trans_mutex);
ret = join_transaction(root); ret = join_transaction(root);
BUG_ON(ret); BUG_ON(ret);
...@@ -69,6 +71,10 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans, ...@@ -69,6 +71,10 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans,
struct btrfs_root *root) struct btrfs_root *root)
{ {
struct btrfs_transaction *cur_trans; struct btrfs_transaction *cur_trans;
/* FIXME, use the right root */
root = root->fs_info->fs_root;
WARN_ON(trans->magic != TRANS_MAGIC); WARN_ON(trans->magic != TRANS_MAGIC);
WARN_ON(trans->magic2 != TRANS_MAGIC); WARN_ON(trans->magic2 != TRANS_MAGIC);
mutex_lock(&root->fs_info->trans_mutex); mutex_lock(&root->fs_info->trans_mutex);
...@@ -148,6 +154,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, ...@@ -148,6 +154,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
struct btrfs_transaction *cur_trans; struct btrfs_transaction *cur_trans;
DEFINE_WAIT(wait); DEFINE_WAIT(wait);
/* FIXME, use the right root */
root = root->fs_info->fs_root;
mutex_lock(&root->fs_info->trans_mutex); mutex_lock(&root->fs_info->trans_mutex);
if (trans->transaction->in_commit) { if (trans->transaction->in_commit) {
printk("already in commit!, waiting\n"); printk("already in commit!, waiting\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment