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 @@
* fsck
* 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 @@
struct btrfs_inode {
u32 magic;
struct btrfs_root *root;
struct btrfs_key location;
struct inode vfs_inode;
u32 magic2;
};
......
......@@ -3,6 +3,7 @@
#include <linux/fs.h>
#include <linux/buffer_head.h>
#include <linux/kobject.h>
#include "bit-radix.h"
struct btrfs_trans_handle;
......@@ -183,13 +184,15 @@ struct btrfs_inline_data_item {
} __attribute__ ((__packed__));
struct btrfs_dir_item {
__le64 objectid;
struct btrfs_disk_key location;
__le16 flags;
__le16 name_len;
u8 type;
} __attribute__ ((__packed__));
struct btrfs_root_item {
struct btrfs_inode_item inode;
__le64 root_dirid;
__le64 blocknr;
__le32 flags;
__le64 block_limit;
......@@ -249,6 +252,7 @@ struct btrfs_fs_info {
struct mutex fs_mutex;
struct crypto_hash *hash_tfm;
spinlock_t hash_lock;
struct kobject kobj;
};
/*
......@@ -504,16 +508,6 @@ static inline void btrfs_set_item_size(struct btrfs_item *item, u16 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)
{
return le16_to_cpu(d->flags);
......@@ -724,6 +718,16 @@ static inline void btrfs_set_root_blocknr(struct btrfs_root_item *item, u64 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)
{
return le32_to_cpu(item->refs);
......@@ -950,8 +954,8 @@ int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct
btrfs_root_item *item, struct btrfs_key *key);
/* dir-item.c */
int btrfs_insert_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
*root, const char *name, int name_len, u64 dir, u64
objectid, u8 type);
*root, const char *name, int name_len, u64 dir,
struct btrfs_key *location, u8 type);
int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root
*root, struct btrfs_path *path, u64 dir,
const char *name, int name_len, int mod);
......@@ -978,7 +982,8 @@ int btrfs_insert_inode(struct btrfs_trans_handle *trans, struct btrfs_root
*root, u64 objectid, struct btrfs_inode_item
*inode_item);
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 */
int btrfs_alloc_file_extent(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,
u64 objectid, u64 offset,
char *data, size_t len);
/* super.c */
extern struct subsystem btrfs_subsys;
#endif
......@@ -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
*root, const char *name, int name_len, u64 dir, u64
objectid, u8 type)
*root, const char *name, int name_len, u64 dir,
struct btrfs_key *location, u8 type)
{
int ret = 0;
struct btrfs_path *path;
......@@ -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]),
path->slots[0],
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_flags(dir_item, 0);
btrfs_set_dir_name_len(dir_item, name_len);
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_mark_buffer_dirty(path->nodes[0]);
btrfs_release_path(root, path);
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);
// FIXME clear the dirindex bit
if (ret)
......@@ -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]),
path->slots[0],
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_flags(dir_item, 0);
btrfs_set_dir_name_len(dir_item, name_len);
......
......@@ -338,7 +338,6 @@ struct btrfs_root *open_ctree(struct super_block *sb)
sb->s_blocksize);
if (!fs_info->sb_buffer) {
printk("failed2\n");
return NULL;
}
disk_super = (struct btrfs_super_block *)fs_info->sb_buffer->b_data;
......@@ -369,6 +368,10 @@ printk("failed2\n");
ret = btrfs_find_highest_inode(root, &root->fs_info->last_inode_alloc);
if (ret == 0)
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);
return root;
}
......@@ -430,7 +433,7 @@ int close_ctree(struct btrfs_root *root)
kfree(root->fs_info->extent_root);
kfree(root->fs_info->inode_root);
kfree(root->fs_info->tree_root);
kfree(root->fs_info);
kobject_unregister(&root->fs_info->kobj);
kfree(root);
return 0;
}
......
......@@ -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
*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 cow = mod != 0;
int ret;
int slot;
struct btrfs_leaf *leaf;
struct btrfs_key found_key;
key.objectid = objectid;
key.flags = 0;
btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY);
key.offset = 0;
return btrfs_search_slot(trans, root, &key, path, ins_len, cow);
ret = btrfs_search_slot(trans, root, location, path, ins_len, cow);
if (ret > 0 && btrfs_key_type(location) == BTRFS_ROOT_ITEM_KEY &&
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);
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)
case BTRFS_DIR_ITEM_KEY:
di = btrfs_item_ptr(l, i, struct btrfs_dir_item);
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_type(di));
printk("\t\tname %.*s\n",
......
This diff is collapsed.
......@@ -52,6 +52,8 @@ struct btrfs_trans_handle *btrfs_start_transaction(struct btrfs_root *root,
kmem_cache_alloc(btrfs_trans_handle_cachep, GFP_NOFS);
int ret;
/* FIXME, use the right root */
root = root->fs_info->fs_root;
mutex_lock(&root->fs_info->trans_mutex);
ret = join_transaction(root);
BUG_ON(ret);
......@@ -69,6 +71,10 @@ int btrfs_end_transaction(struct btrfs_trans_handle *trans,
struct btrfs_root *root)
{
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->magic2 != TRANS_MAGIC);
mutex_lock(&root->fs_info->trans_mutex);
......@@ -148,6 +154,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
struct btrfs_transaction *cur_trans;
DEFINE_WAIT(wait);
/* FIXME, use the right root */
root = root->fs_info->fs_root;
mutex_lock(&root->fs_info->trans_mutex);
if (trans->transaction->in_commit) {
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