Skip to content

Commit

Permalink
Btrfs: Add per-root block accounting and sysfs entries
Browse files Browse the repository at this point in the history
Signed-off-by: Chris Mason <chris.mason@oracle.com>
  • Loading branch information
Josef Bacik authored and David Woodhouse committed Aug 29, 2007
1 parent b888db2 commit 58176a9
Show file tree
Hide file tree
Showing 9 changed files with 393 additions and 11 deletions.
2 changes: 1 addition & 1 deletion fs/btrfs/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ obj-m := btrfs.o
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 \
transaction.o bit-radix.o inode.o file.o tree-defrag.o \
extent_map.o
extent_map.o sysfs.o

#btrfs-y := ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \
# root-tree.o dir-item.o hash.o file-item.o inode-item.o \
Expand Down
54 changes: 54 additions & 0 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <linux/fs.h>
#include <linux/buffer_head.h>
#include <linux/workqueue.h>
#include <linux/completion.h>
#include "bit-radix.h"

struct btrfs_trans_handle;
Expand Down Expand Up @@ -313,6 +314,8 @@ struct btrfs_fs_info {
struct list_head trans_list;
struct list_head dead_roots;
struct delayed_work trans_work;
struct kobject super_kobj;
struct completion kobj_unregister;
int do_barriers;
int closing;
};
Expand All @@ -328,6 +331,8 @@ struct btrfs_root {
struct btrfs_key root_key;
struct btrfs_fs_info *fs_info;
struct inode *inode;
struct kobject root_kobj;
struct completion kobj_unregister;
u64 objectid;
u64 last_trans;
u32 blocksize;
Expand All @@ -338,6 +343,7 @@ struct btrfs_root {
struct btrfs_key defrag_progress;
int defrag_running;
int defrag_level;
char *name;
};

/* the lower bits in the key flags defines the item type */
Expand Down Expand Up @@ -814,6 +820,28 @@ static inline void btrfs_set_root_flags(struct btrfs_root_item *item, u32 val)
item->flags = cpu_to_le32(val);
}

static inline void btrfs_set_root_blocks_used(struct btrfs_root_item *item,
u64 val)
{
item->blocks_used = cpu_to_le64(val);
}

static inline u64 btrfs_root_blocks_used(struct btrfs_root_item *item)
{
return le64_to_cpu(item->blocks_used);
}

static inline void btrfs_set_root_block_limit(struct btrfs_root_item *item,
u64 val)
{
item->block_limit = cpu_to_le64(val);
}

static inline u64 btrfs_root_block_limit(struct btrfs_root_item *item)
{
return le64_to_cpu(item->block_limit);
}

static inline u64 btrfs_super_blocknr(struct btrfs_super_block *s)
{
return le64_to_cpu(s->blocknr);
Expand Down Expand Up @@ -1014,6 +1042,23 @@ static inline void btrfs_memmove(struct btrfs_root *root,
memmove(dst, src, nr);
}

static inline int btrfs_set_root_name(struct btrfs_root *root,
const char *name, int len)
{
/* if we already have a name just free it */
if (root->name)
kfree(root->name);

root->name = kmalloc(len+1, GFP_KERNEL);
if (!root->name)
return -ENOMEM;

memcpy(root->name, name, len);
root->name[len] ='\0';

return 0;
}

/* helper function to cast into the data area of the leaf. */
#define btrfs_item_ptr(leaf, slot, type) \
((type *)(btrfs_leaf_data(leaf) + \
Expand Down Expand Up @@ -1191,4 +1236,13 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans,
/* tree-defrag.c */
int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
struct btrfs_root *root, int cache_only);

/* sysfs.c */
int btrfs_init_sysfs(void);
void btrfs_exit_sysfs(void);
int btrfs_sysfs_add_super(struct btrfs_fs_info *fs);
int btrfs_sysfs_add_root(struct btrfs_root *root);
void btrfs_sysfs_del_root(struct btrfs_root *root);
void btrfs_sysfs_del_super(struct btrfs_fs_info *root);

#endif
31 changes: 29 additions & 2 deletions fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,9 +294,12 @@ static int __setup_root(int blocksize,
root->last_trans = 0;
root->highest_inode = 0;
root->last_inode_alloc = 0;
root->name = NULL;
memset(&root->root_key, 0, sizeof(root->root_key));
memset(&root->root_item, 0, sizeof(root->root_item));
memset(&root->defrag_progress, 0, sizeof(root->defrag_progress));
memset(&root->root_kobj, 0, sizeof(root->root_kobj));
init_completion(&root->kobj_unregister);
root->defrag_running = 0;
root->defrag_level = 0;
root->root_key.objectid = objectid;
Expand Down Expand Up @@ -384,7 +387,8 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_fs_info *fs_info,
}

struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
struct btrfs_key *location)
struct btrfs_key *location,
const char *name, int namelen)
{
struct btrfs_root *root;
int ret;
Expand All @@ -405,6 +409,22 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
kfree(root);
return ERR_PTR(ret);
}

ret = btrfs_set_root_name(root, name, namelen);
if (ret) {
brelse(root->node);
kfree(root);
return ERR_PTR(ret);
}

ret = btrfs_sysfs_add_root(root);
if (ret) {
brelse(root->node);
kfree(root->name);
kfree(root);
return ERR_PTR(ret);
}

return root;
}

Expand Down Expand Up @@ -433,6 +453,8 @@ struct btrfs_root *open_ctree(struct super_block *sb)
INIT_RADIX_TREE(&fs_info->block_group_data_radix, GFP_KERNEL);
INIT_LIST_HEAD(&fs_info->trans_list);
INIT_LIST_HEAD(&fs_info->dead_roots);
memset(&fs_info->super_kobj, 0, sizeof(fs_info->super_kobj));
init_completion(&fs_info->kobj_unregister);
sb_set_blocksize(sb, 4096);
fs_info->running_transaction = NULL;
fs_info->last_trans_committed = 0;
Expand Down Expand Up @@ -500,8 +522,10 @@ struct btrfs_root *open_ctree(struct super_block *sb)

fs_info->generation = btrfs_super_generation(disk_super) + 1;
ret = btrfs_find_dead_roots(tree_root);
if (ret)
if (ret) {
mutex_unlock(&fs_info->fs_mutex);
goto fail_tree_root;
}
mutex_unlock(&fs_info->fs_mutex);
return tree_root;

Expand Down Expand Up @@ -553,12 +577,15 @@ int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root)
{
radix_tree_delete(&fs_info->fs_roots_radix,
(unsigned long)root->root_key.objectid);
btrfs_sysfs_del_root(root);
if (root->inode)
iput(root->inode);
if (root->node)
brelse(root->node);
if (root->commit_root)
brelse(root->commit_root);
if (root->name)
kfree(root->name);
kfree(root);
return 0;
}
Expand Down
3 changes: 2 additions & 1 deletion fs/btrfs/disk-io.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ 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 btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
struct btrfs_key *location);
struct btrfs_key *location,
const char *name, int namelen);
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);
Expand Down
17 changes: 15 additions & 2 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -858,16 +858,23 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
btrfs_set_extent_refs(ei, refs);
btrfs_mark_buffer_dirty(path->nodes[0]);
if (refs == 0) {
u64 super_blocks_used;
u64 super_blocks_used, root_blocks_used;

if (pin) {
ret = pin_down_block(root, blocknr, 0);
BUG_ON(ret);
}

/* block accounting for super block */
super_blocks_used = btrfs_super_blocks_used(&info->super_copy);
btrfs_set_super_blocks_used(&info->super_copy,
super_blocks_used - num_blocks);

/* block accounting for root item */
root_blocks_used = btrfs_root_blocks_used(&root->root_item);
btrfs_set_root_blocks_used(&root->root_item,
root_blocks_used - num_blocks);

ret = btrfs_del_item(trans, extent_root, path);
if (ret) {
return ret;
Expand Down Expand Up @@ -1175,7 +1182,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
{
int ret;
int pending_ret;
u64 super_blocks_used;
u64 super_blocks_used, root_blocks_used;
u64 search_start = 0;
struct btrfs_fs_info *info = root->fs_info;
struct btrfs_root *extent_root = info->extent_root;
Expand All @@ -1193,10 +1200,16 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
if (ret)
return ret;

/* block accounting for super block */
super_blocks_used = btrfs_super_blocks_used(&info->super_copy);
btrfs_set_super_blocks_used(&info->super_copy, super_blocks_used +
num_blocks);

/* block accounting for root item */
root_blocks_used = btrfs_root_blocks_used(&root->root_item);
btrfs_set_root_blocks_used(&root->root_item, root_blocks_used +
num_blocks);

if (root == extent_root) {
BUG_ON(num_blocks != 1);
set_radix_bit(&root->fs_info->extent_ins_radix, ins->objectid);
Expand Down
13 changes: 9 additions & 4 deletions fs/btrfs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,8 @@ static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry,
*/
static int fixup_tree_root_location(struct btrfs_root *root,
struct btrfs_key *location,
struct btrfs_root **sub_root)
struct btrfs_root **sub_root,
struct dentry *dentry)
{
struct btrfs_path *path;
struct btrfs_root_item *ri;
Expand All @@ -747,7 +748,9 @@ static int fixup_tree_root_location(struct btrfs_root *root,
BUG_ON(!path);
mutex_lock(&root->fs_info->fs_mutex);

*sub_root = btrfs_read_fs_root(root->fs_info, location);
*sub_root = btrfs_read_fs_root(root->fs_info, location,
dentry->d_name.name,
dentry->d_name.len);
if (IS_ERR(*sub_root))
return PTR_ERR(*sub_root);

Expand Down Expand Up @@ -812,7 +815,8 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
return ERR_PTR(ret);
inode = NULL;
if (location.objectid) {
ret = fixup_tree_root_location(root, &location, &sub_root);
ret = fixup_tree_root_location(root, &location, &sub_root,
dentry);
if (ret < 0)
return ERR_PTR(ret);
if (ret > 0)
Expand Down Expand Up @@ -1829,6 +1833,7 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen)

btrfs_set_root_blocknr(&root_item, bh_blocknr(subvol));
btrfs_set_root_refs(&root_item, 1);
btrfs_set_root_blocks_used(&root_item, 0);
memset(&root_item.drop_progress, 0, sizeof(root_item.drop_progress));
root_item.drop_level = 0;
brelse(subvol);
Expand Down Expand Up @@ -1865,7 +1870,7 @@ static int create_subvol(struct btrfs_root *root, char *name, int namelen)
if (ret)
goto fail_commit;

new_root = btrfs_read_fs_root(root->fs_info, &key);
new_root = btrfs_read_fs_root(root->fs_info, &key, name, namelen);
BUG_ON(!new_root);

trans = btrfs_start_transaction(new_root, 1);
Expand Down
14 changes: 14 additions & 0 deletions fs/btrfs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,14 @@ static struct super_operations btrfs_super_ops;
static void btrfs_put_super (struct super_block * sb)
{
struct btrfs_root *root = btrfs_sb(sb);
struct btrfs_fs_info *fs = root->fs_info;
int ret;

ret = close_ctree(root);
if (ret) {
printk("close ctree returns %d\n", ret);
}
btrfs_sysfs_del_super(fs);
sb->s_fs_info = NULL;
}

Expand Down Expand Up @@ -101,6 +103,12 @@ static int btrfs_fill_super(struct super_block * sb, void * data, int silent)
err = -ENOMEM;
goto fail_close;
}

/* this does the super kobj at the same time */
err = btrfs_sysfs_add_super(tree_root->fs_info);
if (err)
goto fail_close;

sb->s_root = root_dentry;
btrfs_transaction_queue_work(tree_root, HZ * 30);
return 0;
Expand Down Expand Up @@ -182,6 +190,11 @@ static struct super_operations btrfs_super_ops = {
static int __init init_btrfs_fs(void)
{
int err;

err = btrfs_init_sysfs();
if (err)
return err;

btrfs_init_transaction_sys();
err = btrfs_init_cachep();
if (err)
Expand All @@ -196,6 +209,7 @@ static void __exit exit_btrfs_fs(void)
btrfs_destroy_cachep();
extent_map_exit();
unregister_filesystem(&btrfs_fs_type);
btrfs_exit_sysfs();
}

module_init(init_btrfs_fs)
Expand Down
Loading

0 comments on commit 58176a9

Please sign in to comment.