* [PATCH 0/4] autofs scaling and cleanup patches
@ 2009-01-09 18:46 Valerie Aurora Henson
2009-01-09 18:47 ` [PATCH 1/4] Make hash table scale to thousands of entries Valerie Aurora Henson
0 siblings, 1 reply; 66+ messages in thread
From: Valerie Aurora Henson @ 2009-01-09 18:46 UTC (permalink / raw)
To: autofs
This is a small collection of patches generated from discussions with
Google folks. The first makes the mount entry cache scale to
thousands of entries. The second is prep for the next patch; it just
cleans up use of fixed buffer sizes so that it's easier to tell what's
going on. The third removes some instances of alloca() - I had the
help of Coccinelle on this one. The fourth fixes an include to use
the userland include instead of the kernel include.
Valerie Aurora Henson (4):
Make hash table scale to thousands of entries
Make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit
Easy alloca() replacements
Replace <linux/string.h> with <string.h>
daemon/automount.c | 6 ++--
daemon/direct.c | 8 ++----
daemon/flag.c | 12 +++++-----
daemon/indirect.c | 8 ++----
daemon/module.c | 42 +++++++++------------------------
include/automount.h | 2 +-
include/linux/auto_dev-ioctl.h | 2 +-
lib/cache.c | 49 +++++++++++++++++++--------------------
lib/cat_path.c | 1 -
modules/lookup_ldap.c | 49 ++++++++++++++++++----------------------
modules/lookup_nisplus.c | 22 ++++++++++++++----
modules/mount_autofs.c | 1 -
modules/mount_bind.c | 7 +----
modules/mount_changer.c | 5 +---
modules/mount_ext2.c | 5 +---
modules/mount_generic.c | 5 +---
16 files changed, 97 insertions(+), 127 deletions(-)
^ permalink raw reply [flat|nested] 66+ messages in thread
* [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-09 18:46 [PATCH 0/4] autofs scaling and cleanup patches Valerie Aurora Henson
@ 2009-01-09 18:47 ` Valerie Aurora Henson
2009-01-09 18:47 ` [PATCH 2/4] Make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit Valerie Aurora Henson
` (3 more replies)
0 siblings, 4 replies; 66+ messages in thread
From: Valerie Aurora Henson @ 2009-01-09 18:47 UTC (permalink / raw)
To: autofs
From: Paul Wankadia <junyer@google.com>
Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
---
include/automount.h | 2 +-
lib/cache.c | 29 ++++++++++++++++++-----------
2 files changed, 19 insertions(+), 12 deletions(-)
diff --git a/include/automount.h b/include/automount.h
index 1ba0d3c..2a082b5 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -126,7 +126,7 @@ struct autofs_point;
#define CHE_DUPLICATE 0x0020
#define CHE_UNAVAIL 0x0040
-#define HASHSIZE 77
+#define HASHSIZE 4096
#define NEGATIVE_TIMEOUT 10
#define UMOUNT_RETRIES 8
#define EXPIRE_RETRIES 3
diff --git a/lib/cache.c b/lib/cache.c
index ce47e04..36b8294 100644
--- a/lib/cache.c
+++ b/lib/cache.c
@@ -281,20 +281,27 @@ struct mapent_cache *cache_init_null_cache(struct master *master)
return mc;
}
-static unsigned int hash(const char *key)
+static u_int32_t hash(const char *key)
{
- unsigned long hashval;
+ u_int32_t hashval;
char *s = (char *) key;
- for (hashval = 0; *s != '\0';)
- hashval += *s++;
+ for (hashval = 0; *s != '\0';) {
+ hashval += (unsigned char) *s++;
+ hashval += (hashval << 10);
+ hashval ^= (hashval >> 6);
+ }
+
+ hashval += (hashval << 3);
+ hashval ^= (hashval >> 11);
+ hashval += (hashval << 15);
return hashval % HASHSIZE;
}
-static unsigned int ino_hash(dev_t dev, ino_t ino)
+static u_int32_t ino_hash(dev_t dev, ino_t ino)
{
- unsigned long hashval;
+ u_int32_t hashval;
hashval = dev + ino;
@@ -303,7 +310,7 @@ static unsigned int ino_hash(dev_t dev, ino_t ino)
int cache_set_ino_index(struct mapent_cache *mc, const char *key, dev_t dev, ino_t ino)
{
- unsigned int ino_index = ino_hash(dev, ino);
+ u_int32_t ino_index = ino_hash(dev, ino);
struct mapent *me;
me = cache_lookup_distinct(mc, key);
@@ -325,7 +332,7 @@ struct mapent *cache_lookup_ino(struct mapent_cache *mc, dev_t dev, ino_t ino)
{
struct mapent *me = NULL;
struct list_head *head, *p;
- unsigned int ino_index;
+ u_int32_t ino_index;
ino_index_lock(mc);
ino_index = ino_hash(dev, ino);
@@ -371,7 +378,7 @@ struct mapent *cache_lookup_first(struct mapent_cache *mc)
struct mapent *cache_lookup_next(struct mapent_cache *mc, struct mapent *me)
{
struct mapent *this;
- unsigned long hashval;
+ u_int32_t hashval;
unsigned int i;
if (!me)
@@ -532,7 +539,7 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c
{
struct mapent *me, *existing = NULL;
char *pkey, *pent;
- unsigned int hashval = hash(key);
+ u_int32_t hashval = hash(key);
int status;
me = (struct mapent *) malloc(sizeof(struct mapent));
@@ -752,7 +759,7 @@ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key
int cache_delete(struct mapent_cache *mc, const char *key)
{
struct mapent *me = NULL, *pred;
- unsigned int hashval = hash(key);
+ u_int32_t hashval = hash(key);
int status, ret = CHE_OK;
char *this;
--
1.6.0.4
^ permalink raw reply related [flat|nested] 66+ messages in thread
* [PATCH 2/4] Make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit
2009-01-09 18:47 ` [PATCH 1/4] Make hash table scale to thousands of entries Valerie Aurora Henson
@ 2009-01-09 18:47 ` Valerie Aurora Henson
2009-01-09 18:47 ` [PATCH 3/4] Easy alloca() replacements Valerie Aurora Henson
2009-01-09 19:00 ` [PATCH 2/4] Make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit Jeff Moyer
2009-01-09 19:17 ` [PATCH 1/4] Make hash table scale to thousands of entries Jeff Moyer
` (2 subsequent siblings)
3 siblings, 2 replies; 66+ messages in thread
From: Valerie Aurora Henson @ 2009-01-09 18:47 UTC (permalink / raw)
To: autofs
Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
---
modules/lookup_ldap.c | 49 ++++++++++++++++++++++---------------------------
1 files changed, 22 insertions(+), 27 deletions(-)
diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
index 42c3235..0ef7bcf 100644
--- a/modules/lookup_ldap.c
+++ b/modules/lookup_ldap.c
@@ -275,7 +275,7 @@ LDAP *init_ldap_connection(unsigned logopt, const char *uri, struct lookup_conte
static int get_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt, const char *class, const char *key)
{
- char buf[PARSE_MAX_BUF];
+ char buf[MAX_ERR_BUF];
char *query, *dn, *qdn;
LDAPMessage *result, *e;
struct ldap_searchdn *sdns = NULL;
@@ -299,7 +299,7 @@ static int get_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt
query = alloca(l);
if (query == NULL) {
- char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ char *estr = strerror_r(errno, buf, sizeof(buf));
crit(logopt, MODPREFIX "alloca: %s", estr);
return NSS_STATUS_UNAVAIL;
}
@@ -1074,7 +1074,7 @@ static int parse_server_string(unsigned logopt, const char *url, struct lookup_c
}
if (!tmp) {
char *estr;
- estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ estr = strerror_r(errno, buf, sizeof(buf));
logerr(MODPREFIX "malloc: %s", estr);
return 0;
}
@@ -1096,7 +1096,7 @@ static int parse_server_string(unsigned logopt, const char *url, struct lookup_c
tmp = malloc(l + 1);
if (!tmp) {
char *estr;
- estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ estr = strerror_r(errno, buf, sizeof(buf));
crit(logopt, MODPREFIX "malloc: %s", estr);
return 0;
}
@@ -1131,7 +1131,7 @@ static int parse_server_string(unsigned logopt, const char *url, struct lookup_c
/* Isolate the server's name. */
if (!tmp) {
char *estr;
- estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ estr = strerror_r(errno, buf, sizeof(buf));
logerr(MODPREFIX "malloc: %s", estr);
return 0;
}
@@ -1172,7 +1172,7 @@ static int parse_server_string(unsigned logopt, const char *url, struct lookup_c
ctxt->mapname = map;
else {
char *estr;
- estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ estr = strerror_r(errno, buf, sizeof(buf));
logerr(MODPREFIX "malloc: %s", estr);
if (ctxt->server)
free(ctxt->server);
@@ -1183,7 +1183,7 @@ static int parse_server_string(unsigned logopt, const char *url, struct lookup_c
base = malloc(l + 1);
if (!base) {
char *estr;
- estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ estr = strerror_r(errno, buf, sizeof(buf));
logerr(MODPREFIX "malloc: %s", estr);
if (ctxt->server)
free(ctxt->server);
@@ -1197,7 +1197,7 @@ static int parse_server_string(unsigned logopt, const char *url, struct lookup_c
char *map = malloc(l + 1);
if (!map) {
char *estr;
- estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ estr = strerror_r(errno, buf, sizeof(buf));
logerr(MODPREFIX "malloc: %s", estr);
if (ctxt->server)
free(ctxt->server);
@@ -1310,7 +1310,7 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
/* If we can't build a context, bail. */
ctxt = malloc(sizeof(struct lookup_context));
if (!ctxt) {
- char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ char *estr = strerror_r(errno, buf, sizeof(buf));
logerr(MODPREFIX "malloc: %s", estr);
return 1;
}
@@ -1411,8 +1411,9 @@ int lookup_read_master(struct master *master, time_t age, void *context)
unsigned int timeout = master->default_timeout;
unsigned int logging = master->default_logging;
unsigned int logopt = master->logopt;
- int rv, l, count, blen;
- char buf[PARSE_MAX_BUF];
+ int rv, l, count;
+ char buf[MAX_ERR_BUF];
+ char parse_buf[PARSE_MAX_BUF];
char *query;
LDAPMessage *result, *e;
char *class, *info, *entry;
@@ -1434,7 +1435,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
query = alloca(l);
if (query == NULL) {
- char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ char *estr = strerror_r(errno, buf, sizeof(buf));
logerr(MODPREFIX "alloca: %s", estr);
return NSS_STATUS_UNAVAIL;
}
@@ -1524,18 +1525,12 @@ int lookup_read_master(struct master *master, time_t age, void *context)
goto next;
}
- blen = strlen(*keyValue) + 1 + strlen(*values) + 2;
- if (blen > PARSE_MAX_BUF) {
+ if (snprintf(parse_buf, sizeof(parse_buf), "%s %s",
+ *keyValue, *values) > sizeof(parse_buf)) {
error(logopt, MODPREFIX "map entry too long");
ldap_value_free(values);
goto next;
}
- memset(buf, 0, PARSE_MAX_BUF);
-
- strcpy(buf, *keyValue);
- strcat(buf, " ");
- strcat(buf, *values);
-
master_parse_entry(buf, timeout, logging, age);
next:
ldap_value_free(keyValue);
@@ -1553,7 +1548,7 @@ static int get_percent_decoded_len(const char *name)
{
int escapes = 0;
int escaped = 0;
- char *tmp = name;
+ const char *tmp = name;
int look_for_close = 0;
while (*tmp) {
@@ -2052,7 +2047,7 @@ static int do_get_entries(struct ldap_search_params *sp, struct map_source *sour
mapent = malloc(v_len + 1);
if (!mapent) {
char *estr;
- estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ estr = strerror_r(errno, buf, sizeof(buf));
logerr(MODPREFIX "malloc: %s", estr);
ldap_value_free_len(bvValues);
goto next;
@@ -2072,7 +2067,7 @@ static int do_get_entries(struct ldap_search_params *sp, struct map_source *sour
mapent_len = new_size;
} else {
char *estr;
- estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ estr = strerror_r(errno, buf, sizeof(buf));
logerr(MODPREFIX "realloc: %s", estr);
}
}
@@ -2173,7 +2168,7 @@ static int read_one_map(struct autofs_point *ap,
sp.query = alloca(l);
if (sp.query == NULL) {
- char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ char *estr = strerror_r(errno, buf, sizeof(buf));
logerr(MODPREFIX "malloc: %s", estr);
return NSS_STATUS_UNAVAIL;
}
@@ -2327,7 +2322,7 @@ static int lookup_one(struct autofs_point *ap,
query = alloca(l);
if (query == NULL) {
- char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ char *estr = strerror_r(errno, buf, sizeof(buf));
crit(ap->logopt, MODPREFIX "malloc: %s", estr);
if (enc_len1) {
free(enc_key1);
@@ -2499,7 +2494,7 @@ static int lookup_one(struct autofs_point *ap,
mapent = malloc(v_len + 1);
if (!mapent) {
char *estr;
- estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ estr = strerror_r(errno, buf, sizeof(buf));
logerr(MODPREFIX "malloc: %s", estr);
ldap_value_free_len(bvValues);
goto next;
@@ -2519,7 +2514,7 @@ static int lookup_one(struct autofs_point *ap,
mapent_len = new_size;
} else {
char *estr;
- estr = strerror_r(errno, buf, MAX_ERR_BUF);
+ estr = strerror_r(errno, buf, sizeof(buf));
logerr(MODPREFIX "realloc: %s", estr);
}
}
--
1.6.0.4
^ permalink raw reply related [flat|nested] 66+ messages in thread
* [PATCH 3/4] Easy alloca() replacements
2009-01-09 18:47 ` [PATCH 2/4] Make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit Valerie Aurora Henson
@ 2009-01-09 18:47 ` Valerie Aurora Henson
2009-01-09 18:47 ` [PATCH 4/4] Replace <linux/string.h> with <string.h> Valerie Aurora Henson
` (2 more replies)
2009-01-09 19:00 ` [PATCH 2/4] Make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit Jeff Moyer
1 sibling, 3 replies; 66+ messages in thread
From: Valerie Aurora Henson @ 2009-01-09 18:47 UTC (permalink / raw)
To: autofs
Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
---
daemon/automount.c | 6 +++---
daemon/direct.c | 8 +++-----
daemon/flag.c | 12 ++++++------
daemon/indirect.c | 8 +++-----
daemon/module.c | 42 ++++++++++++------------------------------
lib/cache.c | 20 ++++++--------------
lib/cat_path.c | 1 -
modules/lookup_nisplus.c | 22 +++++++++++++++++-----
modules/mount_autofs.c | 1 -
modules/mount_bind.c | 7 ++-----
modules/mount_changer.c | 5 +----
modules/mount_ext2.c | 5 +----
modules/mount_generic.c | 5 +----
13 files changed, 55 insertions(+), 87 deletions(-)
diff --git a/daemon/automount.c b/daemon/automount.c
index 6f078c1..61bbc80 100644
--- a/daemon/automount.c
+++ b/daemon/automount.c
@@ -124,8 +124,8 @@ static int do_mkdir(const char *parent, const char *path, mode_t mode)
int mkdir_path(const char *path, mode_t mode)
{
- char *buf = alloca(strlen(path) + 1);
- char *parent = alloca(strlen(path) + 1);
+ char buf[PATH_MAX];
+ char parent[PATH_MAX];
const char *cp = path, *lcp = path;
char *bp = buf, *pp = parent;
@@ -160,7 +160,7 @@ int mkdir_path(const char *path, mode_t mode)
int rmdir_path(struct autofs_point *ap, const char *path, dev_t dev)
{
int len = strlen(path);
- char *buf = alloca(len + 1);
+ char buf[PATH_MAX];
char *cp;
int first = 1;
struct stat st;
diff --git a/daemon/direct.c b/daemon/direct.c
index 98fcc07..94216ba 100644
--- a/daemon/direct.c
+++ b/daemon/direct.c
@@ -742,11 +742,9 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me, const char *
type = ap->entry->maps->type;
if (type && !strcmp(ap->entry->maps->type, "hosts")) {
- char *tmp = alloca(7);
- if (tmp) {
- strcpy(tmp, "-hosts");
- map_name = (const char *) tmp;
- }
+ char tmp[7];
+ strcpy(tmp, "-hosts");
+ map_name = (const char *) tmp;
} else
map_name = me->mc->map->argv[0];
diff --git a/daemon/flag.c b/daemon/flag.c
index d8ca61b..5c4f0c2 100644
--- a/daemon/flag.c
+++ b/daemon/flag.c
@@ -25,10 +25,10 @@
#include <time.h>
#include <unistd.h>
#include <string.h>
-#include <alloca.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
+#include <limits.h>
#define MAX_PIDSIZE 20
#define FLAG_FILE AUTOFS_FLAG_DIR "/autofs-running"
@@ -113,12 +113,12 @@ void release_flag_file(void)
/* * Try to create flag file */
int aquire_flag_file(void)
{
- char *linkf;
- int len;
+ char linkf[PATH_MAX];
- len = strlen(FLAG_FILE) + MAX_PIDSIZE;
- linkf = alloca(len + 1);
- snprintf(linkf, len, "%s.%d", FLAG_FILE, getpid());
+ if (snprintf(linkf, sizeof(linkf), "%s.%d", FLAG_FILE, getpid()) >
+ sizeof(linkf))
+ /* Didn't acquire it */
+ return 0;
/*
* Repeat until it was us who made the link or we find the
diff --git a/daemon/indirect.c b/daemon/indirect.c
index 1232810..31713fd 100644
--- a/daemon/indirect.c
+++ b/daemon/indirect.c
@@ -144,11 +144,9 @@ static int do_mount_autofs_indirect(struct autofs_point *ap, const char *root)
type = ap->entry->maps->type;
if (type && !strcmp(ap->entry->maps->type, "hosts")) {
- char *tmp = alloca(7);
- if (tmp) {
- strcpy(tmp, "-hosts");
- map_name = (const char *) tmp;
- }
+ char tmp[7];
+ strcpy(tmp, "-hosts");
+ map_name = (const char *) tmp;
} else
map_name = ap->entry->maps->argv[0];
diff --git a/daemon/module.c b/daemon/module.c
index 36eca00..06b39c9 100644
--- a/daemon/module.c
+++ b/daemon/module.c
@@ -58,15 +58,10 @@ struct lookup_mod *open_lookup(const char *name, const char *err_prefix,
{
struct lookup_mod *mod;
char buf[MAX_ERR_BUF];
- char *fnbuf;
- size_t size_name;
- size_t size_fnbuf;
+ char fnbuf[PATH_MAX];
void *dh;
int *ver;
- size_name = _strlen(name, PATH_MAX + 1);
- if (!size_name)
- return NULL;
mod = malloc(sizeof(struct lookup_mod));
if (!mod) {
@@ -77,9 +72,9 @@ struct lookup_mod *open_lookup(const char *name, const char *err_prefix,
return NULL;
}
- size_fnbuf = size_name + strlen(AUTOFS_LIB_DIR) + 13;
- fnbuf = alloca(size_fnbuf);
- if (!fnbuf) {
+ if (snprintf(fnbuf,
+ sizeof(fnbuf), "%s/lookup_%s.so", AUTOFS_LIB_DIR, name) >
+ sizeof(fnbuf)) {
free(mod);
if (err_prefix) {
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
@@ -87,7 +82,6 @@ struct lookup_mod *open_lookup(const char *name, const char *err_prefix,
}
return NULL;
}
- snprintf(fnbuf, size_fnbuf, "%s/lookup_%s.so", AUTOFS_LIB_DIR, name);
if (!(dh = dlopen(fnbuf, RTLD_NOW))) {
if (err_prefix)
@@ -141,15 +135,10 @@ struct parse_mod *open_parse(const char *name, const char *err_prefix,
{
struct parse_mod *mod;
char buf[MAX_ERR_BUF];
- char *fnbuf;
- size_t size_name;
- size_t size_fnbuf;
+ char fnbuf[PATH_MAX];
void *dh;
int *ver;
- size_name = _strlen(name, PATH_MAX + 1);
- if (!size_name)
- return NULL;
mod = malloc(sizeof(struct parse_mod));
if (!mod) {
@@ -160,9 +149,9 @@ struct parse_mod *open_parse(const char *name, const char *err_prefix,
return NULL;
}
- size_fnbuf = size_name + strlen(AUTOFS_LIB_DIR) + 13;
- fnbuf = alloca(size_fnbuf);
- if (!fnbuf) {
+ if (snprintf(fnbuf,
+ sizeof(fnbuf), "%s/parse_%s.so", AUTOFS_LIB_DIR, name) >
+ sizeof(fnbuf)) {
free(mod);
if (err_prefix) {
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
@@ -170,7 +159,6 @@ struct parse_mod *open_parse(const char *name, const char *err_prefix,
}
return NULL;
}
- snprintf(fnbuf, size_fnbuf, "%s/parse_%s.so", AUTOFS_LIB_DIR, name);
if (!(dh = dlopen(fnbuf, RTLD_NOW))) {
if (err_prefix)
@@ -222,15 +210,10 @@ struct mount_mod *open_mount(const char *name, const char *err_prefix)
{
struct mount_mod *mod;
char buf[MAX_ERR_BUF];
- char *fnbuf;
- size_t size_name;
- size_t size_fnbuf;
+ char fnbuf[PATH_MAX];
void *dh;
int *ver;
- size_name = _strlen(name, PATH_MAX + 1);
- if (!size_name)
- return NULL;
mod = malloc(sizeof(struct mount_mod));
if (!mod) {
@@ -241,9 +224,9 @@ struct mount_mod *open_mount(const char *name, const char *err_prefix)
return NULL;
}
- size_fnbuf = size_name + strlen(AUTOFS_LIB_DIR) + 13;
- fnbuf = alloca(size_fnbuf);
- if (!fnbuf) {
+ if (snprintf(fnbuf,
+ sizeof(fnbuf), "%s/mount_%s.so", AUTOFS_LIB_DIR, name) >
+ sizeof(fnbuf)) {
free(mod);
if (err_prefix) {
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
@@ -251,7 +234,6 @@ struct mount_mod *open_mount(const char *name, const char *err_prefix)
}
return NULL;
}
- snprintf(fnbuf, size_fnbuf, "%s/mount_%s.so", AUTOFS_LIB_DIR, name);
if (!(dh = dlopen(fnbuf, RTLD_NOW))) {
if (err_prefix)
diff --git a/lib/cache.c b/lib/cache.c
index 36b8294..bc2c722 100644
--- a/lib/cache.c
+++ b/lib/cache.c
@@ -484,27 +484,19 @@ struct mapent *cache_lookup_offset(const char *prefix, const char *offset, int s
{
struct list_head *p;
struct mapent *this;
- int plen = strlen(prefix);
- char *o_key;
+ char o_key[KEY_MAX_LEN];
/* root offset duplicates "/" */
- if (plen > 1) {
- o_key = alloca(plen + strlen(offset) + 1);
- strcpy(o_key, prefix);
- strcat(o_key, offset);
- } else {
- o_key = alloca(strlen(offset) + 1);
- strcpy(o_key, offset);
- }
+ if (snprintf(o_key, sizeof(o_key), "%s%s", prefix, offset) >
+ sizeof(o_key))
+ return NULL;
list_for_each(p, head) {
this = list_entry(p, struct mapent, multi_list);
if (!strcmp(&this->key[start], o_key))
- goto done;
+ return this;
}
- this = NULL;
-done:
- return this;
+ return NULL;
}
/* cache must be read locked by caller */
diff --git a/lib/cat_path.c b/lib/cat_path.c
index 576b424..60669db 100644
--- a/lib/cat_path.c
+++ b/lib/cat_path.c
@@ -12,7 +12,6 @@
*
* ----------------------------------------------------------------------- */
-#include <alloca.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
diff --git a/modules/lookup_nisplus.c b/modules/lookup_nisplus.c
index f15465f..279a8d6 100644
--- a/modules/lookup_nisplus.c
+++ b/modules/lookup_nisplus.c
@@ -93,7 +93,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
int cur_state, len;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
- tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20);
+ tablename = malloc(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20);
if (!tablename) {
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
logerr(MODPREFIX "alloca: %s", estr);
@@ -108,6 +108,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
nis_freeresult(result);
crit(logopt,
MODPREFIX "couldn't locate nis+ table %s", ctxt->mapname);
+ free(tablename);
pthread_setcancelstate(cur_state, NULL);
return NSS_STATUS_NOTFOUND;
}
@@ -119,6 +120,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
nis_freeresult(result);
crit(logopt,
MODPREFIX "couldn't enumrate nis+ map %s", ctxt->mapname);
+ free(tablename);
pthread_setcancelstate(cur_state, NULL);
return NSS_STATUS_UNAVAIL;
}
@@ -156,6 +158,7 @@ int lookup_read_master(struct master *master, time_t age, void *context)
}
nis_freeresult(result);
+ free(tablename);
pthread_setcancelstate(cur_state, NULL);
return NSS_STATUS_SUCCESS;
@@ -181,7 +184,8 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
mc = source->mc;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
- tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20);
+ tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) +
+ 20);
if (!tablename) {
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
logerr(MODPREFIX "alloca: %s", estr);
@@ -196,6 +200,7 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
nis_freeresult(result);
crit(ap->logopt,
MODPREFIX "couldn't locate nis+ table %s", ctxt->mapname);
+ free(tablename);
pthread_setcancelstate(cur_state, NULL);
return NSS_STATUS_NOTFOUND;
}
@@ -207,6 +212,7 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
nis_freeresult(result);
crit(ap->logopt,
MODPREFIX "couldn't enumrate nis+ map %s", ctxt->mapname);
+ free(tablename);
pthread_setcancelstate(cur_state, NULL);
return NSS_STATUS_UNAVAIL;
}
@@ -246,6 +252,7 @@ int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
source->age = age;
+ free(tablename);
pthread_setcancelstate(cur_state, NULL);
return NSS_STATUS_SUCCESS;
@@ -272,8 +279,8 @@ static int lookup_one(struct autofs_point *ap,
mc = source->mc;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
- tablename = alloca(strlen(key) +
- strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20);
+ tablename = malloc(strlen(key) + strlen(ctxt->mapname) +
+ strlen(ctxt->domainname) + 20);
if (!tablename) {
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
logerr(MODPREFIX "alloca: %s", estr);
@@ -287,6 +294,7 @@ static int lookup_one(struct autofs_point *ap,
if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) {
nis_error rs = result->status;
nis_freeresult(result);
+ free(tablename);
pthread_setcancelstate(cur_state, NULL);
if (rs == NIS_NOTFOUND ||
rs == NIS_S_NOTFOUND ||
@@ -304,6 +312,7 @@ static int lookup_one(struct autofs_point *ap,
cache_unlock(mc);
nis_freeresult(result);
+ free(tablename);
pthread_setcancelstate(cur_state, NULL);
return ret;
@@ -328,7 +337,8 @@ static int lookup_wild(struct autofs_point *ap, struct lookup_context *ctxt)
mc = source->mc;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
- tablename = alloca(strlen(ctxt->mapname) + strlen(ctxt->domainname) + 20);
+ tablename = malloc(strlen(ctxt->mapname) + strlen(ctxt->domainname) +
+ 20);
if (!tablename) {
char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
logerr(MODPREFIX "alloca: %s", estr);
@@ -342,6 +352,7 @@ static int lookup_wild(struct autofs_point *ap, struct lookup_context *ctxt)
if (result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) {
nis_error rs = result->status;
nis_freeresult(result);
+ free(tablename);
pthread_setcancelstate(cur_state, NULL);
if (rs == NIS_NOTFOUND ||
rs == NIS_S_NOTFOUND ||
@@ -358,6 +369,7 @@ static int lookup_wild(struct autofs_point *ap, struct lookup_context *ctxt)
cache_unlock(mc);
nis_freeresult(result);
+ free(tablename);
pthread_setcancelstate(cur_state, NULL);
return ret;
diff --git a/modules/mount_autofs.c b/modules/mount_autofs.c
index eb63d8e..effa4fc 100644
--- a/modules/mount_autofs.c
+++ b/modules/mount_autofs.c
@@ -20,7 +20,6 @@
#include <unistd.h>
#include <string.h>
#include <signal.h>
-#include <alloca.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
diff --git a/modules/mount_bind.c b/modules/mount_bind.c
index 022d183..3ec467d 100644
--- a/modules/mount_bind.c
+++ b/modules/mount_bind.c
@@ -71,7 +71,7 @@ out:
int mount_mount(struct autofs_point *ap, const char *root, const char *name, int name_len,
const char *what, const char *fstype, const char *options, void *context)
{
- char *fullpath;
+ char fullpath[PATH_MAX];
char buf[MAX_ERR_BUF];
int err;
int i, len;
@@ -82,14 +82,11 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
/* Root offset of multi-mount */
len = strlen(root);
if (root[len - 1] == '/') {
- fullpath = alloca(len);
len = snprintf(fullpath, len, "%s", root);
/* Direct mount name is absolute path so don't use root */
} else if (*name == '/') {
- fullpath = alloca(len + 1);
len = sprintf(fullpath, "%s", root);
} else {
- fullpath = alloca(len + name_len + 2);
len = sprintf(fullpath, "%s/%s", root, name);
}
fullpath[len] = '\0';
@@ -143,7 +140,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
}
} else {
char *cp;
- char *basepath = alloca(strlen(fullpath) + 1);
+ char basepath[PATH_MAX];
int status;
struct stat st;
diff --git a/modules/mount_changer.c b/modules/mount_changer.c
index 43b8355..bf77a98 100644
--- a/modules/mount_changer.c
+++ b/modules/mount_changer.c
@@ -46,7 +46,7 @@ int mount_init(void **context)
int mount_mount(struct autofs_point *ap, const char *root, const char *name, int name_len,
const char *what, const char *fstype, const char *options, void *context)
{
- char *fullpath;
+ char fullpath[PATH_MAX];
char buf[MAX_ERR_BUF];
int err;
int len, status, existed = 1;
@@ -59,14 +59,11 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
/* Root offset of multi-mount */
len = strlen(root);
if (root[len - 1] == '/') {
- fullpath = alloca(len);
len = snprintf(fullpath, len, "%s", root);
/* Direct mount name is absolute path so don't use root */
} else if (*name == '/') {
- fullpath = alloca(len + 1);
len = sprintf(fullpath, "%s", root);
} else {
- fullpath = alloca(len + name_len + 2);
len = sprintf(fullpath, "%s/%s", root, name);
}
fullpath[len] = '\0';
diff --git a/modules/mount_ext2.c b/modules/mount_ext2.c
index 4c5b271..a80ccba 100644
--- a/modules/mount_ext2.c
+++ b/modules/mount_ext2.c
@@ -38,7 +38,7 @@ int mount_init(void **context)
int mount_mount(struct autofs_point *ap, const char *root, const char *name, int name_len,
const char *what, const char *fstype, const char *options, void *context)
{
- char *fullpath;
+ char fullpath[PATH_MAX];
char buf[MAX_ERR_BUF];
const char *p, *p1;
int err, ro = 0;
@@ -51,14 +51,11 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
/* Root offset of multi-mount */
len = strlen(root);
if (root[len - 1] == '/') {
- fullpath = alloca(len);
len = snprintf(fullpath, len, "%s", root);
/* Direct mount name is absolute path so don't use root */
} else if (*name == '/') {
- fullpath = alloca(len + 1);
len = sprintf(fullpath, "%s", root);
} else {
- fullpath = alloca(len + name_len + 2);
len = sprintf(fullpath, "%s/%s", root, name);
}
fullpath[len] = '\0';
diff --git a/modules/mount_generic.c b/modules/mount_generic.c
index f094d07..17ebfd4 100644
--- a/modules/mount_generic.c
+++ b/modules/mount_generic.c
@@ -39,7 +39,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
const char *what, const char *fstype, const char *options,
void *context)
{
- char *fullpath;
+ char fullpath[PATH_MAX];
char buf[MAX_ERR_BUF];
int err;
int len, status, existed = 1;
@@ -50,14 +50,11 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name, int
/* Root offset of multi-mount */
len = strlen(root);
if (root[len - 1] == '/') {
- fullpath = alloca(len);
len = snprintf(fullpath, len, "%s", root);
/* Direct mount name is absolute path so don't use root */
} else if (*name == '/') {
- fullpath = alloca(len + 1);
len = sprintf(fullpath, "%s", root);
} else {
- fullpath = alloca(len + name_len + 2);
len = sprintf(fullpath, "%s/%s", root, name);
}
fullpath[len] = '\0';
--
1.6.0.4
^ permalink raw reply related [flat|nested] 66+ messages in thread
* [PATCH 4/4] Replace <linux/string.h> with <string.h>
2009-01-09 18:47 ` [PATCH 3/4] Easy alloca() replacements Valerie Aurora Henson
@ 2009-01-09 18:47 ` Valerie Aurora Henson
2009-01-12 5:59 ` Ian Kent
2009-01-09 20:48 ` [PATCH 3/4] Easy alloca() replacements Valerie Aurora Henson
2009-01-10 3:18 ` Ian Kent
2 siblings, 1 reply; 66+ messages in thread
From: Valerie Aurora Henson @ 2009-01-09 18:47 UTC (permalink / raw)
To: autofs
If installed, <linux/string.h> just includes the user-level
string.h. If it's not installed, the compile fails.
From: Paul Wankadia <junyer@google.com>
Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
---
include/linux/auto_dev-ioctl.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/include/linux/auto_dev-ioctl.h b/include/linux/auto_dev-ioctl.h
index 91a7739..78f4b47 100644
--- a/include/linux/auto_dev-ioctl.h
+++ b/include/linux/auto_dev-ioctl.h
@@ -10,7 +10,7 @@
#ifndef _LINUX_AUTO_DEV_IOCTL_H
#define _LINUX_AUTO_DEV_IOCTL_H
-#include <linux/string.h>
+#include <string.h>
#include <linux/types.h>
#define AUTOFS_DEVICE_NAME "autofs"
--
1.6.0.4
^ permalink raw reply related [flat|nested] 66+ messages in thread
* Re: [PATCH 2/4] Make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit
2009-01-09 18:47 ` [PATCH 2/4] Make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit Valerie Aurora Henson
2009-01-09 18:47 ` [PATCH 3/4] Easy alloca() replacements Valerie Aurora Henson
@ 2009-01-09 19:00 ` Jeff Moyer
2009-01-09 19:54 ` Valerie Aurora Henson
1 sibling, 1 reply; 66+ messages in thread
From: Jeff Moyer @ 2009-01-09 19:00 UTC (permalink / raw)
To: Valerie Aurora Henson; +Cc: autofs
Valerie Aurora Henson <vaurora@redhat.com> writes:
> Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
> @@ -1524,18 +1525,12 @@ int lookup_read_master(struct master *master, time_t age, void *context)
> goto next;
> }
>
> - blen = strlen(*keyValue) + 1 + strlen(*values) + 2;
> - if (blen > PARSE_MAX_BUF) {
> + if (snprintf(parse_buf, sizeof(parse_buf), "%s %s",
> + *keyValue, *values) > sizeof(parse_buf)) {
I think this should be >=.
Cheers,
Jeff
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-09 18:47 ` [PATCH 1/4] Make hash table scale to thousands of entries Valerie Aurora Henson
2009-01-09 18:47 ` [PATCH 2/4] Make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit Valerie Aurora Henson
@ 2009-01-09 19:17 ` Jeff Moyer
2009-01-09 19:51 ` Valerie Aurora Henson
2009-01-10 2:07 ` Ian Kent
2009-01-10 3:29 ` Ian Kent
2009-01-13 5:51 ` Ian Kent
3 siblings, 2 replies; 66+ messages in thread
From: Jeff Moyer @ 2009-01-09 19:17 UTC (permalink / raw)
To: Valerie Aurora Henson; +Cc: autofs
Valerie Aurora Henson <vaurora@redhat.com> writes:
> From: Paul Wankadia <junyer@google.com>
> Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
Most patches of this nature come with some description of a performance
problem and how the patch solves it. Which caching algorithm is
implemented below? There are, of course, many hashing algorithms for
variable length strings. Can we get some rationale for the change? I'm
not against it, I'd just like a *little* explanation.
Cheers,
Jeff
> ---
> include/automount.h | 2 +-
> lib/cache.c | 29 ++++++++++++++++++-----------
> 2 files changed, 19 insertions(+), 12 deletions(-)
>
> diff --git a/include/automount.h b/include/automount.h
> index 1ba0d3c..2a082b5 100644
> --- a/include/automount.h
> +++ b/include/automount.h
> @@ -126,7 +126,7 @@ struct autofs_point;
> #define CHE_DUPLICATE 0x0020
> #define CHE_UNAVAIL 0x0040
>
> -#define HASHSIZE 77
> +#define HASHSIZE 4096
> #define NEGATIVE_TIMEOUT 10
> #define UMOUNT_RETRIES 8
> #define EXPIRE_RETRIES 3
> diff --git a/lib/cache.c b/lib/cache.c
> index ce47e04..36b8294 100644
> --- a/lib/cache.c
> +++ b/lib/cache.c
> @@ -281,20 +281,27 @@ struct mapent_cache *cache_init_null_cache(struct master *master)
> return mc;
> }
>
> -static unsigned int hash(const char *key)
> +static u_int32_t hash(const char *key)
> {
> - unsigned long hashval;
> + u_int32_t hashval;
> char *s = (char *) key;
>
> - for (hashval = 0; *s != '\0';)
> - hashval += *s++;
> + for (hashval = 0; *s != '\0';) {
> + hashval += (unsigned char) *s++;
> + hashval += (hashval << 10);
> + hashval ^= (hashval >> 6);
> + }
> +
> + hashval += (hashval << 3);
> + hashval ^= (hashval >> 11);
> + hashval += (hashval << 15);
>
> return hashval % HASHSIZE;
> }
>
> -static unsigned int ino_hash(dev_t dev, ino_t ino)
> +static u_int32_t ino_hash(dev_t dev, ino_t ino)
> {
> - unsigned long hashval;
> + u_int32_t hashval;
>
> hashval = dev + ino;
>
> @@ -303,7 +310,7 @@ static unsigned int ino_hash(dev_t dev, ino_t ino)
>
> int cache_set_ino_index(struct mapent_cache *mc, const char *key, dev_t dev, ino_t ino)
> {
> - unsigned int ino_index = ino_hash(dev, ino);
> + u_int32_t ino_index = ino_hash(dev, ino);
> struct mapent *me;
>
> me = cache_lookup_distinct(mc, key);
> @@ -325,7 +332,7 @@ struct mapent *cache_lookup_ino(struct mapent_cache *mc, dev_t dev, ino_t ino)
> {
> struct mapent *me = NULL;
> struct list_head *head, *p;
> - unsigned int ino_index;
> + u_int32_t ino_index;
>
> ino_index_lock(mc);
> ino_index = ino_hash(dev, ino);
> @@ -371,7 +378,7 @@ struct mapent *cache_lookup_first(struct mapent_cache *mc)
> struct mapent *cache_lookup_next(struct mapent_cache *mc, struct mapent *me)
> {
> struct mapent *this;
> - unsigned long hashval;
> + u_int32_t hashval;
> unsigned int i;
>
> if (!me)
> @@ -532,7 +539,7 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c
> {
> struct mapent *me, *existing = NULL;
> char *pkey, *pent;
> - unsigned int hashval = hash(key);
> + u_int32_t hashval = hash(key);
> int status;
>
> me = (struct mapent *) malloc(sizeof(struct mapent));
> @@ -752,7 +759,7 @@ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key
> int cache_delete(struct mapent_cache *mc, const char *key)
> {
> struct mapent *me = NULL, *pred;
> - unsigned int hashval = hash(key);
> + u_int32_t hashval = hash(key);
> int status, ret = CHE_OK;
> char *this;
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-09 19:17 ` [PATCH 1/4] Make hash table scale to thousands of entries Jeff Moyer
@ 2009-01-09 19:51 ` Valerie Aurora Henson
2009-01-10 1:19 ` Paul Wankadia
2009-01-10 14:45 ` Ian Kent
2009-01-10 2:07 ` Ian Kent
1 sibling, 2 replies; 66+ messages in thread
From: Valerie Aurora Henson @ 2009-01-09 19:51 UTC (permalink / raw)
To: Jeff Moyer, Paul Wankadia; +Cc: autofs
On Fri, Jan 09, 2009 at 02:17:55PM -0500, Jeff Moyer wrote:
> Valerie Aurora Henson <vaurora@redhat.com> writes:
> > From: Paul Wankadia <junyer@google.com>
> > Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
>
> Most patches of this nature come with some description of a performance
> problem and how the patch solves it. Which caching algorithm is
> implemented below? There are, of course, many hashing algorithms for
> variable length strings. Can we get some rationale for the change? I'm
> not against it, I'd just like a *little* explanation.
This is where I get to blame my cold for being stupid. :)
Yes, the original author (Paul Wankadia, now cc'd) gave me a little
information on that front, I just forgot to pass it on. It's the
"One-at-a-Time" hash function by Bob Jenkins. See:
http://burtleburtle.net/bob/hash/doobs.html
What I vaguely recall from our conversation is an order of magnitude
improvement in elapsed time for large (thousands) numbers of maps, but
I'll let Paul be more specific. Do we have a test for thousands of
entries somewhere in our automated tests?
-VAL
>
> Cheers,
> Jeff
>
> > ---
> > include/automount.h | 2 +-
> > lib/cache.c | 29 ++++++++++++++++++-----------
> > 2 files changed, 19 insertions(+), 12 deletions(-)
> >
> > diff --git a/include/automount.h b/include/automount.h
> > index 1ba0d3c..2a082b5 100644
> > --- a/include/automount.h
> > +++ b/include/automount.h
> > @@ -126,7 +126,7 @@ struct autofs_point;
> > #define CHE_DUPLICATE 0x0020
> > #define CHE_UNAVAIL 0x0040
> >
> > -#define HASHSIZE 77
> > +#define HASHSIZE 4096
> > #define NEGATIVE_TIMEOUT 10
> > #define UMOUNT_RETRIES 8
> > #define EXPIRE_RETRIES 3
> > diff --git a/lib/cache.c b/lib/cache.c
> > index ce47e04..36b8294 100644
> > --- a/lib/cache.c
> > +++ b/lib/cache.c
> > @@ -281,20 +281,27 @@ struct mapent_cache *cache_init_null_cache(struct master *master)
> > return mc;
> > }
> >
> > -static unsigned int hash(const char *key)
> > +static u_int32_t hash(const char *key)
> > {
> > - unsigned long hashval;
> > + u_int32_t hashval;
> > char *s = (char *) key;
> >
> > - for (hashval = 0; *s != '\0';)
> > - hashval += *s++;
> > + for (hashval = 0; *s != '\0';) {
> > + hashval += (unsigned char) *s++;
> > + hashval += (hashval << 10);
> > + hashval ^= (hashval >> 6);
> > + }
> > +
> > + hashval += (hashval << 3);
> > + hashval ^= (hashval >> 11);
> > + hashval += (hashval << 15);
> >
> > return hashval % HASHSIZE;
> > }
> >
> > -static unsigned int ino_hash(dev_t dev, ino_t ino)
> > +static u_int32_t ino_hash(dev_t dev, ino_t ino)
> > {
> > - unsigned long hashval;
> > + u_int32_t hashval;
> >
> > hashval = dev + ino;
> >
> > @@ -303,7 +310,7 @@ static unsigned int ino_hash(dev_t dev, ino_t ino)
> >
> > int cache_set_ino_index(struct mapent_cache *mc, const char *key, dev_t dev, ino_t ino)
> > {
> > - unsigned int ino_index = ino_hash(dev, ino);
> > + u_int32_t ino_index = ino_hash(dev, ino);
> > struct mapent *me;
> >
> > me = cache_lookup_distinct(mc, key);
> > @@ -325,7 +332,7 @@ struct mapent *cache_lookup_ino(struct mapent_cache *mc, dev_t dev, ino_t ino)
> > {
> > struct mapent *me = NULL;
> > struct list_head *head, *p;
> > - unsigned int ino_index;
> > + u_int32_t ino_index;
> >
> > ino_index_lock(mc);
> > ino_index = ino_hash(dev, ino);
> > @@ -371,7 +378,7 @@ struct mapent *cache_lookup_first(struct mapent_cache *mc)
> > struct mapent *cache_lookup_next(struct mapent_cache *mc, struct mapent *me)
> > {
> > struct mapent *this;
> > - unsigned long hashval;
> > + u_int32_t hashval;
> > unsigned int i;
> >
> > if (!me)
> > @@ -532,7 +539,7 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c
> > {
> > struct mapent *me, *existing = NULL;
> > char *pkey, *pent;
> > - unsigned int hashval = hash(key);
> > + u_int32_t hashval = hash(key);
> > int status;
> >
> > me = (struct mapent *) malloc(sizeof(struct mapent));
> > @@ -752,7 +759,7 @@ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key
> > int cache_delete(struct mapent_cache *mc, const char *key)
> > {
> > struct mapent *me = NULL, *pred;
> > - unsigned int hashval = hash(key);
> > + u_int32_t hashval = hash(key);
> > int status, ret = CHE_OK;
> > char *this;
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 2/4] Make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit
2009-01-09 19:00 ` [PATCH 2/4] Make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit Jeff Moyer
@ 2009-01-09 19:54 ` Valerie Aurora Henson
0 siblings, 0 replies; 66+ messages in thread
From: Valerie Aurora Henson @ 2009-01-09 19:54 UTC (permalink / raw)
To: Jeff Moyer; +Cc: autofs
On Fri, Jan 09, 2009 at 02:00:01PM -0500, Jeff Moyer wrote:
> Valerie Aurora Henson <vaurora@redhat.com> writes:
>
> > Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
>
> > @@ -1524,18 +1525,12 @@ int lookup_read_master(struct master *master, time_t age, void *context)
> > goto next;
> > }
> >
> > - blen = strlen(*keyValue) + 1 + strlen(*values) + 2;
> > - if (blen > PARSE_MAX_BUF) {
> > + if (snprintf(parse_buf, sizeof(parse_buf), "%s %s",
> > + *keyValue, *values) > sizeof(parse_buf)) {
>
> I think this should be >=.
Yes, they all should be. I'll regenerate. Thanks,
-VAL
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 3/4] Easy alloca() replacements
2009-01-09 18:47 ` [PATCH 3/4] Easy alloca() replacements Valerie Aurora Henson
2009-01-09 18:47 ` [PATCH 4/4] Replace <linux/string.h> with <string.h> Valerie Aurora Henson
@ 2009-01-09 20:48 ` Valerie Aurora Henson
2009-01-10 3:18 ` Ian Kent
2 siblings, 0 replies; 66+ messages in thread
From: Valerie Aurora Henson @ 2009-01-09 20:48 UTC (permalink / raw)
To: autofs
On Fri, Jan 09, 2009 at 01:47:02PM -0500, Valerie Aurora Henson wrote:
>
> --- a/daemon/direct.c
> +++ b/daemon/direct.c
> @@ -742,11 +742,9 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me, const char *
>
> type = ap->entry->maps->type;
> if (type && !strcmp(ap->entry->maps->type, "hosts")) {
> - char *tmp = alloca(7);
> - if (tmp) {
> - strcpy(tmp, "-hosts");
> - map_name = (const char *) tmp;
> - }
> + char tmp[7];
> + strcpy(tmp, "-hosts");
> + map_name = (const char *) tmp;
> } else
> map_name = me->mc->map->argv[0];
>
tmp is being accessed outside of the scope it is declared in, I'll fix
that too.
-VAL
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-09 19:51 ` Valerie Aurora Henson
@ 2009-01-10 1:19 ` Paul Wankadia
2009-01-11 16:42 ` Ian Kent
2009-01-10 14:45 ` Ian Kent
1 sibling, 1 reply; 66+ messages in thread
From: Paul Wankadia @ 2009-01-10 1:19 UTC (permalink / raw)
To: Valerie Aurora Henson; +Cc: autofs
[-- Attachment #1.1: Type: text/plain, Size: 1412 bytes --]
On Sat, Jan 10, 2009 at 6:51 AM, Valerie Aurora Henson
<vaurora@redhat.com>wrote:
> Most patches of this nature come with some description of a performance
> > problem and how the patch solves it. Which caching algorithm is
> > implemented below? There are, of course, many hashing algorithms for
> > variable length strings. Can we get some rationale for the change? I'm
> > not against it, I'd just like a *little* explanation.
>
> This is where I get to blame my cold for being stupid. :)
>
> Yes, the original author (Paul Wankadia, now cc'd) gave me a little
> information on that front, I just forgot to pass it on. It's the
> "One-at-a-Time" hash function by Bob Jenkins. See:
>
> http://burtleburtle.net/bob/hash/doobs.html
>
> What I vaguely recall from our conversation is an order of magnitude
> improvement in elapsed time for large (thousands) numbers of maps, but
> I'll let Paul be more specific. Do we have a test for thousands of
> entries somewhere in our automated tests?
It's just that the additive hash function and the tiny, non-prime hash table
size offended my delicate sensibilities. ;)
Actually, we discovered that reloading a large file map took well over ten
seconds. Profiling revealed that the daemon spent most of its time calling
strcmp(3).
Oh, and I should note that the problem was observed in autofs v4. I'll be
looking more closely at autofs v5 in the near future.
[-- Attachment #1.2: Type: text/html, Size: 1899 bytes --]
[-- Attachment #2: Type: text/plain, Size: 140 bytes --]
_______________________________________________
autofs mailing list
autofs@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-09 19:17 ` [PATCH 1/4] Make hash table scale to thousands of entries Jeff Moyer
2009-01-09 19:51 ` Valerie Aurora Henson
@ 2009-01-10 2:07 ` Ian Kent
1 sibling, 0 replies; 66+ messages in thread
From: Ian Kent @ 2009-01-10 2:07 UTC (permalink / raw)
To: Valerie Aurora Henson; +Cc: autofs
On Fri, 2009-01-09 at 14:17 -0500, Jeff Moyer wrote:
> Valerie Aurora Henson <vaurora@redhat.com> writes:
> > From: Paul Wankadia <junyer@google.com>
> > Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
>
> Most patches of this nature come with some description of a performance
> problem and how the patch solves it. Which caching algorithm is
> implemented below? There are, of course, many hashing algorithms for
> variable length strings. Can we get some rationale for the change? I'm
> not against it, I'd just like a *little* explanation.
Thanks for spending some time on autofs Val, it's much appreciated.
As Jeff says, a brief description would save me guessing what to put
with the patches. These days I try to have a description with all
patches, no matter how trivial.
>
> Cheers,
> Jeff
>
> > ---
> > include/automount.h | 2 +-
> > lib/cache.c | 29 ++++++++++++++++++-----------
> > 2 files changed, 19 insertions(+), 12 deletions(-)
> >
> > diff --git a/include/automount.h b/include/automount.h
> > index 1ba0d3c..2a082b5 100644
> > --- a/include/automount.h
> > +++ b/include/automount.h
> > @@ -126,7 +126,7 @@ struct autofs_point;
> > #define CHE_DUPLICATE 0x0020
> > #define CHE_UNAVAIL 0x0040
> >
> > -#define HASHSIZE 77
> > +#define HASHSIZE 4096
> > #define NEGATIVE_TIMEOUT 10
> > #define UMOUNT_RETRIES 8
> > #define EXPIRE_RETRIES 3
> > diff --git a/lib/cache.c b/lib/cache.c
> > index ce47e04..36b8294 100644
> > --- a/lib/cache.c
> > +++ b/lib/cache.c
> > @@ -281,20 +281,27 @@ struct mapent_cache *cache_init_null_cache(struct master *master)
> > return mc;
> > }
> >
> > -static unsigned int hash(const char *key)
> > +static u_int32_t hash(const char *key)
> > {
> > - unsigned long hashval;
> > + u_int32_t hashval;
> > char *s = (char *) key;
> >
> > - for (hashval = 0; *s != '\0';)
> > - hashval += *s++;
> > + for (hashval = 0; *s != '\0';) {
> > + hashval += (unsigned char) *s++;
> > + hashval += (hashval << 10);
> > + hashval ^= (hashval >> 6);
> > + }
> > +
> > + hashval += (hashval << 3);
> > + hashval ^= (hashval >> 11);
> > + hashval += (hashval << 15);
> >
> > return hashval % HASHSIZE;
> > }
> >
> > -static unsigned int ino_hash(dev_t dev, ino_t ino)
> > +static u_int32_t ino_hash(dev_t dev, ino_t ino)
> > {
> > - unsigned long hashval;
> > + u_int32_t hashval;
> >
> > hashval = dev + ino;
> >
> > @@ -303,7 +310,7 @@ static unsigned int ino_hash(dev_t dev, ino_t ino)
> >
> > int cache_set_ino_index(struct mapent_cache *mc, const char *key, dev_t dev, ino_t ino)
> > {
> > - unsigned int ino_index = ino_hash(dev, ino);
> > + u_int32_t ino_index = ino_hash(dev, ino);
> > struct mapent *me;
> >
> > me = cache_lookup_distinct(mc, key);
> > @@ -325,7 +332,7 @@ struct mapent *cache_lookup_ino(struct mapent_cache *mc, dev_t dev, ino_t ino)
> > {
> > struct mapent *me = NULL;
> > struct list_head *head, *p;
> > - unsigned int ino_index;
> > + u_int32_t ino_index;
> >
> > ino_index_lock(mc);
> > ino_index = ino_hash(dev, ino);
> > @@ -371,7 +378,7 @@ struct mapent *cache_lookup_first(struct mapent_cache *mc)
> > struct mapent *cache_lookup_next(struct mapent_cache *mc, struct mapent *me)
> > {
> > struct mapent *this;
> > - unsigned long hashval;
> > + u_int32_t hashval;
> > unsigned int i;
> >
> > if (!me)
> > @@ -532,7 +539,7 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c
> > {
> > struct mapent *me, *existing = NULL;
> > char *pkey, *pent;
> > - unsigned int hashval = hash(key);
> > + u_int32_t hashval = hash(key);
> > int status;
> >
> > me = (struct mapent *) malloc(sizeof(struct mapent));
> > @@ -752,7 +759,7 @@ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key
> > int cache_delete(struct mapent_cache *mc, const char *key)
> > {
> > struct mapent *me = NULL, *pred;
> > - unsigned int hashval = hash(key);
> > + u_int32_t hashval = hash(key);
> > int status, ret = CHE_OK;
> > char *this;
>
> _______________________________________________
> autofs mailing list
> autofs@linux.kernel.org
> http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 3/4] Easy alloca() replacements
2009-01-09 18:47 ` [PATCH 3/4] Easy alloca() replacements Valerie Aurora Henson
2009-01-09 18:47 ` [PATCH 4/4] Replace <linux/string.h> with <string.h> Valerie Aurora Henson
2009-01-09 20:48 ` [PATCH 3/4] Easy alloca() replacements Valerie Aurora Henson
@ 2009-01-10 3:18 ` Ian Kent
2009-01-16 22:11 ` Valerie Aurora Henson
2 siblings, 1 reply; 66+ messages in thread
From: Ian Kent @ 2009-01-10 3:18 UTC (permalink / raw)
To: Valerie Aurora Henson; +Cc: autofs
On Fri, 2009-01-09 at 13:47 -0500, Valerie Aurora Henson wrote:
Just a first pass reading but noticed ....
> diff --git a/lib/cache.c b/lib/cache.c
> index 36b8294..bc2c722 100644
> --- a/lib/cache.c
> +++ b/lib/cache.c
> @@ -484,27 +484,19 @@ struct mapent *cache_lookup_offset(const char *prefix, const char *offset, int s
> {
> struct list_head *p;
> struct mapent *this;
> - int plen = strlen(prefix);
> - char *o_key;
> + char o_key[KEY_MAX_LEN];
I know this looks right but I think it will end up being a problem
latter. I know there are places in the map lookup libraries that
restrict these to KEY_MAX_LEN, which is needed for indirect map keys,
but direct map keys really shouldn't have this restriction as they
should be able to be as long as PATH_MAX but that brings the issue of
needing to audit and adjust the maximum parse buffer as well. So we will
need to get around to that at some point as well.
>
> /* root offset duplicates "/" */
> - if (plen > 1) {
> - o_key = alloca(plen + strlen(offset) + 1);
> - strcpy(o_key, prefix);
> - strcat(o_key, offset);
> - } else {
> - o_key = alloca(strlen(offset) + 1);
> - strcpy(o_key, offset);
> - }
> + if (snprintf(o_key, sizeof(o_key), "%s%s", prefix, offset) >
> + sizeof(o_key))
> + return NULL;
Looks like this will set o_key to "//..." for strlen(prefix) == 1.
>
> list_for_each(p, head) {
> this = list_entry(p, struct mapent, multi_list);
> if (!strcmp(&this->key[start], o_key))
> - goto done;
> + return this;
> }
> - this = NULL;
> -done:
> - return this;
> + return NULL;
> }
>
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-09 18:47 ` [PATCH 1/4] Make hash table scale to thousands of entries Valerie Aurora Henson
2009-01-09 18:47 ` [PATCH 2/4] Make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit Valerie Aurora Henson
2009-01-09 19:17 ` [PATCH 1/4] Make hash table scale to thousands of entries Jeff Moyer
@ 2009-01-10 3:29 ` Ian Kent
2009-01-10 3:57 ` Ian Kent
2009-01-13 5:51 ` Ian Kent
3 siblings, 1 reply; 66+ messages in thread
From: Ian Kent @ 2009-01-10 3:29 UTC (permalink / raw)
To: Valerie Aurora Henson; +Cc: autofs
On Fri, 2009-01-09 at 13:47 -0500, Valerie Aurora Henson wrote:
> From: Paul Wankadia <junyer@google.com>
> Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
Perhaps this will help with the description.
What I think is the main point of this patch is that, with the trivial
hash function, the length of the chains aren't evenly spread causing
some chains to be excessively long for large maps. And the size of the
hash table is too small because for 10000 entries we would have chains
of about 130 entries if they were in fact spread evenly, and the claim
is that they aren't.
> ---
> include/automount.h | 2 +-
> lib/cache.c | 29 ++++++++++++++++++-----------
> 2 files changed, 19 insertions(+), 12 deletions(-)
>
> diff --git a/include/automount.h b/include/automount.h
> index 1ba0d3c..2a082b5 100644
> --- a/include/automount.h
> +++ b/include/automount.h
> @@ -126,7 +126,7 @@ struct autofs_point;
> #define CHE_DUPLICATE 0x0020
> #define CHE_UNAVAIL 0x0040
>
> -#define HASHSIZE 77
> +#define HASHSIZE 4096
> #define NEGATIVE_TIMEOUT 10
> #define UMOUNT_RETRIES 8
> #define EXPIRE_RETRIES 3
> diff --git a/lib/cache.c b/lib/cache.c
> index ce47e04..36b8294 100644
> --- a/lib/cache.c
> +++ b/lib/cache.c
> @@ -281,20 +281,27 @@ struct mapent_cache *cache_init_null_cache(struct master *master)
> return mc;
> }
>
> -static unsigned int hash(const char *key)
> +static u_int32_t hash(const char *key)
> {
> - unsigned long hashval;
> + u_int32_t hashval;
> char *s = (char *) key;
>
> - for (hashval = 0; *s != '\0';)
> - hashval += *s++;
> + for (hashval = 0; *s != '\0';) {
> + hashval += (unsigned char) *s++;
> + hashval += (hashval << 10);
> + hashval ^= (hashval >> 6);
> + }
> +
> + hashval += (hashval << 3);
> + hashval ^= (hashval >> 11);
> + hashval += (hashval << 15);
>
> return hashval % HASHSIZE;
> }
>
> -static unsigned int ino_hash(dev_t dev, ino_t ino)
> +static u_int32_t ino_hash(dev_t dev, ino_t ino)
> {
> - unsigned long hashval;
> + u_int32_t hashval;
>
> hashval = dev + ino;
>
> @@ -303,7 +310,7 @@ static unsigned int ino_hash(dev_t dev, ino_t ino)
>
> int cache_set_ino_index(struct mapent_cache *mc, const char *key, dev_t dev, ino_t ino)
> {
> - unsigned int ino_index = ino_hash(dev, ino);
> + u_int32_t ino_index = ino_hash(dev, ino);
> struct mapent *me;
>
> me = cache_lookup_distinct(mc, key);
> @@ -325,7 +332,7 @@ struct mapent *cache_lookup_ino(struct mapent_cache *mc, dev_t dev, ino_t ino)
> {
> struct mapent *me = NULL;
> struct list_head *head, *p;
> - unsigned int ino_index;
> + u_int32_t ino_index;
>
> ino_index_lock(mc);
> ino_index = ino_hash(dev, ino);
> @@ -371,7 +378,7 @@ struct mapent *cache_lookup_first(struct mapent_cache *mc)
> struct mapent *cache_lookup_next(struct mapent_cache *mc, struct mapent *me)
> {
> struct mapent *this;
> - unsigned long hashval;
> + u_int32_t hashval;
> unsigned int i;
>
> if (!me)
> @@ -532,7 +539,7 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c
> {
> struct mapent *me, *existing = NULL;
> char *pkey, *pent;
> - unsigned int hashval = hash(key);
> + u_int32_t hashval = hash(key);
> int status;
>
> me = (struct mapent *) malloc(sizeof(struct mapent));
> @@ -752,7 +759,7 @@ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key
> int cache_delete(struct mapent_cache *mc, const char *key)
> {
> struct mapent *me = NULL, *pred;
> - unsigned int hashval = hash(key);
> + u_int32_t hashval = hash(key);
> int status, ret = CHE_OK;
> char *this;
>
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-10 3:29 ` Ian Kent
@ 2009-01-10 3:57 ` Ian Kent
0 siblings, 0 replies; 66+ messages in thread
From: Ian Kent @ 2009-01-10 3:57 UTC (permalink / raw)
To: Valerie Aurora Henson; +Cc: autofs
On Sat, 2009-01-10 at 12:29 +0900, Ian Kent wrote:
> On Fri, 2009-01-09 at 13:47 -0500, Valerie Aurora Henson wrote:
> > From: Paul Wankadia <junyer@google.com>
> > Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
>
> Perhaps this will help with the description.
>
> What I think is the main point of this patch is that, with the trivial
> hash function, the length of the chains aren't evenly spread causing
> some chains to be excessively long for large maps. And the size of the
> hash table is too small because for 10000 entries we would have chains
> of about 130 entries if they were in fact spread evenly, and the claim
> is that they aren't.
And, yes, we should also be able to do much better than chain lengths of
around 130.
A simple minded check would be to modify the cache_dump_cache() function
to report chain lengths, add a call to it in a couple of strategic
places and construct a test to load a large map. The difficulty, of
course, is to ensure we are using strings with a distribution of
characters that are really representative of map keys.
>
> > ---
> > include/automount.h | 2 +-
> > lib/cache.c | 29 ++++++++++++++++++-----------
> > 2 files changed, 19 insertions(+), 12 deletions(-)
> >
> > diff --git a/include/automount.h b/include/automount.h
> > index 1ba0d3c..2a082b5 100644
> > --- a/include/automount.h
> > +++ b/include/automount.h
> > @@ -126,7 +126,7 @@ struct autofs_point;
> > #define CHE_DUPLICATE 0x0020
> > #define CHE_UNAVAIL 0x0040
> >
> > -#define HASHSIZE 77
> > +#define HASHSIZE 4096
> > #define NEGATIVE_TIMEOUT 10
> > #define UMOUNT_RETRIES 8
> > #define EXPIRE_RETRIES 3
> > diff --git a/lib/cache.c b/lib/cache.c
> > index ce47e04..36b8294 100644
> > --- a/lib/cache.c
> > +++ b/lib/cache.c
> > @@ -281,20 +281,27 @@ struct mapent_cache *cache_init_null_cache(struct master *master)
> > return mc;
> > }
> >
> > -static unsigned int hash(const char *key)
> > +static u_int32_t hash(const char *key)
> > {
> > - unsigned long hashval;
> > + u_int32_t hashval;
> > char *s = (char *) key;
> >
> > - for (hashval = 0; *s != '\0';)
> > - hashval += *s++;
> > + for (hashval = 0; *s != '\0';) {
> > + hashval += (unsigned char) *s++;
> > + hashval += (hashval << 10);
> > + hashval ^= (hashval >> 6);
> > + }
> > +
> > + hashval += (hashval << 3);
> > + hashval ^= (hashval >> 11);
> > + hashval += (hashval << 15);
> >
> > return hashval % HASHSIZE;
> > }
> >
> > -static unsigned int ino_hash(dev_t dev, ino_t ino)
> > +static u_int32_t ino_hash(dev_t dev, ino_t ino)
> > {
> > - unsigned long hashval;
> > + u_int32_t hashval;
> >
> > hashval = dev + ino;
> >
> > @@ -303,7 +310,7 @@ static unsigned int ino_hash(dev_t dev, ino_t ino)
> >
> > int cache_set_ino_index(struct mapent_cache *mc, const char *key, dev_t dev, ino_t ino)
> > {
> > - unsigned int ino_index = ino_hash(dev, ino);
> > + u_int32_t ino_index = ino_hash(dev, ino);
> > struct mapent *me;
> >
> > me = cache_lookup_distinct(mc, key);
> > @@ -325,7 +332,7 @@ struct mapent *cache_lookup_ino(struct mapent_cache *mc, dev_t dev, ino_t ino)
> > {
> > struct mapent *me = NULL;
> > struct list_head *head, *p;
> > - unsigned int ino_index;
> > + u_int32_t ino_index;
> >
> > ino_index_lock(mc);
> > ino_index = ino_hash(dev, ino);
> > @@ -371,7 +378,7 @@ struct mapent *cache_lookup_first(struct mapent_cache *mc)
> > struct mapent *cache_lookup_next(struct mapent_cache *mc, struct mapent *me)
> > {
> > struct mapent *this;
> > - unsigned long hashval;
> > + u_int32_t hashval;
> > unsigned int i;
> >
> > if (!me)
> > @@ -532,7 +539,7 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c
> > {
> > struct mapent *me, *existing = NULL;
> > char *pkey, *pent;
> > - unsigned int hashval = hash(key);
> > + u_int32_t hashval = hash(key);
> > int status;
> >
> > me = (struct mapent *) malloc(sizeof(struct mapent));
> > @@ -752,7 +759,7 @@ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key
> > int cache_delete(struct mapent_cache *mc, const char *key)
> > {
> > struct mapent *me = NULL, *pred;
> > - unsigned int hashval = hash(key);
> > + u_int32_t hashval = hash(key);
> > int status, ret = CHE_OK;
> > char *this;
> >
>
> _______________________________________________
> autofs mailing list
> autofs@linux.kernel.org
> http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-09 19:51 ` Valerie Aurora Henson
2009-01-10 1:19 ` Paul Wankadia
@ 2009-01-10 14:45 ` Ian Kent
1 sibling, 0 replies; 66+ messages in thread
From: Ian Kent @ 2009-01-10 14:45 UTC (permalink / raw)
To: Valerie Aurora Henson; +Cc: autofs, Paul Wankadia
On Fri, 2009-01-09 at 14:51 -0500, Valerie Aurora Henson wrote:
> On Fri, Jan 09, 2009 at 02:17:55PM -0500, Jeff Moyer wrote:
> > Valerie Aurora Henson <vaurora@redhat.com> writes:
> > > From: Paul Wankadia <junyer@google.com>
> > > Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
> >
> > Most patches of this nature come with some description of a performance
> > problem and how the patch solves it. Which caching algorithm is
> > implemented below? There are, of course, many hashing algorithms for
> > variable length strings. Can we get some rationale for the change? I'm
> > not against it, I'd just like a *little* explanation.
>
> This is where I get to blame my cold for being stupid. :)
>
> Yes, the original author (Paul Wankadia, now cc'd) gave me a little
> information on that front, I just forgot to pass it on. It's the
> "One-at-a-Time" hash function by Bob Jenkins. See:
>
> http://burtleburtle.net/bob/hash/doobs.html
>
> What I vaguely recall from our conversation is an order of magnitude
> improvement in elapsed time for large (thousands) numbers of maps, but
Sorry to be trivail, but that probably should read "maps with thousands
of entries".
> I'll let Paul be more specific. Do we have a test for thousands of
> entries somewhere in our automated tests?
Not yet.
That will be quite interesting to write given that, at best, the test
will work but we are interested in how long it should take which could
be a bit like "how long is a piece of string" with varying hardware.
We will need two parts for the tests, for indirect and direct map types.
>
> -VAL
>
> >
> > Cheers,
> > Jeff
> >
> > > ---
> > > include/automount.h | 2 +-
> > > lib/cache.c | 29 ++++++++++++++++++-----------
> > > 2 files changed, 19 insertions(+), 12 deletions(-)
> > >
> > > diff --git a/include/automount.h b/include/automount.h
> > > index 1ba0d3c..2a082b5 100644
> > > --- a/include/automount.h
> > > +++ b/include/automount.h
> > > @@ -126,7 +126,7 @@ struct autofs_point;
> > > #define CHE_DUPLICATE 0x0020
> > > #define CHE_UNAVAIL 0x0040
> > >
> > > -#define HASHSIZE 77
> > > +#define HASHSIZE 4096
> > > #define NEGATIVE_TIMEOUT 10
> > > #define UMOUNT_RETRIES 8
> > > #define EXPIRE_RETRIES 3
> > > diff --git a/lib/cache.c b/lib/cache.c
> > > index ce47e04..36b8294 100644
> > > --- a/lib/cache.c
> > > +++ b/lib/cache.c
> > > @@ -281,20 +281,27 @@ struct mapent_cache *cache_init_null_cache(struct master *master)
> > > return mc;
> > > }
> > >
> > > -static unsigned int hash(const char *key)
> > > +static u_int32_t hash(const char *key)
> > > {
> > > - unsigned long hashval;
> > > + u_int32_t hashval;
> > > char *s = (char *) key;
> > >
> > > - for (hashval = 0; *s != '\0';)
> > > - hashval += *s++;
> > > + for (hashval = 0; *s != '\0';) {
> > > + hashval += (unsigned char) *s++;
> > > + hashval += (hashval << 10);
> > > + hashval ^= (hashval >> 6);
> > > + }
> > > +
> > > + hashval += (hashval << 3);
> > > + hashval ^= (hashval >> 11);
> > > + hashval += (hashval << 15);
> > >
> > > return hashval % HASHSIZE;
> > > }
> > >
> > > -static unsigned int ino_hash(dev_t dev, ino_t ino)
> > > +static u_int32_t ino_hash(dev_t dev, ino_t ino)
> > > {
> > > - unsigned long hashval;
> > > + u_int32_t hashval;
> > >
> > > hashval = dev + ino;
> > >
> > > @@ -303,7 +310,7 @@ static unsigned int ino_hash(dev_t dev, ino_t ino)
> > >
> > > int cache_set_ino_index(struct mapent_cache *mc, const char *key, dev_t dev, ino_t ino)
> > > {
> > > - unsigned int ino_index = ino_hash(dev, ino);
> > > + u_int32_t ino_index = ino_hash(dev, ino);
> > > struct mapent *me;
> > >
> > > me = cache_lookup_distinct(mc, key);
> > > @@ -325,7 +332,7 @@ struct mapent *cache_lookup_ino(struct mapent_cache *mc, dev_t dev, ino_t ino)
> > > {
> > > struct mapent *me = NULL;
> > > struct list_head *head, *p;
> > > - unsigned int ino_index;
> > > + u_int32_t ino_index;
> > >
> > > ino_index_lock(mc);
> > > ino_index = ino_hash(dev, ino);
> > > @@ -371,7 +378,7 @@ struct mapent *cache_lookup_first(struct mapent_cache *mc)
> > > struct mapent *cache_lookup_next(struct mapent_cache *mc, struct mapent *me)
> > > {
> > > struct mapent *this;
> > > - unsigned long hashval;
> > > + u_int32_t hashval;
> > > unsigned int i;
> > >
> > > if (!me)
> > > @@ -532,7 +539,7 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c
> > > {
> > > struct mapent *me, *existing = NULL;
> > > char *pkey, *pent;
> > > - unsigned int hashval = hash(key);
> > > + u_int32_t hashval = hash(key);
> > > int status;
> > >
> > > me = (struct mapent *) malloc(sizeof(struct mapent));
> > > @@ -752,7 +759,7 @@ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key
> > > int cache_delete(struct mapent_cache *mc, const char *key)
> > > {
> > > struct mapent *me = NULL, *pred;
> > > - unsigned int hashval = hash(key);
> > > + u_int32_t hashval = hash(key);
> > > int status, ret = CHE_OK;
> > > char *this;
>
> _______________________________________________
> autofs mailing list
> autofs@linux.kernel.org
> http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-10 1:19 ` Paul Wankadia
@ 2009-01-11 16:42 ` Ian Kent
2009-01-11 23:25 ` Paul Wankadia
0 siblings, 1 reply; 66+ messages in thread
From: Ian Kent @ 2009-01-11 16:42 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Sat, 2009-01-10 at 12:19 +1100, Paul Wankadia wrote:
> On Sat, Jan 10, 2009 at 6:51 AM, Valerie Aurora Henson
> <vaurora@redhat.com> wrote:
>
> > Most patches of this nature come with some description of a
> performance
> > problem and how the patch solves it. Which caching
> algorithm is
> > implemented below? There are, of course, many hashing
> algorithms for
> > variable length strings. Can we get some rationale for the
> change? I'm
> > not against it, I'd just like a *little* explanation.
>
> This is where I get to blame my cold for being stupid. :)
>
> Yes, the original author (Paul Wankadia, now cc'd) gave me a
> little
> information on that front, I just forgot to pass it on. It's
> the
> "One-at-a-Time" hash function by Bob Jenkins. See:
>
> http://burtleburtle.net/bob/hash/doobs.html
>
> What I vaguely recall from our conversation is an order of
> magnitude
> improvement in elapsed time for large (thousands) numbers of
> maps, but
> I'll let Paul be more specific. Do we have a test for
> thousands of
> entries somewhere in our automated tests?
>
> It's just that the additive hash function and the tiny, non-prime hash
> table size offended my delicate sensibilities. ;)
Oh .. right, looks like v4 uses a prime to me but I did mean to use a
prime in v5, oops!
>
> Actually, we discovered that reloading a large file map took well over
> ten seconds. Profiling revealed that the daemon spent most of its time
> calling strcmp(3).
>
> Oh, and I should note that the problem was observed in autofs v4. I'll
> be looking more closely at autofs v5 in the near future.
It's much the same, the hash size is not much bigger and it can well do
with a healthy increase. I don't know what sort of distribution the
simple additive hash gives and if we are going to change it then we
should do some checking with representative strings to ensure that what
we use is in fact better.
Ian
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-11 16:42 ` Ian Kent
@ 2009-01-11 23:25 ` Paul Wankadia
2009-01-12 1:13 ` Ian Kent
2009-01-12 1:19 ` Ian Kent
0 siblings, 2 replies; 66+ messages in thread
From: Paul Wankadia @ 2009-01-11 23:25 UTC (permalink / raw)
To: Ian Kent; +Cc: autofs
[-- Attachment #1.1: Type: text/plain, Size: 1048 bytes --]
On Mon, Jan 12, 2009 at 3:42 AM, Ian Kent <raven@themaw.net> wrote:
> It's just that the additive hash function and the tiny, non-prime hash
> > table size offended my delicate sensibilities. ;)
>
> Oh .. right, looks like v4 uses a prime to me but I did mean to use a
> prime in v5, oops!
$ factor 27 77
27: 3 3 3
77: 7 11
$
> Actually, we discovered that reloading a large file map took well over
> > ten seconds. Profiling revealed that the daemon spent most of its time
> > calling strcmp(3).
> >
> > Oh, and I should note that the problem was observed in autofs v4. I'll
> > be looking more closely at autofs v5 in the near future.
>
> It's much the same, the hash size is not much bigger and it can well do
> with a healthy increase. I don't know what sort of distribution the
> simple additive hash gives and if we are going to change it then we
> should do some checking with representative strings to ensure that what
> we use is in fact better.
How could it be worse? :P
I'll check our large file map just to satisfy my curiosity.
[-- Attachment #1.2: Type: text/html, Size: 1575 bytes --]
[-- Attachment #2: Type: text/plain, Size: 140 bytes --]
_______________________________________________
autofs mailing list
autofs@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-11 23:25 ` Paul Wankadia
@ 2009-01-12 1:13 ` Ian Kent
2009-01-12 1:19 ` Ian Kent
1 sibling, 0 replies; 66+ messages in thread
From: Ian Kent @ 2009-01-12 1:13 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Mon, 2009-01-12 at 10:25 +1100, Paul Wankadia wrote:
> On Mon, Jan 12, 2009 at 3:42 AM, Ian Kent <raven@themaw.net> wrote:
>
> > It's just that the additive hash function and the tiny,
> non-prime hash
> > table size offended my delicate sensibilities. ;)
>
> Oh .. right, looks like v4 uses a prime to me but I did mean
> to use a
> prime in v5, oops!
>
> $ factor 27 77
> 27: 3 3 3
> 77: 7 11
> $
Yeah, yeah, I realized how stupid I was just after I made the post,
double oops!
>
>
> > Actually, we discovered that reloading a large file map took
> well over
> > ten seconds. Profiling revealed that the daemon spent most
> of its time
> > calling strcmp(3).
> >
> > Oh, and I should note that the problem was observed in
> autofs v4. I'll
> > be looking more closely at autofs v5 in the near future.
>
> It's much the same, the hash size is not much bigger and it
> can well do
> with a healthy increase. I don't know what sort of
> distribution the
> simple additive hash gives and if we are going to change it
> then we
> should do some checking with representative strings to ensure
> that what
> we use is in fact better.
>
> How could it be worse? :P
>
> I'll check our large file map just to satisfy my curiosity.
>
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-11 23:25 ` Paul Wankadia
2009-01-12 1:13 ` Ian Kent
@ 2009-01-12 1:19 ` Ian Kent
2009-01-12 2:10 ` Paul Wankadia
2009-01-12 4:02 ` Ian Kent
1 sibling, 2 replies; 66+ messages in thread
From: Ian Kent @ 2009-01-12 1:19 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Mon, 2009-01-12 at 10:25 +1100, Paul Wankadia wrote:
> On Mon, Jan 12, 2009 at 3:42 AM, Ian Kent <raven@themaw.net> wrote:
>
> > It's just that the additive hash function and the tiny,
> non-prime hash
> > table size offended my delicate sensibilities. ;)
>
> Oh .. right, looks like v4 uses a prime to me but I did mean
> to use a
> prime in v5, oops!
>
> $ factor 27 77
> 27: 3 3 3
> 77: 7 11
> $
>
>
> > Actually, we discovered that reloading a large file map took
> well over
> > ten seconds. Profiling revealed that the daemon spent most
> of its time
> > calling strcmp(3).
> >
> > Oh, and I should note that the problem was observed in
> autofs v4. I'll
> > be looking more closely at autofs v5 in the near future.
>
> It's much the same, the hash size is not much bigger and it
> can well do
> with a healthy increase. I don't know what sort of
> distribution the
> simple additive hash gives and if we are going to change it
> then we
> should do some checking with representative strings to ensure
> that what
> we use is in fact better.
>
Oh .. didn't see this before.
> How could it be worse? :P
Hehe, there's an assumption without evidence in there some where.
>
> I'll check our large file map just to satisfy my curiosity.
>
Give me a chance and I'll do a couple of patches to add some statistical
calculations to cache_dump_cache() so we can see the state of the hash
table after a map is loaded.
Ian
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-12 1:19 ` Ian Kent
@ 2009-01-12 2:10 ` Paul Wankadia
2009-01-12 4:02 ` Ian Kent
1 sibling, 0 replies; 66+ messages in thread
From: Paul Wankadia @ 2009-01-12 2:10 UTC (permalink / raw)
To: Ian Kent; +Cc: autofs
[-- Attachment #1.1: Type: text/plain, Size: 722 bytes --]
On Mon, Jan 12, 2009 at 12:19 PM, Ian Kent <raven@themaw.net> wrote:
Oh .. didn't see this before.
>
> > How could it be worse? :P
>
> Hehe, there's an assumption without evidence in there some where.
Well, yes, I assumed that almost anything would be better than the additive
hash function. ;)
> I'll check our large file map just to satisfy my curiosity.
>
> Give me a chance and I'll do a couple of patches to add some statistical
> calculations to cache_dump_cache() so we can see the state of the hash
> table after a map is loaded.
Here are the raw data and the corresponding plots:
additive.txt (text/plain) 28K
additive.png (image/png) 6K
one-at-a-time.txt (text/plain) 30K
one-at-a-time.png (image/png) 6K
[-- Attachment #1.2: Type: text/html, Size: 1256 bytes --]
[-- Attachment #2: additive.txt --]
[-- Type: text/plain, Size: 28373 bytes --]
0 0
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 0
10 0
11 0
12 0
13 0
14 0
15 0
16 0
17 0
18 0
19 0
20 0
21 0
22 0
23 0
24 0
25 0
26 0
27 0
28 0
29 0
30 0
31 0
32 0
33 0
34 0
35 0
36 0
37 0
38 0
39 0
40 0
41 0
42 0
43 0
44 0
45 0
46 0
47 0
48 0
49 0
50 0
51 0
52 0
53 0
54 0
55 0
56 0
57 0
58 0
59 0
60 0
61 0
62 0
63 0
64 0
65 0
66 0
67 0
68 0
69 0
70 0
71 0
72 0
73 0
74 0
75 0
76 0
77 0
78 0
79 0
80 0
81 0
82 0
83 0
84 0
85 0
86 0
87 0
88 0
89 0
90 0
91 0
92 0
93 0
94 0
95 0
96 0
97 0
98 0
99 1
100 0
101 0
102 0
103 0
104 0
105 0
106 0
107 0
108 0
109 0
110 0
111 0
112 1
113 0
114 1
115 0
116 0
117 0
118 0
119 0
120 0
121 0
122 0
123 0
124 0
125 0
126 0
127 0
128 0
129 0
130 0
131 0
132 0
133 0
134 0
135 0
136 0
137 0
138 0
139 0
140 0
141 0
142 0
143 0
144 0
145 0
146 0
147 0
148 0
149 0
150 0
151 0
152 0
153 0
154 0
155 0
156 0
157 0
158 0
159 0
160 0
161 0
162 0
163 0
164 0
165 0
166 1
167 0
168 0
169 0
170 0
171 0
172 0
173 0
174 0
175 0
176 0
177 0
178 0
179 0
180 0
181 0
182 0
183 0
184 0
185 0
186 0
187 0
188 0
189 0
190 0
191 0
192 0
193 0
194 1
195 0
196 0
197 1
198 0
199 0
200 1
201 0
202 1
203 0
204 1
205 3
206 0
207 1
208 2
209 3
210 2
211 3
212 1
213 0
214 2
215 2
216 0
217 2
218 1
219 2
220 1
221 0
222 3
223 2
224 1
225 1
226 0
227 0
228 1
229 0
230 2
231 0
232 1
233 2
234 0
235 1
236 0
237 0
238 0
239 0
240 0
241 0
242 0
243 0
244 0
245 0
246 0
247 0
248 0
249 0
250 0
251 0
252 0
253 0
254 0
255 0
256 0
257 0
258 1
259 0
260 0
261 0
262 0
263 0
264 0
265 0
266 1
267 0
268 0
269 0
270 0
271 0
272 0
273 0
274 0
275 0
276 0
277 0
278 0
279 0
280 0
281 0
282 0
283 0
284 0
285 0
286 0
287 0
288 0
289 0
290 0
291 0
292 0
293 1
294 4
295 3
296 3
297 3
298 3
299 4
300 5
301 5
302 7
303 10
304 12
305 13
306 13
307 14
308 16
309 26
310 16
311 22
312 18
313 23
314 29
315 31
316 35
317 34
318 33
319 30
320 34
321 40
322 31
323 31
324 49
325 35
326 30
327 38
328 31
329 33
330 26
331 32
332 18
333 23
334 34
335 24
336 20
337 22
338 16
339 19
340 17
341 15
342 8
343 17
344 13
345 12
346 11
347 6
348 10
349 4
350 5
351 7
352 5
353 3
354 3
355 0
356 2
357 2
358 2
359 0
360 3
361 0
362 0
363 1
364 0
365 0
366 0
367 0
368 0
369 0
370 0
371 0
372 0
373 0
374 0
375 0
376 0
377 0
378 0
379 0
380 0
381 0
382 0
383 0
384 0
385 0
386 0
387 0
388 1
389 0
390 0
391 1
392 0
393 0
394 1
395 0
396 0
397 3
398 2
399 1
400 5
401 1
402 8
403 9
404 9
405 13
406 9
407 20
408 16
409 17
410 23
411 18
412 33
413 26
414 34
415 42
416 52
417 44
418 40
419 51
420 54
421 61
422 56
423 56
424 61
425 65
426 65
427 75
428 57
429 65
430 61
431 62
432 60
433 56
434 61
435 52
436 53
437 48
438 61
439 58
440 46
441 38
442 43
443 26
444 33
445 38
446 38
447 20
448 26
449 39
450 25
451 26
452 16
453 16
454 17
455 9
456 10
457 12
458 9
459 4
460 7
461 2
462 7
463 7
464 5
465 0
466 0
467 0
468 1
469 1
470 0
471 1
472 2
473 0
474 1
475 2
476 1
477 0
478 0
479 0
480 0
481 0
482 0
483 0
484 0
485 0
486 0
487 0
488 1
489 0
490 1
491 0
492 0
493 1
494 0
495 0
496 1
497 3
498 2
499 6
500 2
501 4
502 4
503 5
504 5
505 8
506 12
507 20
508 23
509 20
510 39
511 35
512 26
513 38
514 46
515 59
516 56
517 58
518 68
519 65
520 91
521 87
522 101
523 115
524 92
525 114
526 140
527 119
528 129
529 138
530 145
531 123
532 143
533 123
534 159
535 147
536 151
537 140
538 153
539 159
540 114
541 112
542 110
543 124
544 116
545 123
546 108
547 94
548 110
549 80
550 86
551 77
552 68
553 89
554 66
555 46
556 40
557 54
558 41
559 34
560 42
561 44
562 26
563 26
564 24
565 27
566 23
567 20
568 11
569 12
570 20
571 10
572 6
573 13
574 8
575 5
576 3
577 4
578 0
579 1
580 3
581 0
582 3
583 1
584 4
585 0
586 0
587 0
588 4
589 1
590 0
591 0
592 0
593 0
594 0
595 0
596 0
597 2
598 3
599 2
600 0
601 0
602 2
603 5
604 5
605 1
606 5
607 12
608 19
609 16
610 24
611 22
612 33
613 30
614 36
615 33
616 40
617 63
618 54
619 52
620 68
621 73
622 75
623 85
624 90
625 117
626 121
627 116
628 109
629 130
630 142
631 160
632 174
633 153
634 160
635 165
636 192
637 171
638 169
639 187
640 210
641 200
642 212
643 187
644 177
645 191
646 201
647 194
648 158
649 183
650 203
651 182
652 161
653 154
654 154
655 153
656 120
657 120
658 115
659 102
660 122
661 87
662 102
663 93
664 84
665 87
666 75
667 58
668 63
669 62
670 54
671 37
672 43
673 34
674 32
675 24
676 33
677 20
678 12
679 13
680 14
681 11
682 7
683 12
684 5
685 4
686 3
687 3
688 4
689 2
690 2
691 3
692 2
693 0
694 1
695 3
696 1
697 0
698 1
699 1
700 0
701 2
702 1
703 2
704 0
705 2
706 5
707 7
708 5
709 11
710 11
711 8
712 10
713 15
714 15
715 19
716 19
717 18
718 30
719 32
720 27
721 41
722 46
723 59
724 71
725 53
726 59
727 76
728 87
729 72
730 115
731 102
732 135
733 109
734 137
735 133
736 129
737 129
738 174
739 177
740 155
741 167
742 189
743 164
744 187
745 212
746 172
747 194
748 183
749 183
750 170
751 180
752 199
753 199
754 172
755 185
756 160
757 159
758 163
759 163
760 163
761 132
762 118
763 127
764 142
765 113
766 119
767 136
768 102
769 105
770 106
771 93
772 73
773 66
774 65
775 68
776 45
777 61
778 59
779 47
780 38
781 31
782 40
783 34
784 26
785 17
786 21
787 20
788 16
789 11
790 16
791 13
792 6
793 8
794 5
795 2
796 5
797 4
798 4
799 3
800 2
801 3
802 5
803 1
804 2
805 1
806 4
807 2
808 5
809 2
810 7
811 2
812 5
813 8
814 8
815 7
816 9
817 10
818 10
819 18
820 11
821 19
822 17
823 25
824 33
825 30
826 38
827 37
828 42
829 49
830 42
831 50
832 62
833 90
834 57
835 71
836 70
837 81
838 94
839 83
840 93
841 105
842 93
843 110
844 124
845 117
846 142
847 133
848 125
849 127
850 125
851 146
852 155
853 156
854 141
855 143
856 167
857 158
858 135
859 149
860 147
861 145
862 135
863 142
864 139
865 133
866 117
867 119
868 124
869 114
870 121
871 117
872 91
873 91
874 88
875 78
876 94
877 64
878 74
879 70
880 56
881 71
882 63
883 49
884 47
885 28
886 40
887 29
888 23
889 24
890 29
891 17
892 18
893 16
894 18
895 15
896 12
897 15
898 18
899 8
900 7
901 6
902 3
903 3
904 1
905 3
906 2
907 3
908 5
909 4
910 3
911 1
912 2
913 2
914 2
915 2
916 3
917 4
918 1
919 1
920 5
921 4
922 2
923 5
924 6
925 11
926 6
927 5
928 9
929 7
930 19
931 16
932 24
933 30
934 18
935 28
936 19
937 35
938 32
939 30
940 44
941 39
942 37
943 52
944 50
945 73
946 60
947 67
948 59
949 66
950 60
951 70
952 67
953 70
954 74
955 82
956 91
957 78
958 74
959 78
960 84
961 72
962 89
963 73
964 93
965 72
966 91
967 85
968 82
969 83
970 70
971 74
972 83
973 53
974 71
975 66
976 83
977 54
978 68
979 59
980 43
981 49
982 34
983 43
984 33
985 34
986 49
987 30
988 28
989 28
990 34
991 24
992 21
993 26
994 22
995 18
996 22
997 15
998 16
999 17
1000 9
1001 8
1002 8
1003 11
1004 9
1005 5
1006 11
1007 6
1008 3
1009 9
1010 5
1011 3
1012 2
1013 5
1014 3
1015 4
1016 0
1017 4
1018 0
1019 4
1020 2
1021 3
1022 5
1023 4
1024 4
1025 1
1026 5
1027 4
1028 7
1029 7
1030 6
1031 7
1032 9
1033 5
1034 7
1035 6
1036 13
1037 12
1038 9
1039 8
1040 13
1041 21
1042 12
1043 20
1044 15
1045 31
1046 27
1047 14
1048 28
1049 33
1050 30
1051 33
1052 31
1053 38
1054 50
1055 29
1056 39
1057 30
1058 50
1059 47
1060 50
1061 48
1062 45
1063 50
1064 55
1065 38
1066 52
1067 47
1068 53
1069 44
1070 57
1071 46
1072 57
1073 60
1074 60
1075 49
1076 54
1077 63
1078 40
1079 54
1080 41
1081 51
1082 43
1083 39
1084 50
1085 32
1086 37
1087 36
1088 29
1089 28
1090 36
1091 25
1092 33
1093 27
1094 29
1095 22
1096 26
1097 28
1098 17
1099 17
1100 24
1101 11
1102 13
1103 11
1104 4
1105 8
1106 16
1107 7
1108 17
1109 7
1110 9
1111 9
1112 4
1113 7
1114 4
1115 5
1116 3
1117 6
1118 6
1119 3
1120 4
1121 3
1122 4
1123 2
1124 1
1125 5
1126 3
1127 3
1128 3
1129 3
1130 0
1131 4
1132 2
1133 4
1134 2
1135 5
1136 4
1137 6
1138 4
1139 7
1140 4
1141 5
1142 8
1143 5
1144 6
1145 7
1146 10
1147 11
1148 8
1149 9
1150 14
1151 11
1152 16
1153 14
1154 16
1155 26
1156 15
1157 17
1158 19
1159 15
1160 18
1161 22
1162 25
1163 23
1164 28
1165 20
1166 17
1167 20
1168 21
1169 34
1170 35
1171 20
1172 25
1173 28
1174 31
1175 32
1176 23
1177 24
1178 22
1179 33
1180 25
1181 36
1182 26
1183 29
1184 37
1185 34
1186 21
1187 21
1188 26
1189 24
1190 24
1191 21
1192 20
1193 27
1194 29
1195 24
1196 19
1197 25
1198 21
1199 13
1200 15
1201 13
1202 19
1203 13
1204 18
1205 9
1206 12
1207 14
1208 4
1209 11
1210 11
1211 6
1212 6
1213 8
1214 4
1215 4
1216 4
1217 5
1218 3
1219 5
1220 4
1221 3
1222 5
1223 3
1224 3
1225 5
1226 5
1227 0
1228 2
1229 4
1230 1
1231 2
1232 4
1233 1
1234 2
1235 4
1236 5
1237 3
1238 3
1239 4
1240 2
1241 4
1242 6
1243 5
1244 3
1245 1
1246 8
1247 4
1248 3
1249 6
1250 9
1251 6
1252 5
1253 5
1254 10
1255 10
1256 6
1257 5
1258 10
1259 6
1260 7
1261 11
1262 9
1263 12
1264 13
1265 15
1266 8
1267 10
1268 16
1269 16
1270 14
1271 14
1272 10
1273 16
1274 13
1275 15
1276 12
1277 15
1278 14
1279 24
1280 15
1281 13
1282 19
1283 19
1284 19
1285 23
1286 21
1287 13
1288 17
1289 14
1290 17
1291 14
1292 14
1293 12
1294 13
1295 16
1296 17
1297 13
1298 17
1299 16
1300 9
1301 12
1302 7
1303 15
1304 9
1305 17
1306 11
1307 10
1308 1
1309 10
1310 10
1311 5
1312 4
1313 7
1314 7
1315 13
1316 4
1317 2
1318 9
1319 7
1320 2
1321 3
1322 3
1323 8
1324 2
1325 2
1326 2
1327 5
1328 2
1329 3
1330 3
1331 0
1332 2
1333 2
1334 5
1335 2
1336 2
1337 1
1338 3
1339 5
1340 2
1341 2
1342 2
1343 3
1344 2
1345 2
1346 1
1347 5
1348 1
1349 5
1350 1
1351 3
1352 0
1353 2
1354 2
1355 3
1356 6
1357 1
1358 6
1359 5
1360 4
1361 6
1362 13
1363 4
1364 9
1365 8
1366 7
1367 6
1368 10
1369 5
1370 8
1371 5
1372 3
1373 10
1374 11
1375 11
1376 12
1377 7
1378 16
1379 13
1380 2
1381 10
1382 15
1383 8
1384 9
1385 12
1386 8
1387 12
1388 4
1389 9
1390 8
1391 11
1392 13
1393 9
1394 11
1395 11
1396 7
1397 8
1398 9
1399 10
1400 13
1401 11
1402 13
1403 8
1404 8
1405 10
1406 3
1407 10
1408 6
1409 10
1410 10
1411 3
1412 6
1413 3
1414 7
1415 3
1416 3
1417 8
1418 5
1419 4
1420 5
1421 3
1422 4
1423 2
1424 3
1425 3
1426 2
1427 5
1428 6
1429 3
1430 2
1431 3
1432 3
1433 0
1434 1
1435 1
1436 1
1437 2
1438 2
1439 0
1440 2
1441 0
1442 3
1443 2
1444 0
1445 2
1446 1
1447 1
1448 3
1449 3
1450 2
1451 2
1452 6
1453 4
1454 3
1455 3
1456 1
1457 4
1458 1
1459 1
1460 2
1461 3
1462 2
1463 1
1464 3
1465 5
1466 5
1467 5
1468 2
1469 2
1470 2
1471 5
1472 2
1473 6
1474 3
1475 3
1476 1
1477 6
1478 1
1479 3
1480 1
1481 4
1482 7
1483 3
1484 7
1485 2
1486 11
1487 4
1488 8
1489 4
1490 6
1491 6
1492 6
1493 4
1494 4
1495 4
1496 7
1497 5
1498 3
1499 6
1500 13
1501 3
1502 7
1503 4
1504 9
1505 9
1506 2
1507 5
1508 4
1509 9
1510 4
1511 7
1512 6
1513 6
1514 5
1515 5
1516 6
1517 6
1518 3
1519 3
1520 7
1521 5
1522 3
1523 4
1524 1
1525 2
1526 3
1527 7
1528 2
1529 3
1530 4
1531 3
1532 1
1533 1
1534 2
1535 2
1536 3
1537 2
1538 2
1539 0
1540 0
1541 0
1542 2
1543 1
1544 2
1545 0
1546 3
1547 0
1548 1
1549 1
1550 1
1551 2
1552 0
1553 0
1554 0
1555 0
1556 0
1557 0
1558 0
1559 3
1560 0
1561 1
1562 0
1563 2
1564 1
1565 0
1566 0
1567 1
1568 1
1569 1
1570 1
1571 0
1572 1
1573 1
1574 0
1575 2
1576 0
1577 0
1578 0
1579 0
1580 1
1581 2
1582 0
1583 0
1584 0
1585 0
1586 1
1587 0
1588 0
1589 1
1590 0
1591 0
1592 1
1593 0
1594 0
1595 0
1596 1
1597 2
1598 1
1599 0
1600 0
1601 0
1602 0
1603 0
1604 0
1605 1
1606 0
1607 0
1608 1
1609 0
1610 0
1611 0
1612 2
1613 1
1614 2
1615 0
1616 0
1617 0
1618 2
1619 1
1620 0
1621 1
1622 1
1623 0
1624 0
1625 1
1626 0
1627 1
1628 0
1629 0
1630 0
1631 0
1632 0
1633 0
1634 0
1635 1
1636 0
1637 1
1638 0
1639 0
1640 0
1641 1
1642 0
1643 0
1644 0
1645 0
1646 0
1647 1
1648 0
1649 0
1650 0
1651 0
1652 1
1653 1
1654 0
1655 0
1656 0
1657 1
1658 0
1659 1
1660 0
1661 3
1662 0
1663 1
1664 0
1665 0
1666 0
1667 2
1668 1
1669 0
1670 1
1671 0
1672 0
1673 3
1674 0
1675 1
1676 2
1677 0
1678 0
1679 0
1680 0
1681 0
1682 0
1683 1
1684 0
1685 0
1686 0
1687 1
1688 0
1689 0
1690 0
1691 0
1692 0
1693 1
1694 0
1695 1
1696 0
1697 1
1698 2
1699 0
1700 0
1701 0
1702 0
1703 2
1704 1
1705 0
1706 0
1707 0
1708 0
1709 0
1710 0
1711 0
1712 1
1713 0
1714 0
1715 1
1716 0
1717 0
1718 0
1719 1
1720 0
1721 0
1722 1
1723 0
1724 0
1725 1
1726 1
1727 0
1728 0
1729 1
1730 0
1731 0
1732 0
1733 0
1734 0
1735 0
1736 1
1737 0
1738 1
1739 0
1740 0
1741 0
1742 1
1743 0
1744 0
1745 0
1746 2
1747 1
1748 0
1749 1
1750 0
1751 0
1752 0
1753 0
1754 0
1755 1
1756 0
1757 0
1758 0
1759 0
1760 0
1761 0
1762 0
1763 0
1764 0
1765 0
1766 1
1767 0
1768 2
1769 0
1770 1
1771 0
1772 1
1773 2
1774 0
1775 1
1776 0
1777 0
1778 1
1779 0
1780 2
1781 0
1782 0
1783 1
1784 0
1785 1
1786 0
1787 1
1788 0
1789 2
1790 0
1791 1
1792 0
1793 0
1794 0
1795 0
1796 0
1797 0
1798 0
1799 0
1800 0
1801 0
1802 0
1803 0
1804 0
1805 1
1806 0
1807 0
1808 0
1809 0
1810 0
1811 0
1812 0
1813 0
1814 0
1815 0
1816 1
1817 1
1818 0
1819 0
1820 0
1821 0
1822 0
1823 0
1824 0
1825 0
1826 0
1827 0
1828 1
1829 0
1830 1
1831 0
1832 0
1833 0
1834 0
1835 1
1836 1
1837 0
1838 2
1839 0
1840 0
1841 0
1842 0
1843 1
1844 0
1845 0
1846 0
1847 0
1848 0
1849 0
1850 0
1851 0
1852 2
1853 0
1854 1
1855 0
1856 0
1857 0
1858 0
1859 0
1860 0
1861 0
1862 0
1863 0
1864 1
1865 0
1866 0
1867 0
1868 0
1869 0
1870 0
1871 1
1872 0
1873 0
1874 0
1875 0
1876 1
1877 0
1878 0
1879 0
1880 0
1881 0
1882 0
1883 0
1884 0
1885 0
1886 0
1887 0
1888 0
1889 0
1890 0
1891 0
1892 0
1893 0
1894 0
1895 1
1896 0
1897 0
1898 0
1899 0
1900 0
1901 0
1902 1
1903 0
1904 0
1905 1
1906 0
1907 0
1908 0
1909 0
1910 0
1911 1
1912 0
1913 1
1914 0
1915 0
1916 1
1917 0
1918 1
1919 0
1920 0
1921 1
1922 0
1923 0
1924 0
1925 0
1926 0
1927 0
1928 0
1929 0
1930 0
1931 1
1932 1
1933 0
1934 0
1935 0
1936 0
1937 1
1938 0
1939 1
1940 0
1941 0
1942 2
1943 0
1944 1
1945 1
1946 0
1947 0
1948 1
1949 0
1950 0
1951 1
1952 0
1953 1
1954 0
1955 0
1956 0
1957 1
1958 0
1959 0
1960 1
1961 0
1962 0
1963 1
1964 0
1965 0
1966 0
1967 1
1968 0
1969 0
1970 2
1971 0
1972 0
1973 1
1974 0
1975 0
1976 0
1977 0
1978 0
1979 1
1980 0
1981 2
1982 0
1983 1
1984 0
1985 0
1986 1
1987 0
1988 1
1989 1
1990 1
1991 0
1992 0
1993 0
1994 0
1995 0
1996 0
1997 0
1998 0
1999 0
2000 1
2001 0
2002 1
2003 1
2004 0
2005 2
2006 0
2007 0
2008 0
2009 0
2010 0
2011 0
2012 0
2013 0
2014 0
2015 1
2016 0
2017 1
2018 0
2019 0
2020 0
2021 0
2022 0
2023 0
2024 1
2025 1
2026 0
2027 0
2028 0
2029 0
2030 1
2031 0
2032 0
2033 2
2034 1
2035 2
2036 0
2037 0
2038 0
2039 1
2040 0
2041 0
2042 0
2043 0
2044 0
2045 0
2046 0
2047 0
2048 0
2049 0
2050 1
2051 0
2052 0
2053 1
2054 0
2055 0
2056 0
2057 0
2058 0
2059 0
2060 0
2061 0
2062 0
2063 0
2064 0
2065 1
2066 0
2067 0
2068 0
2069 0
2070 1
2071 0
2072 0
2073 0
2074 0
2075 0
2076 0
2077 0
2078 0
2079 1
2080 0
2081 0
2082 0
2083 0
2084 0
2085 0
2086 0
2087 0
2088 0
2089 2
2090 0
2091 0
2092 0
2093 1
2094 1
2095 0
2096 0
2097 0
2098 0
2099 1
2100 0
2101 0
2102 0
2103 0
2104 0
2105 1
2106 0
2107 0
2108 0
2109 0
2110 0
2111 1
2112 0
2113 0
2114 0
2115 0
2116 0
2117 0
2118 0
2119 0
2120 0
2121 1
2122 0
2123 0
2124 0
2125 0
2126 0
2127 0
2128 1
2129 0
2130 1
2131 0
2132 1
2133 0
2134 0
2135 0
2136 0
2137 0
2138 1
2139 1
2140 0
2141 0
2142 0
2143 0
2144 0
2145 1
2146 0
2147 0
2148 0
2149 0
2150 0
2151 0
2152 0
2153 0
2154 1
2155 0
2156 0
2157 0
2158 0
2159 1
2160 0
2161 0
2162 0
2163 0
2164 0
2165 0
2166 0
2167 0
2168 1
2169 0
2170 0
2171 1
2172 0
2173 0
2174 0
2175 0
2176 0
2177 0
2178 0
2179 0
2180 0
2181 0
2182 0
2183 0
2184 0
2185 0
2186 0
2187 0
2188 0
2189 0
2190 0
2191 0
2192 0
2193 0
2194 0
2195 0
2196 0
2197 1
2198 0
2199 0
2200 0
2201 0
2202 0
2203 0
2204 0
2205 0
2206 0
2207 0
2208 0
2209 0
2210 0
2211 1
2212 1
2213 0
2214 0
2215 0
2216 0
2217 1
2218 0
2219 0
2220 0
2221 0
2222 0
2223 0
2224 0
2225 0
2226 1
2227 0
2228 0
2229 1
2230 0
2231 0
2232 0
2233 0
2234 0
2235 1
2236 0
2237 0
2238 0
2239 0
2240 0
2241 0
2242 1
2243 0
2244 0
2245 1
2246 0
2247 0
2248 0
2249 0
2250 0
2251 0
2252 0
2253 1
2254 0
2255 0
2256 0
2257 0
2258 0
2259 0
2260 0
2261 0
2262 0
2263 0
2264 0
2265 0
2266 0
2267 0
2268 0
2269 0
2270 0
2271 0
2272 0
2273 0
2274 2
2275 0
2276 0
2277 0
2278 0
2279 0
2280 0
2281 0
2282 0
2283 0
2284 0
2285 0
2286 0
2287 0
2288 0
2289 0
2290 0
2291 1
2292 0
2293 1
2294 0
2295 0
2296 1
2297 0
2298 0
2299 0
2300 0
2301 0
2302 1
2303 0
2304 0
2305 0
2306 0
2307 0
2308 0
2309 0
2310 0
2311 0
2312 1
2313 2
2314 0
2315 0
2316 0
2317 0
2318 0
2319 0
2320 0
2321 0
2322 0
2323 0
2324 0
2325 0
2326 0
2327 0
2328 0
2329 0
2330 0
2331 0
2332 0
2333 0
2334 0
2335 0
2336 0
2337 0
2338 0
2339 0
2340 0
2341 0
2342 1
2343 0
2344 0
2345 0
2346 0
2347 0
2348 0
2349 1
2350 0
2351 0
2352 0
2353 0
2354 0
2355 0
2356 0
2357 0
2358 0
2359 0
2360 0
2361 0
2362 0
2363 0
2364 1
2365 0
2366 0
2367 0
2368 0
2369 0
2370 0
2371 0
2372 0
2373 0
2374 0
2375 0
2376 0
2377 0
2378 0
2379 1
2380 0
2381 0
2382 1
2383 0
2384 1
2385 0
2386 0
2387 0
2388 0
2389 0
2390 0
2391 0
2392 0
2393 0
2394 0
2395 0
2396 0
2397 0
2398 0
2399 0
2400 0
2401 0
2402 0
2403 0
2404 0
2405 0
2406 0
2407 0
2408 0
2409 0
2410 0
2411 0
2412 0
2413 0
2414 0
2415 0
2416 0
2417 0
2418 0
2419 0
2420 0
2421 0
2422 0
2423 0
2424 0
2425 0
2426 0
2427 0
2428 0
2429 0
2430 0
2431 0
2432 0
2433 0
2434 0
2435 0
2436 1
2437 0
2438 0
2439 0
2440 1
2441 0
2442 0
2443 1
2444 0
2445 0
2446 0
2447 1
2448 0
2449 0
2450 0
2451 0
2452 0
2453 0
2454 0
2455 0
2456 0
2457 0
2458 0
2459 0
2460 0
2461 0
2462 0
2463 0
2464 0
2465 0
2466 0
2467 0
2468 0
2469 0
2470 0
2471 1
2472 0
2473 0
2474 0
2475 0
2476 0
2477 1
2478 0
2479 0
2480 0
2481 0
2482 0
2483 0
2484 0
2485 0
2486 0
2487 0
2488 0
2489 0
2490 0
2491 0
2492 0
2493 0
2494 0
2495 0
2496 0
2497 0
2498 0
2499 0
2500 0
2501 0
2502 0
2503 0
2504 0
2505 0
2506 0
2507 0
2508 0
2509 0
2510 0
2511 0
2512 0
2513 0
2514 0
2515 0
2516 0
2517 0
2518 0
2519 0
2520 0
2521 0
2522 0
2523 0
2524 0
2525 0
2526 0
2527 0
2528 0
2529 0
2530 0
2531 0
2532 0
2533 0
2534 0
2535 0
2536 0
2537 0
2538 0
2539 0
2540 0
2541 0
2542 0
2543 0
2544 0
2545 0
2546 0
2547 0
2548 0
2549 0
2550 1
2551 0
2552 0
2553 0
2554 0
2555 0
2556 0
2557 0
2558 0
2559 0
2560 0
2561 0
2562 0
2563 0
2564 0
2565 0
2566 0
2567 0
2568 0
2569 0
2570 0
2571 0
2572 0
2573 0
2574 0
2575 0
2576 1
2577 0
2578 0
2579 0
2580 0
2581 0
2582 0
2583 0
2584 0
2585 0
2586 0
2587 0
2588 0
2589 0
2590 0
2591 0
2592 0
2593 0
2594 0
2595 0
2596 0
2597 0
2598 0
2599 0
2600 0
2601 0
2602 0
2603 0
2604 0
2605 0
2606 0
2607 0
2608 0
2609 0
2610 0
2611 0
2612 0
2613 0
2614 0
2615 0
2616 0
2617 0
2618 0
2619 0
2620 0
2621 0
2622 0
2623 0
2624 0
2625 0
2626 0
2627 0
2628 0
2629 0
2630 0
2631 0
2632 0
2633 0
2634 0
2635 0
2636 0
2637 0
2638 0
2639 0
2640 0
2641 0
2642 0
2643 0
2644 0
2645 0
2646 0
2647 0
2648 0
2649 0
2650 0
2651 0
2652 0
2653 0
2654 0
2655 0
2656 0
2657 0
2658 0
2659 0
2660 0
2661 0
2662 0
2663 0
2664 0
2665 1
2666 0
2667 1
2668 0
2669 0
2670 0
2671 0
2672 0
2673 0
2674 0
2675 0
2676 0
2677 0
2678 0
2679 0
2680 0
2681 0
2682 0
2683 0
2684 0
2685 0
2686 0
2687 0
2688 0
2689 0
2690 0
2691 0
2692 0
2693 0
2694 0
2695 0
2696 0
2697 0
2698 0
2699 0
2700 0
2701 0
2702 0
2703 0
2704 0
2705 0
2706 0
2707 0
2708 0
2709 0
2710 0
2711 0
2712 0
2713 0
2714 0
2715 0
2716 1
2717 0
2718 0
2719 0
2720 0
2721 0
2722 0
2723 0
2724 0
2725 0
2726 0
2727 0
2728 0
2729 0
2730 0
2731 0
2732 0
2733 0
2734 0
2735 0
2736 0
2737 0
2738 0
2739 0
2740 0
2741 0
2742 0
2743 0
2744 0
2745 0
2746 0
2747 0
2748 0
2749 0
2750 0
2751 0
2752 0
2753 0
2754 0
2755 0
2756 0
2757 0
2758 0
2759 0
2760 0
2761 1
2762 0
2763 0
2764 0
2765 0
2766 0
2767 0
2768 0
2769 0
2770 0
2771 0
2772 0
2773 0
2774 0
2775 0
2776 0
2777 0
2778 0
2779 0
2780 0
2781 0
2782 0
2783 0
2784 0
2785 0
2786 0
2787 0
2788 0
2789 0
2790 0
2791 0
2792 0
2793 0
2794 0
2795 0
2796 0
2797 0
2798 0
2799 0
2800 0
2801 0
2802 0
2803 0
2804 0
2805 0
2806 0
2807 0
2808 0
2809 0
2810 0
2811 0
2812 0
2813 0
2814 0
2815 0
2816 0
2817 0
2818 0
2819 1
2820 0
2821 0
2822 0
2823 0
2824 0
2825 0
2826 0
2827 0
2828 0
2829 0
2830 0
2831 0
2832 0
2833 0
2834 0
2835 0
2836 0
2837 0
2838 0
2839 0
2840 0
2841 0
2842 0
2843 0
2844 0
2845 0
2846 0
2847 0
2848 0
2849 0
2850 0
2851 0
2852 0
2853 0
2854 0
2855 0
2856 0
2857 0
2858 0
2859 1
2860 0
2861 0
2862 0
2863 0
2864 0
2865 0
2866 0
2867 0
2868 0
2869 0
2870 0
2871 0
2872 0
2873 0
2874 0
2875 0
2876 0
2877 0
2878 0
2879 0
2880 0
2881 0
2882 0
2883 0
2884 0
2885 0
2886 0
2887 0
2888 0
2889 0
2890 0
2891 0
2892 0
2893 0
2894 0
2895 0
2896 0
2897 0
2898 0
2899 0
2900 0
2901 0
2902 0
2903 0
2904 0
2905 0
2906 0
2907 0
2908 0
2909 0
2910 0
2911 0
2912 0
2913 0
2914 0
2915 0
2916 0
2917 0
2918 0
2919 0
2920 0
2921 0
2922 0
2923 0
2924 0
2925 0
2926 0
2927 0
2928 0
2929 0
2930 0
2931 0
2932 0
2933 0
2934 0
2935 0
2936 0
2937 0
2938 0
2939 0
2940 0
2941 0
2942 0
2943 0
2944 0
2945 0
2946 0
2947 0
2948 0
2949 0
2950 0
2951 0
2952 0
2953 0
2954 0
2955 0
2956 0
2957 0
2958 0
2959 0
2960 0
2961 0
2962 0
2963 0
2964 0
2965 1
2966 0
2967 0
2968 0
2969 0
2970 0
2971 0
2972 0
2973 0
2974 0
2975 0
2976 0
2977 0
2978 0
2979 0
2980 0
2981 0
2982 0
2983 0
2984 0
2985 0
2986 0
2987 0
2988 0
2989 0
2990 0
2991 0
2992 0
2993 0
2994 0
2995 0
2996 0
2997 0
2998 0
2999 0
3000 0
3001 0
3002 0
3003 0
3004 0
3005 0
3006 0
3007 0
3008 0
3009 0
3010 0
3011 0
3012 0
3013 0
3014 0
3015 0
3016 0
3017 0
3018 0
3019 0
3020 0
3021 0
3022 0
3023 0
3024 0
3025 0
3026 0
3027 0
3028 0
3029 0
3030 0
3031 0
3032 0
3033 0
3034 0
3035 0
3036 0
3037 0
3038 0
3039 0
3040 0
3041 0
3042 0
3043 0
3044 0
3045 0
3046 0
3047 0
3048 0
3049 0
3050 0
3051 0
3052 0
3053 0
3054 0
3055 0
3056 0
3057 0
3058 0
3059 0
3060 0
3061 0
3062 0
3063 0
3064 0
3065 0
3066 0
3067 0
3068 0
3069 0
3070 0
3071 0
3072 0
3073 0
3074 0
3075 0
3076 0
3077 0
3078 0
3079 0
3080 1
3081 0
3082 0
3083 0
3084 0
3085 0
3086 0
3087 0
3088 0
3089 0
3090 0
3091 0
3092 0
3093 0
3094 0
3095 0
3096 0
3097 0
3098 0
3099 0
3100 0
3101 0
3102 0
3103 0
3104 0
3105 0
3106 0
3107 0
3108 0
3109 0
3110 0
3111 0
3112 0
3113 0
3114 0
3115 0
3116 0
3117 0
3118 0
3119 0
3120 0
3121 0
3122 0
3123 0
3124 0
3125 0
3126 0
3127 0
3128 0
3129 0
3130 0
3131 0
3132 0
3133 0
3134 0
3135 0
3136 0
3137 0
3138 0
3139 0
3140 0
3141 0
3142 0
3143 0
3144 0
3145 0
3146 0
3147 0
3148 0
3149 0
3150 0
3151 0
3152 0
3153 0
3154 0
3155 0
3156 0
3157 0
3158 0
3159 0
3160 0
3161 0
3162 0
3163 0
3164 0
3165 0
3166 0
3167 0
3168 0
3169 0
3170 0
3171 0
3172 0
3173 0
3174 0
3175 0
3176 0
3177 0
3178 0
3179 0
3180 0
3181 0
3182 0
3183 0
3184 0
3185 0
3186 0
3187 0
3188 0
3189 0
3190 0
3191 0
3192 0
3193 0
3194 0
3195 0
3196 0
3197 0
3198 0
3199 0
3200 0
3201 0
3202 0
3203 0
3204 0
3205 0
3206 0
3207 0
3208 0
3209 0
3210 0
3211 0
3212 0
3213 0
3214 0
3215 0
3216 0
3217 0
3218 0
3219 0
3220 0
3221 0
3222 0
3223 0
3224 0
3225 0
3226 0
3227 0
3228 0
3229 0
3230 0
3231 0
3232 0
3233 0
3234 0
3235 0
3236 0
3237 0
3238 0
3239 0
3240 0
3241 0
3242 0
3243 0
3244 0
3245 0
3246 0
3247 0
3248 0
3249 0
3250 0
3251 0
3252 0
3253 0
3254 0
3255 0
3256 0
3257 0
3258 0
3259 0
3260 0
3261 0
3262 0
3263 0
3264 0
3265 0
3266 0
3267 0
3268 0
3269 0
3270 0
3271 0
3272 0
3273 0
3274 0
3275 0
3276 0
3277 0
3278 0
3279 0
3280 0
3281 0
3282 0
3283 0
3284 0
3285 0
3286 0
3287 0
3288 0
3289 0
3290 0
3291 0
3292 0
3293 0
3294 0
3295 0
3296 0
3297 0
3298 0
3299 0
3300 0
3301 0
3302 0
3303 0
3304 0
3305 0
3306 0
3307 0
3308 0
3309 0
3310 0
3311 0
3312 0
3313 0
3314 0
3315 0
3316 0
3317 0
3318 0
3319 0
3320 0
3321 0
3322 0
3323 0
3324 0
3325 0
3326 0
3327 0
3328 0
3329 0
3330 0
3331 0
3332 0
3333 0
3334 0
3335 0
3336 0
3337 0
3338 0
3339 0
3340 0
3341 0
3342 0
3343 0
3344 0
3345 0
3346 0
3347 0
3348 0
3349 0
3350 0
3351 0
3352 0
3353 0
3354 0
3355 0
3356 0
3357 0
3358 0
3359 0
3360 0
3361 0
3362 0
3363 0
3364 0
3365 0
3366 0
3367 0
3368 0
3369 0
3370 0
3371 0
3372 0
3373 0
3374 0
3375 0
3376 0
3377 0
3378 0
3379 0
3380 0
3381 0
3382 0
3383 0
3384 0
3385 0
3386 0
3387 0
3388 0
3389 0
3390 0
3391 0
3392 0
3393 0
3394 0
3395 0
3396 0
3397 0
3398 0
3399 0
3400 0
3401 0
3402 0
3403 0
3404 0
3405 0
3406 0
3407 0
3408 0
3409 0
3410 0
3411 0
3412 0
3413 0
3414 0
3415 0
3416 0
3417 0
3418 0
3419 0
3420 0
3421 0
3422 0
3423 0
3424 0
3425 0
3426 0
3427 0
3428 0
3429 0
3430 0
3431 0
3432 0
3433 0
3434 0
3435 0
3436 0
3437 0
3438 0
3439 0
3440 0
3441 0
3442 0
3443 0
3444 0
3445 0
3446 0
3447 0
3448 0
3449 0
3450 0
3451 0
3452 0
3453 0
3454 0
3455 0
3456 0
3457 0
3458 0
3459 0
3460 0
3461 0
3462 0
3463 0
3464 0
3465 0
3466 0
3467 0
3468 0
3469 0
3470 0
3471 0
3472 0
3473 0
3474 0
3475 0
3476 0
3477 0
3478 0
3479 0
3480 0
3481 0
3482 0
3483 0
3484 0
3485 0
3486 0
3487 0
3488 0
3489 0
3490 0
3491 0
3492 0
3493 0
3494 0
3495 0
3496 0
3497 0
3498 0
3499 0
3500 0
3501 0
3502 0
3503 0
3504 0
3505 0
3506 0
3507 0
3508 0
3509 0
3510 0
3511 0
3512 0
3513 0
3514 0
3515 0
3516 0
3517 0
3518 0
3519 0
3520 0
3521 0
3522 0
3523 0
3524 0
3525 0
3526 0
3527 0
3528 0
3529 0
3530 0
3531 0
3532 0
3533 0
3534 0
3535 0
3536 0
3537 0
3538 0
3539 0
3540 0
3541 0
3542 0
3543 0
3544 0
3545 0
3546 0
3547 0
3548 0
3549 0
3550 0
3551 0
3552 0
3553 0
3554 0
3555 0
3556 0
3557 0
3558 0
3559 0
3560 0
3561 0
3562 0
3563 0
3564 0
3565 0
3566 0
3567 0
3568 0
3569 0
3570 0
3571 0
3572 0
3573 0
3574 0
3575 0
3576 0
3577 0
3578 0
3579 0
3580 0
3581 0
3582 0
3583 0
3584 0
3585 0
3586 0
3587 0
3588 0
3589 0
3590 0
3591 0
3592 0
3593 0
3594 0
3595 0
3596 0
3597 0
3598 0
3599 0
3600 0
3601 0
3602 0
3603 0
3604 0
3605 0
3606 0
3607 0
3608 0
3609 0
3610 0
3611 0
3612 0
3613 0
3614 0
3615 0
3616 0
3617 0
3618 0
3619 0
3620 0
3621 0
3622 0
3623 0
3624 0
3625 0
3626 0
3627 0
3628 0
3629 0
3630 0
3631 0
3632 0
3633 0
3634 0
3635 0
3636 0
3637 0
3638 0
3639 0
3640 0
3641 0
3642 0
3643 0
3644 0
3645 0
3646 0
3647 0
3648 0
3649 0
3650 0
3651 0
3652 0
3653 0
3654 0
3655 0
3656 0
3657 0
3658 0
3659 0
3660 0
3661 0
3662 0
3663 0
3664 0
3665 0
3666 0
3667 0
3668 0
3669 0
3670 0
3671 0
3672 0
3673 0
3674 0
3675 0
3676 0
3677 0
3678 0
3679 0
3680 0
3681 0
3682 0
3683 0
3684 0
3685 0
3686 0
3687 0
3688 0
3689 0
3690 0
3691 0
3692 0
3693 0
3694 0
3695 0
3696 0
3697 0
3698 0
3699 0
3700 0
3701 0
3702 0
3703 0
3704 0
3705 0
3706 0
3707 0
3708 0
3709 0
3710 0
3711 0
3712 0
3713 0
3714 0
3715 0
3716 0
3717 0
3718 0
3719 0
3720 0
3721 0
3722 0
3723 0
3724 0
3725 0
3726 0
3727 0
3728 0
3729 0
3730 0
3731 0
3732 0
3733 0
3734 0
3735 0
3736 0
3737 0
3738 0
3739 0
3740 0
3741 0
3742 0
3743 0
3744 0
3745 0
3746 0
3747 0
3748 0
3749 0
3750 0
3751 0
3752 0
3753 0
3754 0
3755 0
3756 0
3757 0
3758 0
3759 0
3760 0
3761 0
3762 0
3763 0
3764 0
3765 0
3766 0
3767 0
3768 0
3769 0
3770 0
3771 0
3772 0
3773 0
3774 0
3775 0
3776 0
3777 0
3778 0
3779 0
3780 0
3781 0
3782 0
3783 0
3784 0
3785 0
3786 0
3787 0
3788 0
3789 0
3790 0
3791 0
3792 0
3793 0
3794 0
3795 0
3796 0
3797 0
3798 0
3799 0
3800 0
3801 0
3802 0
3803 0
3804 0
3805 0
3806 0
3807 0
3808 0
3809 0
3810 0
3811 0
3812 0
3813 0
3814 0
3815 0
3816 0
3817 0
3818 0
3819 0
3820 0
3821 0
3822 0
3823 0
3824 0
3825 0
3826 0
3827 0
3828 0
3829 0
3830 0
3831 0
3832 0
3833 0
3834 0
3835 0
3836 0
3837 0
3838 0
3839 0
3840 0
3841 0
3842 0
3843 0
3844 0
3845 0
3846 0
3847 0
3848 0
3849 0
3850 0
3851 0
3852 0
3853 0
3854 0
3855 0
3856 0
3857 0
3858 0
3859 0
3860 0
3861 0
3862 0
3863 0
3864 0
3865 0
3866 0
3867 0
3868 0
3869 0
3870 0
3871 0
3872 0
3873 0
3874 0
3875 0
3876 0
3877 0
3878 0
3879 0
3880 0
3881 0
3882 0
3883 0
3884 0
3885 0
3886 0
3887 0
3888 0
3889 0
3890 0
3891 0
3892 0
3893 0
3894 0
3895 0
3896 0
3897 0
3898 0
3899 0
3900 0
3901 0
3902 0
3903 0
3904 0
3905 0
3906 0
3907 0
3908 0
3909 0
3910 0
3911 0
3912 0
3913 0
3914 0
3915 0
3916 0
3917 0
3918 0
3919 0
3920 0
3921 0
3922 0
3923 0
3924 0
3925 0
3926 0
3927 0
3928 0
3929 0
3930 0
3931 0
3932 0
3933 0
3934 0
3935 0
3936 0
3937 0
3938 0
3939 0
3940 0
3941 0
3942 0
3943 0
3944 0
3945 0
3946 0
3947 0
3948 0
3949 0
3950 0
3951 0
3952 0
3953 0
3954 0
3955 0
3956 0
3957 0
3958 0
3959 0
3960 0
3961 0
3962 0
3963 0
3964 0
3965 0
3966 0
3967 0
3968 0
3969 0
3970 0
3971 0
3972 0
3973 0
3974 0
3975 0
3976 0
3977 0
3978 0
3979 0
3980 0
3981 0
3982 0
3983 0
3984 0
3985 0
3986 0
3987 0
3988 0
3989 0
3990 0
3991 0
3992 0
3993 0
3994 0
3995 0
3996 0
3997 0
3998 0
3999 0
4000 0
4001 0
4002 0
4003 0
4004 0
4005 0
4006 0
4007 0
4008 0
4009 0
4010 0
4011 0
4012 0
4013 0
4014 0
4015 0
4016 0
4017 0
4018 0
4019 0
4020 0
4021 0
4022 0
4023 0
4024 0
4025 0
4026 0
4027 0
4028 0
4029 0
4030 0
4031 0
4032 0
4033 0
4034 0
4035 0
4036 0
4037 0
4038 0
4039 0
4040 0
4041 0
4042 0
4043 0
4044 0
4045 0
4046 0
4047 0
4048 0
4049 0
4050 0
4051 0
4052 0
4053 0
4054 0
4055 0
4056 0
4057 0
4058 0
4059 0
4060 0
4061 0
4062 0
4063 0
4064 0
4065 0
4066 0
4067 0
4068 0
4069 0
4070 0
4071 0
4072 0
4073 0
4074 0
4075 0
4076 0
4077 0
4078 0
4079 0
4080 0
4081 0
4082 0
4083 0
4084 0
4085 0
4086 0
4087 0
4088 0
4089 0
4090 0
4091 0
4092 0
4093 0
4094 0
4095 0
[-- Attachment #3: additive.png --]
[-- Type: image/png, Size: 5781 bytes --]
[-- Attachment #4: one-at-a-time.txt --]
[-- Type: text/plain, Size: 29772 bytes --]
0 8
1 13
2 6
3 11
4 18
5 12
6 4
7 7
8 14
9 6
10 4
11 10
12 7
13 10
14 16
15 11
16 10
17 5
18 11
19 7
20 9
21 12
22 8
23 11
24 10
25 8
26 9
27 13
28 10
29 17
30 7
31 7
32 6
33 13
34 12
35 10
36 7
37 15
38 12
39 9
40 7
41 5
42 9
43 8
44 8
45 13
46 11
47 8
48 13
49 12
50 7
51 12
52 13
53 7
54 15
55 8
56 9
57 8
58 8
59 12
60 13
61 7
62 8
63 9
64 12
65 13
66 10
67 8
68 6
69 9
70 14
71 9
72 11
73 8
74 10
75 10
76 6
77 10
78 10
79 9
80 15
81 6
82 18
83 8
84 6
85 8
86 13
87 11
88 15
89 6
90 9
91 9
92 8
93 8
94 14
95 13
96 13
97 13
98 4
99 9
100 4
101 9
102 10
103 14
104 9
105 10
106 9
107 11
108 14
109 13
110 12
111 10
112 11
113 12
114 9
115 11
116 10
117 13
118 9
119 11
120 9
121 9
122 11
123 10
124 12
125 9
126 11
127 14
128 13
129 13
130 5
131 11
132 12
133 6
134 14
135 10
136 12
137 7
138 10
139 13
140 10
141 14
142 14
143 10
144 9
145 8
146 20
147 6
148 11
149 17
150 10
151 10
152 7
153 13
154 12
155 14
156 9
157 6
158 15
159 8
160 15
161 16
162 9
163 11
164 8
165 10
166 15
167 10
168 8
169 8
170 10
171 9
172 8
173 5
174 6
175 7
176 6
177 7
178 9
179 14
180 7
181 11
182 7
183 16
184 9
185 7
186 8
187 10
188 8
189 8
190 8
191 7
192 10
193 8
194 13
195 11
196 9
197 9
198 13
199 13
200 6
201 10
202 11
203 16
204 6
205 6
206 11
207 8
208 9
209 13
210 10
211 7
212 12
213 5
214 12
215 14
216 9
217 10
218 8
219 8
220 12
221 10
222 8
223 12
224 10
225 4
226 17
227 10
228 8
229 12
230 11
231 6
232 7
233 9
234 14
235 12
236 9
237 9
238 10
239 12
240 10
241 10
242 10
243 5
244 7
245 10
246 3
247 6
248 8
249 9
250 8
251 7
252 8
253 9
254 11
255 9
256 4
257 13
258 7
259 7
260 6
261 10
262 13
263 9
264 12
265 9
266 10
267 9
268 9
269 10
270 15
271 13
272 6
273 9
274 8
275 14
276 9
277 10
278 4
279 7
280 16
281 8
282 5
283 14
284 10
285 7
286 9
287 12
288 5
289 4
290 12
291 9
292 17
293 11
294 16
295 17
296 7
297 7
298 11
299 12
300 16
301 8
302 6
303 12
304 6
305 6
306 4
307 19
308 10
309 13
310 5
311 11
312 10
313 7
314 7
315 8
316 18
317 11
318 10
319 6
320 8
321 8
322 8
323 6
324 9
325 6
326 8
327 14
328 12
329 5
330 9
331 13
332 14
333 12
334 11
335 18
336 9
337 8
338 9
339 8
340 13
341 15
342 11
343 11
344 11
345 9
346 10
347 7
348 8
349 13
350 10
351 8
352 11
353 11
354 10
355 9
356 13
357 4
358 9
359 8
360 7
361 12
362 10
363 15
364 10
365 11
366 6
367 11
368 14
369 6
370 11
371 15
372 15
373 3
374 16
375 9
376 10
377 8
378 11
379 15
380 18
381 13
382 8
383 16
384 7
385 11
386 12
387 12
388 11
389 9
390 13
391 14
392 9
393 8
394 12
395 9
396 8
397 6
398 6
399 11
400 12
401 13
402 13
403 13
404 8
405 14
406 16
407 12
408 7
409 10
410 12
411 8
412 14
413 12
414 12
415 10
416 13
417 14
418 5
419 11
420 7
421 11
422 12
423 10
424 11
425 3
426 6
427 6
428 10
429 5
430 15
431 7
432 12
433 8
434 7
435 7
436 10
437 11
438 13
439 10
440 17
441 11
442 13
443 5
444 8
445 9
446 11
447 8
448 14
449 9
450 5
451 16
452 9
453 9
454 10
455 13
456 10
457 7
458 7
459 13
460 11
461 12
462 4
463 4
464 11
465 17
466 9
467 11
468 10
469 8
470 11
471 10
472 4
473 11
474 9
475 11
476 19
477 9
478 16
479 15
480 4
481 10
482 9
483 11
484 17
485 17
486 21
487 8
488 5
489 9
490 12
491 19
492 4
493 12
494 10
495 14
496 8
497 8
498 10
499 14
500 10
501 10
502 6
503 2
504 8
505 11
506 6
507 8
508 7
509 11
510 9
511 10
512 10
513 14
514 13
515 11
516 6
517 10
518 6
519 7
520 15
521 11
522 14
523 11
524 12
525 13
526 8
527 12
528 22
529 10
530 11
531 9
532 9
533 8
534 4
535 7
536 6
537 9
538 10
539 10
540 14
541 7
542 9
543 5
544 7
545 13
546 11
547 13
548 10
549 8
550 11
551 10
552 10
553 11
554 15
555 14
556 8
557 12
558 12
559 7
560 7
561 5
562 14
563 13
564 12
565 12
566 7
567 12
568 12
569 12
570 10
571 9
572 15
573 8
574 15
575 11
576 9
577 14
578 7
579 10
580 16
581 14
582 11
583 18
584 6
585 13
586 11
587 13
588 11
589 10
590 13
591 9
592 11
593 10
594 7
595 14
596 6
597 11
598 11
599 6
600 8
601 11
602 6
603 3
604 8
605 9
606 11
607 16
608 9
609 12
610 9
611 13
612 12
613 8
614 6
615 15
616 14
617 9
618 10
619 8
620 9
621 10
622 13
623 8
624 12
625 11
626 8
627 8
628 11
629 9
630 12
631 9
632 15
633 14
634 8
635 9
636 8
637 12
638 5
639 7
640 14
641 13
642 2
643 13
644 6
645 15
646 4
647 13
648 7
649 6
650 7
651 6
652 12
653 11
654 12
655 8
656 13
657 6
658 12
659 10
660 10
661 12
662 10
663 7
664 6
665 8
666 8
667 8
668 12
669 7
670 7
671 12
672 8
673 16
674 6
675 10
676 8
677 12
678 14
679 10
680 13
681 12
682 8
683 14
684 14
685 17
686 10
687 11
688 13
689 11
690 13
691 6
692 8
693 9
694 10
695 7
696 14
697 13
698 11
699 9
700 9
701 8
702 11
703 12
704 10
705 11
706 14
707 10
708 13
709 12
710 8
711 5
712 10
713 14
714 7
715 10
716 13
717 6
718 6
719 13
720 8
721 12
722 10
723 9
724 7
725 6
726 4
727 12
728 8
729 14
730 7
731 9
732 7
733 11
734 10
735 12
736 10
737 12
738 15
739 13
740 8
741 14
742 6
743 7
744 12
745 12
746 12
747 17
748 3
749 14
750 15
751 6
752 11
753 8
754 5
755 5
756 8
757 13
758 13
759 10
760 13
761 8
762 9
763 11
764 7
765 7
766 7
767 9
768 16
769 5
770 17
771 14
772 9
773 7
774 7
775 3
776 8
777 8
778 10
779 8
780 8
781 6
782 11
783 11
784 3
785 10
786 17
787 8
788 12
789 10
790 6
791 9
792 9
793 15
794 9
795 8
796 21
797 10
798 1
799 10
800 13
801 8
802 9
803 3
804 6
805 17
806 13
807 8
808 10
809 12
810 8
811 12
812 12
813 13
814 8
815 6
816 8
817 9
818 13
819 5
820 13
821 10
822 6
823 9
824 11
825 7
826 11
827 19
828 11
829 5
830 8
831 15
832 9
833 4
834 11
835 8
836 6
837 7
838 11
839 9
840 13
841 11
842 5
843 13
844 9
845 11
846 10
847 8
848 11
849 10
850 13
851 12
852 6
853 9
854 16
855 7
856 12
857 9
858 8
859 10
860 10
861 13
862 12
863 7
864 9
865 6
866 8
867 10
868 11
869 4
870 7
871 6
872 9
873 8
874 8
875 10
876 8
877 13
878 6
879 14
880 10
881 6
882 12
883 10
884 10
885 10
886 18
887 7
888 12
889 10
890 18
891 7
892 7
893 7
894 15
895 7
896 9
897 9
898 11
899 10
900 6
901 8
902 4
903 9
904 4
905 5
906 9
907 15
908 10
909 8
910 12
911 9
912 7
913 7
914 6
915 9
916 7
917 13
918 15
919 7
920 8
921 9
922 12
923 15
924 14
925 13
926 10
927 13
928 15
929 14
930 13
931 8
932 5
933 10
934 11
935 6
936 14
937 6
938 9
939 14
940 11
941 7
942 10
943 5
944 15
945 11
946 9
947 8
948 13
949 9
950 9
951 15
952 9
953 5
954 13
955 15
956 9
957 10
958 17
959 12
960 7
961 12
962 13
963 13
964 16
965 5
966 7
967 16
968 7
969 7
970 12
971 4
972 12
973 5
974 10
975 11
976 8
977 2
978 8
979 11
980 9
981 9
982 12
983 14
984 6
985 12
986 8
987 11
988 13
989 8
990 9
991 8
992 9
993 13
994 10
995 8
996 11
997 9
998 13
999 14
1000 11
1001 11
1002 9
1003 13
1004 10
1005 6
1006 12
1007 17
1008 12
1009 8
1010 10
1011 17
1012 8
1013 6
1014 10
1015 7
1016 15
1017 10
1018 11
1019 8
1020 11
1021 12
1022 8
1023 8
1024 8
1025 7
1026 5
1027 8
1028 9
1029 14
1030 13
1031 14
1032 12
1033 11
1034 10
1035 12
1036 8
1037 9
1038 7
1039 16
1040 6
1041 8
1042 15
1043 9
1044 8
1045 5
1046 5
1047 10
1048 10
1049 10
1050 7
1051 9
1052 6
1053 10
1054 5
1055 8
1056 10
1057 8
1058 5
1059 14
1060 9
1061 6
1062 9
1063 9
1064 14
1065 13
1066 8
1067 11
1068 6
1069 6
1070 5
1071 13
1072 9
1073 14
1074 14
1075 13
1076 5
1077 7
1078 10
1079 10
1080 13
1081 8
1082 10
1083 19
1084 6
1085 9
1086 9
1087 7
1088 9
1089 7
1090 8
1091 10
1092 10
1093 6
1094 8
1095 11
1096 10
1097 7
1098 8
1099 14
1100 13
1101 11
1102 12
1103 13
1104 8
1105 6
1106 6
1107 11
1108 11
1109 9
1110 8
1111 7
1112 12
1113 12
1114 13
1115 8
1116 6
1117 8
1118 12
1119 16
1120 12
1121 14
1122 9
1123 5
1124 8
1125 10
1126 5
1127 7
1128 6
1129 12
1130 12
1131 11
1132 10
1133 7
1134 9
1135 4
1136 13
1137 8
1138 15
1139 10
1140 7
1141 9
1142 9
1143 9
1144 10
1145 5
1146 7
1147 10
1148 7
1149 7
1150 14
1151 17
1152 9
1153 14
1154 7
1155 11
1156 8
1157 15
1158 9
1159 6
1160 9
1161 5
1162 4
1163 7
1164 14
1165 17
1166 10
1167 5
1168 11
1169 10
1170 7
1171 6
1172 10
1173 8
1174 11
1175 7
1176 13
1177 8
1178 10
1179 14
1180 15
1181 12
1182 7
1183 10
1184 12
1185 10
1186 11
1187 9
1188 8
1189 12
1190 12
1191 9
1192 15
1193 8
1194 8
1195 11
1196 11
1197 8
1198 16
1199 15
1200 16
1201 9
1202 16
1203 9
1204 8
1205 13
1206 10
1207 8
1208 11
1209 10
1210 9
1211 7
1212 6
1213 7
1214 11
1215 16
1216 7
1217 9
1218 6
1219 13
1220 15
1221 9
1222 11
1223 11
1224 11
1225 11
1226 11
1227 14
1228 10
1229 10
1230 9
1231 8
1232 12
1233 12
1234 7
1235 17
1236 8
1237 7
1238 12
1239 13
1240 10
1241 9
1242 8
1243 9
1244 6
1245 13
1246 6
1247 14
1248 12
1249 9
1250 10
1251 16
1252 9
1253 11
1254 6
1255 12
1256 6
1257 14
1258 8
1259 10
1260 5
1261 10
1262 10
1263 9
1264 9
1265 8
1266 11
1267 9
1268 16
1269 12
1270 15
1271 9
1272 10
1273 5
1274 13
1275 16
1276 13
1277 15
1278 10
1279 9
1280 6
1281 14
1282 9
1283 9
1284 10
1285 11
1286 8
1287 9
1288 4
1289 12
1290 2
1291 8
1292 11
1293 12
1294 8
1295 14
1296 8
1297 14
1298 15
1299 5
1300 5
1301 7
1302 5
1303 10
1304 9
1305 9
1306 7
1307 9
1308 8
1309 9
1310 11
1311 10
1312 13
1313 9
1314 7
1315 5
1316 7
1317 3
1318 11
1319 9
1320 3
1321 8
1322 10
1323 12
1324 8
1325 14
1326 9
1327 14
1328 16
1329 7
1330 11
1331 9
1332 5
1333 6
1334 7
1335 5
1336 9
1337 14
1338 7
1339 10
1340 10
1341 8
1342 9
1343 12
1344 8
1345 9
1346 8
1347 15
1348 10
1349 7
1350 9
1351 8
1352 16
1353 13
1354 16
1355 10
1356 11
1357 7
1358 8
1359 12
1360 9
1361 11
1362 6
1363 17
1364 6
1365 12
1366 11
1367 10
1368 11
1369 12
1370 7
1371 9
1372 10
1373 10
1374 11
1375 10
1376 14
1377 13
1378 13
1379 7
1380 5
1381 11
1382 7
1383 8
1384 9
1385 12
1386 10
1387 13
1388 7
1389 9
1390 11
1391 18
1392 13
1393 13
1394 15
1395 11
1396 13
1397 9
1398 7
1399 12
1400 15
1401 13
1402 9
1403 8
1404 11
1405 12
1406 19
1407 10
1408 13
1409 10
1410 8
1411 13
1412 15
1413 16
1414 7
1415 11
1416 12
1417 10
1418 5
1419 8
1420 11
1421 9
1422 12
1423 9
1424 6
1425 11
1426 15
1427 4
1428 12
1429 12
1430 11
1431 7
1432 11
1433 15
1434 11
1435 11
1436 12
1437 11
1438 8
1439 9
1440 7
1441 9
1442 5
1443 8
1444 10
1445 14
1446 10
1447 8
1448 10
1449 12
1450 10
1451 10
1452 11
1453 8
1454 14
1455 15
1456 10
1457 10
1458 10
1459 6
1460 3
1461 7
1462 12
1463 10
1464 12
1465 10
1466 10
1467 6
1468 6
1469 11
1470 14
1471 9
1472 15
1473 12
1474 7
1475 5
1476 12
1477 17
1478 9
1479 13
1480 9
1481 10
1482 8
1483 15
1484 17
1485 8
1486 6
1487 14
1488 5
1489 17
1490 13
1491 7
1492 10
1493 7
1494 10
1495 9
1496 14
1497 11
1498 18
1499 9
1500 10
1501 7
1502 8
1503 10
1504 9
1505 9
1506 8
1507 12
1508 9
1509 10
1510 11
1511 9
1512 8
1513 6
1514 12
1515 10
1516 7
1517 10
1518 10
1519 14
1520 8
1521 7
1522 14
1523 15
1524 7
1525 9
1526 8
1527 10
1528 5
1529 11
1530 11
1531 12
1532 10
1533 12
1534 11
1535 12
1536 13
1537 11
1538 8
1539 12
1540 11
1541 10
1542 9
1543 11
1544 10
1545 10
1546 10
1547 12
1548 13
1549 10
1550 8
1551 5
1552 7
1553 10
1554 16
1555 11
1556 11
1557 10
1558 17
1559 9
1560 12
1561 14
1562 13
1563 11
1564 14
1565 15
1566 7
1567 10
1568 13
1569 9
1570 8
1571 13
1572 9
1573 10
1574 10
1575 10
1576 16
1577 17
1578 16
1579 10
1580 4
1581 12
1582 5
1583 11
1584 11
1585 16
1586 7
1587 8
1588 10
1589 3
1590 7
1591 10
1592 13
1593 6
1594 10
1595 7
1596 9
1597 11
1598 2
1599 5
1600 10
1601 10
1602 8
1603 13
1604 12
1605 11
1606 12
1607 9
1608 12
1609 9
1610 17
1611 10
1612 7
1613 7
1614 14
1615 13
1616 3
1617 13
1618 10
1619 12
1620 11
1621 11
1622 4
1623 14
1624 8
1625 7
1626 12
1627 9
1628 11
1629 8
1630 10
1631 13
1632 8
1633 8
1634 9
1635 7
1636 3
1637 8
1638 12
1639 7
1640 11
1641 11
1642 12
1643 9
1644 7
1645 9
1646 14
1647 3
1648 14
1649 8
1650 8
1651 7
1652 12
1653 10
1654 7
1655 9
1656 9
1657 16
1658 14
1659 9
1660 11
1661 9
1662 6
1663 10
1664 8
1665 12
1666 8
1667 7
1668 8
1669 6
1670 10
1671 4
1672 8
1673 11
1674 12
1675 12
1676 9
1677 8
1678 8
1679 10
1680 12
1681 11
1682 7
1683 14
1684 10
1685 9
1686 16
1687 7
1688 5
1689 16
1690 5
1691 13
1692 9
1693 13
1694 13
1695 13
1696 7
1697 9
1698 9
1699 7
1700 11
1701 18
1702 10
1703 9
1704 13
1705 8
1706 14
1707 11
1708 9
1709 11
1710 11
1711 13
1712 15
1713 11
1714 4
1715 13
1716 4
1717 8
1718 15
1719 14
1720 14
1721 12
1722 14
1723 12
1724 9
1725 6
1726 11
1727 7
1728 11
1729 6
1730 13
1731 13
1732 5
1733 5
1734 12
1735 5
1736 7
1737 4
1738 7
1739 5
1740 9
1741 15
1742 13
1743 6
1744 12
1745 11
1746 9
1747 12
1748 16
1749 8
1750 16
1751 14
1752 6
1753 14
1754 15
1755 4
1756 12
1757 16
1758 12
1759 8
1760 7
1761 5
1762 6
1763 8
1764 17
1765 10
1766 13
1767 14
1768 8
1769 7
1770 12
1771 7
1772 6
1773 11
1774 7
1775 16
1776 17
1777 11
1778 11
1779 7
1780 9
1781 10
1782 9
1783 15
1784 6
1785 11
1786 4
1787 5
1788 11
1789 15
1790 5
1791 8
1792 10
1793 17
1794 10
1795 16
1796 9
1797 7
1798 7
1799 15
1800 9
1801 15
1802 13
1803 13
1804 14
1805 10
1806 13
1807 12
1808 7
1809 13
1810 7
1811 6
1812 11
1813 11
1814 12
1815 8
1816 7
1817 10
1818 8
1819 10
1820 9
1821 7
1822 17
1823 7
1824 8
1825 9
1826 6
1827 11
1828 12
1829 11
1830 18
1831 10
1832 7
1833 8
1834 2
1835 2
1836 10
1837 11
1838 11
1839 12
1840 10
1841 6
1842 5
1843 10
1844 20
1845 10
1846 8
1847 13
1848 6
1849 10
1850 9
1851 6
1852 14
1853 9
1854 7
1855 15
1856 11
1857 12
1858 10
1859 5
1860 13
1861 11
1862 11
1863 9
1864 15
1865 10
1866 10
1867 11
1868 16
1869 9
1870 9
1871 5
1872 9
1873 10
1874 13
1875 9
1876 10
1877 10
1878 10
1879 14
1880 11
1881 9
1882 13
1883 13
1884 7
1885 7
1886 13
1887 7
1888 10
1889 12
1890 9
1891 14
1892 11
1893 10
1894 14
1895 13
1896 7
1897 9
1898 9
1899 7
1900 5
1901 4
1902 9
1903 10
1904 14
1905 12
1906 16
1907 11
1908 16
1909 15
1910 13
1911 14
1912 6
1913 5
1914 7
1915 17
1916 5
1917 13
1918 13
1919 6
1920 11
1921 10
1922 15
1923 10
1924 12
1925 12
1926 14
1927 10
1928 11
1929 8
1930 4
1931 19
1932 8
1933 11
1934 11
1935 9
1936 10
1937 7
1938 5
1939 8
1940 8
1941 6
1942 13
1943 7
1944 9
1945 13
1946 8
1947 17
1948 7
1949 7
1950 13
1951 11
1952 10
1953 9
1954 12
1955 7
1956 5
1957 9
1958 11
1959 8
1960 11
1961 7
1962 10
1963 13
1964 14
1965 10
1966 11
1967 13
1968 9
1969 10
1970 7
1971 5
1972 5
1973 10
1974 6
1975 21
1976 14
1977 17
1978 13
1979 11
1980 10
1981 7
1982 18
1983 7
1984 9
1985 11
1986 9
1987 11
1988 13
1989 4
1990 10
1991 10
1992 6
1993 11
1994 7
1995 5
1996 9
1997 11
1998 14
1999 9
2000 13
2001 17
2002 8
2003 12
2004 12
2005 13
2006 11
2007 8
2008 7
2009 16
2010 14
2011 15
2012 14
2013 10
2014 11
2015 9
2016 15
2017 17
2018 9
2019 6
2020 11
2021 13
2022 10
2023 8
2024 16
2025 8
2026 5
2027 13
2028 6
2029 11
2030 8
2031 15
2032 14
2033 9
2034 17
2035 6
2036 9
2037 12
2038 14
2039 12
2040 12
2041 8
2042 7
2043 15
2044 11
2045 11
2046 6
2047 11
2048 11
2049 10
2050 11
2051 8
2052 8
2053 12
2054 7
2055 11
2056 3
2057 9
2058 14
2059 6
2060 13
2061 8
2062 7
2063 8
2064 13
2065 12
2066 11
2067 8
2068 8
2069 12
2070 10
2071 11
2072 6
2073 5
2074 12
2075 10
2076 10
2077 14
2078 5
2079 7
2080 9
2081 12
2082 8
2083 9
2084 11
2085 7
2086 9
2087 9
2088 17
2089 15
2090 11
2091 11
2092 13
2093 17
2094 9
2095 10
2096 7
2097 8
2098 8
2099 8
2100 6
2101 11
2102 7
2103 9
2104 7
2105 6
2106 6
2107 12
2108 12
2109 8
2110 11
2111 8
2112 11
2113 9
2114 9
2115 12
2116 6
2117 12
2118 14
2119 9
2120 14
2121 12
2122 16
2123 8
2124 6
2125 10
2126 11
2127 9
2128 6
2129 14
2130 12
2131 8
2132 6
2133 10
2134 17
2135 6
2136 8
2137 10
2138 16
2139 14
2140 13
2141 8
2142 9
2143 13
2144 8
2145 14
2146 12
2147 10
2148 8
2149 7
2150 8
2151 12
2152 7
2153 12
2154 11
2155 10
2156 11
2157 17
2158 11
2159 16
2160 18
2161 7
2162 12
2163 13
2164 11
2165 9
2166 9
2167 12
2168 9
2169 13
2170 7
2171 10
2172 11
2173 15
2174 9
2175 12
2176 10
2177 14
2178 8
2179 4
2180 11
2181 8
2182 11
2183 13
2184 10
2185 11
2186 8
2187 10
2188 12
2189 9
2190 4
2191 11
2192 11
2193 5
2194 9
2195 15
2196 11
2197 16
2198 11
2199 10
2200 5
2201 15
2202 11
2203 13
2204 10
2205 15
2206 11
2207 9
2208 7
2209 12
2210 7
2211 10
2212 13
2213 8
2214 10
2215 12
2216 19
2217 9
2218 11
2219 4
2220 8
2221 4
2222 6
2223 12
2224 10
2225 9
2226 8
2227 10
2228 8
2229 16
2230 8
2231 10
2232 11
2233 4
2234 13
2235 11
2236 12
2237 9
2238 14
2239 7
2240 15
2241 10
2242 10
2243 11
2244 12
2245 9
2246 11
2247 8
2248 8
2249 14
2250 5
2251 14
2252 8
2253 7
2254 10
2255 11
2256 10
2257 12
2258 7
2259 16
2260 9
2261 8
2262 10
2263 11
2264 9
2265 12
2266 15
2267 12
2268 12
2269 15
2270 19
2271 16
2272 11
2273 12
2274 16
2275 13
2276 12
2277 9
2278 8
2279 15
2280 8
2281 13
2282 3
2283 8
2284 12
2285 13
2286 12
2287 10
2288 4
2289 15
2290 8
2291 12
2292 14
2293 8
2294 7
2295 11
2296 10
2297 8
2298 10
2299 16
2300 9
2301 12
2302 4
2303 10
2304 9
2305 11
2306 6
2307 11
2308 11
2309 13
2310 11
2311 11
2312 12
2313 11
2314 8
2315 12
2316 7
2317 5
2318 15
2319 13
2320 9
2321 7
2322 8
2323 11
2324 8
2325 12
2326 11
2327 12
2328 13
2329 9
2330 19
2331 11
2332 13
2333 12
2334 10
2335 10
2336 9
2337 10
2338 11
2339 10
2340 9
2341 6
2342 10
2343 13
2344 10
2345 8
2346 12
2347 6
2348 14
2349 12
2350 14
2351 8
2352 8
2353 5
2354 10
2355 17
2356 4
2357 13
2358 8
2359 11
2360 9
2361 5
2362 9
2363 9
2364 12
2365 10
2366 5
2367 7
2368 10
2369 14
2370 8
2371 10
2372 12
2373 8
2374 5
2375 5
2376 6
2377 9
2378 13
2379 12
2380 9
2381 8
2382 15
2383 8
2384 8
2385 8
2386 13
2387 7
2388 11
2389 16
2390 13
2391 9
2392 16
2393 5
2394 3
2395 11
2396 12
2397 11
2398 10
2399 14
2400 7
2401 9
2402 12
2403 9
2404 17
2405 12
2406 9
2407 12
2408 8
2409 9
2410 7
2411 9
2412 10
2413 8
2414 9
2415 9
2416 7
2417 10
2418 14
2419 11
2420 16
2421 7
2422 16
2423 9
2424 8
2425 14
2426 12
2427 15
2428 14
2429 6
2430 8
2431 9
2432 8
2433 11
2434 11
2435 7
2436 11
2437 7
2438 9
2439 15
2440 14
2441 8
2442 11
2443 15
2444 11
2445 9
2446 9
2447 7
2448 7
2449 10
2450 14
2451 9
2452 7
2453 12
2454 8
2455 8
2456 7
2457 16
2458 10
2459 15
2460 15
2461 11
2462 5
2463 14
2464 11
2465 10
2466 8
2467 12
2468 9
2469 11
2470 10
2471 9
2472 8
2473 12
2474 10
2475 8
2476 12
2477 6
2478 11
2479 9
2480 6
2481 12
2482 9
2483 8
2484 13
2485 9
2486 10
2487 8
2488 8
2489 8
2490 16
2491 11
2492 4
2493 13
2494 13
2495 7
2496 10
2497 9
2498 14
2499 9
2500 11
2501 6
2502 17
2503 11
2504 9
2505 17
2506 5
2507 7
2508 13
2509 6
2510 14
2511 8
2512 12
2513 10
2514 13
2515 8
2516 11
2517 8
2518 11
2519 13
2520 9
2521 9
2522 12
2523 13
2524 12
2525 10
2526 6
2527 4
2528 6
2529 8
2530 7
2531 8
2532 8
2533 8
2534 8
2535 10
2536 11
2537 16
2538 12
2539 9
2540 11
2541 10
2542 7
2543 11
2544 10
2545 9
2546 7
2547 16
2548 13
2549 14
2550 9
2551 11
2552 12
2553 10
2554 6
2555 8
2556 12
2557 6
2558 9
2559 2
2560 9
2561 12
2562 14
2563 7
2564 12
2565 13
2566 9
2567 5
2568 8
2569 5
2570 11
2571 5
2572 9
2573 6
2574 10
2575 7
2576 9
2577 2
2578 9
2579 8
2580 8
2581 17
2582 7
2583 5
2584 10
2585 6
2586 16
2587 12
2588 16
2589 7
2590 15
2591 5
2592 10
2593 8
2594 3
2595 11
2596 8
2597 11
2598 12
2599 13
2600 13
2601 8
2602 11
2603 16
2604 11
2605 10
2606 13
2607 10
2608 5
2609 11
2610 11
2611 13
2612 7
2613 15
2614 9
2615 16
2616 11
2617 10
2618 11
2619 13
2620 15
2621 8
2622 11
2623 8
2624 7
2625 6
2626 7
2627 12
2628 12
2629 10
2630 5
2631 10
2632 10
2633 8
2634 9
2635 10
2636 11
2637 16
2638 16
2639 14
2640 14
2641 8
2642 12
2643 8
2644 8
2645 15
2646 8
2647 7
2648 5
2649 7
2650 10
2651 9
2652 10
2653 7
2654 10
2655 9
2656 12
2657 7
2658 6
2659 10
2660 6
2661 9
2662 11
2663 12
2664 12
2665 13
2666 11
2667 6
2668 10
2669 11
2670 14
2671 11
2672 7
2673 6
2674 10
2675 12
2676 7
2677 9
2678 5
2679 10
2680 4
2681 12
2682 8
2683 8
2684 11
2685 10
2686 11
2687 7
2688 7
2689 13
2690 9
2691 8
2692 13
2693 16
2694 6
2695 7
2696 7
2697 5
2698 11
2699 9
2700 10
2701 9
2702 8
2703 10
2704 16
2705 11
2706 8
2707 10
2708 9
2709 8
2710 13
2711 15
2712 11
2713 13
2714 11
2715 11
2716 8
2717 9
2718 9
2719 11
2720 6
2721 13
2722 15
2723 5
2724 11
2725 13
2726 9
2727 7
2728 10
2729 9
2730 12
2731 4
2732 12
2733 6
2734 10
2735 5
2736 4
2737 12
2738 7
2739 15
2740 14
2741 8
2742 7
2743 14
2744 12
2745 7
2746 5
2747 7
2748 12
2749 10
2750 8
2751 13
2752 8
2753 7
2754 10
2755 10
2756 9
2757 12
2758 11
2759 11
2760 12
2761 11
2762 9
2763 17
2764 4
2765 10
2766 7
2767 8
2768 12
2769 9
2770 12
2771 9
2772 11
2773 14
2774 14
2775 9
2776 5
2777 12
2778 12
2779 11
2780 12
2781 9
2782 6
2783 13
2784 7
2785 12
2786 7
2787 14
2788 9
2789 12
2790 7
2791 9
2792 13
2793 13
2794 15
2795 9
2796 9
2797 11
2798 10
2799 9
2800 5
2801 8
2802 16
2803 7
2804 11
2805 15
2806 7
2807 6
2808 9
2809 5
2810 13
2811 8
2812 10
2813 11
2814 5
2815 8
2816 12
2817 12
2818 7
2819 12
2820 9
2821 8
2822 15
2823 9
2824 7
2825 5
2826 10
2827 8
2828 7
2829 5
2830 6
2831 10
2832 12
2833 7
2834 15
2835 9
2836 8
2837 8
2838 13
2839 11
2840 9
2841 6
2842 8
2843 15
2844 15
2845 7
2846 10
2847 4
2848 11
2849 6
2850 15
2851 7
2852 14
2853 10
2854 14
2855 11
2856 6
2857 9
2858 12
2859 10
2860 7
2861 15
2862 12
2863 9
2864 6
2865 3
2866 13
2867 8
2868 10
2869 10
2870 5
2871 12
2872 15
2873 11
2874 8
2875 9
2876 7
2877 8
2878 14
2879 5
2880 9
2881 16
2882 9
2883 14
2884 18
2885 7
2886 7
2887 6
2888 7
2889 13
2890 14
2891 9
2892 9
2893 12
2894 8
2895 7
2896 13
2897 13
2898 6
2899 6
2900 11
2901 10
2902 7
2903 16
2904 14
2905 13
2906 10
2907 9
2908 15
2909 11
2910 11
2911 10
2912 6
2913 7
2914 14
2915 17
2916 10
2917 9
2918 12
2919 15
2920 13
2921 10
2922 13
2923 8
2924 11
2925 4
2926 14
2927 13
2928 8
2929 9
2930 10
2931 13
2932 9
2933 12
2934 16
2935 16
2936 8
2937 9
2938 13
2939 12
2940 11
2941 16
2942 5
2943 11
2944 10
2945 4
2946 16
2947 8
2948 10
2949 8
2950 5
2951 17
2952 13
2953 11
2954 9
2955 13
2956 13
2957 10
2958 7
2959 9
2960 8
2961 12
2962 12
2963 9
2964 4
2965 9
2966 7
2967 8
2968 3
2969 8
2970 4
2971 11
2972 6
2973 3
2974 11
2975 12
2976 4
2977 12
2978 7
2979 4
2980 9
2981 14
2982 11
2983 16
2984 10
2985 5
2986 11
2987 8
2988 11
2989 5
2990 13
2991 11
2992 6
2993 12
2994 16
2995 6
2996 16
2997 13
2998 9
2999 6
3000 8
3001 7
3002 16
3003 11
3004 10
3005 6
3006 5
3007 9
3008 9
3009 11
3010 7
3011 9
3012 9
3013 12
3014 6
3015 8
3016 5
3017 14
3018 8
3019 4
3020 13
3021 14
3022 7
3023 9
3024 9
3025 9
3026 12
3027 13
3028 10
3029 12
3030 12
3031 12
3032 11
3033 12
3034 12
3035 9
3036 11
3037 11
3038 6
3039 5
3040 15
3041 10
3042 13
3043 4
3044 17
3045 11
3046 14
3047 10
3048 11
3049 3
3050 16
3051 15
3052 17
3053 6
3054 10
3055 14
3056 6
3057 10
3058 11
3059 7
3060 10
3061 9
3062 8
3063 13
3064 6
3065 10
3066 10
3067 5
3068 8
3069 8
3070 3
3071 6
3072 10
3073 9
3074 8
3075 14
3076 9
3077 9
3078 7
3079 14
3080 10
3081 17
3082 11
3083 14
3084 10
3085 8
3086 8
3087 10
3088 12
3089 5
3090 8
3091 18
3092 13
3093 9
3094 7
3095 13
3096 20
3097 13
3098 16
3099 8
3100 11
3101 10
3102 7
3103 14
3104 11
3105 12
3106 6
3107 7
3108 7
3109 11
3110 9
3111 8
3112 12
3113 5
3114 11
3115 11
3116 14
3117 7
3118 15
3119 3
3120 9
3121 10
3122 7
3123 10
3124 8
3125 12
3126 9
3127 10
3128 10
3129 10
3130 7
3131 14
3132 9
3133 5
3134 9
3135 10
3136 9
3137 11
3138 12
3139 9
3140 11
3141 11
3142 13
3143 8
3144 13
3145 10
3146 17
3147 9
3148 14
3149 12
3150 8
3151 14
3152 4
3153 13
3154 8
3155 17
3156 11
3157 8
3158 12
3159 15
3160 13
3161 9
3162 17
3163 11
3164 11
3165 7
3166 14
3167 7
3168 11
3169 15
3170 5
3171 9
3172 6
3173 11
3174 9
3175 17
3176 10
3177 8
3178 11
3179 11
3180 8
3181 17
3182 11
3183 10
3184 9
3185 6
3186 14
3187 8
3188 6
3189 4
3190 12
3191 10
3192 7
3193 7
3194 13
3195 9
3196 6
3197 16
3198 13
3199 12
3200 8
3201 2
3202 13
3203 9
3204 13
3205 13
3206 8
3207 5
3208 5
3209 14
3210 7
3211 9
3212 4
3213 10
3214 13
3215 8
3216 6
3217 12
3218 7
3219 11
3220 5
3221 10
3222 10
3223 11
3224 9
3225 10
3226 10
3227 5
3228 5
3229 12
3230 5
3231 14
3232 7
3233 9
3234 12
3235 15
3236 8
3237 8
3238 13
3239 13
3240 9
3241 11
3242 12
3243 16
3244 5
3245 16
3246 11
3247 10
3248 5
3249 7
3250 6
3251 12
3252 10
3253 11
3254 14
3255 11
3256 2
3257 13
3258 10
3259 10
3260 11
3261 13
3262 10
3263 9
3264 6
3265 9
3266 6
3267 12
3268 8
3269 8
3270 10
3271 10
3272 13
3273 11
3274 9
3275 10
3276 11
3277 12
3278 9
3279 16
3280 9
3281 10
3282 14
3283 13
3284 9
3285 7
3286 9
3287 7
3288 13
3289 10
3290 12
3291 9
3292 7
3293 11
3294 14
3295 10
3296 12
3297 10
3298 7
3299 10
3300 9
3301 6
3302 9
3303 6
3304 8
3305 12
3306 3
3307 10
3308 10
3309 5
3310 14
3311 14
3312 12
3313 6
3314 6
3315 7
3316 6
3317 13
3318 9
3319 4
3320 10
3321 7
3322 9
3323 17
3324 10
3325 11
3326 11
3327 13
3328 10
3329 10
3330 8
3331 8
3332 10
3333 10
3334 9
3335 13
3336 5
3337 11
3338 10
3339 10
3340 9
3341 14
3342 12
3343 11
3344 12
3345 12
3346 17
3347 8
3348 3
3349 9
3350 10
3351 13
3352 8
3353 9
3354 4
3355 12
3356 13
3357 10
3358 12
3359 8
3360 11
3361 8
3362 7
3363 11
3364 10
3365 13
3366 9
3367 8
3368 12
3369 8
3370 7
3371 8
3372 8
3373 10
3374 15
3375 7
3376 9
3377 9
3378 10
3379 10
3380 16
3381 12
3382 9
3383 5
3384 10
3385 9
3386 10
3387 9
3388 13
3389 10
3390 7
3391 6
3392 8
3393 6
3394 13
3395 10
3396 14
3397 10
3398 8
3399 7
3400 8
3401 17
3402 12
3403 9
3404 13
3405 15
3406 7
3407 11
3408 9
3409 5
3410 10
3411 13
3412 8
3413 10
3414 8
3415 8
3416 6
3417 7
3418 8
3419 8
3420 16
3421 10
3422 10
3423 12
3424 9
3425 13
3426 5
3427 7
3428 7
3429 9
3430 13
3431 11
3432 10
3433 9
3434 11
3435 8
3436 4
3437 10
3438 7
3439 12
3440 12
3441 10
3442 5
3443 18
3444 13
3445 9
3446 3
3447 11
3448 7
3449 10
3450 6
3451 7
3452 16
3453 15
3454 11
3455 11
3456 10
3457 9
3458 8
3459 11
3460 12
3461 10
3462 13
3463 8
3464 7
3465 13
3466 11
3467 12
3468 7
3469 11
3470 16
3471 7
3472 11
3473 7
3474 13
3475 11
3476 9
3477 14
3478 13
3479 13
3480 15
3481 10
3482 5
3483 9
3484 11
3485 11
3486 8
3487 9
3488 7
3489 9
3490 3
3491 10
3492 12
3493 14
3494 11
3495 9
3496 14
3497 10
3498 8
3499 12
3500 10
3501 7
3502 11
3503 7
3504 13
3505 8
3506 8
3507 11
3508 12
3509 3
3510 9
3511 4
3512 11
3513 3
3514 8
3515 12
3516 8
3517 7
3518 7
3519 13
3520 5
3521 11
3522 6
3523 7
3524 12
3525 16
3526 11
3527 12
3528 10
3529 6
3530 16
3531 10
3532 9
3533 8
3534 10
3535 9
3536 7
3537 9
3538 12
3539 11
3540 5
3541 11
3542 9
3543 16
3544 12
3545 10
3546 8
3547 9
3548 6
3549 10
3550 10
3551 14
3552 7
3553 12
3554 9
3555 10
3556 9
3557 8
3558 15
3559 12
3560 13
3561 9
3562 9
3563 10
3564 9
3565 11
3566 18
3567 5
3568 8
3569 10
3570 10
3571 9
3572 7
3573 10
3574 8
3575 12
3576 12
3577 15
3578 9
3579 12
3580 16
3581 9
3582 13
3583 4
3584 15
3585 8
3586 8
3587 9
3588 16
3589 9
3590 10
3591 16
3592 12
3593 9
3594 10
3595 12
3596 15
3597 9
3598 4
3599 13
3600 7
3601 9
3602 14
3603 14
3604 6
3605 10
3606 11
3607 11
3608 7
3609 6
3610 6
3611 10
3612 13
3613 4
3614 9
3615 11
3616 17
3617 9
3618 7
3619 8
3620 7
3621 12
3622 9
3623 12
3624 10
3625 8
3626 5
3627 7
3628 12
3629 9
3630 12
3631 4
3632 18
3633 5
3634 4
3635 12
3636 11
3637 5
3638 7
3639 9
3640 4
3641 8
3642 13
3643 7
3644 11
3645 8
3646 19
3647 10
3648 15
3649 12
3650 8
3651 17
3652 12
3653 13
3654 13
3655 13
3656 6
3657 11
3658 9
3659 15
3660 7
3661 8
3662 17
3663 5
3664 15
3665 14
3666 11
3667 16
3668 6
3669 9
3670 17
3671 10
3672 6
3673 6
3674 12
3675 9
3676 9
3677 10
3678 12
3679 14
3680 14
3681 5
3682 7
3683 12
3684 5
3685 7
3686 14
3687 13
3688 7
3689 16
3690 19
3691 11
3692 6
3693 10
3694 10
3695 11
3696 9
3697 9
3698 9
3699 9
3700 10
3701 12
3702 11
3703 10
3704 13
3705 9
3706 13
3707 9
3708 13
3709 11
3710 9
3711 8
3712 9
3713 13
3714 5
3715 6
3716 13
3717 14
3718 10
3719 12
3720 14
3721 7
3722 11
3723 11
3724 7
3725 6
3726 8
3727 10
3728 11
3729 16
3730 15
3731 8
3732 7
3733 3
3734 9
3735 4
3736 14
3737 10
3738 16
3739 9
3740 11
3741 18
3742 9
3743 11
3744 8
3745 8
3746 11
3747 8
3748 16
3749 8
3750 10
3751 16
3752 10
3753 7
3754 8
3755 8
3756 11
3757 11
3758 17
3759 9
3760 9
3761 13
3762 8
3763 17
3764 15
3765 9
3766 9
3767 13
3768 9
3769 13
3770 7
3771 12
3772 10
3773 10
3774 18
3775 9
3776 8
3777 6
3778 9
3779 5
3780 7
3781 6
3782 6
3783 4
3784 17
3785 7
3786 5
3787 13
3788 7
3789 8
3790 16
3791 9
3792 11
3793 5
3794 8
3795 7
3796 8
3797 7
3798 8
3799 11
3800 7
3801 9
3802 13
3803 6
3804 14
3805 15
3806 12
3807 8
3808 6
3809 14
3810 9
3811 10
3812 9
3813 9
3814 12
3815 10
3816 13
3817 12
3818 14
3819 9
3820 6
3821 11
3822 9
3823 9
3824 8
3825 5
3826 12
3827 14
3828 8
3829 12
3830 7
3831 8
3832 9
3833 11
3834 11
3835 10
3836 10
3837 8
3838 8
3839 8
3840 12
3841 6
3842 11
3843 9
3844 8
3845 11
3846 7
3847 11
3848 8
3849 7
3850 9
3851 9
3852 13
3853 13
3854 14
3855 6
3856 10
3857 9
3858 11
3859 10
3860 7
3861 11
3862 12
3863 11
3864 7
3865 10
3866 12
3867 14
3868 11
3869 18
3870 13
3871 15
3872 11
3873 4
3874 14
3875 11
3876 10
3877 12
3878 8
3879 12
3880 10
3881 8
3882 9
3883 9
3884 12
3885 12
3886 7
3887 7
3888 10
3889 10
3890 7
3891 6
3892 3
3893 11
3894 9
3895 8
3896 9
3897 9
3898 12
3899 12
3900 13
3901 7
3902 12
3903 8
3904 9
3905 8
3906 10
3907 7
3908 6
3909 10
3910 10
3911 12
3912 12
3913 15
3914 11
3915 9
3916 6
3917 8
3918 8
3919 9
3920 4
3921 6
3922 11
3923 5
3924 8
3925 7
3926 10
3927 15
3928 8
3929 10
3930 13
3931 15
3932 7
3933 12
3934 14
3935 10
3936 8
3937 6
3938 3
3939 4
3940 9
3941 15
3942 8
3943 8
3944 7
3945 7
3946 5
3947 10
3948 8
3949 8
3950 19
3951 5
3952 8
3953 14
3954 13
3955 14
3956 7
3957 7
3958 12
3959 8
3960 13
3961 10
3962 14
3963 8
3964 12
3965 9
3966 8
3967 8
3968 10
3969 12
3970 15
3971 6
3972 10
3973 10
3974 9
3975 11
3976 8
3977 9
3978 10
3979 12
3980 8
3981 11
3982 13
3983 10
3984 16
3985 10
3986 14
3987 13
3988 8
3989 9
3990 10
3991 12
3992 7
3993 4
3994 9
3995 10
3996 8
3997 7
3998 7
3999 4
4000 15
4001 16
4002 8
4003 10
4004 12
4005 6
4006 11
4007 10
4008 8
4009 14
4010 8
4011 13
4012 12
4013 11
4014 10
4015 14
4016 12
4017 15
4018 8
4019 8
4020 6
4021 15
4022 15
4023 8
4024 8
4025 7
4026 5
4027 9
4028 6
4029 12
4030 9
4031 5
4032 7
4033 13
4034 10
4035 13
4036 8
4037 13
4038 7
4039 11
4040 11
4041 4
4042 9
4043 10
4044 17
4045 4
4046 13
4047 6
4048 12
4049 11
4050 11
4051 9
4052 12
4053 9
4054 11
4055 16
4056 12
4057 13
4058 10
4059 15
4060 11
4061 10
4062 8
4063 10
4064 6
4065 7
4066 9
4067 4
4068 13
4069 6
4070 13
4071 13
4072 13
4073 12
4074 7
4075 3
4076 7
4077 3
4078 9
4079 9
4080 7
4081 10
4082 5
4083 15
4084 11
4085 14
4086 11
4087 9
4088 6
4089 6
4090 13
4091 10
4092 10
4093 5
4094 8
4095 15
[-- Attachment #5: one-at-a-time.png --]
[-- Type: image/png, Size: 5216 bytes --]
[-- Attachment #6: Type: text/plain, Size: 140 bytes --]
_______________________________________________
autofs mailing list
autofs@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-12 1:19 ` Ian Kent
2009-01-12 2:10 ` Paul Wankadia
@ 2009-01-12 4:02 ` Ian Kent
2009-01-12 4:58 ` Ian Kent
1 sibling, 1 reply; 66+ messages in thread
From: Ian Kent @ 2009-01-12 4:02 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
[-- Attachment #1: Type: text/plain, Size: 2231 bytes --]
On Mon, 2009-01-12 at 10:19 +0900, Ian Kent wrote:
>
> Oh .. didn't see this before.
>
> > How could it be worse? :P
>
> Hehe, there's an assumption without evidence in there some where.
>
> >
> > I'll check our large file map just to satisfy my curiosity.
> >
>
> Give me a chance and I'll do a couple of patches to add some statistical
> calculations to cache_dump_cache() so we can see the state of the hash
> table after a map is loaded.
Here are a couple of patches we can use to check what is going on (my
math may be wrong so it would be good if folks could check). They should
apply to the git repo source.
The first patch hash-report-stats.patch modifies cache_dump_cache() to
report some statistics.
The second patch hash-oaat-algo.patch makes the cache use the Vals
proposed oaat algorithm without changing the hash table size for
comparison.
I used an indirect map with 35000 entries as a quick check.
There are a couple of problems with this, first the map keys are a bit
random and so are not representative of actual maps and since we use
multiple caches in v5 the number of entries in a given cache may be
quite different from the total number of entries.
But, if my math is correct, we can get some marginally useful
information from the experiment.
The results:
Current algorithm:
cache: entries 35000 table size 77 ideal chain length 454.55
chain length: empty 0 min 381 max 501 avg 454.55 std 22.78
oaat algorithm:
cache: entries 35000 table size 77 ideal chain length 454.55
chain length: empty 0 min 402 max 532 avg 454.55 std 22.27
This looks a bit odd, my math is probably broken somehow.
I have to conclude that while the oaat algorithm looks worse some how,
if the math is OK, then it is likely that there are more chains closer
to the average length with less outliers (smaller variance in chain
length) than there are with the current algorithm.
It would be good if we could get some real world numbers for both
indirect and direct maps (mainly because direct maps have somewhat
different keys, full path compared to directory component).
I will do some more checks with the proposed large hash table size to
see if the small table size is hiding any bias in the distribution.
Ian
[-- Attachment #2: hash-report-stats.patch --]
[-- Type: text/x-patch, Size: 3462 bytes --]
Make cache_dump_cache() report some statistical measures instead of
From: Ian Kent <raven@themaw.net>
dumping contents of the cache.
This gets a little more complicated with v5 as we have a cache for
each map entry which itself can have multiple caches. So hash size
for large master maps matters.
---
Makefile.rules | 2 +-
daemon/lookup.c | 3 +++
lib/cache.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++----
3 files changed, 63 insertions(+), 6 deletions(-)
diff --git a/Makefile.rules b/Makefile.rules
index 30716dc..a59c3dd 100644
--- a/Makefile.rules
+++ b/Makefile.rules
@@ -13,7 +13,7 @@ INCFILES = COPYING COPYRIGHT NEWS README* TODO Makefile Makefile.rules \
INSTALLROOT = $(DESTDIR)
# autofs utility library
-AUTOFS_LIB = ../lib/autofs.a
+AUTOFS_LIB = ../lib/autofs.a -lm
# Compilers, linkers and flags
# The STRIP defined here *must not* remove any dynamic-loading symbols
diff --git a/daemon/lookup.c b/daemon/lookup.c
index 741d846..a66e3db 100644
--- a/daemon/lookup.c
+++ b/daemon/lookup.c
@@ -261,6 +261,8 @@ int lookup_nss_read_master(struct master *master, time_t age)
return !result;
}
+void cache_dump_cache(struct mapent_cache *mc);
+
static int do_read_map(struct autofs_point *ap, struct map_source *map, time_t age)
{
struct lookup_mod *lookup;
@@ -296,6 +298,7 @@ static int do_read_map(struct autofs_point *ap, struct map_source *map, time_t a
ap->entry->current = map;
status = lookup->lookup_read_map(ap, age, lookup->context);
+ cache_dump_cache(map->mc);
map->stale = 0;
diff --git a/lib/cache.c b/lib/cache.c
index 4a00367..258afd3 100644
--- a/lib/cache.c
+++ b/lib/cache.c
@@ -36,21 +36,75 @@ void cache_dump_multi(struct list_head *list)
}
}
+#include <math.h>
+
+#define min(x, y) (x <= y ? x : y)
+#define max(x, y) (x >= y ? x : y)
+
void cache_dump_cache(struct mapent_cache *mc)
{
struct mapent *me;
+ unsigned long hc_len_min, hc_len_max, hc_empty, h_entries;
+ float hc_len_tot, hc_len_avg, hc_len_var, hc_len_std;
unsigned int i;
+ /* Calculate average, minimum and maximum chain length */
+
+ hc_len_min = 30000;
+ hc_len_max = 0;
+ hc_len_tot = 0;
+ hc_empty = 0;
+ h_entries = 0;
+
for (i = 0; i < mc->size; i++) {
+ unsigned long hc_len = 0;
+
me = mc->hash[i];
+
if (me == NULL)
- continue;
- while (me) {
- logmsg("me->key=%s me->multi=%p dev=%ld ino=%ld",
- me->key, me->multi, me->dev, me->ino);
- me = me->next;
+ hc_empty++;
+ else {
+ while (me) {
+ h_entries++;
+ hc_len++;
+ me = me->next;
+ }
}
+ hc_len_min = min(hc_len_min, hc_len);
+ hc_len_max = max(hc_len_max, hc_len);
+ hc_len_tot = hc_len_tot + hc_len;
}
+
+ hc_len_avg = hc_len_tot / mc->size;
+
+ /* Calculate chain length variance */
+
+ hc_len_var = 0;
+
+ for (i = 0; i < mc->size; i++) {
+ int hc_len = 0;
+ float hc_dev;
+
+ me = mc->hash[i];
+
+ if (me != NULL) {
+ while (me) {
+ hc_len++;
+ me = me->next;
+ }
+ }
+ hc_dev = ((float) hc_len) - hc_len_avg;
+ hc_dev = hc_dev * hc_dev;
+ hc_len_var = hc_len_var + hc_dev;
+ }
+
+ hc_len_var = hc_len_var / mc->size;
+ hc_len_std = sqrtf(hc_len_var);
+
+ logmsg("cache: entries %u table size %u ideal chain length %.2f",
+ h_entries, mc->size, (float) h_entries/mc->size);
+ logmsg("chain length: empty %u min %u max %u avg %.2f std %.2f",
+ hc_empty, hc_len_min, hc_len_max, hc_len_avg, hc_len_std);
}
void cache_readlock(struct mapent_cache *mc)
[-- Attachment #3: hash-oaat-algo.patch --]
[-- Type: text/x-patch, Size: 2598 bytes --]
Use proposed oaat algorithm for hash calculation without
From: Ian Kent <raven@themaw.net>
increasing hash table size for comparison against additive
algorithm.
---
lib/cache.c | 29 ++++++++++++++++++-----------
1 files changed, 18 insertions(+), 11 deletions(-)
diff --git a/lib/cache.c b/lib/cache.c
index 258afd3..5f64359 100644
--- a/lib/cache.c
+++ b/lib/cache.c
@@ -333,20 +333,27 @@ struct mapent_cache *cache_init_null_cache(struct master *master)
return mc;
}
-static unsigned int hash(const char *key)
+static u_int32_t hash(const char *key)
{
- unsigned long hashval;
+ u_int32_t hashval;
char *s = (char *) key;
- for (hashval = 0; *s != '\0';)
- hashval += *s++;
+ for (hashval = 0; *s != '\0';) {
+ hashval += (unsigned char) *s++;
+ hashval += (hashval << 10);
+ hashval ^= (hashval >> 6);
+ }
+
+ hashval += (hashval << 3);
+ hashval ^= (hashval >> 11);
+ hashval += (hashval << 15);
return hashval % HASHSIZE;
}
-static unsigned int ino_hash(dev_t dev, ino_t ino)
+static u_int32_t ino_hash(dev_t dev, ino_t ino)
{
- unsigned long hashval;
+ u_int32_t hashval;
hashval = dev + ino;
@@ -355,7 +362,7 @@ static unsigned int ino_hash(dev_t dev, ino_t ino)
int cache_set_ino_index(struct mapent_cache *mc, const char *key, dev_t dev, ino_t ino)
{
- unsigned int ino_index = ino_hash(dev, ino);
+ u_int32_t ino_index = ino_hash(dev, ino);
struct mapent *me;
me = cache_lookup_distinct(mc, key);
@@ -377,7 +384,7 @@ struct mapent *cache_lookup_ino(struct mapent_cache *mc, dev_t dev, ino_t ino)
{
struct mapent *me = NULL;
struct list_head *head, *p;
- unsigned int ino_index;
+ u_int32_t ino_index;
ino_index_lock(mc);
ino_index = ino_hash(dev, ino);
@@ -423,7 +430,7 @@ struct mapent *cache_lookup_first(struct mapent_cache *mc)
struct mapent *cache_lookup_next(struct mapent_cache *mc, struct mapent *me)
{
struct mapent *this;
- unsigned long hashval;
+ u_int32_t hashval;
unsigned int i;
if (!me)
@@ -584,7 +591,7 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c
{
struct mapent *me, *existing = NULL;
char *pkey, *pent;
- unsigned int hashval = hash(key);
+ u_int32_t hashval = hash(key);
int status;
me = (struct mapent *) malloc(sizeof(struct mapent));
@@ -804,7 +811,7 @@ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key
int cache_delete(struct mapent_cache *mc, const char *key)
{
struct mapent *me = NULL, *pred;
- unsigned int hashval = hash(key);
+ u_int32_t hashval = hash(key);
int status, ret = CHE_OK;
char *this;
[-- Attachment #4: Type: text/plain, Size: 140 bytes --]
_______________________________________________
autofs mailing list
autofs@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply related [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-12 4:02 ` Ian Kent
@ 2009-01-12 4:58 ` Ian Kent
2009-01-13 1:52 ` Paul Wankadia
0 siblings, 1 reply; 66+ messages in thread
From: Ian Kent @ 2009-01-12 4:58 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Mon, 2009-01-12 at 13:02 +0900, Ian Kent wrote:
>
> I used an indirect map with 35000 entries as a quick check.
>
> There are a couple of problems with this, first the map keys are a bit
> random and so are not representative of actual maps and since we use
> multiple caches in v5 the number of entries in a given cache may be
> quite different from the total number of entries.
>
> But, if my math is correct, we can get some marginally useful
> information from the experiment.
>
> The results:
>
> Current algorithm:
> cache: entries 35000 table size 77 ideal chain length 454.55
> chain length: empty 0 min 381 max 501 avg 454.55 std 22.78
>
> oaat algorithm:
> cache: entries 35000 table size 77 ideal chain length 454.55
> chain length: empty 0 min 402 max 532 avg 454.55 std 22.27
>
Here are some more stats.
cache: entries 35000 table size 977 ideal chain length 35.82
chain length: empty 627 min 0 max 284 avg 35.82 std 72.14
cache: entries 35000 table size 977 ideal chain length 35.82
chain length: empty 0 min 17 max 59 avg 35.82 std 6.05
cache: entries 35000 table size 2039 ideal chain length 17.17
chain length: empty 1689 min 0 max 284 avg 17.17 std 53.05
cache: entries 35000 table size 2039 ideal chain length 17.17
chain length: empty 0 min 6 max 32 avg 17.17 std 4.18
cache: entries 35000 table size 4093 ideal chain length 8.55
chain length: empty 3743 min 0 max 284 avg 8.55 std 38.41
cache: entries 35000 table size 4093 ideal chain length 8.55
chain length: empty 2 min 0 max 21 avg 8.55 std 2.99
There's clearly something wrong with my min and probably max calculation
but the stats still show some interesting information.
It looks like the additive algorithm is biased toward a small range of
hash indexes which becomes more significant as the table size increases.
So the distribution is significantly better as table size increases.
I'm not clear on what the graphs (Pauls) are displaying but my
impression is that they also show this same distribution bias toward
clustering for the additive hash. Assuming they were done using actual
map keys that would indicate that the benefit is likely fairly general.
The only question remaining is how large should we make the table.
A size of around 4k will lead to a lot of wasted space for many common
configurations (including configurations that have many map entries
spread over several individual maps) but a size around 1k still gives
fairly long chains for large maps.
Suggestions?
PS. I'll need to make a couple of other changes as well, eg. the null
map entry cache is typically very small.
Ian
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 4/4] Replace <linux/string.h> with <string.h>
2009-01-09 18:47 ` [PATCH 4/4] Replace <linux/string.h> with <string.h> Valerie Aurora Henson
@ 2009-01-12 5:59 ` Ian Kent
0 siblings, 0 replies; 66+ messages in thread
From: Ian Kent @ 2009-01-12 5:59 UTC (permalink / raw)
To: Valerie Aurora Henson; +Cc: autofs
On Fri, 2009-01-09 at 13:47 -0500, Valerie Aurora Henson wrote:
> If installed, <linux/string.h> just includes the user-level
> string.h. If it's not installed, the compile fails.
Right.
This include file is also used by the kernel and I'd like to keep them
the same. Maybe we need some #ifdef __KERNEL__ here as I think include
<string.h> will fail during a kernel build.
Or maybe we need to move the include to fs/autofs4/dev-ioctl.c as I
don't use any str* functions in the include file any more.
>
> From: Paul Wankadia <junyer@google.com>
> Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
> ---
> include/linux/auto_dev-ioctl.h | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/include/linux/auto_dev-ioctl.h b/include/linux/auto_dev-ioctl.h
> index 91a7739..78f4b47 100644
> --- a/include/linux/auto_dev-ioctl.h
> +++ b/include/linux/auto_dev-ioctl.h
> @@ -10,7 +10,7 @@
> #ifndef _LINUX_AUTO_DEV_IOCTL_H
> #define _LINUX_AUTO_DEV_IOCTL_H
>
> -#include <linux/string.h>
> +#include <string.h>
> #include <linux/types.h>
>
> #define AUTOFS_DEVICE_NAME "autofs"
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-12 4:58 ` Ian Kent
@ 2009-01-13 1:52 ` Paul Wankadia
2009-01-13 2:24 ` Ian Kent
0 siblings, 1 reply; 66+ messages in thread
From: Paul Wankadia @ 2009-01-13 1:52 UTC (permalink / raw)
To: Ian Kent; +Cc: autofs
[-- Attachment #1.1: Type: text/plain, Size: 4119 bytes --]
On Mon, Jan 12, 2009 at 3:02 PM, Ian Kent <raven@themaw.net> wrote:
Here are a couple of patches we can use to check what is going on (my
> math may be wrong so it would be good if folks could check). They should
> apply to the git repo source.
>
> The first patch hash-report-stats.patch modifies cache_dump_cache() to
> report some statistics.
>
> The second patch hash-oaat-algo.patch makes the cache use the Vals
> proposed oaat algorithm without changing the hash table size for
> comparison.
>
> I used an indirect map with 35000 entries as a quick check.
>
> There are a couple of problems with this, first the map keys are a bit
> random and so are not representative of actual maps and since we use
> multiple caches in v5 the number of entries in a given cache may be
> quite different from the total number of entries.
>
> But, if my math is correct, we can get some marginally useful
> information from the experiment.
>
> The results:
>
> Current algorithm:
> cache: entries 35000 table size 77 ideal chain length 454.55
> chain length: empty 0 min 381 max 501 avg 454.55 std 22.78
>
> oaat algorithm:
> cache: entries 35000 table size 77 ideal chain length 454.55
> chain length: empty 0 min 402 max 532 avg 454.55 std 22.27
>
> This looks a bit odd, my math is probably broken somehow.
Perhaps you could calculate the median instead of the mean?
I have to conclude that while the oaat algorithm looks worse some how,
> if the math is OK, then it is likely that there are more chains closer
> to the average length with less outliers (smaller variance in chain
> length) than there are with the current algorithm.
>
> It would be good if we could get some real world numbers for both
> indirect and direct maps (mainly because direct maps have somewhat
> different keys, full path compared to directory component).
>
> I will do some more checks with the proposed large hash table size to
> see if the small table size is hiding any bias in the distribution.
On Mon, Jan 12, 2009 at 3:58 PM, Ian Kent <raven@themaw.net> wrote:
Here are some more stats.
>
> cache: entries 35000 table size 977 ideal chain length 35.82
> chain length: empty 627 min 0 max 284 avg 35.82 std 72.14
>
> cache: entries 35000 table size 977 ideal chain length 35.82
> chain length: empty 0 min 17 max 59 avg 35.82 std 6.05
>
>
> cache: entries 35000 table size 2039 ideal chain length 17.17
> chain length: empty 1689 min 0 max 284 avg 17.17 std 53.05
>
> cache: entries 35000 table size 2039 ideal chain length 17.17
> chain length: empty 0 min 6 max 32 avg 17.17 std 4.18
>
>
> cache: entries 35000 table size 4093 ideal chain length 8.55
> chain length: empty 3743 min 0 max 284 avg 8.55 std 38.41
>
> cache: entries 35000 table size 4093 ideal chain length 8.55
> chain length: empty 2 min 0 max 21 avg 8.55 std 2.99
>
>
> There's clearly something wrong with my min and probably max calculation
> but the stats still show some interesting information.
Why do you think that you've miscalculated the minimum?
It looks like the additive algorithm is biased toward a small range of
> hash indexes which becomes more significant as the table size increases.
> So the distribution is significantly better as table size increases.
>
> I'm not clear on what the graphs (Pauls) are displaying but my
> impression is that they also show this same distribution bias toward
> clustering for the additive hash. Assuming they were done using actual
> map keys that would indicate that the benefit is likely fairly general.
I plotted the number of elements in each bucket.
As you now see, the additive hash function doesn't scale.
The only question remaining is how large should we make the table.
> A size of around 4k will lead to a lot of wasted space for many common
> configurations (including configurations that have many map entries
> spread over several individual maps) but a size around 1k still gives
> fairly long chains for large maps.
>
> Suggestions?
Perhaps you could make it configurable?
PS. I'll need to make a couple of other changes as well, eg. the null
> map entry cache is typically very small.
[-- Attachment #1.2: Type: text/html, Size: 5559 bytes --]
[-- Attachment #2: Type: text/plain, Size: 140 bytes --]
_______________________________________________
autofs mailing list
autofs@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-13 1:52 ` Paul Wankadia
@ 2009-01-13 2:24 ` Ian Kent
2009-01-13 4:15 ` Ian Kent
0 siblings, 1 reply; 66+ messages in thread
From: Ian Kent @ 2009-01-13 2:24 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Tue, 2009-01-13 at 12:52 +1100, Paul Wankadia wrote:
> On Mon, Jan 12, 2009 at 3:02 PM, Ian Kent <raven@themaw.net> wrote:
>
> Here are a couple of patches we can use to check what is going
> on (my
> math may be wrong so it would be good if folks could check).
> They should
> apply to the git repo source.
>
> The first patch hash-report-stats.patch modifies
> cache_dump_cache() to
> report some statistics.
>
> The second patch hash-oaat-algo.patch makes the cache use the
> Vals
> proposed oaat algorithm without changing the hash table size
> for
> comparison.
>
> I used an indirect map with 35000 entries as a quick check.
>
> There are a couple of problems with this, first the map keys
> are a bit
> random and so are not representative of actual maps and since
> we use
> multiple caches in v5 the number of entries in a given cache
> may be
> quite different from the total number of entries.
>
> But, if my math is correct, we can get some marginally useful
> information from the experiment.
>
> The results:
>
> Current algorithm:
> cache: entries 35000 table size 77 ideal chain length 454.55
> chain length: empty 0 min 381 max 501 avg 454.55 std 22.78
>
> oaat algorithm:
> cache: entries 35000 table size 77 ideal chain length 454.55
> chain length: empty 0 min 402 max 532 avg 454.55 std 22.27
>
> This looks a bit odd, my math is probably broken somehow.
>
> Perhaps you could calculate the median instead of the mean?
I was thinking that the min and max looked a bit odd.
To calculate the median we would have to assume a normal distribution
(or find some way to work out what type of distribution it is, too hard)
and then it's (min + max)/2.
>
>
> I have to conclude that while the oaat algorithm looks worse
> some how,
> if the math is OK, then it is likely that there are more
> chains closer
> to the average length with less outliers (smaller variance in
> chain
> length) than there are with the current algorithm.
>
> It would be good if we could get some real world numbers for
> both
> indirect and direct maps (mainly because direct maps have
> somewhat
> different keys, full path compared to directory component).
>
> I will do some more checks with the proposed large hash table
> size to
> see if the small table size is hiding any bias in the
> distribution.
>
> On Mon, Jan 12, 2009 at 3:58 PM, Ian Kent <raven@themaw.net> wrote:
>
> Here are some more stats.
>
> cache: entries 35000 table size 977 ideal chain length 35.82
> chain length: empty 627 min 0 max 284 avg 35.82 std 72.14
>
> cache: entries 35000 table size 977 ideal chain length 35.82
> chain length: empty 0 min 17 max 59 avg 35.82 std 6.05
>
>
> cache: entries 35000 table size 2039 ideal chain length 17.17
> chain length: empty 1689 min 0 max 284 avg 17.17 std 53.05
>
> cache: entries 35000 table size 2039 ideal chain length 17.17
> chain length: empty 0 min 6 max 32 avg 17.17 std 4.18
>
>
> cache: entries 35000 table size 4093 ideal chain length 8.55
> chain length: empty 3743 min 0 max 284 avg 8.55 std 38.41
>
> cache: entries 35000 table size 4093 ideal chain length 8.55
> chain length: empty 2 min 0 max 21 avg 8.55 std 2.99
>
>
> There's clearly something wrong with my min and probably max
> calculation
> but the stats still show some interesting information.
>
> Why do you think that you've miscalculated the minimum?
Well, maybe I haven't but I thought min should be > 0.
But, it's not worth worrying about as I think we've managed to show a
clear improvement.
>
>
> It looks like the additive algorithm is biased toward a small
> range of
> hash indexes which becomes more significant as the table size
> increases.
> So the distribution is significantly better as table size
> increases.
>
> I'm not clear on what the graphs (Pauls) are displaying but my
> impression is that they also show this same distribution bias
> toward
> clustering for the additive hash. Assuming they were done
> using actual
> map keys that would indicate that the benefit is likely fairly
> general.
>
> I plotted the number of elements in each bucket.
>
> As you now see, the additive hash function doesn't scale.
Sure and now we can say why it doesn't scale in the patch description.
>
>
> The only question remaining is how large should we make the
> table.
> A size of around 4k will lead to a lot of wasted space for
> many common
> configurations (including configurations that have many map
> entries
> spread over several individual maps) but a size around 1k
> still gives
> fairly long chains for large maps.
>
> Suggestions?
>
> Perhaps you could make it configurable?
Perhaps, but I don't think this is the sort of thing that should be
configurable so I'd prefer to make it a compile time option rather than
a run time configuration setting.
>
>
> PS. I'll need to make a couple of other changes as well, eg.
> the null
> map entry cache is typically very small.
>
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-13 2:24 ` Ian Kent
@ 2009-01-13 4:15 ` Ian Kent
2009-01-13 5:07 ` Paul Wankadia
0 siblings, 1 reply; 66+ messages in thread
From: Ian Kent @ 2009-01-13 4:15 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Tue, 2009-01-13 at 11:24 +0900, Ian Kent wrote:
> On Tue, 2009-01-13 at 12:52 +1100, Paul Wankadia wrote:
> >
> >
> > The only question remaining is how large should we make the
> > table.
> > A size of around 4k will lead to a lot of wasted space for
> > many common
> > configurations (including configurations that have many map
> > entries
> > spread over several individual maps) but a size around 1k
> > still gives
> > fairly long chains for large maps.
> >
> > Suggestions?
> >
> > Perhaps you could make it configurable?
>
> Perhaps, but I don't think this is the sort of thing that should be
> configurable so I'd prefer to make it a compile time option rather than
> a run time configuration setting.
I've changed my mind, ;), configurable it is with a default of 977.
Ian
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-13 4:15 ` Ian Kent
@ 2009-01-13 5:07 ` Paul Wankadia
2009-01-13 5:19 ` Ian Kent
0 siblings, 1 reply; 66+ messages in thread
From: Paul Wankadia @ 2009-01-13 5:07 UTC (permalink / raw)
To: Ian Kent; +Cc: autofs
[-- Attachment #1.1: Type: text/plain, Size: 1023 bytes --]
On Tue, Jan 13, 2009 at 1:24 PM, Ian Kent <raven@themaw.net> wrote:
> Why do you think that you've miscalculated the minimum?
>
> Well, maybe I haven't but I thought min should be > 0.
> But, it's not worth worrying about as I think we've managed to show a
> clear improvement.
The minimum was zero because there were empty buckets.
> I plotted the number of elements in each bucket.
> >
> > As you now see, the additive hash function doesn't scale.
>
> Sure and now we can say why it doesn't scale in the patch description.
More importantly, who's the scapegoat? :P
> Perhaps you could make it configurable?
>
> Perhaps, but I don't think this is the sort of thing that should be
> configurable so I'd prefer to make it a compile time option rather than
> a run time configuration setting.
On Tue, Jan 13, 2009 at 3:15 PM, Ian Kent <raven@themaw.net> wrote:
I've changed my mind, ;), configurable it is with a default of 977.
The hash function is good now, so the size of the hash table can be a power
of two.
[-- Attachment #1.2: Type: text/html, Size: 1955 bytes --]
[-- Attachment #2: Type: text/plain, Size: 140 bytes --]
_______________________________________________
autofs mailing list
autofs@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-13 5:07 ` Paul Wankadia
@ 2009-01-13 5:19 ` Ian Kent
2009-01-14 3:43 ` Paul Wankadia
0 siblings, 1 reply; 66+ messages in thread
From: Ian Kent @ 2009-01-13 5:19 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Tue, 2009-01-13 at 16:07 +1100, Paul Wankadia wrote:
> On Tue, Jan 13, 2009 at 1:24 PM, Ian Kent <raven@themaw.net> wrote:
>
> > Why do you think that you've miscalculated the minimum?
>
> Well, maybe I haven't but I thought min should be > 0.
> But, it's not worth worrying about as I think we've managed to
> show a
> clear improvement.
>
> The minimum was zero because there were empty buckets.
Probably, but I used a separate variable to count zero buckets so the
chain lengths should be at least 1, but hey, unless the analysis here is
wrong (and I don't think it is) I'm not not going to spend time on it.
>
>
> > I plotted the number of elements in each bucket.
> >
> > As you now see, the additive hash function doesn't scale.
>
> Sure and now we can say why it doesn't scale in the patch
> description.
>
> More importantly, who's the scapegoat? :P
That would be me, ;)
>
>
> > Perhaps you could make it configurable?
>
> Perhaps, but I don't think this is the sort of thing that
> should be
> configurable so I'd prefer to make it a compile time option
> rather than
> a run time configuration setting.
>
> On Tue, Jan 13, 2009 at 3:15 PM, Ian Kent <raven@themaw.net> wrote:
>
> I've changed my mind, ;), configurable it is with a default of
> 977.
>
> The hash function is good now, so the size of the hash table can be a
> power of two.
So your suggesting 1024 then, does it matter?
Ian
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-09 18:47 ` [PATCH 1/4] Make hash table scale to thousands of entries Valerie Aurora Henson
` (2 preceding siblings ...)
2009-01-10 3:29 ` Ian Kent
@ 2009-01-13 5:51 ` Ian Kent
2009-01-14 3:58 ` Paul Wankadia
3 siblings, 1 reply; 66+ messages in thread
From: Ian Kent @ 2009-01-13 5:51 UTC (permalink / raw)
To: Valerie Aurora Henson, Paul Wankadia; +Cc: autofs
On Fri, 2009-01-09 at 13:47 -0500, Valerie Aurora Henson wrote:
> From: Paul Wankadia <junyer@google.com>
> Signed-off-by: Valerie Aurora Henson <vaurora@redhat.com>
I think were about done with this.
Here's a patch with a few changes by me, please comment.
--
autofs-5.0.4 - make hash table scale to thousands of entries
From: Valerie Aurora Henson <vaurora@redhat.com>
Originally written by Paul Wankadia <junyer@google.com>.
The autofs cache lookup performs poorly for large maps.
The additive hashing algorithm used by autofs results in a clustering
of hash values around the average hash chain size. It is biased toward
a small range of hash indexes which becomes worse as the hash table size
increases.
Simple testing shows that the "One-at-a-time" hash function (implemented
by this patch) gives a much better distribution of hash indexes as table
size increases.
The only change made to the original patch is to make the hash table size
configurable with a default somewhat larger than it is currently.
---
CHANGELOG | 2 ++
include/automount.h | 2 +-
include/defaults.h | 3 +++
lib/cache.c | 47 +++++++++++++++++++++++-----------------
lib/defaults.c | 16 +++++++++++++-
redhat/autofs.sysconfig.in | 6 +++++
samples/autofs.conf.default.in | 6 +++++
7 files changed, 60 insertions(+), 22 deletions(-)
diff --git a/CHANGELOG b/CHANGELOG
index 43f3205..c1dc1b1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -4,6 +4,8 @@
- fix nested submount expire deadlock.
- fix negative caching for non-existent map keys.
- use CLOEXEC flag.
+- make hash table scale to thousands of entries (Paul Wankadia,
+ Valerie Aurora Henson).
4/11/2008 autofs-5.0.4
-----------------------
diff --git a/include/automount.h b/include/automount.h
index a083b61..938690f 100644
--- a/include/automount.h
+++ b/include/automount.h
@@ -128,7 +128,7 @@ struct autofs_point;
#define CHE_DUPLICATE 0x0020
#define CHE_UNAVAIL 0x0040
-#define HASHSIZE 77
+#define NULL_MAP_HASHSIZE 64
#define NEGATIVE_TIMEOUT 10
#define UMOUNT_RETRIES 8
#define EXPIRE_RETRIES 3
diff --git a/include/defaults.h b/include/defaults.h
index 12534ec..9a2430f 100644
--- a/include/defaults.h
+++ b/include/defaults.h
@@ -40,6 +40,8 @@
#define DEFAULT_APPEND_OPTIONS 1
#define DEFAULT_AUTH_CONF_FILE AUTOFS_MAP_DIR "/autofs_ldap_auth.conf"
+#define DEFAULT_MAP_HASH_TABLE_SIZE 1024
+
struct ldap_schema;
struct ldap_searchdn;
@@ -62,6 +64,7 @@ void defaults_free_searchdns(struct ldap_searchdn *);
unsigned int defaults_get_append_options(void);
unsigned int defaults_get_umount_wait(void);
const char *defaults_get_auth_conf_file(void);
+unsigned int defaults_get_map_hash_table_size(void);
#endif
diff --git a/lib/cache.c b/lib/cache.c
index 4a00367..edb3192 100644
--- a/lib/cache.c
+++ b/lib/cache.c
@@ -190,7 +190,7 @@ struct mapent_cache *cache_init(struct autofs_point *ap, struct map_source *map)
if (!mc)
return NULL;
- mc->size = HASHSIZE;
+ mc->size = defaults_get_map_hash_table_size();
mc->hash = malloc(mc->size * sizeof(struct entry *));
if (!mc->hash) {
@@ -241,7 +241,7 @@ struct mapent_cache *cache_init_null_cache(struct master *master)
if (!mc)
return NULL;
- mc->size = HASHSIZE;
+ mc->size = NULL_MAP_HASHSIZE;
mc->hash = malloc(mc->size * sizeof(struct entry *));
if (!mc->hash) {
@@ -279,29 +279,36 @@ struct mapent_cache *cache_init_null_cache(struct master *master)
return mc;
}
-static unsigned int hash(const char *key)
+static u_int32_t hash(const char *key, unsigned int size)
{
- unsigned long hashval;
+ u_int32_t hashval;
char *s = (char *) key;
- for (hashval = 0; *s != '\0';)
- hashval += *s++;
+ for (hashval = 0; *s != '\0';) {
+ hashval += (unsigned char) *s++;
+ hashval += (hashval << 10);
+ hashval ^= (hashval >> 6);
+ }
+
+ hashval += (hashval << 3);
+ hashval ^= (hashval >> 11);
+ hashval += (hashval << 15);
- return hashval % HASHSIZE;
+ return hashval % size;
}
-static unsigned int ino_hash(dev_t dev, ino_t ino)
+static u_int32_t ino_hash(dev_t dev, ino_t ino, unsigned int size)
{
- unsigned long hashval;
+ u_int32_t hashval;
hashval = dev + ino;
- return hashval % HASHSIZE;
+ return hashval % size;
}
int cache_set_ino_index(struct mapent_cache *mc, const char *key, dev_t dev, ino_t ino)
{
- unsigned int ino_index = ino_hash(dev, ino);
+ u_int32_t ino_index = ino_hash(dev, ino, mc->size);
struct mapent *me;
me = cache_lookup_distinct(mc, key);
@@ -323,10 +330,10 @@ struct mapent *cache_lookup_ino(struct mapent_cache *mc, dev_t dev, ino_t ino)
{
struct mapent *me = NULL;
struct list_head *head, *p;
- unsigned int ino_index;
+ u_int32_t ino_index;
ino_index_lock(mc);
- ino_index = ino_hash(dev, ino);
+ ino_index = ino_hash(dev, ino, mc->size);
head = &mc->ino_index[ino_index];
list_for_each(p, head) {
@@ -369,7 +376,7 @@ struct mapent *cache_lookup_first(struct mapent_cache *mc)
struct mapent *cache_lookup_next(struct mapent_cache *mc, struct mapent *me)
{
struct mapent *this;
- unsigned long hashval;
+ u_int32_t hashval;
unsigned int i;
if (!me)
@@ -385,7 +392,7 @@ struct mapent *cache_lookup_next(struct mapent_cache *mc, struct mapent *me)
return this;
}
- hashval = hash(me->key) + 1;
+ hashval = hash(me->key, mc->size) + 1;
if (hashval < mc->size) {
for (i = (unsigned int) hashval; i < mc->size; i++) {
this = mc->hash[i];
@@ -433,7 +440,7 @@ struct mapent *cache_lookup(struct mapent_cache *mc, const char *key)
if (!key)
return NULL;
- for (me = mc->hash[hash(key)]; me != NULL; me = me->next) {
+ for (me = mc->hash[hash(key, mc->size)]; me != NULL; me = me->next) {
if (strcmp(key, me->key) == 0)
goto done;
}
@@ -446,7 +453,7 @@ struct mapent *cache_lookup(struct mapent_cache *mc, const char *key)
goto done;
}
- for (me = mc->hash[hash("*")]; me != NULL; me = me->next)
+ for (me = mc->hash[hash("*", mc->size)]; me != NULL; me = me->next)
if (strcmp("*", me->key) == 0)
goto done;
}
@@ -462,7 +469,7 @@ struct mapent *cache_lookup_distinct(struct mapent_cache *mc, const char *key)
if (!key)
return NULL;
- for (me = mc->hash[hash(key)]; me != NULL; me = me->next) {
+ for (me = mc->hash[hash(key, mc->size)]; me != NULL; me = me->next) {
if (strcmp(key, me->key) == 0)
return me;
}
@@ -530,7 +537,7 @@ int cache_add(struct mapent_cache *mc, struct map_source *ms, const char *key, c
{
struct mapent *me, *existing = NULL;
char *pkey, *pent;
- unsigned int hashval = hash(key);
+ u_int32_t hashval = hash(key, mc->size);
int status;
me = (struct mapent *) malloc(sizeof(struct mapent));
@@ -750,7 +757,7 @@ int cache_update(struct mapent_cache *mc, struct map_source *ms, const char *key
int cache_delete(struct mapent_cache *mc, const char *key)
{
struct mapent *me = NULL, *pred;
- unsigned int hashval = hash(key);
+ u_int32_t hashval = hash(key, mc->size);
int status, ret = CHE_OK;
char *this;
diff --git a/lib/defaults.c b/lib/defaults.c
index ff653e3..0d39716 100644
--- a/lib/defaults.c
+++ b/lib/defaults.c
@@ -49,6 +49,8 @@
#define ENV_UMOUNT_WAIT "UMOUNT_WAIT"
#define ENV_AUTH_CONF_FILE "AUTH_CONF_FILE"
+#define ENV_MAP_HASH_TABLE_SIZE "MAP_HASH_TABLE_SIZE"
+
static const char *default_master_map_name = DEFAULT_MASTER_MAP_NAME;
static const char *default_auth_conf_file = DEFAULT_AUTH_CONF_FILE;
@@ -323,7 +325,8 @@ unsigned int defaults_read_config(unsigned int to_syslog)
check_set_config_value(key, ENV_NAME_VALUE_ATTR, value, to_syslog) ||
check_set_config_value(key, ENV_APPEND_OPTIONS, value, to_syslog) ||
check_set_config_value(key, ENV_UMOUNT_WAIT, value, to_syslog) ||
- check_set_config_value(key, ENV_AUTH_CONF_FILE, value, to_syslog))
+ check_set_config_value(key, ENV_AUTH_CONF_FILE, value, to_syslog) ||
+ check_set_config_value(key, ENV_MAP_HASH_TABLE_SIZE, value, to_syslog))
;
}
@@ -672,3 +675,14 @@ const char *defaults_get_auth_conf_file(void)
return (const char *) cf;
}
+unsigned int defaults_get_map_hash_table_size(void)
+{
+ long size;
+
+ size = get_env_number(ENV_MAP_HASH_TABLE_SIZE);
+ if (size < 0)
+ size = DEFAULT_MAP_HASH_TABLE_SIZE;
+
+ return (unsigned int) size;
+}
+
diff --git a/redhat/autofs.sysconfig.in b/redhat/autofs.sysconfig.in
index 8256888..ff49ff6 100644
--- a/redhat/autofs.sysconfig.in
+++ b/redhat/autofs.sysconfig.in
@@ -89,6 +89,12 @@ BROWSE_MODE="no"
#
#AUTH_CONF_FILE="@@autofsmapdir@@/autofs_ldap_auth.conf"
#
+# MAP_HASH_TABLE_SIZE - set the map cache hash table size.
+# Should be a power of 2 with a ratio roughly
+# between 1:10 and 1:20 for each map.
+#
+#MAP_HASH_TABLE_SIZE=1024
+#
# General global options
#
# If the kernel supports using the autofs miscellanous device
diff --git a/samples/autofs.conf.default.in b/samples/autofs.conf.default.in
index 844a6f3..4496738 100644
--- a/samples/autofs.conf.default.in
+++ b/samples/autofs.conf.default.in
@@ -89,6 +89,12 @@ BROWSE_MODE="no"
#
#AUTH_CONF_FILE="@@autofsmapdir@@/autofs_ldap_auth.conf"
#
+# MAP_HASH_TABLE_SIZE - set the map cache hash table size.
+# Should be a power of 2 with a ratio roughly
+# between 1:10 and 1:20 for each map.
+#
+#MAP_HASH_TABLE_SIZE=1024
+#
# General global options
#
# If the kernel supports using the autofs miscellanous device
^ permalink raw reply related [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-13 5:19 ` Ian Kent
@ 2009-01-14 3:43 ` Paul Wankadia
2009-01-14 8:47 ` Ian Kent
0 siblings, 1 reply; 66+ messages in thread
From: Paul Wankadia @ 2009-01-14 3:43 UTC (permalink / raw)
To: Ian Kent; +Cc: autofs
[-- Attachment #1.1: Type: text/plain, Size: 596 bytes --]
On Tue, Jan 13, 2009 at 4:19 PM, Ian Kent <raven@themaw.net> wrote:
> More importantly, who's the scapegoat? :P
>
> That would be me, ;)
It seems that autofs v5 doesn't read an indirect map into the cache unless
ghosting is enabled, so I'm thinking about adding a map option to force the
read. Has the file map reloading logic changed significantly since autofs
v4?
> The hash function is good now, so the size of the hash table can be a
> > power of two.
>
> So your suggesting 1024 then, does it matter?
%1024 should become &1023 due to strength reduction, but it's not overly
important.
[-- Attachment #1.2: Type: text/html, Size: 1062 bytes --]
[-- Attachment #2: Type: text/plain, Size: 140 bytes --]
_______________________________________________
autofs mailing list
autofs@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-13 5:51 ` Ian Kent
@ 2009-01-14 3:58 ` Paul Wankadia
2009-01-14 8:48 ` Ian Kent
2009-01-15 4:42 ` Ian Kent
0 siblings, 2 replies; 66+ messages in thread
From: Paul Wankadia @ 2009-01-14 3:58 UTC (permalink / raw)
To: Ian Kent; +Cc: autofs
[-- Attachment #1.1: Type: text/plain, Size: 179 bytes --]
On Tue, Jan 13, 2009 at 4:51 PM, Ian Kent <raven@themaw.net> wrote:
I think were about done with this.
> Here's a patch with a few changes by me, please comment.
LGTM. Thanks.
[-- Attachment #1.2: Type: text/html, Size: 455 bytes --]
[-- Attachment #2: Type: text/plain, Size: 140 bytes --]
_______________________________________________
autofs mailing list
autofs@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-14 3:43 ` Paul Wankadia
@ 2009-01-14 8:47 ` Ian Kent
2009-01-14 10:52 ` Paul Wankadia
0 siblings, 1 reply; 66+ messages in thread
From: Ian Kent @ 2009-01-14 8:47 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Wed, 2009-01-14 at 14:43 +1100, Paul Wankadia wrote:
> On Tue, Jan 13, 2009 at 4:19 PM, Ian Kent <raven@themaw.net> wrote:
>
> > More importantly, who's the scapegoat? :P
>
> That would be me, ;)
>
> It seems that autofs v5 doesn't read an indirect map into the cache
> unless ghosting is enabled, so I'm thinking about adding a map option
> to force the read. Has the file map reloading logic changed
> significantly since autofs v4?
It's a bit hard to give a good answer to that as there have been so many
changes but, having said that, it shouldn't have changed much except for
the obvious one that it tries not to read the entire map unless it has
to. Adding the "--ghost" or "browse" option will cause it to read the
entire map. Also, the internal default, which is "browse" enabled by
default, is overridden by the default installed configuration with
BROWSE_MODE="no" so v5 behaves the same as v4.
>
>
> > The hash function is good now, so the size of the hash table
> can be a
> > power of two.
>
> So your suggesting 1024 then, does it matter?
>
> %1024 should become &1023 due to strength reduction, but it's not
> overly important.
>
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-14 3:58 ` Paul Wankadia
@ 2009-01-14 8:48 ` Ian Kent
2009-01-15 2:47 ` Valerie Aurora Henson
2009-01-15 4:42 ` Ian Kent
1 sibling, 1 reply; 66+ messages in thread
From: Ian Kent @ 2009-01-14 8:48 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Wed, 2009-01-14 at 14:58 +1100, Paul Wankadia wrote:
> On Tue, Jan 13, 2009 at 4:51 PM, Ian Kent <raven@themaw.net> wrote:
>
> I think were about done with this.
> Here's a patch with a few changes by me, please comment.
>
> LGTM. Thanks.
Great.
I'll wait and see if Val spots anything before I commit it.
Ian
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-14 8:47 ` Ian Kent
@ 2009-01-14 10:52 ` Paul Wankadia
2009-01-14 13:17 ` Ian Kent
0 siblings, 1 reply; 66+ messages in thread
From: Paul Wankadia @ 2009-01-14 10:52 UTC (permalink / raw)
To: Ian Kent; +Cc: autofs
[-- Attachment #1.1: Type: text/plain, Size: 958 bytes --]
On Wed, Jan 14, 2009 at 7:47 PM, Ian Kent <raven@themaw.net> wrote:
> It seems that autofs v5 doesn't read an indirect map into the cache
> > unless ghosting is enabled, so I'm thinking about adding a map option
> > to force the read. Has the file map reloading logic changed
> > significantly since autofs v4?
>
> It's a bit hard to give a good answer to that as there have been so many
> changes but, having said that, it shouldn't have changed much except for
> the obvious one that it tries not to read the entire map unless it has
> to. Adding the "--ghost" or "browse" option will cause it to read the
> entire map. Also, the internal default, which is "browse" enabled by
> default, is overridden by the default installed configuration with
> BROWSE_MODE="no" so v5 behaves the same as v4.
Sorry, I meant the logic that reloads the file map if it's been modified. I
know that autofs v4 checked the mtime, but I can't see where autofs v5 does
that.
[-- Attachment #1.2: Type: text/html, Size: 1350 bytes --]
[-- Attachment #2: Type: text/plain, Size: 140 bytes --]
_______________________________________________
autofs mailing list
autofs@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-14 10:52 ` Paul Wankadia
@ 2009-01-14 13:17 ` Ian Kent
2009-01-14 14:20 ` Paul Wankadia
0 siblings, 1 reply; 66+ messages in thread
From: Ian Kent @ 2009-01-14 13:17 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Wed, 2009-01-14 at 21:52 +1100, Paul Wankadia wrote:
> On Wed, Jan 14, 2009 at 7:47 PM, Ian Kent <raven@themaw.net> wrote:
>
> > It seems that autofs v5 doesn't read an indirect map into
> the cache
> > unless ghosting is enabled, so I'm thinking about adding a
> map option
> > to force the read. Has the file map reloading logic changed
> > significantly since autofs v4?
>
>
> It's a bit hard to give a good answer to that as there have
> been so many
> changes but, having said that, it shouldn't have changed much
> except for
> the obvious one that it tries not to read the entire map
> unless it has
> to. Adding the "--ghost" or "browse" option will cause it to
> read the
> entire map. Also, the internal default, which is "browse"
> enabled by
> default, is overridden by the default installed configuration
> with
> BROWSE_MODE="no" so v5 behaves the same as v4.
>
> Sorry, I meant the logic that reloads the file map if it's been
> modified. I know that autofs v4 checked the mtime, but I can't see
> where autofs v5 does that.
Yeah, I didn't think I got rid of that.
But the check for a mismatch between the cache and a file key lookup
should be sufficient to only cause a read when the map has actually
changed. I guess we could get multiple HUP signals, one following just
after the other has finished, but that would be a system admin error and
you'd probably want to know about that since we can't make a similar
check some other map sources. I probably should get around to removing
the mtime stuff all-together, perhaps you could let me know if things
work as they should (or not) so I can clean (or fix) that up.
Ian
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-14 13:17 ` Ian Kent
@ 2009-01-14 14:20 ` Paul Wankadia
2009-01-15 1:41 ` Ian Kent
0 siblings, 1 reply; 66+ messages in thread
From: Paul Wankadia @ 2009-01-14 14:20 UTC (permalink / raw)
To: Ian Kent; +Cc: autofs
[-- Attachment #1.1: Type: text/plain, Size: 1140 bytes --]
On Thu, Jan 15, 2009 at 12:17 AM, Ian Kent <raven@themaw.net> wrote:
> Sorry, I meant the logic that reloads the file map if it's been
> > modified. I know that autofs v4 checked the mtime, but I can't see
> > where autofs v5 does that.
>
> Yeah, I didn't think I got rid of that.
>
> But the check for a mismatch between the cache and a file key lookup
> should be sufficient to only cause a read when the map has actually
> changed. I guess we could get multiple HUP signals, one following just
> after the other has finished, but that would be a system admin error and
> you'd probably want to know about that since we can't make a similar
> check some other map sources. I probably should get around to removing
> the mtime stuff all-together, perhaps you could let me know if things
> work as they should (or not) so I can clean (or fix) that up.
Are you saying that every lookup for an indirect map will hit the file? If
that's the case, then what's the point of the cache? If that's not the case,
but you're not checking the mtime either, then how do you know when the file
has been modified? (Please excuse the silly questions.)
[-- Attachment #1.2: Type: text/html, Size: 1530 bytes --]
[-- Attachment #2: Type: text/plain, Size: 140 bytes --]
_______________________________________________
autofs mailing list
autofs@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-14 14:20 ` Paul Wankadia
@ 2009-01-15 1:41 ` Ian Kent
2009-01-15 15:04 ` Jeff Moyer
0 siblings, 1 reply; 66+ messages in thread
From: Ian Kent @ 2009-01-15 1:41 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Thu, 2009-01-15 at 01:20 +1100, Paul Wankadia wrote:
> On Thu, Jan 15, 2009 at 12:17 AM, Ian Kent <raven@themaw.net> wrote:
>
>
> > Sorry, I meant the logic that reloads the file map if it's
> been
> > modified. I know that autofs v4 checked the mtime, but I
> can't see
> > where autofs v5 does that.
>
>
> Yeah, I didn't think I got rid of that.
>
> But the check for a mismatch between the cache and a file key
> lookup
> should be sufficient to only cause a read when the map has
> actually
> changed. I guess we could get multiple HUP signals, one
> following just
> after the other has finished, but that would be a system admin
> error and
> you'd probably want to know about that since we can't make a
> similar
> check some other map sources. I probably should get around to
> removing
> the mtime stuff all-together, perhaps you could let me know if
> things
> work as they should (or not) so I can clean (or fix) that up.
>
> Are you saying that every lookup for an indirect map will hit the
> file? If that's the case, then what's the point of the cache? If
> that's not the case, but you're not checking the mtime either, then
> how do you know when the file has been modified? (Please excuse the
> silly questions.)
>
Umm .... yeah (runs and hides behind a large bookshelf in office).
This isn't a silly question at all.
It's something that could make the poor performance of the hash function
look efficient and needs to be fixed (at least it matters for large
maps).
In the beginning I used the cache, well, like a cache, and required a
HUP signal to update the maps. That was seen to be "just not good
enough" as people required the map entry used to be up to date at the
time of use. This lead to the cache gradually becoming more of a
reference used to check currency of map entries to trigger map re-reads
when differences were spotted. This seemed better than just using
periodic map re-reads and seems to work OK. Remember that in v5 the
cache starts empty for nobrowse indirect mounts and old entries get
cleaned out upon receiving a HUP signal. That's OK for maps that have
direct key lookup but for really large file maps it's almost certainly
worse than the poor hashing algorithm.
We use the cache a lot, for a bunch of other checks, to maintain context
for multi-mount map entries and for direct maps. Map entries with
multiple offsets (the so called multi-mount map entries) the entry is
expanded, each offset added to the cache and a mount trigger mounted.
This is part of the mount/umount "as you go" functionality in v5 which
is really useful for servers with really large export lists, for
example. Because of the nature of direct mounts the entire map must be
read at startup and a HUP signal must be sent to the daemon for changes
to be seen and we never go to the map during lookups, only the cache.
But onto the problem.
It should be fairly straight forward to start using the map mtime again.
The time stamp on cache entries that have been added will be later than
the mtime if the file map hasn't changed so we can use that. But we also
need to prevent re-reading the map from the beginning as we populate the
cache. I was thinking that I could add each entry read during a lookup
to the cache so that they would be found on subsequent lookups (as long
as the mtime is earlier than the time stamp). Additionally, I could keep
track of the file position so I don't read entries already read. It
likely won't be quite as simple in the end but we really need to do
something to for really large maps.
Any other thoughts?
Ian
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-14 8:48 ` Ian Kent
@ 2009-01-15 2:47 ` Valerie Aurora Henson
2009-01-15 3:02 ` Ian Kent
2009-01-15 5:06 ` Paul Wankadia
0 siblings, 2 replies; 66+ messages in thread
From: Valerie Aurora Henson @ 2009-01-15 2:47 UTC (permalink / raw)
To: Ian Kent; +Cc: autofs, Paul Wankadia
On Wed, Jan 14, 2009 at 05:48:09PM +0900, Ian Kent wrote:
> On Wed, 2009-01-14 at 14:58 +1100, Paul Wankadia wrote:
> > On Tue, Jan 13, 2009 at 4:51 PM, Ian Kent <raven@themaw.net> wrote:
> >
> > I think were about done with this.
> > Here's a patch with a few changes by me, please comment.
> >
> > LGTM. Thanks.
>
> Great.
> I'll wait and see if Val spots anything before I commit it.
Just a quick note - I'm very sick right now (just a cold, but a nasty
one) and not up to writing or reviewing patches. I'll take a look as
soon as my brain is reliable, hopefully in the next couple of days.
Thanks to both of you! BTW, Paul found and wrote the one-at-a-time
hash algorithm, credit where credit is due.
-VAL
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-15 2:47 ` Valerie Aurora Henson
@ 2009-01-15 3:02 ` Ian Kent
2009-01-16 21:39 ` Valerie Aurora Henson
2009-01-15 5:06 ` Paul Wankadia
1 sibling, 1 reply; 66+ messages in thread
From: Ian Kent @ 2009-01-15 3:02 UTC (permalink / raw)
To: Valerie Aurora Henson; +Cc: autofs, Paul Wankadia
On Wed, 2009-01-14 at 21:47 -0500, Valerie Aurora Henson wrote:
> On Wed, Jan 14, 2009 at 05:48:09PM +0900, Ian Kent wrote:
> > On Wed, 2009-01-14 at 14:58 +1100, Paul Wankadia wrote:
> > > On Tue, Jan 13, 2009 at 4:51 PM, Ian Kent <raven@themaw.net> wrote:
> > >
> > > I think were about done with this.
> > > Here's a patch with a few changes by me, please comment.
> > >
> > > LGTM. Thanks.
> >
> > Great.
> > I'll wait and see if Val spots anything before I commit it.
>
> Just a quick note - I'm very sick right now (just a cold, but a nasty
> one) and not up to writing or reviewing patches. I'll take a look as
> soon as my brain is reliable, hopefully in the next couple of days.
Bummer, hope you recover soon.
I'm about to commit it so we'll have to deal with any concerns you have
as update patches. It's not much different to the original anyway. We
also need to spend a bit more time on the other three patches you posted
when your up to it. I think Jeff got some regressions when testing
these. In any case the most recent issue Paul has flagged is probably a
higher priority atm.
>
> Thanks to both of you! BTW, Paul found and wrote the one-at-a-time
> hash algorithm, credit where credit is due.
Yep, I noted both of you in the CHANGELOG.
>
> -VAL
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-14 3:58 ` Paul Wankadia
2009-01-14 8:48 ` Ian Kent
@ 2009-01-15 4:42 ` Ian Kent
1 sibling, 0 replies; 66+ messages in thread
From: Ian Kent @ 2009-01-15 4:42 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Wed, 2009-01-14 at 14:58 +1100, Paul Wankadia wrote:
> On Tue, Jan 13, 2009 at 4:51 PM, Ian Kent <raven@themaw.net> wrote:
>
> I think were about done with this.
> Here's a patch with a few changes by me, please comment.
>
> LGTM. Thanks.
>
>
Committed to git, along with a couple of others.
Ian
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-15 2:47 ` Valerie Aurora Henson
2009-01-15 3:02 ` Ian Kent
@ 2009-01-15 5:06 ` Paul Wankadia
1 sibling, 0 replies; 66+ messages in thread
From: Paul Wankadia @ 2009-01-15 5:06 UTC (permalink / raw)
To: Valerie Aurora Henson; +Cc: autofs, bob_jenkins, Ian Kent
[-- Attachment #1.1: Type: text/plain, Size: 293 bytes --]
On Thu, Jan 15, 2009 at 1:47 PM, Valerie Aurora Henson
<vaurora@redhat.com>wrote:
Thanks to both of you! BTW, Paul found and wrote the one-at-a-time
> hash algorithm, credit where credit is due.
I must point out that Bob Jenkins wrote it and released it into the public
domain. (Hi, Bob!)
[-- Attachment #1.2: Type: text/html, Size: 562 bytes --]
[-- Attachment #2: Type: text/plain, Size: 140 bytes --]
_______________________________________________
autofs mailing list
autofs@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-15 1:41 ` Ian Kent
@ 2009-01-15 15:04 ` Jeff Moyer
2009-01-15 15:16 ` Ian Kent
0 siblings, 1 reply; 66+ messages in thread
From: Jeff Moyer @ 2009-01-15 15:04 UTC (permalink / raw)
To: Ian Kent; +Cc: autofs, Paul Wankadia
Ian Kent <raven@themaw.net> writes:
> But onto the problem.
>
> It should be fairly straight forward to start using the map mtime again.
> The time stamp on cache entries that have been added will be later than
> the mtime if the file map hasn't changed so we can use that. But we also
> need to prevent re-reading the map from the beginning as we populate the
> cache. I was thinking that I could add each entry read during a lookup
> to the cache so that they would be found on subsequent lookups (as long
> as the mtime is earlier than the time stamp). Additionally, I could keep
> track of the file position so I don't read entries already read. It
> likely won't be quite as simple in the end but we really need to do
> something to for really large maps.
>
> Any other thoughts?
Sure, just read the whole map. Even large maps aren't that big. What
are we talking, 10k? 50k? You're better off reading the whole thing in
at once.
Cheers,
Jeff
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-15 15:04 ` Jeff Moyer
@ 2009-01-15 15:16 ` Ian Kent
2009-01-15 20:33 ` Paul Wankadia
2009-01-16 0:33 ` Ian Kent
0 siblings, 2 replies; 66+ messages in thread
From: Ian Kent @ 2009-01-15 15:16 UTC (permalink / raw)
To: Jeff Moyer; +Cc: autofs, Paul Wankadia
On Thu, 2009-01-15 at 10:04 -0500, Jeff Moyer wrote:
> Ian Kent <raven@themaw.net> writes:
>
> > But onto the problem.
> >
> > It should be fairly straight forward to start using the map mtime again.
> > The time stamp on cache entries that have been added will be later than
> > the mtime if the file map hasn't changed so we can use that. But we also
> > need to prevent re-reading the map from the beginning as we populate the
> > cache. I was thinking that I could add each entry read during a lookup
> > to the cache so that they would be found on subsequent lookups (as long
> > as the mtime is earlier than the time stamp). Additionally, I could keep
> > track of the file position so I don't read entries already read. It
> > likely won't be quite as simple in the end but we really need to do
> > something to for really large maps.
> >
> > Any other thoughts?
>
> Sure, just read the whole map. Even large maps aren't that big. What
> are we talking, 10k? 50k? You're better off reading the whole thing in
> at once.
Yeah, that would be best. I'll have a think about how to detect when to
do that. Maybe we can rip out that convoluted change detection logic for
file maps, after all they should be fairly simple to deal with.
Ian
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-15 15:16 ` Ian Kent
@ 2009-01-15 20:33 ` Paul Wankadia
2009-01-15 20:41 ` Jeff Moyer
2009-01-16 0:33 ` Ian Kent
1 sibling, 1 reply; 66+ messages in thread
From: Paul Wankadia @ 2009-01-15 20:33 UTC (permalink / raw)
To: Ian Kent; +Cc: autofs
On 1/16/09, Ian Kent <raven@themaw.net> wrote:
>> Sure, just read the whole map. Even large maps aren't that big. What
>> are we talking, 10k? 50k? You're better off reading the whole thing in
>> at once.
>
> Yeah, that would be best. I'll have a think about how to detect when to
> do that. Maybe we can rip out that convoluted change detection logic for
> file maps, after all they should be fairly simple to deal with.
If inotify can play nicely with the existing event handling, then it
could be worth considering.
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-15 20:33 ` Paul Wankadia
@ 2009-01-15 20:41 ` Jeff Moyer
2009-01-15 20:57 ` Paul Wankadia
0 siblings, 1 reply; 66+ messages in thread
From: Jeff Moyer @ 2009-01-15 20:41 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs, Ian Kent
Paul Wankadia <junyer@google.com> writes:
> On 1/16/09, Ian Kent <raven@themaw.net> wrote:
>
>>> Sure, just read the whole map. Even large maps aren't that big. What
>>> are we talking, 10k? 50k? You're better off reading the whole thing in
>>> at once.
>>
>> Yeah, that would be best. I'll have a think about how to detect when to
>> do that. Maybe we can rip out that convoluted change detection logic for
>> file maps, after all they should be fairly simple to deal with.
>
> If inotify can play nicely with the existing event handling, then it
> could be worth considering.
Ian was coming up with a scheme to only read part of the map. Because
the map is just a flat file, he surmised that a lookup could happen like
so:
first lookup, start at the beginning of the file
walk the entries, adding each to the cache until you find the entry
you're looking for
cache the offset into the file and stop reading
When a cache miss comes in, start reading the file again at the last
offset (so long as the file hasn't changed on disk)
My argument is that you're not really saving much. Just cache the whole
file. I agree that you probably want to detect changes, still. For
that, you can use mtime or inotify. You could make a case for either
side, though I think I'd argue for keeping the mtime approach (as the
map may change multiple times before we actually try to read it, and
doing the read in the lookup path really shouldn't be that big of a
deal). Of course, I haven't profiled this, so that may be worth doing.
Cheers,
Jeff
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-15 20:41 ` Jeff Moyer
@ 2009-01-15 20:57 ` Paul Wankadia
2009-01-16 0:27 ` Ian Kent
0 siblings, 1 reply; 66+ messages in thread
From: Paul Wankadia @ 2009-01-15 20:57 UTC (permalink / raw)
To: Jeff Moyer; +Cc: autofs, Ian Kent
On 1/16/09, Jeff Moyer <jmoyer@redhat.com> wrote:
> My argument is that you're not really saving much. Just cache the whole
> file. I agree that you probably want to detect changes, still. For
> that, you can use mtime or inotify. You could make a case for either
> side, though I think I'd argue for keeping the mtime approach (as the
> map may change multiple times before we actually try to read it, and
> doing the read in the lookup path really shouldn't be that big of a
> deal). Of course, I haven't profiled this, so that may be worth doing.
If we can simply flag the cached version as stale, then lazy reloads
should be possible.
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-15 20:57 ` Paul Wankadia
@ 2009-01-16 0:27 ` Ian Kent
2009-01-16 0:40 ` Ian Kent
0 siblings, 1 reply; 66+ messages in thread
From: Ian Kent @ 2009-01-16 0:27 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Fri, 2009-01-16 at 07:57 +1100, Paul Wankadia wrote:
> On 1/16/09, Jeff Moyer <jmoyer@redhat.com> wrote:
>
> > My argument is that you're not really saving much. Just cache the whole
> > file. I agree that you probably want to detect changes, still. For
> > that, you can use mtime or inotify. You could make a case for either
> > side, though I think I'd argue for keeping the mtime approach (as the
> > map may change multiple times before we actually try to read it, and
> > doing the read in the lookup path really shouldn't be that big of a
> > deal). Of course, I haven't profiled this, so that may be worth doing.
>
> If we can simply flag the cached version as stale, then lazy reloads
> should be possible.
Maybe not.
The layer of code above the lookup modules does the re-loads but it is
general wrt. the map type so for a "nobrowse" map it won't read the map.
I'm not sure yet that putting special case exceptions in that code is a
good thing to do or even straight forward. But, for the large map case,
we can consider reading the entire map an expensive operation, so if we
did change the layer above and we found the map needed to be modified
then marked the map as stale we would need to scan the file map for the
key (as the map is out of date) and then read the whole map later. That
means we would end up reading the map at least one and a half times (on
average) instead of once (assuming no lookups between marking the map
stale and re-reading).
I'm tending toward reading the map during the lookup so the map is up to
date when we look for the key in the cache.
Ian
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-15 15:16 ` Ian Kent
2009-01-15 20:33 ` Paul Wankadia
@ 2009-01-16 0:33 ` Ian Kent
1 sibling, 0 replies; 66+ messages in thread
From: Ian Kent @ 2009-01-16 0:33 UTC (permalink / raw)
To: Jeff Moyer; +Cc: autofs, Paul Wankadia
On Fri, 2009-01-16 at 00:16 +0900, Ian Kent wrote:
> >
> > Sure, just read the whole map. Even large maps aren't that big. What
> > are we talking, 10k? 50k? You're better off reading the whole thing in
> > at once.
As far as I can tell, up to about 10k is most common for large
configurations. But people also have maps as large as 30 - 40k entries,
so we should be thinking maps of that order in this discussion.
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-16 0:27 ` Ian Kent
@ 2009-01-16 0:40 ` Ian Kent
2009-01-16 1:43 ` Ian Kent
0 siblings, 1 reply; 66+ messages in thread
From: Ian Kent @ 2009-01-16 0:40 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Fri, 2009-01-16 at 09:27 +0900, Ian Kent wrote:
> On Fri, 2009-01-16 at 07:57 +1100, Paul Wankadia wrote:
> > On 1/16/09, Jeff Moyer <jmoyer@redhat.com> wrote:
> >
> > > My argument is that you're not really saving much. Just cache the whole
> > > file. I agree that you probably want to detect changes, still. For
> > > that, you can use mtime or inotify. You could make a case for either
> > > side, though I think I'd argue for keeping the mtime approach (as the
> > > map may change multiple times before we actually try to read it, and
> > > doing the read in the lookup path really shouldn't be that big of a
> > > deal). Of course, I haven't profiled this, so that may be worth doing.
> >
> > If we can simply flag the cached version as stale, then lazy reloads
> > should be possible.
>
> Maybe not.
>
> The layer of code above the lookup modules does the re-loads but it is
> general wrt. the map type so for a "nobrowse" map it won't read the map.
> I'm not sure yet that putting special case exceptions in that code is a
> good thing to do or even straight forward. But, for the large map case,
Or maybe I'm talking nonsense as it looks like I've actually got plenty
of map type context in the layer above, hehe.
> we can consider reading the entire map an expensive operation, so if we
> did change the layer above and we found the map needed to be modified
> then marked the map as stale we would need to scan the file map for the
> key (as the map is out of date) and then read the whole map later. That
> means we would end up reading the map at least one and a half times (on
> average) instead of once (assuming no lookups between marking the map
> stale and re-reading).
>
> I'm tending toward reading the map during the lookup so the map is up to
> date when we look for the key in the cache.
>
> Ian
>
>
> _______________________________________________
> autofs mailing list
> autofs@linux.kernel.org
> http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-16 0:40 ` Ian Kent
@ 2009-01-16 1:43 ` Ian Kent
2009-01-16 3:59 ` Paul Wankadia
2009-01-16 5:23 ` Ian Kent
0 siblings, 2 replies; 66+ messages in thread
From: Ian Kent @ 2009-01-16 1:43 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Fri, 2009-01-16 at 09:40 +0900, Ian Kent wrote:
> On Fri, 2009-01-16 at 09:27 +0900, Ian Kent wrote:
> > On Fri, 2009-01-16 at 07:57 +1100, Paul Wankadia wrote:
> > > On 1/16/09, Jeff Moyer <jmoyer@redhat.com> wrote:
> > >
> > > > My argument is that you're not really saving much. Just cache the whole
> > > > file. I agree that you probably want to detect changes, still. For
> > > > that, you can use mtime or inotify. You could make a case for either
> > > > side, though I think I'd argue for keeping the mtime approach (as the
> > > > map may change multiple times before we actually try to read it, and
> > > > doing the read in the lookup path really shouldn't be that big of a
> > > > deal). Of course, I haven't profiled this, so that may be worth doing.
> > >
> > > If we can simply flag the cached version as stale, then lazy reloads
> > > should be possible.
> >
> > Maybe not.
> >
> > The layer of code above the lookup modules does the re-loads but it is
> > general wrt. the map type so for a "nobrowse" map it won't read the map.
> > I'm not sure yet that putting special case exceptions in that code is a
> > good thing to do or even straight forward. But, for the large map case,
>
> Or maybe I'm talking nonsense as it looks like I've actually got plenty
> of map type context in the layer above, hehe.
>
> > we can consider reading the entire map an expensive operation, so if we
> > did change the layer above and we found the map needed to be modified
> > then marked the map as stale we would need to scan the file map for the
> > key (as the map is out of date) and then read the whole map later. That
> > means we would end up reading the map at least one and a half times (on
> > average) instead of once (assuming no lookups between marking the map
> > stale and re-reading).
> >
> > I'm tending toward reading the map during the lookup so the map is up to
> > date when we look for the key in the cache.
Or maybe not.
If we take advantage of the existing code to mark the map as stale and
handle the re-read and we accept the overhead of scanning the file map
while waiting for the update something like this could be all that's
needed.
autofs-5.0.4 - always read file maps
From: Ian Kent <raven@themaw.net>
---
daemon/lookup.c | 9 ++++++---
modules/lookup_file.c | 11 ++++++++++-
2 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/daemon/lookup.c b/daemon/lookup.c
index 741d846..b954045 100644
--- a/daemon/lookup.c
+++ b/daemon/lookup.c
@@ -283,10 +283,13 @@ static int do_read_map(struct autofs_point *ap, struct map_source *map, time_t a
* for the fail cases to function correctly and to cache the
* lookup handle.
*
- * We always need to whole map for direct mounts in order to
- * mount the triggers.
+ * We always need to read the whole map for direct mounts in
+ * order to mount the triggers. We also want to read the whole
+ * map if it's a file map to avoid potentially lengthy linear
+ * file scanning.
*/
- if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT)
+ if (strcmp(map->type, "file") ||
+ (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT))
return NSS_STATUS_SUCCESS;
if (!map->stale)
diff --git a/modules/lookup_file.c b/modules/lookup_file.c
index 95b9f6f..9a1c39b 100644
--- a/modules/lookup_file.c
+++ b/modules/lookup_file.c
@@ -93,7 +93,6 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
argv[0]);
return 1;
}
-
ctxt->mtime = st.st_mtime;
if (!mapfmt)
@@ -1064,7 +1063,16 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
if (ap->type == LKP_INDIRECT && *key != '/') {
char *lkp_key;
+ /*
+ * We can skip the map lookup and cache update altogether
+ * if we know the map hasn't been modified since it was
+ * last read.
+ */
cache_readlock(mc);
+ me = cache_lookup_first(mc);
+ if (me && ctxt->mtime <= me->age)
+ goto do_lookup;
+
me = cache_lookup_distinct(mc, key);
if (me && me->multi)
lkp_key = strdup(me->multi->key);
@@ -1088,6 +1096,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
}
cache_readlock(mc);
+do_lookup:
me = cache_lookup(mc, key);
/* Stale mapent => check for entry in alternate source or wildcard */
if (me && !me->mapent) {
^ permalink raw reply related [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-16 1:43 ` Ian Kent
@ 2009-01-16 3:59 ` Paul Wankadia
2009-01-16 4:21 ` Ian Kent
2009-01-16 5:23 ` Ian Kent
1 sibling, 1 reply; 66+ messages in thread
From: Paul Wankadia @ 2009-01-16 3:59 UTC (permalink / raw)
To: Ian Kent; +Cc: autofs
[-- Attachment #1.1: Type: text/plain, Size: 4348 bytes --]
On Fri, Jan 16, 2009 at 12:43 PM, Ian Kent <raven@themaw.net> wrote:
> > > If we can simply flag the cached version as stale, then lazy reloads
> > > > should be possible.
> > >
> > > Maybe not.
> > >
> > > The layer of code above the lookup modules does the re-loads but it is
> > > general wrt. the map type so for a "nobrowse" map it won't read the
> map.
> > > I'm not sure yet that putting special case exceptions in that code is a
> > > good thing to do or even straight forward. But, for the large map case,
> >
> > Or maybe I'm talking nonsense as it looks like I've actually got plenty
> > of map type context in the layer above, hehe.
> >
> > > we can consider reading the entire map an expensive operation, so if we
> > > did change the layer above and we found the map needed to be modified
> > > then marked the map as stale we would need to scan the file map for the
> > > key (as the map is out of date) and then read the whole map later. That
> > > means we would end up reading the map at least one and a half times (on
> > > average) instead of once (assuming no lookups between marking the map
> > > stale and re-reading).
> > >
> > > I'm tending toward reading the map during the lookup so the map is up
> to
> > > date when we look for the key in the cache.
>
> Or maybe not.
>
> If we take advantage of the existing code to mark the map as stale and
> handle the re-read and we accept the overhead of scanning the file map
> while waiting for the update something like this could be all that's
> needed.
>
> autofs-5.0.4 - always read file maps
>
> From: Ian Kent <raven@themaw.net>
>
>
> ---
>
> daemon/lookup.c | 9 ++++++---
> modules/lookup_file.c | 11 ++++++++++-
> 2 files changed, 16 insertions(+), 4 deletions(-)
>
>
> diff --git a/daemon/lookup.c b/daemon/lookup.c
> index 741d846..b954045 100644
> --- a/daemon/lookup.c
> +++ b/daemon/lookup.c
> @@ -283,10 +283,13 @@ static int do_read_map(struct autofs_point *ap,
> struct map_source *map, time_t a
> * for the fail cases to function correctly and to cache the
> * lookup handle.
> *
> - * We always need to whole map for direct mounts in order to
> - * mount the triggers.
> + * We always need to read the whole map for direct mounts in
> + * order to mount the triggers. We also want to read the whole
> + * map if it's a file map to avoid potentially lengthy linear
> + * file scanning.
> */
> - if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT)
> + if (strcmp(map->type, "file") ||
I suspect that you want && instead.
+ (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT))
> return NSS_STATUS_SUCCESS;
>
> if (!map->stale)
> diff --git a/modules/lookup_file.c b/modules/lookup_file.c
> index 95b9f6f..9a1c39b 100644
> --- a/modules/lookup_file.c
> +++ b/modules/lookup_file.c
> @@ -93,7 +93,6 @@ int lookup_init(const char *mapfmt, int argc, const char
> *const *argv, void **co
> argv[0]);
> return 1;
> }
> -
> ctxt->mtime = st.st_mtime;
>
> if (!mapfmt)
> @@ -1064,7 +1063,16 @@ int lookup_mount(struct autofs_point *ap, const char
> *name, int name_len, void *
> if (ap->type == LKP_INDIRECT && *key != '/') {
> char *lkp_key;
>
> + /*
> + * We can skip the map lookup and cache update altogether
> + * if we know the map hasn't been modified since it was
> + * last read.
> + */
> cache_readlock(mc);
> + me = cache_lookup_first(mc);
> + if (me && ctxt->mtime <= me->age)
You have to call stat(2) or fstat(2) at some point or else ctxt->mtime will
never change.
+ goto do_lookup;
My brain is bleeding.
+
> me = cache_lookup_distinct(mc, key);
> if (me && me->multi)
> lkp_key = strdup(me->multi->key);
> @@ -1088,6 +1096,7 @@ int lookup_mount(struct autofs_point *ap, const char
> *name, int name_len, void *
> }
>
> cache_readlock(mc);
> +do_lookup:
> me = cache_lookup(mc, key);
> /* Stale mapent => check for entry in alternate source or wildcard
> */
> if (me && !me->mapent) {
>
>
>
[-- Attachment #1.2: Type: text/html, Size: 6932 bytes --]
[-- Attachment #2: Type: text/plain, Size: 140 bytes --]
_______________________________________________
autofs mailing list
autofs@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-16 3:59 ` Paul Wankadia
@ 2009-01-16 4:21 ` Ian Kent
2009-01-16 5:05 ` Ian Kent
2009-01-16 6:04 ` Paul Wankadia
0 siblings, 2 replies; 66+ messages in thread
From: Ian Kent @ 2009-01-16 4:21 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Fri, 2009-01-16 at 14:59 +1100, Paul Wankadia wrote:
> On Fri, Jan 16, 2009 at 12:43 PM, Ian Kent <raven@themaw.net> wrote:
>
> > > > If we can simply flag the cached version as stale, then
> lazy reloads
> > > > should be possible.
> > >
> > > Maybe not.
> > >
> > > The layer of code above the lookup modules does the
> re-loads but it is
> > > general wrt. the map type so for a "nobrowse" map it won't
> read the map.
> > > I'm not sure yet that putting special case exceptions in
> that code is a
> > > good thing to do or even straight forward. But, for the
> large map case,
> >
> > Or maybe I'm talking nonsense as it looks like I've actually
> got plenty
> > of map type context in the layer above, hehe.
> >
> > > we can consider reading the entire map an expensive
> operation, so if we
> > > did change the layer above and we found the map needed to
> be modified
> > > then marked the map as stale we would need to scan the
> file map for the
> > > key (as the map is out of date) and then read the whole
> map later. That
> > > means we would end up reading the map at least one and a
> half times (on
> > > average) instead of once (assuming no lookups between
> marking the map
> > > stale and re-reading).
> > >
> > > I'm tending toward reading the map during the lookup so
> the map is up to
> > > date when we look for the key in the cache.
>
> Or maybe not.
>
> If we take advantage of the existing code to mark the map as
> stale and
> handle the re-read and we accept the overhead of scanning the
> file map
> while waiting for the update something like this could be all
> that's
> needed.
>
> autofs-5.0.4 - always read file maps
>
> From: Ian Kent <raven@themaw.net>
>
>
> ---
>
> daemon/lookup.c | 9 ++++++---
> modules/lookup_file.c | 11 ++++++++++-
> 2 files changed, 16 insertions(+), 4 deletions(-)
>
>
> diff --git a/daemon/lookup.c b/daemon/lookup.c
> index 741d846..b954045 100644
> --- a/daemon/lookup.c
> +++ b/daemon/lookup.c
> @@ -283,10 +283,13 @@ static int do_read_map(struct
> autofs_point *ap, struct map_source *map, time_t a
> * for the fail cases to function correctly and to
> cache the
> * lookup handle.
> *
> - * We always need to whole map for direct mounts in
> order to
> - * mount the triggers.
> + * We always need to read the whole map for direct
> mounts in
> + * order to mount the triggers. We also want to read
> the whole
> + * map if it's a file map to avoid potentially lengthy
> linear
> + * file scanning.
> */
> - if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type !=
> LKP_DIRECT)
> + if (strcmp(map->type, "file") ||
>
> I suspect that you want && instead.
Yeah, I think that isn't quite right but I also think that && won't fix
it. I'll think on that one again.
>
>
> + (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type !=
> LKP_DIRECT))
> return NSS_STATUS_SUCCESS;
>
> if (!map->stale)
> diff --git a/modules/lookup_file.c b/modules/lookup_file.c
> index 95b9f6f..9a1c39b 100644
> --- a/modules/lookup_file.c
> +++ b/modules/lookup_file.c
> @@ -93,7 +93,6 @@ int lookup_init(const char *mapfmt, int
> argc, const char *const *argv, void **co
> argv[0]);
> return 1;
> }
> -
> ctxt->mtime = st.st_mtime;
>
> if (!mapfmt)
> @@ -1064,7 +1063,16 @@ int lookup_mount(struct autofs_point
> *ap, const char *name, int name_len, void *
> if (ap->type == LKP_INDIRECT && *key != '/') {
> char *lkp_key;
>
> + /*
> + * We can skip the map lookup and cache update
> altogether
> + * if we know the map hasn't been modified
> since it was
> + * last read.
> + */
> cache_readlock(mc);
> + me = cache_lookup_first(mc);
> + if (me && ctxt->mtime <= me->age)
>
> You have to call stat(2) or fstat(2) at some point or else ctxt->mtime
> will never change.
We set the mtime when we read the entire map, see
modules/lookup_file.c:lookup_read_map(). This is totally taking
advantage of the existing code to read a map that is marked as stale. It
doesn't however attempt to simplify the code which works out if we need
to mark the map stale but we probably don't want to anyway as we need to
ensure we use up to date entries for lookups done while waiting for the
map update to be done.
>
>
> + goto do_lookup;
>
> My brain is bleeding.
>
>
> +
> me = cache_lookup_distinct(mc, key);
> if (me && me->multi)
> lkp_key = strdup(me->multi->key);
> @@ -1088,6 +1096,7 @@ int lookup_mount(struct autofs_point
> *ap, const char *name, int name_len, void *
> }
>
> cache_readlock(mc);
> +do_lookup:
> me = cache_lookup(mc, key);
> /* Stale mapent => check for entry in alternate source
> or wildcard */
> if (me && !me->mapent) {
>
>
>
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-16 4:21 ` Ian Kent
@ 2009-01-16 5:05 ` Ian Kent
2009-01-16 6:04 ` Paul Wankadia
1 sibling, 0 replies; 66+ messages in thread
From: Ian Kent @ 2009-01-16 5:05 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Fri, 2009-01-16 at 13:22 +0900, Ian Kent wrote:
> >
> > diff --git a/daemon/lookup.c b/daemon/lookup.c
> > index 741d846..b954045 100644
> > --- a/daemon/lookup.c
> > +++ b/daemon/lookup.c
> > @@ -283,10 +283,13 @@ static int do_read_map(struct
> > autofs_point *ap, struct map_source *map, time_t a
> > * for the fail cases to function correctly and to
> > cache the
> > * lookup handle.
> > *
> > - * We always need to whole map for direct mounts in
> > order to
> > - * mount the triggers.
> > + * We always need to read the whole map for direct
> > mounts in
> > + * order to mount the triggers. We also want to read
> > the whole
> > + * map if it's a file map to avoid potentially lengthy
> > linear
> > + * file scanning.
> > */
> > - if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type !=
> > LKP_DIRECT)
> > + if (strcmp(map->type, "file") ||
> >
> > I suspect that you want && instead.
>
> Yeah, I think that isn't quite right but I also think that && won't fix
> it. I'll think on that one again.
On second thoughts, I think you were right the first time, && it is.
But the real question is whether we are willing to put up with the
overhead of file scan lookups while we wait for the a map read to
complete. That probably won't happen all that often so I'm thinking
maybe it's ok.
Ian
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-16 1:43 ` Ian Kent
2009-01-16 3:59 ` Paul Wankadia
@ 2009-01-16 5:23 ` Ian Kent
1 sibling, 0 replies; 66+ messages in thread
From: Ian Kent @ 2009-01-16 5:23 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Fri, 2009-01-16 at 10:43 +0900, Ian Kent wrote:
> > >
> > > I'm tending toward reading the map during the lookup so the map is up to
> > > date when we look for the key in the cache.
>
> Or maybe not.
>
> If we take advantage of the existing code to mark the map as stale and
> handle the re-read and we accept the overhead of scanning the file map
> while waiting for the update something like this could be all that's
> needed.
So here is a slightly updated patch.
autofs-5.0.4 - always read file maps
From: Ian Kent <raven@themaw.net>
---
daemon/lookup.c | 9 ++++++---
modules/lookup_file.c | 26 ++++++++++++++------------
2 files changed, 20 insertions(+), 15 deletions(-)
diff --git a/daemon/lookup.c b/daemon/lookup.c
index 741d846..e034348 100644
--- a/daemon/lookup.c
+++ b/daemon/lookup.c
@@ -283,10 +283,13 @@ static int do_read_map(struct autofs_point *ap, struct map_source *map, time_t a
* for the fail cases to function correctly and to cache the
* lookup handle.
*
- * We always need to whole map for direct mounts in order to
- * mount the triggers.
+ * We always need to read the whole map for direct mounts in
+ * order to mount the triggers. We also want to read the whole
+ * map if it's a file map to avoid potentially lengthy linear
+ * file scanning.
*/
- if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT)
+ if (strcmp(map->type, "file") &&
+ !(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT)
return NSS_STATUS_SUCCESS;
if (!map->stale)
diff --git a/modules/lookup_file.c b/modules/lookup_file.c
index 95b9f6f..6f426a5 100644
--- a/modules/lookup_file.c
+++ b/modules/lookup_file.c
@@ -93,7 +93,6 @@ int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **co
argv[0]);
return 1;
}
-
ctxt->mtime = st.st_mtime;
if (!mapfmt)
@@ -951,9 +950,6 @@ static int check_map_indirect(struct autofs_point *ap,
if (ret == CHE_FAIL)
return NSS_STATUS_NOTFOUND;
- if (ret & CHE_UPDATED)
- source->stale = 1;
-
pthread_cleanup_push(cache_lock_cleanup, mc);
cache_writelock(mc);
exists = cache_lookup_distinct(mc, key);
@@ -963,7 +959,6 @@ static int check_map_indirect(struct autofs_point *ap,
free(exists->mapent);
exists->mapent = NULL;
exists->status = 0;
- source->stale = 1;
}
}
pthread_cleanup_pop(1);
@@ -985,14 +980,8 @@ static int check_map_indirect(struct autofs_point *ap,
we = cache_lookup_distinct(mc, "*");
if (we) {
/* Wildcard entry existed and is now gone */
- if (we->source == source && (wild & CHE_MISSING)) {
+ if (we->source == source && (wild & CHE_MISSING))
cache_delete(mc, "*");
- source->stale = 1;
- }
- } else {
- /* Wildcard not in map but now is */
- if (wild & (CHE_OK | CHE_UPDATED))
- source->stale = 1;
}
pthread_cleanup_pop(1);
@@ -1064,7 +1053,19 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
if (ap->type == LKP_INDIRECT && *key != '/') {
char *lkp_key;
+ /*
+ * We can skip the map lookup and cache update altogether
+ * if we know the map hasn't been modified since it was
+ * last read. If it has then we can mark the map stale
+ * so a re-read is triggered following the lookup.
+ */
cache_readlock(mc);
+ me = cache_lookup_first(mc);
+ if (me && ctxt->mtime <= me->age)
+ goto do_cache_lookup;
+ else
+ source->stale = 1;
+
me = cache_lookup_distinct(mc, key);
if (me && me->multi)
lkp_key = strdup(me->multi->key);
@@ -1088,6 +1089,7 @@ int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *
}
cache_readlock(mc);
+do_cache_lookup:
me = cache_lookup(mc, key);
/* Stale mapent => check for entry in alternate source or wildcard */
if (me && !me->mapent) {
^ permalink raw reply related [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-16 4:21 ` Ian Kent
2009-01-16 5:05 ` Ian Kent
@ 2009-01-16 6:04 ` Paul Wankadia
2009-01-16 6:24 ` Ian Kent
1 sibling, 1 reply; 66+ messages in thread
From: Paul Wankadia @ 2009-01-16 6:04 UTC (permalink / raw)
To: Ian Kent; +Cc: autofs
[-- Attachment #1.1: Type: text/plain, Size: 839 bytes --]
On Fri, Jan 16, 2009 at 3:21 PM, Ian Kent <raven@themaw.net> wrote:
> + if (me && ctxt->mtime <= me->age)
> >
> > You have to call stat(2) or fstat(2) at some point or else ctxt->mtime
> > will never change.
>
> We set the mtime when we read the entire map, see
> modules/lookup_file.c:lookup_read_map(). This is totally taking
> advantage of the existing code to read a map that is marked as stale. It
> doesn't however attempt to simplify the code which works out if we need
> to mark the map stale but we probably don't want to anyway as we need to
> ensure we use up to date entries for lookups done while waiting for the
> map update to be done.
Sorry, I don't understand how that condition will evaluate to false. You
won't read the map until ctxt->mtime changes, but it won't change until you
read the map.
[-- Attachment #1.2: Type: text/html, Size: 1274 bytes --]
[-- Attachment #2: Type: text/plain, Size: 140 bytes --]
_______________________________________________
autofs mailing list
autofs@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-16 6:04 ` Paul Wankadia
@ 2009-01-16 6:24 ` Ian Kent
2009-01-16 6:39 ` Ian Kent
0 siblings, 1 reply; 66+ messages in thread
From: Ian Kent @ 2009-01-16 6:24 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Fri, 2009-01-16 at 17:04 +1100, Paul Wankadia wrote:
> On Fri, Jan 16, 2009 at 3:21 PM, Ian Kent <raven@themaw.net> wrote:
>
> > + if (me && ctxt->mtime <= me->age)
> >
> > You have to call stat(2) or fstat(2) at some point or else
> ctxt->mtime
> > will never change.
>
>
> We set the mtime when we read the entire map, see
> modules/lookup_file.c:lookup_read_map(). This is totally
> taking
> advantage of the existing code to read a map that is marked as
> stale. It
> doesn't however attempt to simplify the code which works out
> if we need
> to mark the map stale but we probably don't want to anyway as
> we need to
> ensure we use up to date entries for lookups done while
> waiting for the
> map update to be done.
>
> Sorry, I don't understand how that condition will evaluate to false.
> You won't read the map until ctxt->mtime changes, but it won't change
> until you read the map.
Mmmm .. before that last change I was assuming the code which sets the
stale flag would cause the read but then I removed that bit and ...
oops!
Ian
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-16 6:24 ` Ian Kent
@ 2009-01-16 6:39 ` Ian Kent
2009-01-17 17:11 ` Paul Wankadia
0 siblings, 1 reply; 66+ messages in thread
From: Ian Kent @ 2009-01-16 6:39 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Fri, 2009-01-16 at 15:24 +0900, Ian Kent wrote:
> On Fri, 2009-01-16 at 17:04 +1100, Paul Wankadia wrote:
> > On Fri, Jan 16, 2009 at 3:21 PM, Ian Kent <raven@themaw.net> wrote:
> >
> > > + if (me && ctxt->mtime <= me->age)
> > >
> > > You have to call stat(2) or fstat(2) at some point or else
> > ctxt->mtime
> > > will never change.
> >
> >
> > We set the mtime when we read the entire map, see
> > modules/lookup_file.c:lookup_read_map(). This is totally
> > taking
> > advantage of the existing code to read a map that is marked as
> > stale. It
> > doesn't however attempt to simplify the code which works out
> > if we need
> > to mark the map stale but we probably don't want to anyway as
> > we need to
> > ensure we use up to date entries for lookups done while
> > waiting for the
> > map update to be done.
> >
> > Sorry, I don't understand how that condition will evaluate to false.
> > You won't read the map until ctxt->mtime changes, but it won't change
> > until you read the map.
>
> Mmmm .. before that last change I was assuming the code which sets the
> stale flag would cause the read but then I removed that bit and ...
> oops!
Because, after a mount lookup we check the stale status and queue a map
read if the map is stale. But then I went and removed the bit that sets
the map stale because it's lazy in identifying if the map has changed so
we could get quite a few mount lookups before a map read gets queued.
I'll add back the stat(2) I originally had their before I posted the
patch.
I'm also thinking of checking if a map read task is in progress when a
mount lookup comes in and waiting for it to complete before continuing
with the lookup (to reduce the number of file scans a bit). But I'll
need to have a look around to see if that will be a problem.
Ian
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-15 3:02 ` Ian Kent
@ 2009-01-16 21:39 ` Valerie Aurora Henson
0 siblings, 0 replies; 66+ messages in thread
From: Valerie Aurora Henson @ 2009-01-16 21:39 UTC (permalink / raw)
To: Ian Kent; +Cc: autofs, Paul Wankadia
On Thu, Jan 15, 2009 at 12:02:04PM +0900, Ian Kent wrote:
>
> Bummer, hope you recover soon.
>
> I'm about to commit it so we'll have to deal with any concerns you have
> as update patches. It's not much different to the original anyway. We
I just reviewed and no concerns. Thanks!
-VAL
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 3/4] Easy alloca() replacements
2009-01-10 3:18 ` Ian Kent
@ 2009-01-16 22:11 ` Valerie Aurora Henson
0 siblings, 0 replies; 66+ messages in thread
From: Valerie Aurora Henson @ 2009-01-16 22:11 UTC (permalink / raw)
To: Ian Kent; +Cc: autofs
On Sat, Jan 10, 2009 at 12:18:36PM +0900, Ian Kent wrote:
> On Fri, 2009-01-09 at 13:47 -0500, Valerie Aurora Henson wrote:
>
> Just a first pass reading but noticed ....
>
> > diff --git a/lib/cache.c b/lib/cache.c
> > index 36b8294..bc2c722 100644
> > --- a/lib/cache.c
> > +++ b/lib/cache.c
> > @@ -484,27 +484,19 @@ struct mapent *cache_lookup_offset(const char *prefix, const char *offset, int s
> > {
> > struct list_head *p;
> > struct mapent *this;
> > - int plen = strlen(prefix);
> > - char *o_key;
> > + char o_key[KEY_MAX_LEN];
>
> I know this looks right but I think it will end up being a problem
> latter. I know there are places in the map lookup libraries that
> restrict these to KEY_MAX_LEN, which is needed for indirect map keys,
> but direct map keys really shouldn't have this restriction as they
> should be able to be as long as PATH_MAX but that brings the issue of
> needing to audit and adjust the maximum parse buffer as well. So we will
> need to get around to that at some point as well.
It certainly won't hurt to make this PATH_MAX - I'll do that unless I
hear otherwise.
> >
> > /* root offset duplicates "/" */
> > - if (plen > 1) {
> > - o_key = alloca(plen + strlen(offset) + 1);
> > - strcpy(o_key, prefix);
> > - strcat(o_key, offset);
> > - } else {
> > - o_key = alloca(strlen(offset) + 1);
> > - strcpy(o_key, offset);
> > - }
> > + if (snprintf(o_key, sizeof(o_key), "%s%s", prefix, offset) >
> > + sizeof(o_key))
> > + return NULL;
>
> Looks like this will set o_key to "//..." for strlen(prefix) == 1.
I'll fix it, thanks
-VAL
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-16 6:39 ` Ian Kent
@ 2009-01-17 17:11 ` Paul Wankadia
2009-01-18 3:26 ` Ian Kent
0 siblings, 1 reply; 66+ messages in thread
From: Paul Wankadia @ 2009-01-17 17:11 UTC (permalink / raw)
To: Ian Kent; +Cc: autofs
[-- Attachment #1.1: Type: text/plain, Size: 1150 bytes --]
On Fri, Jan 16, 2009 at 5:39 PM, Ian Kent <raven@themaw.net> wrote:
> > Sorry, I don't understand how that condition will evaluate to false.
> > > You won't read the map until ctxt->mtime changes, but it won't change
> > > until you read the map.
> >
> > Mmmm .. before that last change I was assuming the code which sets the
> > stale flag would cause the read but then I removed that bit and ...
> > oops!
>
> Because, after a mount lookup we check the stale status and queue a map
> read if the map is stale. But then I went and removed the bit that sets
> the map stale because it's lazy in identifying if the map has changed so
> we could get quite a few mount lookups before a map read gets queued.
> I'll add back the stat(2) I originally had their before I posted the
> patch.
Thanks!
I'm also thinking of checking if a map read task is in progress when a
> mount lookup comes in and waiting for it to complete before continuing
> with the lookup (to reduce the number of file scans a bit). But I'll
> need to have a look around to see if that will be a problem.
Is there a design document for autofs v5 that you're permitted to share?
[-- Attachment #1.2: Type: text/html, Size: 1684 bytes --]
[-- Attachment #2: Type: text/plain, Size: 140 bytes --]
_______________________________________________
autofs mailing list
autofs@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-17 17:11 ` Paul Wankadia
@ 2009-01-18 3:26 ` Ian Kent
2009-01-19 1:28 ` Paul Wankadia
0 siblings, 1 reply; 66+ messages in thread
From: Ian Kent @ 2009-01-18 3:26 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
[-- Attachment #1: Type: text/plain, Size: 1806 bytes --]
On Sun, 2009-01-18 at 04:11 +1100, Paul Wankadia wrote:
> On Fri, Jan 16, 2009 at 5:39 PM, Ian Kent <raven@themaw.net> wrote:
>
> > > Sorry, I don't understand how that condition will evaluate
> to false.
> > > You won't read the map until ctxt->mtime changes, but it
> won't change
> > > until you read the map.
> >
> > Mmmm .. before that last change I was assuming the code
> which sets the
> > stale flag would cause the read but then I removed that bit
> and ...
> > oops!
>
> Because, after a mount lookup we check the stale status and
> queue a map
> read if the map is stale. But then I went and removed the bit
> that sets
> the map stale because it's lazy in identifying if the map has
> changed so
> we could get quite a few mount lookups before a map read gets
> queued.
> I'll add back the stat(2) I originally had their before I
> posted the
> patch.
>
> Thanks!
>
>
> I'm also thinking of checking if a map read task is in
> progress when a
> mount lookup comes in and waiting for it to complete before
> continuing
> with the lookup (to reduce the number of file scans a bit).
> But I'll
> need to have a look around to see if that will be a problem.
>
> Is there a design document for autofs v5 that you're permitted to
> share?
There isn't, but even of there were it wouldn't have a level of detail
that would be useful in cases like this and if it did it would have
become hopelessly out of date as time has passed.
However, the attached pdf, written by Jeff and myself, has a high level
overview of v5 and what it seeks to achieve.
Ian
[-- Attachment #2: ols-paper.pdf --]
[-- Type: application/pdf, Size: 128092 bytes --]
[-- Attachment #3: Type: text/plain, Size: 140 bytes --]
_______________________________________________
autofs mailing list
autofs@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-18 3:26 ` Ian Kent
@ 2009-01-19 1:28 ` Paul Wankadia
2009-01-19 2:03 ` Ian Kent
0 siblings, 1 reply; 66+ messages in thread
From: Paul Wankadia @ 2009-01-19 1:28 UTC (permalink / raw)
To: Ian Kent; +Cc: autofs
[-- Attachment #1.1: Type: text/plain, Size: 763 bytes --]
On Sun, Jan 18, 2009 at 2:26 PM, Ian Kent <raven@themaw.net> wrote:
> Is there a design document for autofs v5 that you're permitted to
> > share?
>
> There isn't, but even of there were it wouldn't have a level of detail
> that would be useful in cases like this and if it did it would have
> become hopelessly out of date as time has passed.
>
> However, the attached pdf, written by Jeff and myself, has a high level
> overview of v5 and what it seeks to achieve.
Cool, thanks.
It's just that your earlier comment regarding a concurrency issue led me to
wonder about the use of Pthreads. In particular, I'm not sure what the
rationale was, but I'd also like to understand the control flow, so that's
why I was interested in a design document of some sort.
[-- Attachment #1.2: Type: text/html, Size: 1137 bytes --]
[-- Attachment #2: Type: text/plain, Size: 140 bytes --]
_______________________________________________
autofs mailing list
autofs@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-19 1:28 ` Paul Wankadia
@ 2009-01-19 2:03 ` Ian Kent
2009-01-19 5:23 ` Paul Wankadia
0 siblings, 1 reply; 66+ messages in thread
From: Ian Kent @ 2009-01-19 2:03 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Mon, 2009-01-19 at 12:28 +1100, Paul Wankadia wrote:
> On Sun, Jan 18, 2009 at 2:26 PM, Ian Kent <raven@themaw.net> wrote:
>
>
> > Is there a design document for autofs v5 that you're
> permitted to
> > share?
>
>
> There isn't, but even of there were it wouldn't have a level
> of detail
> that would be useful in cases like this and if it did it would
> have
> become hopelessly out of date as time has passed.
>
> However, the attached pdf, written by Jeff and myself, has a
> high level
> overview of v5 and what it seeks to achieve.
>
> Cool, thanks.
>
> It's just that your earlier comment regarding a concurrency issue led
> me to wonder about the use of Pthreads. In particular, I'm not sure
> what the rationale was, but I'd also like to understand the control
> flow, so that's why I was interested in a design document of some
> sort.
Right.
One of the things that v5 does is to move the master map parsing out of
the init script and into the daemon itself. That means that the daemon
then has to manage each of the master map mounts as well. Using
individual sub-processes has a whole set of problems related to the
supervising process communicating with and knowing the state of those
sub-processes so v5 changed to a threaded model which of course has it's
own set of difficulties.
Ian
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-19 2:03 ` Ian Kent
@ 2009-01-19 5:23 ` Paul Wankadia
2009-01-19 6:13 ` Ian Kent
0 siblings, 1 reply; 66+ messages in thread
From: Paul Wankadia @ 2009-01-19 5:23 UTC (permalink / raw)
To: Ian Kent; +Cc: autofs
[-- Attachment #1.1: Type: text/plain, Size: 1162 bytes --]
On Mon, Jan 19, 2009 at 1:03 PM, Ian Kent <raven@themaw.net> wrote:
> It's just that your earlier comment regarding a concurrency issue led
> > me to wonder about the use of Pthreads. In particular, I'm not sure
> > what the rationale was, but I'd also like to understand the control
> > flow, so that's why I was interested in a design document of some
> > sort.
>
> Right.
>
> One of the things that v5 does is to move the master map parsing out of
> the init script and into the daemon itself. That means that the daemon
> then has to manage each of the master map mounts as well. Using
> individual sub-processes has a whole set of problems related to the
> supervising process communicating with and knowing the state of those
> sub-processes so v5 changed to a threaded model which of course has it's
> own set of difficulties.
Does the daemon need multiple processes/threads because of the ioctl(2)
calls that block?
On a related note, is the autofs device a step towards a completely revised
kernel interface? I've started to contemplate the use of socket pairs
instead of pipes and ioctl(2) calls. (NBD seems to be a simple example of
this style.)
[-- Attachment #1.2: Type: text/html, Size: 1563 bytes --]
[-- Attachment #2: Type: text/plain, Size: 140 bytes --]
_______________________________________________
autofs mailing list
autofs@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/autofs
^ permalink raw reply [flat|nested] 66+ messages in thread
* Re: [PATCH 1/4] Make hash table scale to thousands of entries
2009-01-19 5:23 ` Paul Wankadia
@ 2009-01-19 6:13 ` Ian Kent
0 siblings, 0 replies; 66+ messages in thread
From: Ian Kent @ 2009-01-19 6:13 UTC (permalink / raw)
To: Paul Wankadia; +Cc: autofs
On Mon, 2009-01-19 at 16:23 +1100, Paul Wankadia wrote:
> On Mon, Jan 19, 2009 at 1:03 PM, Ian Kent <raven@themaw.net> wrote:
>
>
> > It's just that your earlier comment regarding a concurrency
> issue led
> > me to wonder about the use of Pthreads. In particular, I'm
> not sure
> > what the rationale was, but I'd also like to understand the
> control
> > flow, so that's why I was interested in a design document of
> some
> > sort.
>
>
> Right.
>
> One of the things that v5 does is to move the master map
> parsing out of
> the init script and into the daemon itself. That means that
> the daemon
> then has to manage each of the master map mounts as well.
> Using
> individual sub-processes has a whole set of problems related
> to the
> supervising process communicating with and knowing the state
> of those
> sub-processes so v5 changed to a threaded model which of
> course has it's
> own set of difficulties.
>
> Does the daemon need multiple processes/threads because of the
> ioctl(2) calls that block?
A whole bunch of things can block, for example stat(2) on a path against
a down server.
There is one thread for each master map mount which creates worker
threads to do mounts and expires. Ideally any mount blocking will not
affect other mounts and hopefully an expire blocked for some reason
won't stop mount requests. That seems to pretty much work now so things
aren't too bad.
>
> On a related note, is the autofs device a step towards a completely
> revised kernel interface? I've started to contemplate the use of
> socket pairs instead of pipes and ioctl(2) calls. (NBD seems to be a
> simple example of this style.)
Kind of. The change was needed to solve a fairly significant problem. I
can't see how using sockets can make a difference really because the
source of blocking isn't the interface but rather the things it needs to
do.
But it gets worse as Generic Netlink is a socket based interface, a
recommended ioctl replacement and trying to use that for the
re-implementation was nothing short of a nightmare. I failed to get a
working implementation after several weeks of work. I have the broken
implementation around somewhere, at least as far as I got, if you want
to run with that as a project. Mind you, if user space libnl becomes
thread safe at some point we may want to re-consider this as a viable
approach. It depends on other things as well, but mostly on how we might
change the expire infrastructure post 5.0 (it isn't going to change for
5.0 and we need to retain backward compatibility), namely. whether we
change to using the in kernel VFS mount expire mechanism and whether
that will resolve the significant overhead when expiring large maps that
use the "browse" option or how that issue will be otherwise resolved.
So, yes, I'm thinking about these things but there is still enough to do
with 5.0 to not spend a lot of time on it.
So this interface is the one that will be used until we can come up with
a better one. The reason for the re-implementation is described in
detail in Documentation/filesystems/autofs4-mount-control.txt. The most
important part of this, as it relates to this thread of work, is the
AUTOFS_DEV_IOCTL_ISMOUNTPOINT ioctl. We observed that is_mounted() was
by far and away the top CPU user because it is used a lot and scans
either /proc/mounts or /etc/mtab. My testing showed that using an
updated kernel had a big effect on CPU usage.
Ian
^ permalink raw reply [flat|nested] 66+ messages in thread
end of thread, other threads:[~2009-01-19 6:13 UTC | newest]
Thread overview: 66+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-09 18:46 [PATCH 0/4] autofs scaling and cleanup patches Valerie Aurora Henson
2009-01-09 18:47 ` [PATCH 1/4] Make hash table scale to thousands of entries Valerie Aurora Henson
2009-01-09 18:47 ` [PATCH 2/4] Make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit Valerie Aurora Henson
2009-01-09 18:47 ` [PATCH 3/4] Easy alloca() replacements Valerie Aurora Henson
2009-01-09 18:47 ` [PATCH 4/4] Replace <linux/string.h> with <string.h> Valerie Aurora Henson
2009-01-12 5:59 ` Ian Kent
2009-01-09 20:48 ` [PATCH 3/4] Easy alloca() replacements Valerie Aurora Henson
2009-01-10 3:18 ` Ian Kent
2009-01-16 22:11 ` Valerie Aurora Henson
2009-01-09 19:00 ` [PATCH 2/4] Make MAX_ERR_BUF and PARSE_MAX_BUF use easier to audit Jeff Moyer
2009-01-09 19:54 ` Valerie Aurora Henson
2009-01-09 19:17 ` [PATCH 1/4] Make hash table scale to thousands of entries Jeff Moyer
2009-01-09 19:51 ` Valerie Aurora Henson
2009-01-10 1:19 ` Paul Wankadia
2009-01-11 16:42 ` Ian Kent
2009-01-11 23:25 ` Paul Wankadia
2009-01-12 1:13 ` Ian Kent
2009-01-12 1:19 ` Ian Kent
2009-01-12 2:10 ` Paul Wankadia
2009-01-12 4:02 ` Ian Kent
2009-01-12 4:58 ` Ian Kent
2009-01-13 1:52 ` Paul Wankadia
2009-01-13 2:24 ` Ian Kent
2009-01-13 4:15 ` Ian Kent
2009-01-13 5:07 ` Paul Wankadia
2009-01-13 5:19 ` Ian Kent
2009-01-14 3:43 ` Paul Wankadia
2009-01-14 8:47 ` Ian Kent
2009-01-14 10:52 ` Paul Wankadia
2009-01-14 13:17 ` Ian Kent
2009-01-14 14:20 ` Paul Wankadia
2009-01-15 1:41 ` Ian Kent
2009-01-15 15:04 ` Jeff Moyer
2009-01-15 15:16 ` Ian Kent
2009-01-15 20:33 ` Paul Wankadia
2009-01-15 20:41 ` Jeff Moyer
2009-01-15 20:57 ` Paul Wankadia
2009-01-16 0:27 ` Ian Kent
2009-01-16 0:40 ` Ian Kent
2009-01-16 1:43 ` Ian Kent
2009-01-16 3:59 ` Paul Wankadia
2009-01-16 4:21 ` Ian Kent
2009-01-16 5:05 ` Ian Kent
2009-01-16 6:04 ` Paul Wankadia
2009-01-16 6:24 ` Ian Kent
2009-01-16 6:39 ` Ian Kent
2009-01-17 17:11 ` Paul Wankadia
2009-01-18 3:26 ` Ian Kent
2009-01-19 1:28 ` Paul Wankadia
2009-01-19 2:03 ` Ian Kent
2009-01-19 5:23 ` Paul Wankadia
2009-01-19 6:13 ` Ian Kent
2009-01-16 5:23 ` Ian Kent
2009-01-16 0:33 ` Ian Kent
2009-01-10 14:45 ` Ian Kent
2009-01-10 2:07 ` Ian Kent
2009-01-10 3:29 ` Ian Kent
2009-01-10 3:57 ` Ian Kent
2009-01-13 5:51 ` Ian Kent
2009-01-14 3:58 ` Paul Wankadia
2009-01-14 8:48 ` Ian Kent
2009-01-15 2:47 ` Valerie Aurora Henson
2009-01-15 3:02 ` Ian Kent
2009-01-16 21:39 ` Valerie Aurora Henson
2009-01-15 5:06 ` Paul Wankadia
2009-01-15 4:42 ` Ian Kent
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.