Example #1
0
/** Place a copy of a given object in local physical memory.
 *  @author Renaud Lottiaux
 *
 *  @param set        KDDM set hosting the object.
 *  @param obj_entry  Object entry of the object to get.
 *  @param objid      Identifier of the object to get.
 *  @param flags      Sync / Async request, FT or not, etc...
 *
 *  @return        Address of the object if found.
 *                 NULL if the object does not exist.
 *                 Negative value if error.
 *
 *  A object is retreived from a remote node owning a copy. If there is
 *  no copy in the cluster and the NO_FT flag is not set,
 *  the object is created by the IO Linker. Otherwise NULL is returned.
 */
void *generic_kddm_get_object(struct kddm_set *set,
			      objid_t objid,
			      int flags)
{
	struct kddm_obj *obj_entry;
	void *object = NULL;

	inc_get_object_counter (set);

	obj_entry = __get_kddm_obj_entry(set, objid);
	if (likely(obj_entry != NULL))
		goto try_again;

	if (I_AM_DEFAULT_OWNER(set, objid) && (flags & KDDM_NO_FT_REQ) &&
	    !(flags & KDDM_SEND_OWNERSHIP))
		return NULL;

	obj_entry = __get_alloc_kddm_obj_entry(set, objid);

try_again:
	switch (OBJ_STATE(obj_entry)) {
	case INV_COPY:
		request_object_on_read(set, obj_entry, objid, flags);
		kddm_change_obj_state(set, obj_entry, objid, WAIT_OBJ_READ);
		/* Fall through */

	case WAIT_ACK_WRITE:
	case WAIT_OBJ_WRITE:
	case WAIT_OBJ_READ:
	case INV_FILLING:
		if (flags & KDDM_ASYNC_REQ)
			goto exit_no_freeze;

		sleep_on_kddm_obj(set, obj_entry, objid, flags);

		if ((flags & KDDM_NO_FT_REQ) &&
		    ((OBJ_STATE(obj_entry) == INV_COPY) ||
		     (OBJ_STATE(obj_entry) == INV_OWNER)))
			goto exit;

		if (!(OBJ_STATE(obj_entry) & KDDM_READ_OBJ)) {
			/* Argh, object has been invalidated before we
			   woke up. */
			goto try_again;
		}
		break;

	case WAIT_CHG_OWN_ACK:
	case READ_COPY:
	case READ_OWNER:
	case WRITE_OWNER:
	case WAIT_ACK_INV:
		break;

	case WAIT_OBJ_RM_DONE:
	case WAIT_OBJ_RM_ACK:
	case WAIT_OBJ_RM_ACK2:
		sleep_on_kddm_obj(set, obj_entry, objid, flags);
		goto try_again;

	case WRITE_GHOST:
		kddm_change_obj_state(set, obj_entry, objid, WRITE_OWNER);
		break;

	case INV_OWNER:          /* First Touch */
		if (flags & KDDM_NO_FT_REQ)
			goto exit;

		/*** The object can be created on the local node  ***/
		if (object_first_touch(set, obj_entry, objid,
				       READ_OWNER, flags) != 0)
			BUG();
		break;

	default:
		STATE_MACHINE_ERROR(set->id, objid, obj_entry);
		break;
	}

exit:
	if (flags & KDDM_ASYNC_REQ)
		goto exit_no_freeze;

	if (check_sleep_on_local_exclusive(set, obj_entry, objid, flags))
		goto try_again;
	if (!(flags & KDDM_NO_FREEZE))
		set_object_frozen(obj_entry, set);

exit_no_freeze:
	object = obj_entry->object;
	put_kddm_obj_entry(set, obj_entry, objid);

	return object;
}
Example #2
0
/** Get a copy of a object and invalidate any other existing copy.
 *  @author Renaud Lottiaux
 *
 *  @param set        KDDM set hosting the object.
 *  @param obj_entry  Object entry of the object to grab.
 *  @param objid      Identifier of the object to grab.
 *  @param flags      Sync / Async request, FT or not, etc...
 *
 *  @return              Address of the object if found.
 *                       NULL if the object does not exist.
 *                       Negative value if error.
 */
void *generic_kddm_grab_object(struct kddm_set *set,
			       objid_t objid,
			       int flags)
{
	struct kddm_obj *obj_entry;
	void *object;
	int retry;

	inc_grab_object_counter(set);

	obj_entry = __get_kddm_obj_entry(set, objid);
	if (likely(obj_entry != NULL))
		goto try_again;

	if (I_AM_DEFAULT_OWNER(set, objid) && (flags & KDDM_NO_FT_REQ) &&
	    !(flags & KDDM_SEND_OWNERSHIP))
		return NULL;

	obj_entry = __get_alloc_kddm_obj_entry(set, objid);

try_again:
	switch (OBJ_STATE(obj_entry)) {
	case READ_COPY:
		if (object_frozen(obj_entry, set)) {
			if (flags & KDDM_ASYNC_REQ)
				BUG();
			goto sleep;
		}

	case INV_COPY:
		request_object_on_write(set, obj_entry, objid, flags);
		CLEAR_SET(COPYSET(obj_entry));
		kddm_change_obj_state(set, obj_entry, objid, WAIT_OBJ_WRITE);
		if (flags & KDDM_TRY_GRAB)
			goto sleep_on_wait_page;
		/* Else Fall through */

	case WAIT_ACK_WRITE:
	case WAIT_OBJ_WRITE:
	case INV_FILLING:
		if (flags & KDDM_TRY_GRAB)
			goto exit_try_failed;

		if (flags & KDDM_ASYNC_REQ)
			goto exit_no_freeze;

sleep_on_wait_page:
		sleep_on_kddm_obj(set, obj_entry, objid, flags);

		if (OBJ_STATE(obj_entry) == WRITE_OWNER) {
			obj_entry = check_cow (set, obj_entry, objid, flags,
					       &retry);
			if (retry)
				goto try_again;
			break;
		}

		if (flags & KDDM_NO_FT_REQ) {
			if (OBJ_STATE(obj_entry) == INV_OWNER)
				break;

			if (OBJ_STATE(obj_entry) == INV_COPY) {
				if (!(flags & KDDM_SEND_OWNERSHIP))
					break;
				BUG();
			}
		}

		if (flags & KDDM_TRY_GRAB)
			goto exit_try_failed;

		/* Argh, object has been invalidated before we woke up. */
		goto try_again;

	case INV_OWNER:
		if (flags & KDDM_NO_FT_REQ)
			break;

		/*** The object can be created on the local node  ***/
		if (object_first_touch(set, obj_entry, objid,
				       WRITE_OWNER, flags) != 0)
			BUG();
		break;

	case READ_OWNER:
		obj_entry = check_cow (set, obj_entry, objid, flags,
				       &retry);
		if (retry)
			goto try_again;

		if (!OBJ_EXCLUSIVE(obj_entry)) {
			kddm_change_obj_state(set, obj_entry, objid,
					      WAIT_ACK_WRITE);
			request_copies_invalidation(set, obj_entry, objid,
						    kerrighed_node_id);
			if (flags & KDDM_ASYNC_REQ)
				goto exit_no_freeze;
			sleep_on_kddm_obj(set, obj_entry, objid, flags);

			if (OBJ_STATE(obj_entry) != WRITE_OWNER) {
				/* Argh, object has been invalidated before
				   we woke up. */
				goto try_again;
			}
		} else
			kddm_change_obj_state(set, obj_entry, objid,
					      WRITE_OWNER);
		break;

	case WRITE_OWNER:
		obj_entry = check_cow (set, obj_entry, objid, flags, &retry);
		if (retry)
			goto try_again;
		break;

	case WRITE_GHOST:
		obj_entry = check_cow (set, obj_entry, objid, flags, &retry);
		if (retry)
			goto try_again;
		kddm_change_obj_state(set, obj_entry, objid, WRITE_OWNER);
		break;

	case WAIT_ACK_INV:
	case WAIT_OBJ_READ:
		if (flags & KDDM_TRY_GRAB)
			goto exit_try_failed;

		/* Fall through */
	case WAIT_OBJ_RM_DONE:
	case WAIT_OBJ_RM_ACK:
	case WAIT_OBJ_RM_ACK2:
	case WAIT_CHG_OWN_ACK:
sleep:
		if (flags & KDDM_ASYNC_REQ)
			goto exit_no_freeze;

		sleep_on_kddm_obj(set, obj_entry, objid, flags);
		goto try_again;

	default:
		STATE_MACHINE_ERROR(set->id, objid, obj_entry);
		break;
	}

	if (flags & KDDM_ASYNC_REQ)
		goto exit_no_freeze;

	if (object_frozen(obj_entry, set) &&
	    (flags & KDDM_TRY_GRAB) &&
	    (kddm_local_exclusive (set)))
		goto exit_try_failed;

	if (check_sleep_on_local_exclusive(set, obj_entry, objid, flags))
		goto try_again;

	if (!(flags & KDDM_NO_FREEZE))
		set_object_frozen(obj_entry, set);

exit_no_freeze:
	object = obj_entry->object;
	put_kddm_obj_entry(set, obj_entry, objid);

	return object;

exit_try_failed:
	put_kddm_obj_entry(set, obj_entry, objid);
	return ERR_PTR(-EBUSY);
}