Skip to content

Commit

Permalink
Btrfs: Metadata reservation for orphan inodes
Browse files Browse the repository at this point in the history
reserve metadata space for handling orphan inodes

Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
  • Loading branch information
Yan, Zheng authored and Chris Mason committed May 25, 2010
1 parent 8929ecf commit d68fc57
Show file tree
Hide file tree
Showing 9 changed files with 365 additions and 66 deletions.
1 change: 1 addition & 0 deletions fs/btrfs/btrfs_inode.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ struct btrfs_inode {
* of these.
*/
unsigned ordered_data_close:1;
unsigned orphan_meta_reserved:1;
unsigned dummy_inode:1;

/*
Expand Down
16 changes: 14 additions & 2 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -1069,7 +1069,6 @@ struct btrfs_root {
int ref_cows;
int track_dirty;
int in_radix;
int clean_orphans;

u64 defrag_trans_start;
struct btrfs_key defrag_progress;
Expand All @@ -1083,8 +1082,11 @@ struct btrfs_root {

struct list_head root_list;

spinlock_t list_lock;
spinlock_t orphan_lock;
struct list_head orphan_list;
struct btrfs_block_rsv *orphan_block_rsv;
int orphan_item_inserted;
int orphan_cleanup_state;

spinlock_t inode_lock;
/* red-black tree that keeps track of in-memory inodes */
Expand Down Expand Up @@ -2080,6 +2082,9 @@ int btrfs_trans_reserve_metadata(struct btrfs_trans_handle *trans,
int num_items, int *retries);
void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans,
struct btrfs_root *root);
int btrfs_orphan_reserve_metadata(struct btrfs_trans_handle *trans,
struct inode *inode);
void btrfs_orphan_release_metadata(struct inode *inode);
int btrfs_snap_reserve_metadata(struct btrfs_trans_handle *trans,
struct btrfs_pending_snapshot *pending);
int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes);
Expand Down Expand Up @@ -2404,6 +2409,13 @@ int btrfs_update_inode(struct btrfs_trans_handle *trans,
int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode);
int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode);
void btrfs_orphan_cleanup(struct btrfs_root *root);
void btrfs_orphan_pre_snapshot(struct btrfs_trans_handle *trans,
struct btrfs_pending_snapshot *pending,
u64 *bytes_to_reserve);
void btrfs_orphan_post_snapshot(struct btrfs_trans_handle *trans,
struct btrfs_pending_snapshot *pending);
void btrfs_orphan_commit_root(struct btrfs_trans_handle *trans,
struct btrfs_root *root);
int btrfs_cont_expand(struct inode *inode, loff_t size);
int btrfs_invalidate_inodes(struct btrfs_root *root);
void btrfs_add_delayed_iput(struct inode *inode);
Expand Down
32 changes: 20 additions & 12 deletions fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -894,7 +894,8 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
root->ref_cows = 0;
root->track_dirty = 0;
root->in_radix = 0;
root->clean_orphans = 0;
root->orphan_item_inserted = 0;
root->orphan_cleanup_state = 0;

root->fs_info = fs_info;
root->objectid = objectid;
Expand All @@ -904,12 +905,13 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
root->in_sysfs = 0;
root->inode_tree = RB_ROOT;
root->block_rsv = NULL;
root->orphan_block_rsv = NULL;

INIT_LIST_HEAD(&root->dirty_list);
INIT_LIST_HEAD(&root->orphan_list);
INIT_LIST_HEAD(&root->root_list);
spin_lock_init(&root->node_lock);
spin_lock_init(&root->list_lock);
spin_lock_init(&root->orphan_lock);
spin_lock_init(&root->inode_lock);
spin_lock_init(&root->accounting_lock);
mutex_init(&root->objectid_mutex);
Expand Down Expand Up @@ -1193,19 +1195,23 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
if (root)
return root;

ret = btrfs_find_orphan_item(fs_info->tree_root, location->objectid);
if (ret == 0)
ret = -ENOENT;
if (ret < 0)
return ERR_PTR(ret);

root = btrfs_read_fs_root_no_radix(fs_info->tree_root, location);
if (IS_ERR(root))
return root;

WARN_ON(btrfs_root_refs(&root->root_item) == 0);
set_anon_super(&root->anon_super, NULL);

if (btrfs_root_refs(&root->root_item) == 0) {
ret = -ENOENT;
goto fail;
}

ret = btrfs_find_orphan_item(fs_info->tree_root, location->objectid);
if (ret < 0)
goto fail;
if (ret == 0)
root->orphan_item_inserted = 1;

ret = radix_tree_preload(GFP_NOFS & ~__GFP_HIGHMEM);
if (ret)
goto fail;
Expand All @@ -1214,10 +1220,9 @@ struct btrfs_root *btrfs_read_fs_root_no_name(struct btrfs_fs_info *fs_info,
ret = radix_tree_insert(&fs_info->fs_roots_radix,
(unsigned long)root->root_key.objectid,
root);
if (ret == 0) {
if (ret == 0)
root->in_radix = 1;
root->clean_orphans = 1;
}

spin_unlock(&fs_info->fs_roots_radix_lock);
radix_tree_preload_end();
if (ret) {
Expand Down Expand Up @@ -1981,6 +1986,9 @@ struct btrfs_root *open_ctree(struct super_block *sb,
BUG_ON(ret);

if (!(sb->s_flags & MS_RDONLY)) {
ret = btrfs_cleanup_fs_roots(fs_info);
BUG_ON(ret);

ret = btrfs_recover_relocation(tree_root);
if (ret < 0) {
printk(KERN_WARNING
Expand Down
28 changes: 28 additions & 0 deletions fs/btrfs/extent-tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -3626,6 +3626,34 @@ void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans,
trans->bytes_reserved = 0;
}

int btrfs_orphan_reserve_metadata(struct btrfs_trans_handle *trans,
struct inode *inode)
{
struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_block_rsv *src_rsv = get_block_rsv(trans, root);
struct btrfs_block_rsv *dst_rsv = root->orphan_block_rsv;

/*
* one for deleting orphan item, one for updating inode and
* two for calling btrfs_truncate_inode_items.
*
* btrfs_truncate_inode_items is a delete operation, it frees
* more space than it uses in most cases. So two units of
* metadata space should be enough for calling it many times.
* If all of the metadata space is used, we can commit
* transaction and use space it freed.
*/
u64 num_bytes = calc_trans_metadata_size(root, 4);
return block_rsv_migrate_bytes(src_rsv, dst_rsv, num_bytes);
}

void btrfs_orphan_release_metadata(struct inode *inode)
{
struct btrfs_root *root = BTRFS_I(inode)->root;
u64 num_bytes = calc_trans_metadata_size(root, 4);
btrfs_block_rsv_release(root, root->orphan_block_rsv, num_bytes);
}

int btrfs_snap_reserve_metadata(struct btrfs_trans_handle *trans,
struct btrfs_pending_snapshot *pending)
{
Expand Down
Loading

0 comments on commit d68fc57

Please sign in to comment.