https://fedorahosted.org/sssd/ticket/1166
From da8219b8d671a516a436174ce36f34464d37c98b Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhro...@redhat.com>
Date: Thu, 23 Feb 2012 18:57:27 +0100
Subject: [PATCH] AUTOFS: speed up the client by requesting multiple entries
 at once

https://fedorahosted.org/sssd/ticket/1166
---
 src/responder/autofs/autofs_private.h |    1 +
 src/responder/autofs/autofssrv_cmd.c  |  112 ++++++++++++-----
 src/sss_client/autofs/sss_autofs.c    |  224 +++++++++++++++++++++++++--------
 3 files changed, 249 insertions(+), 88 deletions(-)

diff --git a/src/responder/autofs/autofs_private.h 
b/src/responder/autofs/autofs_private.h
index 
b29b3bb0df7c92e23f5a752b0d57a7f3c59548e2..bb0c618961f60d6989c8f1f5986f0e2213c76bfa
 100644
--- a/src/responder/autofs/autofs_private.h
+++ b/src/responder/autofs/autofs_private.h
@@ -39,6 +39,7 @@ struct autofs_cmd_ctx {
     char *mapname;
     char *key;
     uint32_t cursor;
+    uint32_t max_entries;
     bool check_next;
 };
 
diff --git a/src/responder/autofs/autofssrv_cmd.c 
b/src/responder/autofs/autofssrv_cmd.c
index 
58ffce1a05e640173f7e0a8b2fc0b4657f4dd4ba..8123db2a4b624d15cea43416da4ff61710ff50fe
 100644
--- a/src/responder/autofs/autofssrv_cmd.c
+++ b/src/responder/autofs/autofssrv_cmd.c
@@ -814,9 +814,12 @@ setautomntent_recv(struct tevent_req *req)
 static errno_t
 getautomntent_process(struct autofs_cmd_ctx *cmdctx,
                       struct autofs_map_ctx *map,
-                      uint32_t cursor);
+                      uint32_t cursor, uint32_t max_entries);
 static void
 getautomntent_implicit_done(struct tevent_req *req);
+static errno_t
+fill_autofs_entry(struct ldb_message *entry, struct sss_packet *packet, size_t 
*rp);
+
 
 static int
 sss_autofs_cmd_getautomntent(struct cli_ctx *client)
@@ -870,9 +873,11 @@ sss_autofs_cmd_getautomntent(struct cli_ctx *client)
     }
 
     SAFEALIGN_COPY_UINT32_CHECK(&cmdctx->cursor, body+c+namelen+1, blen, &c);
+    SAFEALIGN_COPY_UINT32_CHECK(&cmdctx->max_entries, body+c+namelen+1, blen, 
&c);
 
     DEBUG(SSSDBG_TRACE_FUNC,
-          ("Requested data of map %s cursor %d\n", cmdctx->mapname, 
cmdctx->cursor));
+          ("Requested data of map %s cursor %d max entries %d\n",
+           cmdctx->mapname, cmdctx->cursor, cmdctx->max_entries));
 
     ret = get_autofs_map(actx, cmdctx->mapname, &map);
     if (ret == ENOENT) {
@@ -915,7 +920,7 @@ sss_autofs_cmd_getautomntent(struct cli_ctx *client)
     DEBUG(SSSDBG_TRACE_INTERNAL,
           ("returning entries for [%s]\n", map->mapname));
 
-    ret = getautomntent_process(cmdctx, map, cmdctx->cursor);
+    ret = getautomntent_process(cmdctx, map, cmdctx->cursor, 
cmdctx->max_entries);
 
 done:
     return autofs_cmd_done(cmdctx, ret);
@@ -955,7 +960,8 @@ getautomntent_implicit_done(struct tevent_req *req)
         goto done;
     }
 
-    ret = getautomntent_process(cmdctx, map, cmdctx->cursor);
+    ret = getautomntent_process(cmdctx, map,
+                                cmdctx->cursor, cmdctx->max_entries);
 done:
     autofs_cmd_done(cmdctx, ret);
     return;
@@ -964,18 +970,15 @@ done:
 static errno_t
 getautomntent_process(struct autofs_cmd_ctx *cmdctx,
                       struct autofs_map_ctx *map,
-                      uint32_t cursor)
+                      uint32_t cursor, uint32_t max_entries)
 {
     struct cli_ctx *client = cmdctx->cctx;
     errno_t ret;
-    const char *key;
-    size_t keylen;
-    const char *value;
-    size_t valuelen;
     struct ldb_message *entry;
-    size_t len;
+    size_t rp;
+    uint32_t i, stop, left, nentries;
     uint8_t *body;
-    size_t blen, rp;
+    size_t blen;
 
     /* create response packet */
     ret = sss_packet_new(client->creq, 0,
@@ -994,51 +997,92 @@ getautomntent_process(struct autofs_cmd_ctx *cmdctx,
         }
         goto done;
     }
-    entry = map->entries[cursor];
+
+    ret = sss_packet_grow(client->creq->out, sizeof(uint32_t));
+    if (ret != EOK) {
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot grow packet\n"));
+        goto done;
+    }
+
+    sss_packet_get_body(client->creq->out, &body, &blen);
+    rp = sizeof(uint32_t);  /* We'll write the number of entries here */
+
+    left = map->entry_count - cursor;
+    stop = max_entries < left ? max_entries : left;
+
+    nentries = 0;
+    for (i=0; i < stop; i++) {
+        entry = map->entries[cursor];
+        cursor++;
+
+        ret = fill_autofs_entry(entry, client->creq->out, &rp);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_MINOR_FAILURE,
+                  ("Cannot fill entry %d/%d, skipping\n", i, stop));
+            continue;
+        }
+        nentries++;
+    }
+
+    rp = 0;
+    SAFEALIGN_SET_UINT32(&body[rp], nentries, &rp);
+
+    ret = EOK;
+done:
+    sss_packet_set_error(client->creq->out, ret);
+    sss_cmd_done(client, cmdctx);
+
+    return EOK;
+}
+
+static errno_t
+fill_autofs_entry(struct ldb_message *entry, struct sss_packet *packet, size_t 
*rp)
+{
+    errno_t ret;
+    const char *key;
+    size_t keylen;
+    const char *value;
+    size_t valuelen;
+    uint8_t *body;
+    size_t blen;
+    size_t len;
 
     key = ldb_msg_find_attr_as_string(entry, SYSDB_AUTOFS_ENTRY_KEY, NULL);
     value = ldb_msg_find_attr_as_string(entry, SYSDB_AUTOFS_ENTRY_VALUE, NULL);
     if (!key || !value) {
-        ret = EAGAIN;
         DEBUG(SSSDBG_MINOR_FAILURE, ("Incomplete entry\n"));
-        goto done;
+        return EINVAL;
     }
 
-    /* FIXME - split below into a separate function */
     keylen = 1 + strlen(key);
     valuelen = 1 + strlen(value);
-    len = sizeof(uint32_t) + sizeof(uint32_t) + keylen  + sizeof(uint32_t)+ 
valuelen;
+    len = sizeof(uint32_t) + sizeof(uint32_t) + keylen + sizeof(uint32_t) + 
valuelen;
 
-    ret = sss_packet_grow(client->creq->out, len);
+    ret = sss_packet_grow(packet, len);
     if (ret != EOK) {
-        goto done;
+        DEBUG(SSSDBG_OP_FAILURE, ("Cannot grow packet\n"));
+        return ret;
     }
 
-    sss_packet_get_body(client->creq->out, &body, &blen);
+    sss_packet_get_body(packet, &body, &blen);
 
-    rp = 0;
-    SAFEALIGN_SET_UINT32(&body[rp], len, &rp);
-    SAFEALIGN_SET_UINT32(&body[rp], keylen, &rp);
+    SAFEALIGN_SET_UINT32(&body[*rp], len, rp);
+    SAFEALIGN_SET_UINT32(&body[*rp], keylen, rp);
 
     if (keylen == 1) {
-        body[rp] = '\0';
+        body[*rp] = '\0';
     } else {
-        memcpy(&body[rp], key, keylen);
+        memcpy(&body[*rp], key, keylen);
     }
-    rp += keylen;
+    *rp += keylen;
 
-    SAFEALIGN_SET_UINT32(&body[rp], valuelen, &rp);
+    SAFEALIGN_SET_UINT32(&body[*rp], valuelen, rp);
     if (valuelen == 1) {
-        body[rp] = '\0';
+        body[*rp] = '\0';
     } else {
-        memcpy(&body[rp], value, valuelen);
+        memcpy(&body[*rp], value, valuelen);
     }
-    rp += valuelen;
-
-    ret = EOK;
-done:
-    sss_packet_set_error(client->creq->out, ret);
-    sss_cmd_done(client, cmdctx);
+    *rp += valuelen;
 
     return EOK;
 }
diff --git a/src/sss_client/autofs/sss_autofs.c 
b/src/sss_client/autofs/sss_autofs.c
index 
6195c0fc416e15e2b703c68d04707aa7b89eaf5a..218c1ed7935cf3fcce7fc113b3926c19470d0257
 100644
--- a/src/sss_client/autofs/sss_autofs.c
+++ b/src/sss_client/autofs/sss_autofs.c
@@ -28,11 +28,29 @@
 #define MAX_AUTOMNTMAPNAME_LEN  NAME_MAX
 #define MAX_AUTOMNTKEYNAME_LEN  NAME_MAX
 
+/* How many entries shall _sss_getautomntent_r retreive at once */
+#define GETAUTOMNTENT_MAX_ENTRIES   512
+
 struct automtent {
     char *mapname;
     size_t cursor;
 };
 
+static struct sss_getautomntent_data {
+    char *mapname;
+    size_t len;
+    size_t ptr;
+    uint8_t *data;
+} sss_getautomntent_data;
+
+static void
+sss_getautomntent_data_clean(void)
+{
+    free(sss_getautomntent_data.data);
+    free(sss_getautomntent_data.mapname);
+    memset(&sss_getautomntent_data, 0, sizeof(struct sss_getautomntent_data));
+}
+
 errno_t
 _sss_setautomntent(const char *mapname, void **context)
 {
@@ -49,6 +67,9 @@ _sss_setautomntent(const char *mapname, void **context)
 
     sss_nss_lock();
 
+    /* Make sure there are no leftovers from previous runs */
+    sss_getautomntent_data_clean();
+
     ret = sss_strnlen(mapname, MAX_AUTOMNTMAPNAME_LEN, &name_len);
     if (ret != 0) {
         ret = EINVAL;
@@ -106,26 +127,132 @@ out:
     return ret;
 }
 
-errno_t
-_sss_getautomntent_r(char **key, char **value, void *context)
+static errno_t
+sss_getautomntent_data_return(const char *mapname, char **_key, char **_value)
 {
-    int errnop;
-    errno_t ret;
-    size_t name_len;
-    struct sss_cli_req_data rd;
-    uint8_t *repbuf = NULL;
-    size_t replen;
-    struct automtent *ctx;
-    size_t ctr = 0;
-    size_t data_len = 0;
-    uint8_t *data;
-    uint32_t v;
-
-    char *buf;
-    uint32_t len;
+    size_t dp;
+    uint32_t len = 0;
+    char *key = NULL;
     uint32_t keylen;
+    char *value = NULL;
     uint32_t vallen;
+    errno_t ret;
+
+    if (sss_getautomntent_data.mapname == NULL ||
+        sss_getautomntent_data.data == NULL ||
+        sss_getautomntent_data.ptr >= sss_getautomntent_data.len) {
+        /* We're done with this buffer */
+        ret = ENOENT;
+        goto done;
+    }
+
+    ret = strcmp(mapname, sss_getautomntent_data.mapname);
+    if (ret != EOK) {
+        /* The map we're looking for is not cached. Let responder
+         * do an implicit setautomntent */
+        ret = ENOENT;
+        goto done;
+    }
+
+    dp = sss_getautomntent_data.ptr;
+
+    SAFEALIGN_COPY_UINT32(&len, sss_getautomntent_data.data+dp, &dp);
+    if (len + sss_getautomntent_data.ptr > sss_getautomntent_data.len) {
+        /* len is bigger than the buffer */
+        ret = EIO;
+        goto done;
+    }
+
+    if (len == 0) {
+        /* There are no more records. */
+        *_key = NULL;
+        *_value = NULL;
+        ret = ENOENT;
+        goto done;
+    }
+
+    SAFEALIGN_COPY_UINT32(&keylen, sss_getautomntent_data.data+dp, &dp);
+    if (keylen + dp > sss_getautomntent_data.len) {
+        ret = EIO;
+        goto done;
+    }
+
+    key = malloc(keylen);
+    if (!key) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    safealign_memcpy(key, sss_getautomntent_data.data+dp, keylen, &dp);
+
+    SAFEALIGN_COPY_UINT32(&vallen, sss_getautomntent_data.data+dp, &dp);
+    if (vallen + dp > sss_getautomntent_data.len) {
+        ret = EIO;
+        goto done;
+    }
+
+    value = malloc(vallen);
+    if (!value) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    safealign_memcpy(value, sss_getautomntent_data.data+dp, vallen, &dp);
+
+    sss_getautomntent_data.ptr = dp;
+    *_key = key;
+    *_value = value;
+    return EOK;
+
+done:
+    free(key);
+    free(value);
+    sss_getautomntent_data_clean();
+    return ret;
+}
+
+/* The repbuf is owned by the sss_getautomntent_data once this
+ * function is called */
+static errno_t
+sss_getautomntent_data_save(const char *mapname, uint8_t **repbuf, size_t 
replen)
+{
     size_t rp;
+    uint32_t num;
+
+    rp = 0;
+    SAFEALIGN_COPY_UINT32(&num, repbuf+rp, &rp);
+    if (num == 0) {
+        free(repbuf);
+        return ENOENT;
+    }
+
+    sss_getautomntent_data.mapname = strdup(mapname);
+    if (sss_getautomntent_data.mapname == NULL) {
+        free(repbuf);
+        return ENOENT;
+    }
+
+    sss_getautomntent_data.data = *repbuf;
+    sss_getautomntent_data.len = replen;
+    sss_getautomntent_data.ptr = rp;
+    *repbuf = NULL;
+    return EOK;
+}
+
+errno_t
+_sss_getautomntent_r(char **key, char **value, void *context)
+{
+    int errnop;
+    errno_t ret;
+    size_t name_len;
+    struct sss_cli_req_data rd;
+    uint8_t *repbuf = NULL;
+    size_t replen;
+    struct automtent *ctx;
+    size_t ctr = 0;
+    size_t data_len = 0;
+    uint8_t *data;
+    uint32_t v;
 
     sss_nss_lock();
 
@@ -142,9 +269,21 @@ _sss_getautomntent_r(char **key, char **value, void 
*context)
         goto out;
     }
 
+    ret = sss_getautomntent_data_return(ctx->mapname, key, value);
+    if (ret == EOK) {
+        /* The results are available from cache. Just advance the
+         * cursor and return. */
+        ctx->cursor++;
+        ret = 0;
+        goto out;
+    }
+    /* Don't try to handle any error codes, just go to the responder again */
+
+    ret = 0;
     data_len = sizeof(uint32_t) +            /* mapname len */
                name_len + 1 +                /* mapname\0   */
-               sizeof(uint32_t);             /* index into the map */
+               sizeof(uint32_t) +            /* index into the map */
+               sizeof(uint32_t);             /* num entries to retreive */
 
     data = malloc(data_len);
     if (!data) {
@@ -152,12 +291,13 @@ _sss_getautomntent_r(char **key, char **value, void 
*context)
         goto out;
     }
 
-    v = name_len;
-    SAFEALIGN_COPY_UINT32(data, &v, &ctr);
+    SAFEALIGN_COPY_UINT32(data, &name_len, &ctr);
 
     safealign_memcpy(data+ctr, ctx->mapname, name_len + 1, &ctr);
 
-    v = ctx->cursor;
+    SAFEALIGN_COPY_UINT32(data+ctr, &ctx->cursor, &ctr);
+
+    v = GETAUTOMNTENT_MAX_ENTRIES;
     SAFEALIGN_COPY_UINT32(data+ctr, &v, &ctr);
 
     rd.data = data;
@@ -171,54 +311,28 @@ _sss_getautomntent_r(char **key, char **value, void 
*context)
         goto out;
     }
 
-    /* Got reply, let's parse it */
-    rp = 0;
-    SAFEALIGN_COPY_UINT32(&len, repbuf+rp, &rp);
-    if (len == 0) {
-        /* End of iteration */
+    /* Got reply, let's save it and return from "cache" */
+    ret = sss_getautomntent_data_save(ctx->mapname, &repbuf, replen);
+    if (ret == ENOENT) {
+        /* No results */
         *key = NULL;
         *value = NULL;
-        ret = ENOENT;
         goto out;
-    }
-
-    SAFEALIGN_COPY_UINT32(&keylen, repbuf+rp, &rp);
-    if (keylen > len-rp) {
-        ret = EIO;
-        goto out;
-    }
-
-    buf = malloc(keylen);
-    if (!buf) {
-        ret = ENOMEM;
+    } else if (ret != EOK) {
+        /* Unexpected error */
         goto out;
     }
 
-    safealign_memcpy(buf, repbuf+rp, keylen, &rp);
-    *key = buf;
-
-    SAFEALIGN_COPY_UINT32(&vallen, repbuf+rp, &rp);
-    if (vallen > len-rp) {
-        ret = EIO;
+    ret = sss_getautomntent_data_return(ctx->mapname, key, value);
+    if (ret != EOK) {
         goto out;
     }
 
-    buf = malloc(vallen);
-    if (!buf) {
-        free(*key);
-        ret = ENOMEM;
-        goto out;
-    }
-
-    safealign_memcpy(buf, repbuf+rp, vallen, &rp);
-    *value = buf;
-
     /* Advance the cursor so that we'll fetch the next map
      * next time getautomntent is called */
     ctx->cursor++;
     ret = 0;
 out:
-    free(repbuf);
     sss_nss_unlock();
     return ret;
 }
@@ -341,6 +455,8 @@ _sss_endautomntent(void **context)
 
     sss_nss_lock();
 
+    sss_getautomntent_data_clean();
+
     fctx = (struct automtent *) *context;
 
     free(fctx->mapname);
-- 
1.7.7.6

_______________________________________________
sssd-devel mailing list
sssd-devel@lists.fedorahosted.org
https://fedorahosted.org/mailman/listinfo/sssd-devel

Reply via email to