>From 4b777c8c78bd0ce49c1ac791f2fa202925b88d23 Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Tue, 3 Jan 2012 00:43:58 -0500
Subject: [PATCH 7/9] nsssrv: add handling of memory cache group map

---
 src/responder/nss/nsssrv.c            |    9 ++++-
 src/responder/nss/nsssrv.h            |    1 +
 src/responder/nss/nsssrv_cmd.c        |   16 ++++++-
 src/responder/nss/nsssrv_mmap_cache.c |   70 +++++++++++++++++++++++++++++++++
 src/responder/nss/nsssrv_mmap_cache.h |    6 +++
 src/util/mmap_cache.h                 |   10 +++++
 6 files changed, 108 insertions(+), 4 deletions(-)

diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
index 5ba91f3c3594a2e6c28f0aee93a8a979a27c8e03..f2c893033029e8240d22a49feaf56f3deeed810d 100644
--- a/src/responder/nss/nsssrv.c
+++ b/src/responder/nss/nsssrv.c
@@ -316,7 +316,14 @@ int nss_process_init(TALLOC_CTX *mem_ctx,
                               50000,
                               &nctx->pwd_mc_ctx);
     if (ret) {
-        DEBUG(SSSDBG_CRIT_FAILURE, ("mmap cache is DISABLED"));
+        DEBUG(SSSDBG_CRIT_FAILURE, ("passwd mmap cache is DISABLED"));
+    }
+
+    ret = sss_mmap_cache_init(nctx, "group", SSS_MC_GROUP,
+                              50000,
+                              &nctx->grp_mc_ctx);
+    if (ret) {
+        DEBUG(SSSDBG_CRIT_FAILURE, ("group mmap cache is DISABLED"));
     }
 
     /* Set up file descriptor limits */
diff --git a/src/responder/nss/nsssrv.h b/src/responder/nss/nsssrv.h
index ba52f5827bfc11cc5a837bb63314cb987a21beb0..2871c2bf863019dbda5816f9d8aab961351c0495 100644
--- a/src/responder/nss/nsssrv.h
+++ b/src/responder/nss/nsssrv.h
@@ -67,6 +67,7 @@ struct nss_ctx {
     char *shell_fallback;
 
     struct sss_mc_ctx *pwd_mc_ctx;
+    struct sss_mc_ctx *grp_mc_ctx;
 };
 
 struct nss_packet;
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
index cda2e563fa93e23842ae14646f99656c47937ed4..4706e98b8e4b49ea6bd10b9910ad21d9e5c7f388 100644
--- a/src/responder/nss/nsssrv_cmd.c
+++ b/src/responder/nss/nsssrv_cmd.c
@@ -1676,7 +1676,7 @@ done:
 static int fill_grent(struct sss_packet *packet,
                       struct sss_domain_info *dom,
                       struct nss_ctx *nctx,
-                      bool filter_groups,
+                      bool filter_groups, bool gr_mmap_cache,
                       struct ldb_message **msgs,
                       int *count)
 {
@@ -1917,6 +1917,16 @@ static int fill_grent(struct sss_packet *packet,
         }
 
         num++;
+
+        if (gr_mmap_cache) {
+            ret = sss_mmap_cache_gr_store(nctx->grp_mc_ctx,
+                                          &fullname, &pwfield, gid, memnum,
+                                          (char *)&body[rzero] + STRS_ROFFSET +
+                                            fullname.len + pwfield.len,
+                                          rsize - STRS_ROFFSET -
+                                            fullname.len - pwfield.len);
+        }
+
         continue;
     }
     talloc_zfree(tmp_ctx);
@@ -1957,7 +1967,7 @@ static int nss_cmd_getgr_send_reply(struct nss_dom_ctx *dctx, bool filter)
     i = dctx->res->count;
     ret = fill_grent(cctx->creq->out,
                      dctx->domain,
-                     nctx, filter,
+                     nctx, filter, true,
                      dctx->res->msgs, &i);
     if (ret) {
         return ret;
@@ -2824,7 +2834,7 @@ static int nss_cmd_retgrent(struct cli_ctx *cctx, int num)
 
         ret = fill_grent(cctx->creq->out,
                          gdom->domain,
-                         nctx, true, msgs, &n);
+                         nctx, true, false, msgs, &n);
 
         cctx->grent_cur += n;
     }
diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c
index 40c15af0ae0e17c7b275e36853cfc3ca7629de98..ff54702c24b7a84b404e875117107acdf52c194f 100644
--- a/src/responder/nss/nsssrv_mmap_cache.c
+++ b/src/responder/nss/nsssrv_mmap_cache.c
@@ -423,6 +423,76 @@ errno_t sss_mmap_cache_pw_store(struct sss_mc_ctx *mcc,
 
 
 /***************************************************************************
+ * group map
+ ***************************************************************************/
+
+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;
+}
+
+
+/***************************************************************************
  * initialization
  ***************************************************************************/
 
diff --git a/src/responder/nss/nsssrv_mmap_cache.h b/src/responder/nss/nsssrv_mmap_cache.h
index fc99cdbbd1814e7f564f0e59cb07ea284251affe..72fcf2206275503abb2ee4e11e048a248ed93c39 100644
--- a/src/responder/nss/nsssrv_mmap_cache.h
+++ b/src/responder/nss/nsssrv_mmap_cache.h
@@ -42,4 +42,10 @@ errno_t sss_mmap_cache_pw_store(struct sss_mc_ctx *mcc,
                                 struct sized_string *homedir,
                                 struct sized_string *shell);
 
+errno_t 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);
+
 #endif /* _NSSSRV_MMAP_CACHE_H_ */
diff --git a/src/util/mmap_cache.h b/src/util/mmap_cache.h
index 0a4044a7120309c9e095910514060d1cf759f773..b3dac6ee2ea4b35acc4a65eaea13bbf58297c342 100644
--- a/src/util/mmap_cache.h
+++ b/src/util/mmap_cache.h
@@ -111,6 +111,16 @@ struct sss_mc_pwd_data {
                              * string is zero terminated ordered as follows:
                              * name, passwd, gecos, dir, shell */
 };
+
+struct sss_mc_grp_data {
+    rel_ptr_t name;         /* ptr to name string, rel. to struct base addr */
+    uint32_t gid;
+    uint32_t members;       /* number of members in strs */
+    uint32_t strs_len;      /* length of strs */
+    char strs[0];           /* concatenation of all group strings, each
+                             * string is zero terminated ordered as follows:
+                             * name, passwd, member1, member2, ... */
+};
 #pragma pack()
 
 
-- 
1.7.7.6

