/** 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; }
/** 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); }