Exemplo n.º 1
0
static int ocfs2_steal_resource(struct ocfs2_super *osb,
				struct ocfs2_alloc_context *ac,
				int type)
{
	int i, status = -ENOSPC;
	int slot = __ocfs2_get_steal_slot(osb, type);

	/* Start to steal resource from the first slot after ours. */
	if (slot == OCFS2_INVALID_SLOT)
		slot = osb->slot_num + 1;

	for (i = 0; i < osb->max_slots; i++, slot++) {
		if (slot == osb->max_slots)
			slot = 0;

		if (slot == osb->slot_num)
			continue;

		status = ocfs2_reserve_suballoc_bits(osb, ac,
						     type,
						     (u32)slot, NULL,
						     NOT_ALLOC_NEW_GROUP);
		if (status >= 0) {
			__ocfs2_set_steal_slot(osb, slot, type);
			break;
		}

		ocfs2_free_ac_resource(ac);
	}

	return status;
}
Exemplo n.º 2
0
static int ocfs2_steal_inode_from_other_nodes(struct ocfs2_super *osb,
					      struct ocfs2_alloc_context *ac)
{
	int i, status = -ENOSPC;
	s16 slot = ocfs2_get_inode_steal_slot(osb);

	/* Start to steal inodes from the first slot after ours. */
	if (slot == OCFS2_INVALID_SLOT)
		slot = osb->slot_num + 1;

	for (i = 0; i < osb->max_slots; i++, slot++) {
		if (slot == osb->max_slots)
			slot = 0;

		if (slot == osb->slot_num)
			continue;

		status = ocfs2_reserve_suballoc_bits(osb, ac,
						     INODE_ALLOC_SYSTEM_INODE,
						     slot, NULL,
						     NOT_ALLOC_NEW_GROUP);
		if (status >= 0) {
			ocfs2_set_inode_steal_slot(osb, slot);
			break;
		}

		ocfs2_free_ac_resource(ac);
	}

	return status;
}
Exemplo n.º 3
0
void ocfs2_free_alloc_context(struct ocfs2_alloc_context *ac)
{
	ocfs2_free_ac_resource(ac);
	kfree(ac);
}
Exemplo n.º 4
0
int ocfs2_reserve_new_metadata_blocks(struct ocfs2_super *osb,
				      int blocks,
				      struct ocfs2_alloc_context **ac)
{
	int status;
	int slot = ocfs2_get_meta_steal_slot(osb);

	*ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
	if (!(*ac)) {
		status = -ENOMEM;
		mlog_errno(status);
		goto bail;
	}

	(*ac)->ac_bits_wanted = blocks;
	(*ac)->ac_which = OCFS2_AC_USE_META;
	(*ac)->ac_group_search = ocfs2_block_group_search;

	if (slot != OCFS2_INVALID_SLOT &&
		atomic_read(&osb->s_num_meta_stolen) < OCFS2_MAX_TO_STEAL)
		goto extent_steal;

	atomic_set(&osb->s_num_meta_stolen, 0);
	status = ocfs2_reserve_suballoc_bits(osb, (*ac),
					     EXTENT_ALLOC_SYSTEM_INODE,
					     (u32)osb->slot_num, NULL,
					     ALLOC_GROUPS_FROM_GLOBAL|ALLOC_NEW_GROUP);


	if (status >= 0) {
		status = 0;
		if (slot != OCFS2_INVALID_SLOT)
			ocfs2_init_meta_steal_slot(osb);
		goto bail;
	} else if (status < 0 && status != -ENOSPC) {
		mlog_errno(status);
		goto bail;
	}

	ocfs2_free_ac_resource(*ac);

extent_steal:
	status = ocfs2_steal_meta(osb, *ac);
	atomic_inc(&osb->s_num_meta_stolen);
	if (status < 0) {
		if (status != -ENOSPC)
			mlog_errno(status);
		goto bail;
	}

	status = 0;
bail:
	if ((status < 0) && *ac) {
		ocfs2_free_alloc_context(*ac);
		*ac = NULL;
	}

	if (status)
		mlog_errno(status);
	return status;
}
Exemplo n.º 5
0
int ocfs2_reserve_new_inode(struct ocfs2_super *osb,
			    struct ocfs2_alloc_context **ac)
{
	int status;
	int slot = ocfs2_get_inode_steal_slot(osb);
	u64 alloc_group;

	*ac = kzalloc(sizeof(struct ocfs2_alloc_context), GFP_KERNEL);
	if (!(*ac)) {
		status = -ENOMEM;
		mlog_errno(status);
		goto bail;
	}

	(*ac)->ac_bits_wanted = 1;
	(*ac)->ac_which = OCFS2_AC_USE_INODE;

	(*ac)->ac_group_search = ocfs2_block_group_search;

	/*
	 * stat(2) can't handle i_ino > 32bits, so we tell the
	 * lower levels not to allocate us a block group past that
	 * limit.  The 'inode64' mount option avoids this behavior.
	 */
	if (!(osb->s_mount_opt & OCFS2_MOUNT_INODE64))
		(*ac)->ac_max_block = (u32)~0U;

	/*
	 * slot is set when we successfully steal inode from other nodes.
	 * It is reset in 3 places:
	 * 1. when we flush the truncate log
	 * 2. when we complete local alloc recovery.
	 * 3. when we successfully allocate from our own slot.
	 * After it is set, we will go on stealing inodes until we find the
	 * need to check our slots to see whether there is some space for us.
	 */
	if (slot != OCFS2_INVALID_SLOT &&
	    atomic_read(&osb->s_num_inodes_stolen) < OCFS2_MAX_TO_STEAL)
		goto inode_steal;

	atomic_set(&osb->s_num_inodes_stolen, 0);
	alloc_group = osb->osb_inode_alloc_group;
	status = ocfs2_reserve_suballoc_bits(osb, *ac,
					     INODE_ALLOC_SYSTEM_INODE,
					     (u32)osb->slot_num,
					     &alloc_group,
					     ALLOC_NEW_GROUP |
					     ALLOC_GROUPS_FROM_GLOBAL);
	if (status >= 0) {
		status = 0;

		spin_lock(&osb->osb_lock);
		osb->osb_inode_alloc_group = alloc_group;
		spin_unlock(&osb->osb_lock);
		trace_ocfs2_reserve_new_inode_new_group(
			(unsigned long long)alloc_group);

		/*
		 * Some inodes must be freed by us, so try to allocate
		 * from our own next time.
		 */
		if (slot != OCFS2_INVALID_SLOT)
			ocfs2_init_inode_steal_slot(osb);
		goto bail;
	} else if (status < 0 && status != -ENOSPC) {
		mlog_errno(status);
		goto bail;
	}

	ocfs2_free_ac_resource(*ac);

inode_steal:
	status = ocfs2_steal_inode(osb, *ac);
	atomic_inc(&osb->s_num_inodes_stolen);
	if (status < 0) {
		if (status != -ENOSPC)
			mlog_errno(status);
		goto bail;
	}

	status = 0;
bail:
	if ((status < 0) && *ac) {
		ocfs2_free_alloc_context(*ac);
		*ac = NULL;
	}

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