Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 58176a96 authored by Josef Bacik's avatar Josef Bacik Committed by David Woodhouse
Browse files

Btrfs: Add per-root block accounting and sysfs entries

parent b888db2b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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 \
+54 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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;
};
@@ -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;
@@ -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 */
@@ -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);
@@ -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) + \
@@ -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
+29 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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;
}

@@ -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;
@@ -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;

@@ -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;
}
+2 −1
Original line number Diff line number Diff line
@@ -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);
+15 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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);
Loading