/** Set the initial value of an object.
 *  @author Renaud Lottiaux
 *
 *  @param set        KDDM set hosting the object.
 *  @param obj_entry  Object entry of the object to set.
 *  @param objid      Identifier of the object to set.
 *  @param object     Object to store in the kddm set entry.
 *
 *  This function assumes that a call to kddm_*_object_manual_ft has been done
 *  before. A kddm_put_object must be done after.
 *
 *  @return        0 if everything OK, -1 otherwise.
 */
int _kddm_set_object_state(struct kddm_set *set,
			    objid_t objid,
			    void *object,
			    kddm_obj_state_t state)
{
	struct kddm_obj *obj_entry;

retry:
	obj_entry = __get_kddm_obj_entry(set, objid);

	BUG_ON(OBJ_STATE(obj_entry) != INV_OWNER);
	BUG_ON(!object_frozen(obj_entry));

	if (obj_entry->object != NULL) {
		kddm_io_remove_object_and_unlock(obj_entry, set, objid, NULL);
		printk ("Humf.... Can do really better !\n");
		goto retry;
	}

	obj_entry->object = object;
	atomic_inc(&set->nr_objects);
	ADD_TO_SET (COPYSET(obj_entry), kerrighed_node_id);
	kddm_insert_object (set, objid, obj_entry, state);
	put_kddm_obj_entry(set, obj_entry, objid);

	return 0;
}
Beispiel #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);
}