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