Btrfs: Metadata reservation for orphan inodes
PATCH v2 9/12 Btrfs: Metadata reservation for orphan inodes
reserve metadata space for handling orphan inodes
Signed-off-by Yan Zheng <[email protected]>
---
fs/btrfs/btrfs_inode.h +1 -0
@@ -151,6 +151,7 @@ struct btrfs_inode {* of these. */ unsigned ordered_data_close:1; + unsigned orphan_meta_reserved:1; unsigned dummy_inode:1;/*
fs/btrfs/ctree.h +14 -2
@@ -1068,7 +1068,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;
@@ -1082,8 +1081,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 */
@@ -2079,6 +2081,9 @@ int btrfs_trans_reserve_metadata(struct 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);
@@ -2403,6 +2408,13 @@ int btrfs_update_inode(struct btrfs_tranint 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);
fs/btrfs/disk-io.c +20 -12
@@ -895,7 +895,8 @@ static int __setup_root(u32 nodesize, u3 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;
@@ -905,12 +906,13 @@ static int __setup_root(u32 nodesize, u3 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);
@@ -1194,19 +1196,23 @@ again: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;
@@ -1215,10 +1221,9 @@ again: 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) {
@@ -1989,6 +1994,9 @@ struct btrfs_root *open_ctree(struct supBUG_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
fs/btrfs/extent-tree.c +28 -0
@@ -3625,6 +3625,34 @@ void btrfs_trans_release_metadata(struct 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) {
fs/btrfs/inode.c +257 -42
431 lines not on this page · raw message
fs/btrfs/ioctl.c +6 -4
@@ -1296,10 +1296,12 @@ static noinline int btrfs_ioctl_snap_des dest->root_item.drop_level =0 ;btrfs_set_root_refs (&dest->root_item,0 ); - ret =btrfs_insert_orphan_item (trans, - root->fs_info->tree_root, - dest->root_key.objectid); -BUG_ON (ret); +if (!xchg (&dest->orphan_item_inserted,1 )) { + ret =btrfs_insert_orphan_item (trans, + root->fs_info->tree_root, + dest->root_key.objectid); +BUG_ON (ret); + } ret =btrfs_commit_transaction (trans, root);BUG_ON (ret);
fs/btrfs/root-tree.c +20 -3
@@ -259,6 +259,8 @@ int btrfs_find_orphan_roots(struct btrfsstruct extent_buffer *leaf;struct btrfs_path *path;struct btrfs_key key; +struct btrfs_key root_key; +struct btrfs_root *root;int err =0 ;int ret;
@@ -270,6 +272,9 @@ int btrfs_find_orphan_roots(struct btrfs key.type =BTRFS_ORPHAN_ITEM_KEY ; key.offset =0 ; + root_key.type =BTRFS_ROOT_ITEM_KEY ; + root_key.offset = (u64)-1 ; +while (1 ) { ret =btrfs_search_slot (NULL , tree_root, &key, path,0 ,0 );if (ret <0 ) {
@@ -294,13 +299,25 @@ int btrfs_find_orphan_roots(struct btrfs key.type != BTRFS_ORPHAN_ITEM_KEY)break ; - ret =btrfs_find_dead_roots (tree_root, key.offset); -if (ret) { + root_key.objectid = key.offset; + key.offset++; + + root =btrfs_read_fs_root_no_name (tree_root->fs_info, + &root_key); +if (!IS_ERR (root)) +continue ; + + ret =PTR_ERR (root); +if (ret != -ENOENT ) { err = ret;break ; } - key.offset++; + ret =btrfs_find_dead_roots (tree_root, root_key.objectid); +if (ret) { + err = ret; +break ; + } }btrfs_free_path (path);
fs/btrfs/super.c +3 -3
@@ -693,11 +693,11 @@ static int btrfs_remount(struct super_blif (btrfs_super_log_root (&root->fs_info->super_copy) !=0 )return -EINVAL ; -/* recover relocation */ - ret =btrfs_recover_relocation (root); + ret =btrfs_cleanup_fs_roots (root->fs_info);WARN_ON (ret); - ret =btrfs_cleanup_fs_roots (root->fs_info); +/* recover relocation */ + ret =btrfs_recover_relocation (root);WARN_ON (ret); sb->s_flags &= ~MS_RDONLY ;
fs/btrfs/transaction.c +16 -0
@@ -675,6 +675,7 @@ static noinline int commit_fs_roots(strubtrfs_free_log (trans, root);btrfs_update_reloc_root (trans, root); +btrfs_orphan_commit_root (trans, root);if (root->commit_root != root->node) {switch_commit_root (root);
@@ -834,6 +835,8 @@ static noinline int create_pending_snapsstruct extent_buffer *tmp;struct extent_buffer *old;int ret; +int retries =0 ; +u64 to_reserve =0 ;u64 index =0 ;u64 objectid;
@@ -849,6 +852,17 @@ static noinline int create_pending_snaps goto fail; } +btrfs_orphan_pre_snapshot (trans, pending, &to_reserve); + +if (to_reserve >0 ) { + ret =btrfs_block_rsv_add (trans, root, &pending->block_rsv, + to_reserve, &retries); +if (ret) { + pending->error = ret; + goto fail; + } + } + key.objectid = objectid; key.offset = (u64)-1 ; key.type =BTRFS_ROOT_ITEM_KEY ;
@@ -908,6 +922,8 @@ static noinline int create_pending_snaps key.offset = (u64)-1 ; pending->snap =btrfs_read_fs_root_no_name (root->fs_info, &key);BUG_ON (IS_ERR (pending->snap)); + +btrfs_orphan_post_snapshot (trans, pending); fail:kfree (new_root_item);btrfs_block_rsv_release (root, &pending->block_rsv, (u64)-1 );