Пример #1
0
static void sss_mc_add_rec_to_chain(struct sss_mc_ctx *mcc,
                                    struct sss_mc_rec *rec,
                                    uint32_t hash)
{
    struct sss_mc_rec *cur;
    uint32_t slot;

    slot = mcc->hash_table[hash];
    if (slot == MC_INVALID_VAL) {
        /* no previous record/collision, just add to hash table */
        mcc->hash_table[hash] = MC_PTR_TO_SLOT(mcc->data_table, rec);
        return;
    }

    do {
        cur = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
        if (cur == rec) {
            /* rec already stored in hash chain */
            return;
        }
        slot = cur->next;
    } while (slot != MC_INVALID_VAL);
    /* end of chain, append our record here */

    /* changing a single uint32_t is atomic, so there is no
     * need to use barriers in this case */
    cur->next = MC_PTR_TO_SLOT(mcc->data_table, rec);
}
Пример #2
0
static void sss_mc_add_rec_to_chain(struct sss_mc_ctx *mcc,
                                    struct sss_mc_rec *rec,
                                    uint32_t hash)
{
    struct sss_mc_rec *cur;
    uint32_t slot;

    if (hash > MC_HT_ELEMS(mcc->ht_size)) {
        /* Invalid hash. This should never happen, but better
         * return than trying to access out of bounds memory */
        return;
    }

    slot = mcc->hash_table[hash];
    if (slot == MC_INVALID_VAL) {
        /* no previous record/collision, just add to hash table */
        mcc->hash_table[hash] = MC_PTR_TO_SLOT(mcc->data_table, rec);
        return;
    }

    do {
        cur = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
        if (cur == rec) {
            /* rec already stored in hash chain */
            return;
        }
        slot = sss_mc_next_slot_with_hash(cur, hash);
    } while (slot != MC_INVALID_VAL);
    /* end of chain, append our record here */

    slot = MC_PTR_TO_SLOT(mcc->data_table, rec);
    sss_mc_chain_slot_to_record_with_hash(cur, hash, slot);
}
Пример #3
0
static void sss_mc_free_slots(struct sss_mc_ctx *mcc, struct sss_mc_rec *rec)
{
    uint32_t slot;
    uint32_t num;
    uint32_t i;

    slot = MC_PTR_TO_SLOT(mcc->data_table, rec);
    num = MC_SIZE_TO_SLOTS(rec->len);
    for (i = 0; i < num; i++) {
        MC_CLEAR_BIT(mcc->free_table, slot + i);
    }
}
Пример #4
0
static struct sss_mc_rec *sss_mc_get_record(struct sss_mc_ctx *mcc,
                                            size_t rec_len,
                                            struct sized_string *key)
{
    struct sss_mc_rec *old_rec = NULL;
    struct sss_mc_rec *rec;
    int old_slots;
    int num_slots;
    uint32_t base_slot;
    int i;

    num_slots = MC_SIZE_TO_SLOTS(rec_len);

    old_rec = sss_mc_find_record(mcc, key);
    if (old_rec) {
        old_slots = MC_SIZE_TO_SLOTS(old_rec->len);

        if (old_slots == num_slots) {
            return old_rec;
        }

        /* slot size changed, invalidate record and fall through to get a
        * fully new record */
        base_slot = MC_PTR_TO_SLOT(mcc->data_table, old_rec);
        sss_mc_invalidate_rec(mcc, old_rec);

        /* and now free slots */
        for (i = 0; i < old_slots; i++) {
            MC_CLEAR_BIT(mcc->free_table, base_slot + i);
        }
    }

    /* we are going to use more space, find enough free slots */
    base_slot = sss_mc_find_free_slots(mcc, num_slots);

    rec = MC_SLOT_TO_PTR(mcc->data_table, base_slot, struct sss_mc_rec);

    /* mark as not valid yet */
    MC_RAISE_INVALID_BARRIER(rec);
    rec->len = rec_len;
    rec->next = MC_INVALID_VAL;
    MC_LOWER_BARRIER(rec);

    /* and now mark slots as used */
    for (i = 0; i < num_slots; i++) {
        MC_SET_BIT(mcc->free_table, base_slot + i);
    }

    return rec;
}