示例#1
0
static int osp_precreate_ready_condition(const struct lu_env *env,
					 struct osp_device *d)
{
	if (d->opd_pre_recovering)
		return 0;

	/* ready if got enough precreated objects */
	/* we need to wait for others (opd_pre_reserved) and our object (+1) */
	if (d->opd_pre_reserved + 1 < osp_objs_precreated(env, d))
		return 1;

	/* ready if OST reported no space and no destroys in progress */
	if (d->opd_syn_changes + d->opd_syn_rpc_in_progress == 0 &&
	    d->opd_pre_status == -ENOSPC)
		return 1;

	/* Bail out I/O fails to OST */
	if (d->opd_pre_status != 0 &&
	    d->opd_pre_status != -EAGAIN &&
	    d->opd_pre_status != -ENODEV &&
	    d->opd_pre_status != -ENOSPC) {
		/* DEBUG LU-3230 */
		if (d->opd_pre_status != -EIO)
			CERROR("%s: precreate failed opd_pre_status %d\n",
			       d->opd_obd->obd_name, d->opd_pre_status);
		return 1;
	}

	return 0;
}
示例#2
0
static inline int osp_precreate_near_empty_nolock(const struct lu_env *env,
						  struct osp_device *d)
{
	int window = osp_objs_precreated(env, d);

	/* don't consider new precreation till OST is healty and
	 * has free space */
	return ((window - d->opd_pre_reserved < d->opd_pre_grow_count / 2) &&
		(d->opd_pre_status == 0));
}
static int osp_precreate_ready_condition(const struct lu_env *env,
					 struct osp_device *d)
{
	if (d->opd_pre_recovering)
		return 0;

	/* ready if got enough precreated objects */
	/* we need to wait for others (opd_pre_reserved) and our object (+1) */
	if (d->opd_pre_reserved + 1 < osp_objs_precreated(env, d))
		return 1;

	/* ready if OST reported no space and no destoys in progress */
	if (d->opd_syn_changes + d->opd_syn_rpc_in_progress == 0 &&
	    d->opd_pre_status == -ENOSPC)
		return 1;

	return 0;
}
示例#4
0
/*
 * called to reserve object in the pool
 * return codes:
 *  ENOSPC - no space on corresponded OST
 *  EAGAIN - precreation is in progress, try later
 *  EIO    - no access to OST
 */
int osp_precreate_reserve(const struct lu_env *env, struct osp_device *d)
{
	struct l_wait_info	 lwi;
	cfs_time_t		 expire = cfs_time_shift(obd_timeout);
	int			 precreated, rc;

	ENTRY;

	LASSERTF(osp_objs_precreated(env, d) >= 0, "Last created FID "DFID
		 "Next FID "DFID"\n", PFID(&d->opd_pre_last_created_fid),
		 PFID(&d->opd_pre_used_fid));

	/*
	 * wait till:
	 *  - preallocation is done
	 *  - no free space expected soon
	 *  - can't connect to OST for too long (obd_timeout)
	 *  - OST can allocate fid sequence.
	 */
	while ((rc = d->opd_pre_status) == 0 || rc == -ENOSPC ||
		rc == -ENODEV || rc == -EAGAIN || rc == -ENOTCONN) {

		/*
		 * increase number of precreations
		 */
		precreated = osp_objs_precreated(env, d);
		if (d->opd_pre_grow_count < d->opd_pre_max_grow_count &&
		    d->opd_pre_grow_slow == 0 &&
		    precreated <= (d->opd_pre_grow_count / 4 + 1)) {
			spin_lock(&d->opd_pre_lock);
			d->opd_pre_grow_slow = 1;
			d->opd_pre_grow_count *= 2;
			spin_unlock(&d->opd_pre_lock);
		}

		spin_lock(&d->opd_pre_lock);
		precreated = osp_objs_precreated(env, d);
		if (precreated > d->opd_pre_reserved &&
		    !d->opd_pre_recovering) {
			d->opd_pre_reserved++;
			spin_unlock(&d->opd_pre_lock);
			rc = 0;

			/* XXX: don't wake up if precreation is in progress */
			if (osp_precreate_near_empty_nolock(env, d) &&
			   !osp_precreate_end_seq_nolock(env, d))
				wake_up(&d->opd_pre_waitq);

			break;
		}
		spin_unlock(&d->opd_pre_lock);

		/*
		 * all precreated objects have been used and no-space
		 * status leave us no chance to succeed very soon
		 * but if there is destroy in progress, then we should
		 * wait till that is done - some space might be released
		 */
		if (unlikely(rc == -ENOSPC)) {
			if (d->opd_syn_changes) {
				/* force local commit to release space */
				dt_commit_async(env, d->opd_storage);
			}
			if (d->opd_syn_rpc_in_progress) {
				/* just wait till destroys are done */
				/* see l_wait_even() few lines below */
			}
			if (d->opd_syn_changes +
			    d->opd_syn_rpc_in_progress == 0) {
				/* no hope for free space */
				break;
			}
		}

		/* XXX: don't wake up if precreation is in progress */
		wake_up(&d->opd_pre_waitq);

		lwi = LWI_TIMEOUT(expire - cfs_time_current(),
				osp_precreate_timeout_condition, d);
		if (cfs_time_aftereq(cfs_time_current(), expire)) {
			rc = -ETIMEDOUT;
			break;
		}

		l_wait_event(d->opd_pre_user_waitq,
			     osp_precreate_ready_condition(env, d), &lwi);
	}

	RETURN(rc);
}