diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
| -rw-r--r-- | fs/btrfs/extent-tree.c | 185 | 
1 files changed, 86 insertions, 99 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 61b494e8e604..0450dc410533 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -60,21 +60,6 @@ enum {  	CHUNK_ALLOC_FORCE = 2,  }; -/* - * Control how reservations are dealt with. - * - * RESERVE_FREE - freeing a reservation. - * RESERVE_ALLOC - allocating space and we need to update bytes_may_use for - *   ENOSPC accounting - * RESERVE_ALLOC_NO_ACCOUNT - allocating space and we should not update - *   bytes_may_use as the ENOSPC accounting is done elsewhere - */ -enum { -	RESERVE_FREE = 0, -	RESERVE_ALLOC = 1, -	RESERVE_ALLOC_NO_ACCOUNT = 2, -}; -  static int update_block_group(struct btrfs_trans_handle *trans,  			      struct btrfs_root *root, u64 bytenr,  			      u64 num_bytes, int alloc); @@ -104,9 +89,10 @@ static int find_next_key(struct btrfs_path *path, int level,  			 struct btrfs_key *key);  static void dump_space_info(struct btrfs_space_info *info, u64 bytes,  			    int dump_block_groups); -static int btrfs_update_reserved_bytes(struct btrfs_block_group_cache *cache, -				       u64 num_bytes, int reserve, -				       int delalloc); +static int btrfs_add_reserved_bytes(struct btrfs_block_group_cache *cache, +				    u64 ram_bytes, u64 num_bytes, int delalloc); +static int btrfs_free_reserved_bytes(struct btrfs_block_group_cache *cache, +				     u64 num_bytes, int delalloc);  static int block_rsv_use_bytes(struct btrfs_block_rsv *block_rsv,  			       u64 num_bytes);  int btrfs_pin_extent(struct btrfs_root *root, @@ -3501,7 +3487,6 @@ again:  		dcs = BTRFS_DC_SETUP;  	else if (ret == -ENOSPC)  		set_bit(BTRFS_TRANS_CACHE_ENOSPC, &trans->transaction->flags); -	btrfs_free_reserved_data_space(inode, 0, num_pages);  out_put:  	iput(inode); @@ -4472,6 +4457,15 @@ void check_system_chunk(struct btrfs_trans_handle *trans,  	}  } +/* + * If force is CHUNK_ALLOC_FORCE: + *    - return 1 if it successfully allocates a chunk, + *    - return errors including -ENOSPC otherwise. + * If force is NOT CHUNK_ALLOC_FORCE: + *    - return 0 if it doesn't need to allocate a new chunk, + *    - return 1 if it successfully allocates a chunk, + *    - return errors including -ENOSPC otherwise. + */  static int do_chunk_alloc(struct btrfs_trans_handle *trans,  			  struct btrfs_root *extent_root, u64 flags, int force)  { @@ -4882,7 +4876,7 @@ static int flush_space(struct btrfs_root *root,  				     btrfs_get_alloc_profile(root, 0),  				     CHUNK_ALLOC_NO_FORCE);  		btrfs_end_transaction(trans, root); -		if (ret == -ENOSPC) +		if (ret > 0 || ret == -ENOSPC)  			ret = 0;  		break;  	case COMMIT_TRANS: @@ -6497,19 +6491,15 @@ void btrfs_wait_block_group_reservations(struct btrfs_block_group_cache *bg)  }  /** - * btrfs_update_reserved_bytes - update the block_group and space info counters + * btrfs_add_reserved_bytes - update the block_group and space info counters   * @cache:	The cache we are manipulating + * @ram_bytes:  The number of bytes of file content, and will be same to + *              @num_bytes except for the compress path.   * @num_bytes:	The number of bytes in question - * @reserve:	One of the reservation enums   * @delalloc:   The blocks are allocated for the delalloc write   * - * This is called by the allocator when it reserves space, or by somebody who is - * freeing space that was never actually used on disk.  For example if you - * reserve some space for a new leaf in transaction A and before transaction A - * commits you free that leaf, you call this with reserve set to 0 in order to - * clear the reservation. - * - * Metadata reservations should be called with RESERVE_ALLOC so we do the proper + * This is called by the allocator when it reserves space. Metadata + * reservations should be called with RESERVE_ALLOC so we do the proper   * ENOSPC accounting.  For data we handle the reservation through clearing the   * delalloc bits in the io_tree.  We have to do this since we could end up   * allocating less disk space for the amount of data we have reserved in the @@ -6519,44 +6509,63 @@ void btrfs_wait_block_group_reservations(struct btrfs_block_group_cache *bg)   * make the reservation and return -EAGAIN, otherwise this function always   * succeeds.   */ -static int btrfs_update_reserved_bytes(struct btrfs_block_group_cache *cache, -				       u64 num_bytes, int reserve, int delalloc) +static int btrfs_add_reserved_bytes(struct btrfs_block_group_cache *cache, +				    u64 ram_bytes, u64 num_bytes, int delalloc)  {  	struct btrfs_space_info *space_info = cache->space_info;  	int ret = 0;  	spin_lock(&space_info->lock);  	spin_lock(&cache->lock); -	if (reserve != RESERVE_FREE) { -		if (cache->ro) { -			ret = -EAGAIN; -		} else { -			cache->reserved += num_bytes; -			space_info->bytes_reserved += num_bytes; -			if (reserve == RESERVE_ALLOC) { -				trace_btrfs_space_reservation(cache->fs_info, -						"space_info", space_info->flags, -						num_bytes, 0); -				space_info->bytes_may_use -= num_bytes; -			} - -			if (delalloc) -				cache->delalloc_bytes += num_bytes; -		} +	if (cache->ro) { +		ret = -EAGAIN;  	} else { -		if (cache->ro) -			space_info->bytes_readonly += num_bytes; -		cache->reserved -= num_bytes; -		space_info->bytes_reserved -= num_bytes; +		cache->reserved += num_bytes; +		space_info->bytes_reserved += num_bytes; +		trace_btrfs_space_reservation(cache->fs_info, +				"space_info", space_info->flags, +				ram_bytes, 0); +		space_info->bytes_may_use -= ram_bytes;  		if (delalloc) -			cache->delalloc_bytes -= num_bytes; +			cache->delalloc_bytes += num_bytes;  	}  	spin_unlock(&cache->lock);  	spin_unlock(&space_info->lock);  	return ret;  } +/** + * btrfs_free_reserved_bytes - update the block_group and space info counters + * @cache:      The cache we are manipulating + * @num_bytes:  The number of bytes in question + * @delalloc:   The blocks are allocated for the delalloc write + * + * This is called by somebody who is freeing space that was never actually used + * on disk.  For example if you reserve some space for a new leaf in transaction + * A and before transaction A commits you free that leaf, you call this with + * reserve set to 0 in order to clear the reservation. + */ + +static int btrfs_free_reserved_bytes(struct btrfs_block_group_cache *cache, +				     u64 num_bytes, int delalloc) +{ +	struct btrfs_space_info *space_info = cache->space_info; +	int ret = 0; + +	spin_lock(&space_info->lock); +	spin_lock(&cache->lock); +	if (cache->ro) +		space_info->bytes_readonly += num_bytes; +	cache->reserved -= num_bytes; +	space_info->bytes_reserved -= num_bytes; + +	if (delalloc) +		cache->delalloc_bytes -= num_bytes; +	spin_unlock(&cache->lock); +	spin_unlock(&space_info->lock); +	return ret; +}  void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans,  				struct btrfs_root *root)  { @@ -7191,7 +7200,7 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans,  		WARN_ON(test_bit(EXTENT_BUFFER_DIRTY, &buf->bflags));  		btrfs_add_free_space(cache, buf->start, buf->len); -		btrfs_update_reserved_bytes(cache, buf->len, RESERVE_FREE, 0); +		btrfs_free_reserved_bytes(cache, buf->len, 0);  		btrfs_put_block_group(cache);  		trace_btrfs_reserved_extent_free(root, buf->start, buf->len);  		pin = 0; @@ -7416,9 +7425,9 @@ btrfs_release_block_group(struct btrfs_block_group_cache *cache,   * the free space extent currently.   */  static noinline int find_free_extent(struct btrfs_root *orig_root, -				     u64 num_bytes, u64 empty_size, -				     u64 hint_byte, struct btrfs_key *ins, -				     u64 flags, int delalloc) +				u64 ram_bytes, u64 num_bytes, u64 empty_size, +				u64 hint_byte, struct btrfs_key *ins, +				u64 flags, int delalloc)  {  	int ret = 0;  	struct btrfs_root *root = orig_root->fs_info->extent_root; @@ -7430,8 +7439,6 @@ static noinline int find_free_extent(struct btrfs_root *orig_root,  	struct btrfs_space_info *space_info;  	int loop = 0;  	int index = __get_raid_index(flags); -	int alloc_type = (flags & BTRFS_BLOCK_GROUP_DATA) ? -		RESERVE_ALLOC_NO_ACCOUNT : RESERVE_ALLOC;  	bool failed_cluster_refill = false;  	bool failed_alloc = false;  	bool use_cluster = true; @@ -7763,8 +7770,8 @@ checks:  					     search_start - offset);  		BUG_ON(offset > search_start); -		ret = btrfs_update_reserved_bytes(block_group, num_bytes, -						  alloc_type, delalloc); +		ret = btrfs_add_reserved_bytes(block_group, ram_bytes, +				num_bytes, delalloc);  		if (ret == -EAGAIN) {  			btrfs_add_free_space(block_group, offset, num_bytes);  			goto loop; @@ -7936,7 +7943,7 @@ again:  	up_read(&info->groups_sem);  } -int btrfs_reserve_extent(struct btrfs_root *root, +int btrfs_reserve_extent(struct btrfs_root *root, u64 ram_bytes,  			 u64 num_bytes, u64 min_alloc_size,  			 u64 empty_size, u64 hint_byte,  			 struct btrfs_key *ins, int is_data, int delalloc) @@ -7948,8 +7955,8 @@ int btrfs_reserve_extent(struct btrfs_root *root,  	flags = btrfs_get_alloc_profile(root, is_data);  again:  	WARN_ON(num_bytes < root->sectorsize); -	ret = find_free_extent(root, num_bytes, empty_size, hint_byte, ins, -			       flags, delalloc); +	ret = find_free_extent(root, ram_bytes, num_bytes, empty_size, +			       hint_byte, ins, flags, delalloc);  	if (!ret && !is_data) {  		btrfs_dec_block_group_reservations(root->fs_info,  						   ins->objectid); @@ -7958,6 +7965,7 @@ again:  			num_bytes = min(num_bytes >> 1, ins->offset);  			num_bytes = round_down(num_bytes, root->sectorsize);  			num_bytes = max(num_bytes, min_alloc_size); +			ram_bytes = num_bytes;  			if (num_bytes == min_alloc_size)  				final_tried = true;  			goto again; @@ -7995,7 +8003,7 @@ static int __btrfs_free_reserved_extent(struct btrfs_root *root,  		if (btrfs_test_opt(root->fs_info, DISCARD))  			ret = btrfs_discard_extent(root, start, len, NULL);  		btrfs_add_free_space(cache, start, len); -		btrfs_update_reserved_bytes(cache, len, RESERVE_FREE, delalloc); +		btrfs_free_reserved_bytes(cache, len, delalloc);  		trace_btrfs_reserved_extent_free(root, start, len);  	} @@ -8223,8 +8231,8 @@ int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,  	if (!block_group)  		return -EINVAL; -	ret = btrfs_update_reserved_bytes(block_group, ins->offset, -					  RESERVE_ALLOC_NO_ACCOUNT, 0); +	ret = btrfs_add_reserved_bytes(block_group, ins->offset, +				       ins->offset, 0);  	BUG_ON(ret); /* logic error */  	ret = alloc_reserved_file_extent(trans, root, 0, root_objectid,  					 0, owner, offset, ins, 1); @@ -8368,7 +8376,7 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans,  	if (IS_ERR(block_rsv))  		return ERR_CAST(block_rsv); -	ret = btrfs_reserve_extent(root, blocksize, blocksize, +	ret = btrfs_reserve_extent(root, blocksize, blocksize, blocksize,  				   empty_size, hint, &ins, 0, 0);  	if (ret)  		goto out_unuse; @@ -8521,35 +8529,6 @@ reada:  	wc->reada_slot = slot;  } -/* - * These may not be seen by the usual inc/dec ref code so we have to - * add them here. - */ -static int record_one_subtree_extent(struct btrfs_trans_handle *trans, -				     struct btrfs_root *root, u64 bytenr, -				     u64 num_bytes) -{ -	struct btrfs_qgroup_extent_record *qrecord; -	struct btrfs_delayed_ref_root *delayed_refs; - -	qrecord = kmalloc(sizeof(*qrecord), GFP_NOFS); -	if (!qrecord) -		return -ENOMEM; - -	qrecord->bytenr = bytenr; -	qrecord->num_bytes = num_bytes; -	qrecord->old_roots = NULL; - -	delayed_refs = &trans->transaction->delayed_refs; -	spin_lock(&delayed_refs->lock); -	if (btrfs_qgroup_insert_dirty_extent(trans->fs_info, -					     delayed_refs, qrecord)) -		kfree(qrecord); -	spin_unlock(&delayed_refs->lock); - -	return 0; -} -  static int account_leaf_items(struct btrfs_trans_handle *trans,  			      struct btrfs_root *root,  			      struct extent_buffer *eb) @@ -8583,7 +8562,8 @@ static int account_leaf_items(struct btrfs_trans_handle *trans,  		num_bytes = btrfs_file_extent_disk_num_bytes(eb, fi); -		ret = record_one_subtree_extent(trans, root, bytenr, num_bytes); +		ret = btrfs_qgroup_insert_dirty_extent(trans, root->fs_info, +				bytenr, num_bytes, GFP_NOFS);  		if (ret)  			return ret;  	} @@ -8732,8 +8712,9 @@ walk_down:  			btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);  			path->locks[level] = BTRFS_READ_LOCK_BLOCKING; -			ret = record_one_subtree_extent(trans, root, child_bytenr, -							root->nodesize); +			ret = btrfs_qgroup_insert_dirty_extent(trans, +					root->fs_info, child_bytenr, +					root->nodesize, GFP_NOFS);  			if (ret)  				goto out;  		} @@ -9906,6 +9887,7 @@ static int find_first_block_group(struct btrfs_root *root,  			} else {  				ret = 0;  			} +			free_extent_map(em);  			goto out;  		}  		path->slots[0]++; @@ -9942,6 +9924,7 @@ void btrfs_put_block_group_cache(struct btrfs_fs_info *info)  		block_group->iref = 0;  		block_group->inode = NULL;  		spin_unlock(&block_group->lock); +		ASSERT(block_group->io_ctl.inode == NULL);  		iput(inode);  		last = block_group->key.objectid + block_group->key.offset;  		btrfs_put_block_group(block_group); @@ -9999,6 +9982,10 @@ int btrfs_free_block_groups(struct btrfs_fs_info *info)  			free_excluded_extents(info->extent_root, block_group);  		btrfs_remove_free_space_cache(block_group); +		ASSERT(list_empty(&block_group->dirty_list)); +		ASSERT(list_empty(&block_group->io_list)); +		ASSERT(list_empty(&block_group->bg_list)); +		ASSERT(atomic_read(&block_group->count) == 1);  		btrfs_put_block_group(block_group);  		spin_lock(&info->block_group_cache_lock);  |