static void sss_mc_invalidate_rec(struct sss_mc_ctx *mcc, struct sss_mc_rec *rec) { if (rec->b1 == MC_INVALID_VAL) { /* record already invalid */ return; } /* Remove from hash chains */ /* hash chain 1 */ sss_mc_rm_rec_from_chain(mcc, rec, rec->hash1); /* hash chain 2 */ sss_mc_rm_rec_from_chain(mcc, rec, rec->hash2); /* Clear from free_table */ sss_mc_free_slots(mcc, rec); /* Invalidate record fields */ MC_RAISE_INVALID_BARRIER(rec); memset(rec->data, MC_INVALID_VAL8, ((MC_SLOT_SIZE * MC_SIZE_TO_SLOTS(rec->len)) - sizeof(struct sss_mc_rec))); rec->len = MC_INVALID_VAL32; rec->expire = MC_INVALID_VAL64; rec->next = MC_INVALID_VAL32; rec->hash1 = MC_INVALID_VAL32; rec->hash2 = MC_INVALID_VAL32; MC_LOWER_BARRIER(rec); }
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; }
static void sss_mc_invalidate_rec(struct sss_mc_ctx *mcc, struct sss_mc_rec *rec) { if (rec->b1 == MC_INVALID_VAL) { /* record already invalid */ return; } /* hash chain 1 */ sss_mc_rm_rec_from_chain(mcc, rec, rec->hash1); /* hash chain 2 */ sss_mc_rm_rec_from_chain(mcc, rec, rec->hash2); MC_RAISE_INVALID_BARRIER(rec); memset(rec->data, 'X', rec->len - sizeof(struct sss_mc_rec)); rec->len = MC_INVALID_VAL; rec->expire = (uint64_t)-1; rec->next = MC_INVALID_VAL; rec->hash1 = MC_INVALID_VAL; rec->hash2 = MC_INVALID_VAL; MC_LOWER_BARRIER(rec); }
static void sss_mc_header_update(struct sss_mc_ctx *mc_ctx, int status) { struct sss_mc_header *h; /* update header using barriers */ h = (struct sss_mc_header *)mc_ctx->mmap_base; MC_RAISE_BARRIER(h); if (status != SSS_MC_HEADER_RECYCLED) { /* no reason to update anything else if the file is recycled */ h->hash_table = MC_PTR_DIFF(mc_ctx->hash_table, mc_ctx->mmap_base); h->free_table = MC_PTR_DIFF(mc_ctx->free_table, mc_ctx->mmap_base); h->data_table = MC_PTR_DIFF(mc_ctx->data_table, mc_ctx->mmap_base); h->ht_size = mc_ctx->ht_size; h->ft_size = mc_ctx->ft_size; h->dt_size = mc_ctx->dt_size; h->major_vno = SSS_MC_MAJOR_VNO; h->minor_vno = SSS_MC_MINOR_VNO; h->seed = mc_ctx->seed; h->reserved = 0; } h->status = status; MC_LOWER_BARRIER(h); }
int sss_mmap_cache_gr_store(struct sss_mc_ctx *mcc, struct sized_string *name, struct sized_string *pw, gid_t gid, size_t memnum, char *membuf, size_t memsize) { struct sss_mc_rec *rec; struct sss_mc_grp_data *data; struct sized_string gidkey; char gidstr[11]; size_t data_len; size_t rec_len; size_t pos; int ret; ret = snprintf(gidstr, 11, "%ld", (long)gid); if (ret > 10) { return EINVAL; } to_sized_string(&gidkey, gidstr); data_len = name->len + pw->len + memsize; rec_len = sizeof(struct sss_mc_rec) + sizeof(struct sss_mc_grp_data) + data_len; if (rec_len > mcc->dt_size) { return ENOMEM; } rec = sss_mc_get_record(mcc, rec_len, name); data = (struct sss_mc_grp_data *)rec->data; pos = 0; MC_RAISE_BARRIER(rec); /* header */ rec->len = rec_len; rec->expire = time(NULL) + mcc->valid_time_slot; rec->hash1 = sss_mc_hash(mcc, name->str, name->len); rec->hash2 = sss_mc_hash(mcc, gidkey.str, gidkey.len); /* group struct */ data->name = MC_PTR_DIFF(data->strs, data); data->gid = gid; data->members = memnum; data->strs_len = data_len; memcpy(&data->strs[pos], name->str, name->len); pos += name->len; memcpy(&data->strs[pos], pw->str, pw->len); pos += pw->len; memcpy(&data->strs[pos], membuf, memsize); pos += memsize; MC_LOWER_BARRIER(rec); /* finally chain the rec in the hash table */ /* name hash first */ sss_mc_add_rec_to_chain(mcc, rec, rec->hash1); /* then gid */ sss_mc_add_rec_to_chain(mcc, rec, rec->hash2); return EOK; }
errno_t sss_mmap_cache_pw_store(struct sss_mc_ctx *mcc, struct sized_string *name, struct sized_string *pw, uid_t uid, gid_t gid, struct sized_string *gecos, struct sized_string *homedir, struct sized_string *shell) { struct sss_mc_rec *rec; struct sss_mc_pwd_data *data; struct sized_string uidkey; char uidstr[11]; size_t data_len; size_t rec_len; size_t pos; int ret; ret = snprintf(uidstr, 11, "%ld", (long)uid); if (ret > 10) { return EINVAL; } to_sized_string(&uidkey, uidstr); data_len = name->len + pw->len + gecos->len + homedir->len + shell->len; rec_len = sizeof(struct sss_mc_rec) + sizeof(struct sss_mc_pwd_data) + data_len; if (rec_len > mcc->dt_size) { return ENOMEM; } rec = sss_mc_get_record(mcc, rec_len, name); data = (struct sss_mc_pwd_data *)rec->data; pos = 0; MC_RAISE_BARRIER(rec); /* header */ rec->len = rec_len; rec->expire = time(NULL) + mcc->valid_time_slot; rec->hash1 = sss_mc_hash(mcc, name->str, name->len); rec->hash2 = sss_mc_hash(mcc, uidkey.str, uidkey.len); /* passwd struct */ data->name = MC_PTR_DIFF(data->strs, data); data->uid = uid; data->gid = gid; data->strs_len = data_len; memcpy(&data->strs[pos], name->str, name->len); pos += name->len; memcpy(&data->strs[pos], pw->str, pw->len); pos += pw->len; memcpy(&data->strs[pos], gecos->str, gecos->len); pos += gecos->len; memcpy(&data->strs[pos], homedir->str, homedir->len); pos += homedir->len; memcpy(&data->strs[pos], shell->str, shell->len); pos += shell->len; MC_LOWER_BARRIER(rec); /* finally chain the rec in the hash table */ /* name hash first */ sss_mc_add_rec_to_chain(mcc, rec, rec->hash1); /* then uid */ sss_mc_add_rec_to_chain(mcc, rec, rec->hash2); return EOK; }