Skip to content
Snippets Groups Projects
extent-tree.c 222 KiB
Newer Older
  • Learn to ignore specific revisions
  • 		btrfs_end_transaction(trans, root);
    		break;
    
    	case FLUSH_DELALLOC:
    	case FLUSH_DELALLOC_WAIT:
    		shrink_delalloc(root, num_bytes, orig_bytes,
    				state == FLUSH_DELALLOC_WAIT);
    		break;
    
    	case ALLOC_CHUNK:
    		trans = btrfs_join_transaction(root);
    		if (IS_ERR(trans)) {
    			ret = PTR_ERR(trans);
    			break;
    		}
    		ret = do_chunk_alloc(trans, root->fs_info->extent_root,
    				     btrfs_get_alloc_profile(root, 0),
    				     CHUNK_ALLOC_NO_FORCE);
    		btrfs_end_transaction(trans, root);
    		if (ret == -ENOSPC)
    			ret = 0;
    		break;
    
    	case COMMIT_TRANS:
    		ret = may_commit_transaction(root, space_info, orig_bytes, 0);
    		break;
    	default:
    		ret = -ENOSPC;
    		break;
    	}
    
    	return ret;
    }
    
    /**
     * reserve_metadata_bytes - try to reserve bytes from the block_rsv's space
     * @root - the root we're allocating for
     * @block_rsv - the block_rsv we're allocating for
     * @orig_bytes - the number of bytes we want
    
     * @flush - whether or not we can flush to make our reservation
    
     * This will reserve orgi_bytes number of bytes from the space info associated
     * with the block_rsv.  If there is not enough space it will make an attempt to
     * flush out space to make room.  It will do this by flushing delalloc if
     * possible or committing the transaction.  If flush is 0 then no attempts to
     * regain reservations will be made and this will fail if there is not enough
     * space already.
    
    static int reserve_metadata_bytes(struct btrfs_root *root,
    
    				  struct btrfs_block_rsv *block_rsv,
    
    				  u64 orig_bytes,
    				  enum btrfs_reserve_flush_enum flush)
    
    	struct btrfs_space_info *space_info = block_rsv->space_info;
    
    	u64 num_bytes = orig_bytes;
    
    	int flush_state = FLUSH_DELAYED_ITEMS_NR;
    
    	bool flushing = false;
    
    	spin_lock(&space_info->lock);
    
    	 * We only want to wait if somebody other than us is flushing and we
    	 * are actually allowed to flush all things.
    
    	while (flush == BTRFS_RESERVE_FLUSH_ALL && !flushing &&
    	       space_info->flush) {
    
    		spin_unlock(&space_info->lock);
    		/*
    		 * If we have a trans handle we can't wait because the flusher
    		 * may have to commit the transaction, which would mean we would
    		 * deadlock since we are waiting for the flusher to finish, but
    		 * hold the current transaction open.
    		 */
    
    Arne Jansen's avatar
    Arne Jansen committed
    		ret = wait_event_killable(space_info->wait, !space_info->flush);
    		/* Must have been killed, return */
    		if (ret)
    
    			return -EINTR;
    
    		spin_lock(&space_info->lock);
    	}
    
    	ret = -ENOSPC;
    
    	used = space_info->bytes_used + space_info->bytes_reserved +
    		space_info->bytes_pinned + space_info->bytes_readonly +
    		space_info->bytes_may_use;
    
    	/*
    	 * The idea here is that we've not already over-reserved the block group
    	 * then we can go ahead and save our reservation first and then start
    	 * flushing if we need to.  Otherwise if we've already overcommitted
    	 * lets start flushing stuff first and then come back and try to make
    	 * our reservation.
    	 */
    
    	if (used <= space_info->total_bytes) {
    		if (used + orig_bytes <= space_info->total_bytes) {
    
    			space_info->bytes_may_use += orig_bytes;
    
    			trace_btrfs_space_reservation(root->fs_info,
    
    				"space_info", space_info->flags, orig_bytes, 1);
    
    			ret = 0;
    		} else {
    			/*
    			 * Ok set num_bytes to orig_bytes since we aren't
    			 * overocmmitted, this way we only try and reclaim what
    			 * we need.
    			 */
    			num_bytes = orig_bytes;
    		}
    	} else {
    		/*
    		 * Ok we're over committed, set num_bytes to the overcommitted
    		 * amount plus the amount of bytes that we need for this
    		 * reservation.
    		 */
    
    		num_bytes = used - space_info->total_bytes +
    
    	if (ret && can_overcommit(root, space_info, orig_bytes, flush)) {
    		space_info->bytes_may_use += orig_bytes;
    		trace_btrfs_space_reservation(root->fs_info, "space_info",
    					      space_info->flags, orig_bytes,
    					      1);
    		ret = 0;
    
    	/*
    	 * Couldn't make our reservation, save our place so while we're trying
    	 * to reclaim space we can actually use it instead of somebody else
    	 * stealing it from us.
    
    	 *
    	 * We make the other tasks wait for the flush only when we can flush
    	 * all things.
    
    	if (ret && flush != BTRFS_RESERVE_NO_FLUSH) {
    
    		flushing = true;
    		space_info->flush = 1;
    
    	spin_unlock(&space_info->lock);
    
    	if (!ret || flush == BTRFS_RESERVE_NO_FLUSH)
    
    	ret = flush_space(root, space_info, num_bytes, orig_bytes,
    			  flush_state);
    	flush_state++;
    
    
    	/*
    	 * If we are FLUSH_LIMIT, we can not flush delalloc, or the deadlock
    	 * would happen. So skip delalloc flush.
    	 */
    	if (flush == BTRFS_RESERVE_FLUSH_LIMIT &&
    	    (flush_state == FLUSH_DELALLOC ||
    	     flush_state == FLUSH_DELALLOC_WAIT))
    		flush_state = ALLOC_CHUNK;
    
    
    	else if (flush == BTRFS_RESERVE_FLUSH_LIMIT &&
    		 flush_state < COMMIT_TRANS)
    		goto again;
    	else if (flush == BTRFS_RESERVE_FLUSH_ALL &&
    		 flush_state <= COMMIT_TRANS)
    
    	if (ret == -ENOSPC &&
    	    unlikely(root->orphan_cleanup_state == ORPHAN_CLEANUP_STARTED)) {
    		struct btrfs_block_rsv *global_rsv =
    			&root->fs_info->global_block_rsv;
    
    		if (block_rsv != global_rsv &&
    		    !block_rsv_use_bytes(global_rsv, orig_bytes))
    			ret = 0;
    	}
    
    		spin_lock(&space_info->lock);
    
    		space_info->flush = 0;
    		wake_up_all(&space_info->wait);
    
    		spin_unlock(&space_info->lock);
    
    static struct btrfs_block_rsv *get_block_rsv(
    					const struct btrfs_trans_handle *trans,
    					const struct btrfs_root *root)
    
    	struct btrfs_block_rsv *block_rsv = NULL;
    
    
    	if (root->ref_cows)
    		block_rsv = trans->block_rsv;
    
    	if (root == root->fs_info->csum_root && trans->adding_csums)
    
    		block_rsv = trans->block_rsv;
    
    		block_rsv = root->block_rsv;
    
    	if (!block_rsv)
    		block_rsv = &root->fs_info->empty_block_rsv;
    
    	return block_rsv;
    }
    
    static int block_rsv_use_bytes(struct btrfs_block_rsv *block_rsv,
    			       u64 num_bytes)
    {
    	int ret = -ENOSPC;
    	spin_lock(&block_rsv->lock);
    	if (block_rsv->reserved >= num_bytes) {
    		block_rsv->reserved -= num_bytes;
    		if (block_rsv->reserved < block_rsv->size)
    			block_rsv->full = 0;
    		ret = 0;
    	}
    	spin_unlock(&block_rsv->lock);
    	return ret;
    }
    
    static void block_rsv_add_bytes(struct btrfs_block_rsv *block_rsv,
    				u64 num_bytes, int update_size)
    {
    	spin_lock(&block_rsv->lock);
    	block_rsv->reserved += num_bytes;
    	if (update_size)
    		block_rsv->size += num_bytes;
    	else if (block_rsv->reserved >= block_rsv->size)
    		block_rsv->full = 1;
    	spin_unlock(&block_rsv->lock);
    }
    
    
    static void block_rsv_release_bytes(struct btrfs_fs_info *fs_info,
    				    struct btrfs_block_rsv *block_rsv,
    
    				    struct btrfs_block_rsv *dest, u64 num_bytes)
    
    {
    	struct btrfs_space_info *space_info = block_rsv->space_info;
    
    	spin_lock(&block_rsv->lock);
    	if (num_bytes == (u64)-1)
    		num_bytes = block_rsv->size;
    	block_rsv->size -= num_bytes;
    	if (block_rsv->reserved >= block_rsv->size) {
    		num_bytes = block_rsv->reserved - block_rsv->size;
    		block_rsv->reserved = block_rsv->size;
    		block_rsv->full = 1;
    	} else {
    		num_bytes = 0;
    	}
    	spin_unlock(&block_rsv->lock);
    
    	if (num_bytes > 0) {
    		if (dest) {
    
    			spin_lock(&dest->lock);
    			if (!dest->full) {
    				u64 bytes_to_add;
    
    				bytes_to_add = dest->size - dest->reserved;
    				bytes_to_add = min(num_bytes, bytes_to_add);
    				dest->reserved += bytes_to_add;
    				if (dest->reserved >= dest->size)
    					dest->full = 1;
    				num_bytes -= bytes_to_add;
    			}
    			spin_unlock(&dest->lock);
    		}
    		if (num_bytes) {
    
    			spin_lock(&space_info->lock);
    
    			space_info->bytes_may_use -= num_bytes;
    
    			trace_btrfs_space_reservation(fs_info, "space_info",
    
    					space_info->flags, num_bytes, 0);
    
    			space_info->reservation_progress++;
    
    			spin_unlock(&space_info->lock);
    
    static int block_rsv_migrate_bytes(struct btrfs_block_rsv *src,
    				   struct btrfs_block_rsv *dst, u64 num_bytes)
    {
    	int ret;
    
    	ret = block_rsv_use_bytes(src, num_bytes);
    	if (ret)
    		return ret;
    
    	block_rsv_add_bytes(dst, num_bytes, 1);
    
    void btrfs_init_block_rsv(struct btrfs_block_rsv *rsv, unsigned short type)
    
    	memset(rsv, 0, sizeof(*rsv));
    	spin_lock_init(&rsv->lock);
    
    struct btrfs_block_rsv *btrfs_alloc_block_rsv(struct btrfs_root *root,
    					      unsigned short type)
    
    {
    	struct btrfs_block_rsv *block_rsv;
    	struct btrfs_fs_info *fs_info = root->fs_info;
    
    	block_rsv = kmalloc(sizeof(*block_rsv), GFP_NOFS);
    	if (!block_rsv)
    		return NULL;
    
    	btrfs_init_block_rsv(block_rsv, type);
    
    	block_rsv->space_info = __find_space_info(fs_info,
    						  BTRFS_BLOCK_GROUP_METADATA);
    	return block_rsv;
    }
    
    void btrfs_free_block_rsv(struct btrfs_root *root,
    			  struct btrfs_block_rsv *rsv)
    {
    
    Josef Bacik's avatar
    Josef Bacik committed
    	if (!rsv)
    		return;
    
    	btrfs_block_rsv_release(root, rsv, (u64)-1);
    	kfree(rsv);
    
    int btrfs_block_rsv_add(struct btrfs_root *root,
    			struct btrfs_block_rsv *block_rsv, u64 num_bytes,
    			enum btrfs_reserve_flush_enum flush)
    
    	if (num_bytes == 0)
    		return 0;
    
    	ret = reserve_metadata_bytes(root, block_rsv, num_bytes, flush);
    
    	if (!ret) {
    		block_rsv_add_bytes(block_rsv, num_bytes, 1);
    		return 0;
    	}
    
    int btrfs_block_rsv_check(struct btrfs_root *root,
    
    			  struct btrfs_block_rsv *block_rsv, int min_factor)
    
    {
    	u64 num_bytes = 0;
    	int ret = -ENOSPC;
    
    	if (!block_rsv)
    		return 0;
    
    	spin_lock(&block_rsv->lock);
    
    	num_bytes = div_factor(block_rsv->size, min_factor);
    	if (block_rsv->reserved >= num_bytes)
    		ret = 0;
    	spin_unlock(&block_rsv->lock);
    
    int btrfs_block_rsv_refill(struct btrfs_root *root,
    			   struct btrfs_block_rsv *block_rsv, u64 min_reserved,
    			   enum btrfs_reserve_flush_enum flush)
    
    {
    	u64 num_bytes = 0;
    	int ret = -ENOSPC;
    
    	if (!block_rsv)
    		return 0;
    
    	spin_lock(&block_rsv->lock);
    	num_bytes = min_reserved;
    
    	if (block_rsv->reserved >= num_bytes)
    
    		num_bytes -= block_rsv->reserved;
    	spin_unlock(&block_rsv->lock);
    
    	ret = reserve_metadata_bytes(root, block_rsv, num_bytes, flush);
    
    	if (!ret) {
    		block_rsv_add_bytes(block_rsv, num_bytes, 0);
    
    }
    
    int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv,
    			    struct btrfs_block_rsv *dst_rsv,
    			    u64 num_bytes)
    {
    	return block_rsv_migrate_bytes(src_rsv, dst_rsv, num_bytes);
    }
    
    void btrfs_block_rsv_release(struct btrfs_root *root,
    			     struct btrfs_block_rsv *block_rsv,
    			     u64 num_bytes)
    {
    	struct btrfs_block_rsv *global_rsv = &root->fs_info->global_block_rsv;
    	if (global_rsv->full || global_rsv == block_rsv ||
    	    block_rsv->space_info != global_rsv->space_info)
    		global_rsv = NULL;
    
    	block_rsv_release_bytes(root->fs_info, block_rsv, global_rsv,
    				num_bytes);
    
     * helper to calculate size of global block reservation.
     * the desired value is sum of space used by extent tree,
     * checksum tree and root tree
    
    static u64 calc_global_metadata_size(struct btrfs_fs_info *fs_info)
    
    	struct btrfs_space_info *sinfo;
    	u64 num_bytes;
    	u64 meta_used;
    	u64 data_used;
    
    	int csum_size = btrfs_super_csum_size(fs_info->super_copy);
    
    	sinfo = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_DATA);
    	spin_lock(&sinfo->lock);
    	data_used = sinfo->bytes_used;
    	spin_unlock(&sinfo->lock);
    
    	sinfo = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA);
    	spin_lock(&sinfo->lock);
    
    	if (sinfo->flags & BTRFS_BLOCK_GROUP_DATA)
    		data_used = 0;
    
    	meta_used = sinfo->bytes_used;
    	spin_unlock(&sinfo->lock);
    
    	num_bytes = (data_used >> fs_info->sb->s_blocksize_bits) *
    		    csum_size * 2;
    	num_bytes += div64_u64(data_used + meta_used, 50);
    
    	if (num_bytes * 3 > meta_used)
    
    		num_bytes = div64_u64(meta_used, 3);
    
    	return ALIGN(num_bytes, fs_info->extent_root->leafsize << 10);
    }
    
    static void update_global_block_rsv(struct btrfs_fs_info *fs_info)
    {
    	struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
    	struct btrfs_space_info *sinfo = block_rsv->space_info;
    	u64 num_bytes;
    
    	num_bytes = calc_global_metadata_size(fs_info);
    
    	spin_lock(&sinfo->lock);
    
    	spin_lock(&block_rsv->lock);
    
    	block_rsv->size = num_bytes;
    
    	num_bytes = sinfo->bytes_used + sinfo->bytes_pinned +
    
    		    sinfo->bytes_reserved + sinfo->bytes_readonly +
    		    sinfo->bytes_may_use;
    
    
    	if (sinfo->total_bytes > num_bytes) {
    		num_bytes = sinfo->total_bytes - num_bytes;
    		block_rsv->reserved += num_bytes;
    
    		sinfo->bytes_may_use += num_bytes;
    
    		trace_btrfs_space_reservation(fs_info, "space_info",
    
    				      sinfo->flags, num_bytes, 1);
    
    	if (block_rsv->reserved >= block_rsv->size) {
    		num_bytes = block_rsv->reserved - block_rsv->size;
    
    		sinfo->bytes_may_use -= num_bytes;
    
    		trace_btrfs_space_reservation(fs_info, "space_info",
    
    				      sinfo->flags, num_bytes, 0);
    
    		sinfo->reservation_progress++;
    
    		block_rsv->reserved = block_rsv->size;
    		block_rsv->full = 1;
    	}
    
    	spin_unlock(&block_rsv->lock);
    
    	spin_unlock(&sinfo->lock);
    
    static void init_global_block_rsv(struct btrfs_fs_info *fs_info)
    
    	struct btrfs_space_info *space_info;
    
    	space_info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_SYSTEM);
    	fs_info->chunk_block_rsv.space_info = space_info;
    
    	space_info = __find_space_info(fs_info, BTRFS_BLOCK_GROUP_METADATA);
    
    	fs_info->global_block_rsv.space_info = space_info;
    	fs_info->delalloc_block_rsv.space_info = space_info;
    
    	fs_info->trans_block_rsv.space_info = space_info;
    	fs_info->empty_block_rsv.space_info = space_info;
    
    	fs_info->delayed_block_rsv.space_info = space_info;
    
    	fs_info->extent_root->block_rsv = &fs_info->global_block_rsv;
    	fs_info->csum_root->block_rsv = &fs_info->global_block_rsv;
    	fs_info->dev_root->block_rsv = &fs_info->global_block_rsv;
    	fs_info->tree_root->block_rsv = &fs_info->global_block_rsv;
    
    	fs_info->chunk_root->block_rsv = &fs_info->chunk_block_rsv;
    
    
    	update_global_block_rsv(fs_info);
    
    static void release_global_block_rsv(struct btrfs_fs_info *fs_info)
    
    	block_rsv_release_bytes(fs_info, &fs_info->global_block_rsv, NULL,
    				(u64)-1);
    
    	WARN_ON(fs_info->delalloc_block_rsv.size > 0);
    	WARN_ON(fs_info->delalloc_block_rsv.reserved > 0);
    	WARN_ON(fs_info->trans_block_rsv.size > 0);
    	WARN_ON(fs_info->trans_block_rsv.reserved > 0);
    	WARN_ON(fs_info->chunk_block_rsv.size > 0);
    	WARN_ON(fs_info->chunk_block_rsv.reserved > 0);
    
    	WARN_ON(fs_info->delayed_block_rsv.size > 0);
    	WARN_ON(fs_info->delayed_block_rsv.reserved > 0);
    
    void btrfs_trans_release_metadata(struct btrfs_trans_handle *trans,
    				  struct btrfs_root *root)
    
    	if (!trans->block_rsv)
    		return;
    
    
    	if (!trans->bytes_reserved)
    		return;
    
    	trace_btrfs_space_reservation(root->fs_info, "transaction",
    
    				      trans->transid, trans->bytes_reserved, 0);
    
    	btrfs_block_rsv_release(root, trans->block_rsv, trans->bytes_reserved);
    
    /* Can only return 0 or -ENOSPC */
    
    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;
    
    	/*
    
    	 * We need to hold space in order to delete our orphan item once we've
    	 * added it, so this takes the reservation so we can release it later
    	 * when we are truly done with the orphan item.
    
    Chris Mason's avatar
    Chris Mason committed
    	u64 num_bytes = btrfs_calc_trans_metadata_size(root, 1);
    
    	trace_btrfs_space_reservation(root->fs_info, "orphan",
    				      btrfs_ino(inode), num_bytes, 1);
    
    	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;
    
    Chris Mason's avatar
    Chris Mason committed
    	u64 num_bytes = btrfs_calc_trans_metadata_size(root, 1);
    
    	trace_btrfs_space_reservation(root->fs_info, "orphan",
    				      btrfs_ino(inode), num_bytes, 0);
    
    	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)
    {
    	struct btrfs_root *root = pending->root;
    	struct btrfs_block_rsv *src_rsv = get_block_rsv(trans, root);
    	struct btrfs_block_rsv *dst_rsv = &pending->block_rsv;
    	/*
    
    	 * two for root back/forward refs, two for directory entries,
    	 * one for root of the snapshot and one for parent inode.
    
    	u64 num_bytes = btrfs_calc_trans_metadata_size(root, 6);
    
    	dst_rsv->space_info = src_rsv->space_info;
    	return block_rsv_migrate_bytes(src_rsv, dst_rsv, num_bytes);
    
    /**
     * drop_outstanding_extent - drop an outstanding extent
     * @inode: the inode we're dropping the extent for
     *
     * This is called when we are freeing up an outstanding extent, either called
     * after an error or after an extent is written.  This will return the number of
     * reserved extents that need to be freed.  This must be called with
     * BTRFS_I(inode)->lock held.
     */
    
    static unsigned drop_outstanding_extent(struct inode *inode)
    {
    
    	unsigned dropped_extents = 0;
    
    	BUG_ON(!BTRFS_I(inode)->outstanding_extents);
    	BTRFS_I(inode)->outstanding_extents--;
    
    
    	if (BTRFS_I(inode)->outstanding_extents == 0 &&
    
    	    test_and_clear_bit(BTRFS_INODE_DELALLOC_META_RESERVED,
    			       &BTRFS_I(inode)->runtime_flags))
    
    	/*
    	 * If we have more or the same amount of outsanding extents than we have
    	 * reserved then we need to leave the reserved extents count alone.
    	 */
    	if (BTRFS_I(inode)->outstanding_extents >=
    	    BTRFS_I(inode)->reserved_extents)
    
    
    	dropped_extents = BTRFS_I(inode)->reserved_extents -
    		BTRFS_I(inode)->outstanding_extents;
    	BTRFS_I(inode)->reserved_extents -= dropped_extents;
    
    	return dropped_extents + drop_inode_space;
    
    /**
     * calc_csum_metadata_size - return the amount of metada space that must be
     *	reserved/free'd for the given bytes.
     * @inode: the inode we're manipulating
     * @num_bytes: the number of bytes in question
     * @reserve: 1 if we are reserving space, 0 if we are freeing space
     *
     * This adjusts the number of csum_bytes in the inode and then returns the
     * correct amount of metadata that must either be reserved or freed.  We
     * calculate how many checksums we can fit into one leaf and then divide the
     * number of bytes that will need to be checksumed by this value to figure out
     * how many checksums will be required.  If we are adding bytes then the number
     * may go up and we will return the number of additional bytes that must be
     * reserved.  If it is going down we will return the number of bytes that must
     * be freed.
     *
     * This must be called with BTRFS_I(inode)->lock held.
     */
    static u64 calc_csum_metadata_size(struct inode *inode, u64 num_bytes,
    				   int reserve)
    
    	struct btrfs_root *root = BTRFS_I(inode)->root;
    	u64 csum_size;
    	int num_csums_per_leaf;
    	int num_csums;
    	int old_csums;
    
    	if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM &&
    	    BTRFS_I(inode)->csum_bytes == 0)
    		return 0;
    
    	old_csums = (int)div64_u64(BTRFS_I(inode)->csum_bytes, root->sectorsize);
    	if (reserve)
    		BTRFS_I(inode)->csum_bytes += num_bytes;
    	else
    		BTRFS_I(inode)->csum_bytes -= num_bytes;
    	csum_size = BTRFS_LEAF_DATA_SIZE(root) - sizeof(struct btrfs_item);
    	num_csums_per_leaf = (int)div64_u64(csum_size,
    					    sizeof(struct btrfs_csum_item) +
    					    sizeof(struct btrfs_disk_key));
    	num_csums = (int)div64_u64(BTRFS_I(inode)->csum_bytes, root->sectorsize);
    	num_csums = num_csums + num_csums_per_leaf - 1;
    	num_csums = num_csums / num_csums_per_leaf;
    
    	old_csums = old_csums + num_csums_per_leaf - 1;
    	old_csums = old_csums / num_csums_per_leaf;
    
    	/* No change, no need to reserve more */
    	if (old_csums == num_csums)
    		return 0;
    
    	if (reserve)
    		return btrfs_calc_trans_metadata_size(root,
    						      num_csums - old_csums);
    
    	return btrfs_calc_trans_metadata_size(root, old_csums - num_csums);
    
    int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
    {
    	struct btrfs_root *root = BTRFS_I(inode)->root;
    	struct btrfs_block_rsv *block_rsv = &root->fs_info->delalloc_block_rsv;
    
    	u64 to_reserve = 0;
    
    	unsigned nr_extents = 0;
    
    	enum btrfs_reserve_flush_enum flush = BTRFS_RESERVE_FLUSH_ALL;
    
    	/* If we are a free space inode we need to not flush since we will be in
    	 * the middle of a transaction commit.  We also don't need the delalloc
    	 * mutex since we won't race with anybody.  We need this mostly to make
    	 * lockdep shut its filthy mouth.
    	 */
    	if (btrfs_is_free_space_inode(inode)) {
    
    		flush = BTRFS_RESERVE_NO_FLUSH;
    
    	if (flush != BTRFS_RESERVE_NO_FLUSH &&
    	    btrfs_transaction_in_commit(root->fs_info))
    
    	if (delalloc_lock)
    		mutex_lock(&BTRFS_I(inode)->delalloc_mutex);
    
    
    	num_bytes = ALIGN(num_bytes, root->sectorsize);
    
    	spin_lock(&BTRFS_I(inode)->lock);
    	BTRFS_I(inode)->outstanding_extents++;
    
    	if (BTRFS_I(inode)->outstanding_extents >
    
    		nr_extents = BTRFS_I(inode)->outstanding_extents -
    			BTRFS_I(inode)->reserved_extents;
    
    	/*
    	 * Add an item to reserve for updating the inode when we complete the
    	 * delalloc io.
    	 */
    
    	if (!test_bit(BTRFS_INODE_DELALLOC_META_RESERVED,
    		      &BTRFS_I(inode)->runtime_flags)) {
    
    
    	to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents);
    
    	to_reserve += calc_csum_metadata_size(inode, num_bytes, 1);
    
    	csum_bytes = BTRFS_I(inode)->csum_bytes;
    
    	spin_unlock(&BTRFS_I(inode)->lock);
    
    	if (root->fs_info->quota_enabled)
    
    		ret = btrfs_qgroup_reserve(root, num_bytes +
    					   nr_extents * root->leafsize);
    
    
    	/*
    	 * ret != 0 here means the qgroup reservation failed, we go straight to
    	 * the shared error handling then.
    	 */
    	if (ret == 0)
    		ret = reserve_metadata_bytes(root, block_rsv,
    					     to_reserve, flush);
    
    
    		unsigned dropped;
    
    		spin_lock(&BTRFS_I(inode)->lock);
    
    		dropped = drop_outstanding_extent(inode);
    		/*
    
    		 * If the inodes csum_bytes is the same as the original
    		 * csum_bytes then we know we haven't raced with any free()ers
    		 * so we can just reduce our inodes csum bytes and carry on.
    		 * Otherwise we have to do the normal free thing to account for
    		 * the case that the free side didn't free up its reserve
    		 * because of this outstanding reservation.
    
    		if (BTRFS_I(inode)->csum_bytes == csum_bytes)
    			calc_csum_metadata_size(inode, num_bytes, 0);
    		else
    			to_free = calc_csum_metadata_size(inode, num_bytes, 0);
    		spin_unlock(&BTRFS_I(inode)->lock);
    		if (dropped)
    			to_free += btrfs_calc_trans_metadata_size(root, dropped);
    
    
    		if (to_free) {
    
    			btrfs_block_rsv_release(root, block_rsv, to_free);
    
    			trace_btrfs_space_reservation(root->fs_info,
    						      "delalloc",
    						      btrfs_ino(inode),
    						      to_free, 0);
    		}
    
    		if (root->fs_info->quota_enabled) {
    			btrfs_qgroup_free(root, num_bytes +
    						nr_extents * root->leafsize);
    		}
    
    		if (delalloc_lock)
    			mutex_unlock(&BTRFS_I(inode)->delalloc_mutex);
    
    	spin_lock(&BTRFS_I(inode)->lock);
    	if (extra_reserve) {
    
    		set_bit(BTRFS_INODE_DELALLOC_META_RESERVED,
    			&BTRFS_I(inode)->runtime_flags);
    
    		nr_extents--;
    	}
    	BTRFS_I(inode)->reserved_extents += nr_extents;
    	spin_unlock(&BTRFS_I(inode)->lock);
    
    
    	if (delalloc_lock)
    		mutex_unlock(&BTRFS_I(inode)->delalloc_mutex);
    
    	if (to_reserve)
    		trace_btrfs_space_reservation(root->fs_info,"delalloc",
    					      btrfs_ino(inode), to_reserve, 1);
    
    	block_rsv_add_bytes(block_rsv, to_reserve, 1);
    
    	return 0;
    }
    
    
    /**
     * btrfs_delalloc_release_metadata - release a metadata reservation for an inode
     * @inode: the inode to release the reservation for
     * @num_bytes: the number of bytes we're releasing
     *
     * This will release the metadata reservation for an inode.  This can be called
     * once we complete IO for a given set of bytes to release their metadata
     * reservations.
     */
    
    void btrfs_delalloc_release_metadata(struct inode *inode, u64 num_bytes)
    {
    	struct btrfs_root *root = BTRFS_I(inode)->root;
    
    	u64 to_free = 0;
    	unsigned dropped;
    
    
    	num_bytes = ALIGN(num_bytes, root->sectorsize);
    
    	spin_lock(&BTRFS_I(inode)->lock);
    
    	dropped = drop_outstanding_extent(inode);
    
    	if (num_bytes)
    		to_free = calc_csum_metadata_size(inode, num_bytes, 0);
    
    	spin_unlock(&BTRFS_I(inode)->lock);
    
    	if (dropped > 0)
    		to_free += btrfs_calc_trans_metadata_size(root, dropped);
    
    	trace_btrfs_space_reservation(root->fs_info, "delalloc",
    				      btrfs_ino(inode), to_free, 0);
    
    	if (root->fs_info->quota_enabled) {
    		btrfs_qgroup_free(root, num_bytes +
    					dropped * root->leafsize);
    	}
    
    
    	btrfs_block_rsv_release(root, &root->fs_info->delalloc_block_rsv,
    				to_free);
    }
    
    
    /**
     * btrfs_delalloc_reserve_space - reserve data and metadata space for delalloc
     * @inode: inode we're writing to
     * @num_bytes: the number of bytes we want to allocate
     *
     * This will do the following things
     *
     * o reserve space in the data space info for num_bytes
     * o reserve space in the metadata space info based on number of outstanding
     *   extents and how much csums will be needed
     * o add to the inodes ->delalloc_bytes
     * o add it to the fs_info's delalloc inodes list.
     *
     * This will return 0 for success and -ENOSPC if there is no space left.
     */
    
    int btrfs_delalloc_reserve_space(struct inode *inode, u64 num_bytes)
    {
    	int ret;
    
    	ret = btrfs_check_data_free_space(inode, num_bytes);
    
    	if (ret)
    
    		return ret;
    
    	ret = btrfs_delalloc_reserve_metadata(inode, num_bytes);
    	if (ret) {
    		btrfs_free_reserved_data_space(inode, num_bytes);
    		return ret;
    	}
    
    	return 0;
    }
    
    
    /**
     * btrfs_delalloc_release_space - release data and metadata space for delalloc
     * @inode: inode we're releasing space for
     * @num_bytes: the number of bytes we want to free up
     *
     * This must be matched with a call to btrfs_delalloc_reserve_space.  This is
     * called in the case that we don't need the metadata AND data reservations
     * anymore.  So if there is an error or we insert an inline extent.
     *
     * This function will release the metadata space that was not used and will
     * decrement ->delalloc_bytes and remove it from the fs_info delalloc_inodes
     * list if there are no delalloc bytes left.
     */
    
    void btrfs_delalloc_release_space(struct inode *inode, u64 num_bytes)
    {
    	btrfs_delalloc_release_metadata(inode, num_bytes);
    	btrfs_free_reserved_data_space(inode, num_bytes);
    
    static int update_block_group(struct btrfs_root *root,
    
    			      u64 bytenr, u64 num_bytes, int alloc)
    
    	struct btrfs_block_group_cache *cache = NULL;
    
    	struct btrfs_fs_info *info = root->fs_info;
    
    	u64 total = num_bytes;
    
    	u64 old_val;
    
    	/* block accounting for super block */
    	spin_lock(&info->delalloc_lock);
    
    	old_val = btrfs_super_bytes_used(info->super_copy);
    
    	if (alloc)
    		old_val += num_bytes;
    	else
    		old_val -= num_bytes;
    
    	btrfs_set_super_bytes_used(info->super_copy, old_val);
    
    	spin_unlock(&info->delalloc_lock);
    
    
    	while (total) {
    
    		cache = btrfs_lookup_block_group(info, bytenr);
    
    		if (cache->flags & (BTRFS_BLOCK_GROUP_DUP |
    				    BTRFS_BLOCK_GROUP_RAID1 |
    				    BTRFS_BLOCK_GROUP_RAID10))
    			factor = 2;
    		else
    			factor = 1;
    
    		/*
    		 * If this block group has free space cache written out, we
    		 * need to make sure to load it if we are removing space.  This
    		 * is because we need the unpinning stage to actually add the
    		 * space back to the block group, otherwise we will leak space.
    		 */
    		if (!alloc && cache->cached == BTRFS_CACHE_NO)
    
    			cache_block_group(cache, 1);
    
    		byte_in_group = bytenr - cache->key.objectid;
    		WARN_ON(byte_in_group > cache->key.offset);
    
    		spin_lock(&cache->space_info->lock);
    
    		spin_lock(&cache->lock);
    
    		if (btrfs_test_opt(root, SPACE_CACHE) &&
    
    		    cache->disk_cache_state < BTRFS_DC_CLEAR)
    			cache->disk_cache_state = BTRFS_DC_CLEAR;
    
    
    		cache->dirty = 1;
    
    		old_val = btrfs_block_group_used(&cache->item);
    
    		num_bytes = min(total, cache->key.offset - byte_in_group);
    
    		if (alloc) {
    
    			old_val += num_bytes;
    
    			btrfs_set_block_group_used(&cache->item, old_val);
    			cache->reserved -= num_bytes;
    			cache->space_info->bytes_reserved -= num_bytes;
    
    			cache->space_info->bytes_used += num_bytes;
    			cache->space_info->disk_used += num_bytes * factor;
    
    			spin_unlock(&cache->lock);
    
    			spin_unlock(&cache->space_info->lock);
    
    		} else {
    
    			old_val -= num_bytes;
    
    			btrfs_set_block_group_used(&cache->item, old_val);
    
    			cache->pinned += num_bytes;
    			cache->space_info->bytes_pinned += num_bytes;
    
    			cache->space_info->bytes_used -= num_bytes;
    
    			cache->space_info->disk_used -= num_bytes * factor;
    
    			spin_unlock(&cache->lock);
    
    			spin_unlock(&cache->space_info->lock);
    
    			set_extent_dirty(info->pinned_extents,
    					 bytenr, bytenr + num_bytes - 1,
    					 GFP_NOFS | __GFP_NOFAIL);
    
    		btrfs_put_block_group(cache);
    
    		total -= num_bytes;
    		bytenr += num_bytes;
    
    static u64 first_logical_byte(struct btrfs_root *root, u64 search_start)
    {
    
    	struct btrfs_block_group_cache *cache;
    
    	spin_lock(&root->fs_info->block_group_cache_lock);
    	bytenr = root->fs_info->first_logical_byte;
    	spin_unlock(&root->fs_info->block_group_cache_lock);
    
    	if (bytenr < (u64)-1)
    		return bytenr;
    
    
    	cache = btrfs_lookup_first_block_group(root->fs_info, search_start);
    	if (!cache)
    
    	bytenr = cache->key.objectid;
    
    	btrfs_put_block_group(cache);
    
    static int pin_down_extent(struct btrfs_root *root,
    			   struct btrfs_block_group_cache *cache,
    			   u64 bytenr, u64 num_bytes, int reserved)
    
    	spin_lock(&cache->space_info->lock);
    	spin_lock(&cache->lock);
    	cache->pinned += num_bytes;
    	cache->space_info->bytes_pinned += num_bytes;
    	if (reserved) {
    		cache->reserved -= num_bytes;
    		cache->space_info->bytes_reserved -= num_bytes;
    	}
    	spin_unlock(&cache->lock);
    	spin_unlock(&cache->space_info->lock);