diff options
Diffstat (limited to 'fs/btrfs/inode-map.c')
| -rw-r--r-- | fs/btrfs/inode-map.c | 32 | 
1 files changed, 25 insertions, 7 deletions
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c index 2e8bb402050b..63cad7865d75 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c @@ -13,6 +13,19 @@  #include "transaction.h"  #include "delalloc-space.h" +static void fail_caching_thread(struct btrfs_root *root) +{ +	struct btrfs_fs_info *fs_info = root->fs_info; + +	btrfs_warn(fs_info, "failed to start inode caching task"); +	btrfs_clear_pending_and_info(fs_info, INODE_MAP_CACHE, +				     "disabling inode map caching"); +	spin_lock(&root->ino_cache_lock); +	root->ino_cache_state = BTRFS_CACHE_ERROR; +	spin_unlock(&root->ino_cache_lock); +	wake_up(&root->ino_cache_wait); +} +  static int caching_kthread(void *data)  {  	struct btrfs_root *root = data; @@ -29,8 +42,10 @@ static int caching_kthread(void *data)  		return 0;  	path = btrfs_alloc_path(); -	if (!path) +	if (!path) { +		fail_caching_thread(root);  		return -ENOMEM; +	}  	/* Since the commit root is read-only, we can safely skip locking. */  	path->skip_locking = 1; @@ -146,6 +161,7 @@ static void start_caching(struct btrfs_root *root)  		spin_lock(&root->ino_cache_lock);  		root->ino_cache_state = BTRFS_CACHE_FINISHED;  		spin_unlock(&root->ino_cache_lock); +		wake_up(&root->ino_cache_wait);  		return;  	} @@ -160,15 +176,13 @@ static void start_caching(struct btrfs_root *root)  	if (!ret && objectid <= BTRFS_LAST_FREE_OBJECTID) {  		__btrfs_add_free_space(fs_info, ctl, objectid,  				       BTRFS_LAST_FREE_OBJECTID - objectid + 1); +		wake_up(&root->ino_cache_wait);  	}  	tsk = kthread_run(caching_kthread, root, "btrfs-ino-cache-%llu",  			  root->root_key.objectid); -	if (IS_ERR(tsk)) { -		btrfs_warn(fs_info, "failed to start inode caching task"); -		btrfs_clear_pending_and_info(fs_info, INODE_MAP_CACHE, -					     "disabling inode map caching"); -	} +	if (IS_ERR(tsk)) +		fail_caching_thread(root);  }  int btrfs_find_free_ino(struct btrfs_root *root, u64 *objectid) @@ -186,11 +200,14 @@ again:  	wait_event(root->ino_cache_wait,  		   root->ino_cache_state == BTRFS_CACHE_FINISHED || +		   root->ino_cache_state == BTRFS_CACHE_ERROR ||  		   root->free_ino_ctl->free_space > 0);  	if (root->ino_cache_state == BTRFS_CACHE_FINISHED &&  	    root->free_ino_ctl->free_space == 0)  		return -ENOSPC; +	else if (root->ino_cache_state == BTRFS_CACHE_ERROR) +		return btrfs_find_free_objectid(root, objectid);  	else  		goto again;  } @@ -419,7 +436,7 @@ int btrfs_save_ino_cache(struct btrfs_root *root,  	 * 1 item for free space object  	 * 3 items for pre-allocation  	 */ -	trans->bytes_reserved = btrfs_calc_trans_metadata_size(fs_info, 10); +	trans->bytes_reserved = btrfs_calc_insert_metadata_size(fs_info, 10);  	ret = btrfs_block_rsv_add(root, trans->block_rsv,  				  trans->bytes_reserved,  				  BTRFS_RESERVE_NO_FLUSH); @@ -485,6 +502,7 @@ again:  					      prealloc, prealloc, &alloc_hint);  	if (ret) {  		btrfs_delalloc_release_extents(BTRFS_I(inode), prealloc, true); +		btrfs_delalloc_release_metadata(BTRFS_I(inode), prealloc, true);  		goto out_put;  	}  |