Example #1
0
/*
 * make sure we've got at least bits_wanted contiguous bits in the
 * local alloc. You lose them when you drop i_mutex.
 *
 * We will add ourselves to the transaction passed in, but may start
 * our own in order to shift windows.
 */
int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
				   u32 bits_wanted,
				   struct ocfs2_alloc_context *ac)
{
	int status;
	struct ocfs2_dinode *alloc;
	struct inode *local_alloc_inode;
	unsigned int free_bits;

	BUG_ON(!ac);

	local_alloc_inode =
		ocfs2_get_system_file_inode(osb,
					    LOCAL_ALLOC_SYSTEM_INODE,
					    osb->slot_num);
	if (!local_alloc_inode) {
		status = -ENOENT;
		mlog_errno(status);
		goto bail;
	}

	inode_lock(local_alloc_inode);

	/*
	 * We must double check state and allocator bits because
	 * another process may have changed them while holding i_mutex.
	 */
	spin_lock(&osb->osb_lock);
	if (!ocfs2_la_state_enabled(osb) ||
	    (bits_wanted > osb->local_alloc_bits)) {
		spin_unlock(&osb->osb_lock);
		status = -ENOSPC;
		goto bail;
	}
	spin_unlock(&osb->osb_lock);

	alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data;

#ifdef CONFIG_OCFS2_DEBUG_FS
	if (le32_to_cpu(alloc->id1.bitmap1.i_used) !=
	    ocfs2_local_alloc_count_bits(alloc)) {
		ocfs2_error(osb->sb, "local alloc inode %llu says it has %u used bits, but a count shows %u\n",
			    (unsigned long long)le64_to_cpu(alloc->i_blkno),
			    le32_to_cpu(alloc->id1.bitmap1.i_used),
			    ocfs2_local_alloc_count_bits(alloc));
		status = -EIO;
		goto bail;
	}
#endif

	free_bits = le32_to_cpu(alloc->id1.bitmap1.i_total) -
		le32_to_cpu(alloc->id1.bitmap1.i_used);
	if (bits_wanted > free_bits) {
		/* uhoh, window change time. */
		status =
			ocfs2_local_alloc_slide_window(osb, local_alloc_inode);
		if (status < 0) {
			if (status != -ENOSPC)
				mlog_errno(status);
			goto bail;
		}

		/*
		 * Under certain conditions, the window slide code
		 * might have reduced the number of bits available or
		 * disabled the the local alloc entirely. Re-check
		 * here and return -ENOSPC if necessary.
		 */
		status = -ENOSPC;
		if (!ocfs2_la_state_enabled(osb))
			goto bail;

		free_bits = le32_to_cpu(alloc->id1.bitmap1.i_total) -
			le32_to_cpu(alloc->id1.bitmap1.i_used);
		if (bits_wanted > free_bits)
			goto bail;
	}

	ac->ac_inode = local_alloc_inode;
	/* We should never use localalloc from another slot */
	ac->ac_alloc_slot = osb->slot_num;
	ac->ac_which = OCFS2_AC_USE_LOCAL;
	get_bh(osb->local_alloc_bh);
	ac->ac_bh = osb->local_alloc_bh;
	status = 0;
bail:
	if (status < 0 && local_alloc_inode) {
		inode_unlock(local_alloc_inode);
		iput(local_alloc_inode);
	}

	trace_ocfs2_reserve_local_alloc_bits(
		(unsigned long long)ac->ac_max_block,
		bits_wanted, osb->slot_num, status);

	if (status)
		mlog_errno(status);
	return status;
}
int ocfs2_reserve_local_alloc_bits(struct ocfs2_super *osb,
				   u32 bits_wanted,
				   struct ocfs2_alloc_context *ac)
{
	int status;
	struct ocfs2_dinode *alloc;
	struct inode *local_alloc_inode;
	unsigned int free_bits;

	BUG_ON(!ac);

	local_alloc_inode =
		ocfs2_get_system_file_inode(osb,
					    LOCAL_ALLOC_SYSTEM_INODE,
					    osb->slot_num);
	if (!local_alloc_inode) {
		status = -ENOENT;
		mlog_errno(status);
		goto bail;
	}

	mutex_lock(&local_alloc_inode->i_mutex);

	/*
                                                         
                                                                
  */
	spin_lock(&osb->osb_lock);
	if (!ocfs2_la_state_enabled(osb) ||
	    (bits_wanted > osb->local_alloc_bits)) {
		spin_unlock(&osb->osb_lock);
		status = -ENOSPC;
		goto bail;
	}
	spin_unlock(&osb->osb_lock);

	alloc = (struct ocfs2_dinode *) osb->local_alloc_bh->b_data;

#ifdef CONFIG_OCFS2_DEBUG_FS
	if (le32_to_cpu(alloc->id1.bitmap1.i_used) !=
	    ocfs2_local_alloc_count_bits(alloc)) {
		ocfs2_error(osb->sb, "local alloc inode %llu says it has "
			    "%u free bits, but a count shows %u",
			    (unsigned long long)le64_to_cpu(alloc->i_blkno),
			    le32_to_cpu(alloc->id1.bitmap1.i_used),
			    ocfs2_local_alloc_count_bits(alloc));
		status = -EIO;
		goto bail;
	}
#endif

	free_bits = le32_to_cpu(alloc->id1.bitmap1.i_total) -
		le32_to_cpu(alloc->id1.bitmap1.i_used);
	if (bits_wanted > free_bits) {
		/*                           */
		status =
			ocfs2_local_alloc_slide_window(osb, local_alloc_inode);
		if (status < 0) {
			if (status != -ENOSPC)
				mlog_errno(status);
			goto bail;
		}

		/*
                                                    
                                                       
                                                    
                                          
   */
		status = -ENOSPC;
		if (!ocfs2_la_state_enabled(osb))
			goto bail;

		free_bits = le32_to_cpu(alloc->id1.bitmap1.i_total) -
			le32_to_cpu(alloc->id1.bitmap1.i_used);
		if (bits_wanted > free_bits)
			goto bail;
	}

	ac->ac_inode = local_alloc_inode;
	/*                                                  */
	ac->ac_alloc_slot = osb->slot_num;
	ac->ac_which = OCFS2_AC_USE_LOCAL;
	get_bh(osb->local_alloc_bh);
	ac->ac_bh = osb->local_alloc_bh;
	status = 0;
bail:
	if (status < 0 && local_alloc_inode) {
		mutex_unlock(&local_alloc_inode->i_mutex);
		iput(local_alloc_inode);
	}

	trace_ocfs2_reserve_local_alloc_bits(
		(unsigned long long)ac->ac_max_block,
		bits_wanted, osb->slot_num, status);

	if (status)
		mlog_errno(status);
	return status;
}