summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/responder/nss/nsssrv_mmap_cache.c66
-rw-r--r--src/sss_client/nss_mc.h2
-rw-r--r--src/sss_client/nss_mc_common.c13
-rw-r--r--src/sss_client/nss_mc_group.c8
-rw-r--r--src/sss_client/nss_mc_passwd.c8
-rw-r--r--src/util/mmap_cache.h20
6 files changed, 83 insertions, 34 deletions
diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c
index 69fe2078..8655a1a0 100644
--- a/src/responder/nss/nsssrv_mmap_cache.c
+++ b/src/responder/nss/nsssrv_mmap_cache.c
@@ -93,6 +93,34 @@ struct sss_mc_ctx {
else used = false; \
} while (0)
+static inline
+uint32_t sss_mc_next_slot_with_hash(struct sss_mc_rec *rec,
+ uint32_t hash)
+{
+ if (rec->hash1 == hash) {
+ return rec->next1;
+ } else if (rec->hash2 == hash) {
+ return rec->next2;
+ } else {
+ /* it should never happen. */
+ return MC_INVALID_VAL;
+ }
+}
+
+static inline
+void sss_mc_chain_slot_to_record_with_hash(struct sss_mc_rec *rec,
+ uint32_t hash,
+ uint32_t slot)
+{
+ /* changing a single uint32_t is atomic, so there is no
+ * need to use barriers in this case */
+ if (rec->hash1 == hash) {
+ rec->next1 = slot;
+ } else if (rec->hash2 == hash) {
+ rec->next2 = slot;
+ }
+}
+
/* This function will store corrupted memcache to disk for later
* analysis. */
static void sss_mc_save_corrupted(struct sss_mc_ctx *mc_ctx)
@@ -196,13 +224,12 @@ static void sss_mc_add_rec_to_chain(struct sss_mc_ctx *mcc,
/* rec already stored in hash chain */
return;
}
- slot = cur->next;
+ slot = sss_mc_next_slot_with_hash(cur, hash);
} 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);
+ slot = MC_PTR_TO_SLOT(mcc->data_table, rec);
+ sss_mc_chain_slot_to_record_with_hash(cur, hash, slot);
}
static void sss_mc_rm_rec_from_chain(struct sss_mc_ctx *mcc,
@@ -230,19 +257,19 @@ static void sss_mc_rm_rec_from_chain(struct sss_mc_ctx *mcc,
}
cur = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
if (cur == rec) {
- mcc->hash_table[hash] = rec->next;
+ mcc->hash_table[hash] = sss_mc_next_slot_with_hash(rec, hash);
} else {
- slot = cur->next;
+ slot = sss_mc_next_slot_with_hash(cur, hash);
while (slot != MC_INVALID_VAL) {
prev = cur;
cur = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
if (cur == rec) {
- /* changing a single uint32_t is atomic, so there is no
- * need to use barriers in this case */
- prev->next = cur->next;
+ slot = sss_mc_next_slot_with_hash(cur, hash);
+
+ sss_mc_chain_slot_to_record_with_hash(prev, hash, slot);
slot = MC_INVALID_VAL;
} else {
- slot = cur->next;
+ slot = sss_mc_next_slot_with_hash(cur, hash);
}
}
}
@@ -284,7 +311,8 @@ static void sss_mc_invalidate_rec(struct sss_mc_ctx *mcc,
- sizeof(struct sss_mc_rec)));
rec->len = MC_INVALID_VAL32;
rec->expire = MC_INVALID_VAL64;
- rec->next = MC_INVALID_VAL32;
+ rec->next1 = MC_INVALID_VAL32;
+ rec->next2 = MC_INVALID_VAL32;
rec->hash1 = MC_INVALID_VAL32;
rec->hash2 = MC_INVALID_VAL32;
MC_LOWER_BARRIER(rec);
@@ -313,7 +341,7 @@ static bool sss_mc_is_valid_rec(struct sss_mc_ctx *mcc, struct sss_mc_rec *rec)
return false;
}
- /* rec->next can be invalid if there are no next records */
+ /* next record can be invalid if there are no next records */
if (rec->hash1 == MC_INVALID_VAL32) {
return false;
@@ -322,7 +350,7 @@ static bool sss_mc_is_valid_rec(struct sss_mc_ctx *mcc, struct sss_mc_rec *rec)
slot = mcc->hash_table[rec->hash1];
while (slot != MC_INVALID_VAL32 && self != rec) {
self = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
- slot = self->next;
+ slot = sss_mc_next_slot_with_hash(self, rec->hash1);
}
if (self != rec) {
return false;
@@ -333,7 +361,7 @@ static bool sss_mc_is_valid_rec(struct sss_mc_ctx *mcc, struct sss_mc_rec *rec)
slot = mcc->hash_table[rec->hash2];
while (slot != MC_INVALID_VAL32 && self != rec) {
self = MC_SLOT_TO_PTR(mcc->data_table, slot, struct sss_mc_rec);
- slot = self->next;
+ slot = sss_mc_next_slot_with_hash(self, rec->hash2);
}
if (self != rec) {
return false;
@@ -527,7 +555,7 @@ static struct sss_mc_rec *sss_mc_find_record(struct sss_mc_ctx *mcc,
break;
}
- slot = rec->next;
+ slot = sss_mc_next_slot_with_hash(rec, hash);
}
if (slot == MC_INVALID_VAL) {
@@ -583,7 +611,9 @@ static errno_t sss_mc_get_record(struct sss_mc_ctx **_mcc,
/* mark as not valid yet */
MC_RAISE_INVALID_BARRIER(rec);
rec->len = rec_len;
- rec->next = MC_INVALID_VAL;
+ rec->next1 = MC_INVALID_VAL;
+ rec->next2 = MC_INVALID_VAL;
+ rec->padding = MC_INVALID_VAL;
MC_LOWER_BARRIER(rec);
/* and now mark slots as used */
@@ -769,7 +799,7 @@ errno_t sss_mmap_cache_pw_invalidate_uid(struct sss_mc_ctx *mcc, uid_t uid)
break;
}
- slot = rec->next;
+ slot = sss_mc_next_slot_with_hash(rec, hash);
}
if (slot == MC_INVALID_VAL) {
@@ -908,7 +938,7 @@ errno_t sss_mmap_cache_gr_invalidate_gid(struct sss_mc_ctx *mcc, gid_t gid)
break;
}
- slot = rec->next;
+ slot = sss_mc_next_slot_with_hash(rec, hash);
}
if (slot == MC_INVALID_VAL) {
diff --git a/src/sss_client/nss_mc.h b/src/sss_client/nss_mc.h
index f3abaab9..685cc41c 100644
--- a/src/sss_client/nss_mc.h
+++ b/src/sss_client/nss_mc.h
@@ -58,6 +58,8 @@ errno_t sss_nss_mc_get_record(struct sss_cli_mc_ctx *ctx,
uint32_t slot, struct sss_mc_rec **_rec);
errno_t sss_nss_str_ptr_from_buffer(char **str, void **cookie,
char *buf, size_t len);
+uint32_t sss_nss_mc_next_slot_with_hash(struct sss_mc_rec *rec,
+ uint32_t hash);
/* passwd db */
errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len,
diff --git a/src/sss_client/nss_mc_common.c b/src/sss_client/nss_mc_common.c
index a0a70abc..db9be94b 100644
--- a/src/sss_client/nss_mc_common.c
+++ b/src/sss_client/nss_mc_common.c
@@ -291,3 +291,16 @@ errno_t sss_nss_str_ptr_from_buffer(char **str, void **cookie,
return 0;
}
+uint32_t sss_nss_mc_next_slot_with_hash(struct sss_mc_rec *rec,
+ uint32_t hash)
+{
+ if (rec->hash1 == hash) {
+ return rec->next1;
+ } else if (rec->hash2 == hash) {
+ return rec->next2;
+ } else {
+ /* it should never happen. */
+ return MC_INVALID_VAL;
+ }
+
+}
diff --git a/src/sss_client/nss_mc_group.c b/src/sss_client/nss_mc_group.c
index 4e3d9fb0..5610233e 100644
--- a/src/sss_client/nss_mc_group.c
+++ b/src/sss_client/nss_mc_group.c
@@ -130,7 +130,7 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len,
/* check record matches what we are searching for */
if (hash != rec->hash1) {
/* if name hash does not match we can skip this immediately */
- slot = rec->next;
+ slot = sss_nss_mc_next_slot_with_hash(rec, hash);
continue;
}
@@ -152,7 +152,7 @@ errno_t sss_nss_mc_getgrnam(const char *name, size_t name_len,
break;
}
- slot = rec->next;
+ slot = sss_nss_mc_next_slot_with_hash(rec, hash);
}
if (!MC_SLOT_WITHIN_BOUNDS(slot, gr_mc_ctx.dt_size)) {
@@ -205,7 +205,7 @@ errno_t sss_nss_mc_getgrgid(gid_t gid,
/* check record matches what we are searching for */
if (hash != rec->hash2) {
/* if uid hash does not match we can skip this immediately */
- slot = rec->next;
+ slot = sss_nss_mc_next_slot_with_hash(rec, hash);
continue;
}
@@ -214,7 +214,7 @@ errno_t sss_nss_mc_getgrgid(gid_t gid,
break;
}
- slot = rec->next;
+ slot = sss_nss_mc_next_slot_with_hash(rec, hash);
}
if (!MC_SLOT_WITHIN_BOUNDS(slot, gr_mc_ctx.dt_size)) {
diff --git a/src/sss_client/nss_mc_passwd.c b/src/sss_client/nss_mc_passwd.c
index a0a8d87f..95b8a040 100644
--- a/src/sss_client/nss_mc_passwd.c
+++ b/src/sss_client/nss_mc_passwd.c
@@ -131,7 +131,7 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len,
/* check record matches what we are searching for */
if (hash != rec->hash1) {
/* if name hash does not match we can skip this immediately */
- slot = rec->next;
+ slot = sss_nss_mc_next_slot_with_hash(rec, hash);
continue;
}
@@ -154,7 +154,7 @@ errno_t sss_nss_mc_getpwnam(const char *name, size_t name_len,
break;
}
- slot = rec->next;
+ slot = sss_nss_mc_next_slot_with_hash(rec, hash);
}
if (!MC_SLOT_WITHIN_BOUNDS(slot, pw_mc_ctx.dt_size)) {
@@ -207,7 +207,7 @@ errno_t sss_nss_mc_getpwuid(uid_t uid,
/* check record matches what we are searching for */
if (hash != rec->hash2) {
/* if uid hash does not match we can skip this immediately */
- slot = rec->next;
+ slot = sss_nss_mc_next_slot_with_hash(rec, hash);
continue;
}
@@ -216,7 +216,7 @@ errno_t sss_nss_mc_getpwuid(uid_t uid,
break;
}
- slot = rec->next;
+ slot = sss_nss_mc_next_slot_with_hash(rec, hash);
}
if (!MC_SLOT_WITHIN_BOUNDS(slot, pw_mc_ctx.dt_size)) {
diff --git a/src/util/mmap_cache.h b/src/util/mmap_cache.h
index 7c6693ac..81269fe7 100644
--- a/src/util/mmap_cache.h
+++ b/src/util/mmap_cache.h
@@ -53,15 +53,15 @@ typedef uint32_t rel_ptr_t;
#define MC_INVALID_VAL MC_INVALID_VAL32
/*
- * 32 seem a good compromise for slot size
+ * 40 seem a good compromise for slot size
* 4 blocks are enough for the average passwd entry of 42 bytes
- * passwd records have 84 bytes of overhead, 128 - 82 = 46 bytes
- * 3 blocks can contain a very minimal entry, 96 - 82 = 14 bytes
+ * passwd records have 84 bytes of overhead, 160 - 82 = 78 bytes
+ * 3 blocks can contain a very minimal entry, 120 - 82 = 38 bytes
*
* 3 blocks are enough for groups w/o users (private user groups)
- * group records have 68 bytes of overhead, 96 - 66 = 30 bytes
+ * group records have 68 bytes of overhead, 120 - 66 = 54 bytes
*/
-#define MC_SLOT_SIZE 32
+#define MC_SLOT_SIZE 40
#define MC_SIZE_TO_SLOTS(len) (((len) + (MC_SLOT_SIZE - 1)) / MC_SLOT_SIZE)
#define MC_PTR_TO_SLOT(base, ptr) (MC_PTR_DIFF(ptr, base) / MC_SLOT_SIZE)
#define MC_SLOT_TO_PTR(base, slot, type) \
@@ -78,8 +78,8 @@ typedef uint32_t rel_ptr_t;
- MC_PTR_DIFF(rec, (mc_ctx)->data_table))))
-#define SSS_MC_MAJOR_VNO 0
-#define SSS_MC_MINOR_VNO 4
+#define SSS_MC_MAJOR_VNO 1
+#define SSS_MC_MINOR_VNO 0
#define SSS_MC_HEADER_UNINIT 0 /* after ftruncate or before reset */
#define SSS_MC_HEADER_ALIVE 1 /* current and in use */
@@ -106,9 +106,13 @@ struct sss_mc_rec {
uint32_t b1; /* barrier 1 */
uint32_t len; /* total record length including record data */
uint64_t expire; /* record expiration time (cast to time_t) */
- rel_ptr_t next; /* ptr of next record rel to data_table */
+ rel_ptr_t next1; /* ptr of next record rel to data_table */
+ /* next1 is related to hash1 */
+ rel_ptr_t next2; /* ptr of next record rel to data_table */
+ /* next2 is related to hash2 */
uint32_t hash1; /* val of first hash (usually name of record) */
uint32_t hash2; /* val of second hash (usually id of record) */
+ uint32_t padding; /* padding & reserved for future changes */
uint32_t b2; /* barrier 2 - 32 bytes mark, fits a slot */
char data[0];
};