379 lines
11 KiB
Diff
379 lines
11 KiB
Diff
autofs-5.1.7 - eliminate cache_lookup_offset() usage
|
|
|
|
From: Ian Kent <raven@themaw.net>
|
|
|
|
The function cache_lookup_offset() will do a linear search when
|
|
looking for an offset. If the number of offsets is large this
|
|
can be a lot of overhead.
|
|
|
|
But it's possible to use the information already present where
|
|
this is called to to do a hashed lookup instead.
|
|
|
|
Signed-off-by: Ian Kent <raven@themaw.net>
|
|
---
|
|
CHANGELOG | 1 +
|
|
lib/mounts.c | 82 +++++++++++++++++++++++++++++++++------------------
|
|
modules/parse_sun.c | 77 ++++++++++++++++++++++++++++++------------------
|
|
3 files changed, 102 insertions(+), 58 deletions(-)
|
|
|
|
diff --git a/CHANGELOG b/CHANGELOG
|
|
index 0b577909..484bd866 100644
|
|
--- a/CHANGELOG
|
|
+++ b/CHANGELOG
|
|
@@ -5,6 +5,7 @@
|
|
- use sprintf() when constructing hosts mapent.
|
|
- fix mnts_remove_amdmount() uses wrong list.
|
|
- Fix option for master read wait.
|
|
+- eliminate cache_lookup_offset() usage.
|
|
|
|
25/01/2021 autofs-5.1.7
|
|
- make bind mounts propagation slave by default.
|
|
diff --git a/lib/mounts.c b/lib/mounts.c
|
|
index ccbd52e0..42e8ef07 100644
|
|
--- a/lib/mounts.c
|
|
+++ b/lib/mounts.c
|
|
@@ -2495,24 +2495,27 @@ int mount_multi_triggers(struct autofs_point *ap, struct mapent *me,
|
|
char *offset = path;
|
|
struct mapent *oe;
|
|
struct list_head *pos = NULL;
|
|
- unsigned int fs_path_len;
|
|
+ unsigned int root_len = strlen(root);
|
|
int mounted;
|
|
|
|
- fs_path_len = start + strlen(base);
|
|
- if (fs_path_len > PATH_MAX)
|
|
- return -1;
|
|
-
|
|
mounted = 0;
|
|
offset = cache_get_offset(base, offset, start, &me->multi_list, &pos);
|
|
while (offset) {
|
|
- int plen = fs_path_len + strlen(offset);
|
|
+ char key[PATH_MAX + 1];
|
|
+ int key_len = root_len + strlen(offset);
|
|
|
|
- if (plen > PATH_MAX) {
|
|
+ if (key_len > PATH_MAX) {
|
|
warn(ap->logopt, "path loo long");
|
|
goto cont;
|
|
}
|
|
|
|
- oe = cache_lookup_offset(base, offset, start, &me->multi_list);
|
|
+ /* The root offset is always mounted seperately so the
|
|
+ * offset path will always be root + offset.
|
|
+ */
|
|
+ strcpy(key, root);
|
|
+ strcat(key, offset);
|
|
+
|
|
+ oe = cache_lookup_distinct(me->mc, key);
|
|
if (!oe || !oe->mapent)
|
|
goto cont;
|
|
|
|
@@ -2525,12 +2528,8 @@ int mount_multi_triggers(struct autofs_point *ap, struct mapent *me,
|
|
*/
|
|
if (ap->state == ST_READMAP && ap->flags & MOUNT_FLAG_REMOUNT) {
|
|
if (oe->ioctlfd != -1 ||
|
|
- is_mounted(oe->key, MNTS_REAL)) {
|
|
- char oe_root[PATH_MAX + 1];
|
|
- strcpy(oe_root, root);
|
|
- strcat(oe_root, offset);
|
|
- mount_multi_triggers(ap, oe, oe_root, strlen(oe_root), base);
|
|
- }
|
|
+ is_mounted(oe->key, MNTS_REAL))
|
|
+ mount_multi_triggers(ap, oe, key, strlen(key), base);
|
|
}
|
|
cont:
|
|
offset = cache_get_offset(base,
|
|
@@ -2584,6 +2583,8 @@ int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root
|
|
const char o_root[] = "/";
|
|
const char *mm_base;
|
|
int left, start;
|
|
+ unsigned int root_len;
|
|
+ unsigned int mm_base_len;
|
|
|
|
left = 0;
|
|
start = strlen(root);
|
|
@@ -2597,11 +2598,28 @@ int umount_multi_triggers(struct autofs_point *ap, struct mapent *me, char *root
|
|
|
|
pos = NULL;
|
|
offset = path;
|
|
+ root_len = start;
|
|
+ mm_base_len = strlen(mm_base);
|
|
|
|
while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
|
|
+ char key[PATH_MAX + 1];
|
|
+ int key_len = root_len + strlen(offset);
|
|
char *oe_base;
|
|
|
|
- oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
|
|
+ if (mm_base_len > 1)
|
|
+ key_len += mm_base_len;
|
|
+
|
|
+ if (key_len > PATH_MAX) {
|
|
+ warn(ap->logopt, "path loo long");
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ strcpy(key, root);
|
|
+ if (mm_base_len > 1)
|
|
+ strcat(key, mm_base);
|
|
+ strcat(key, offset);
|
|
+
|
|
+ oe = cache_lookup_distinct(me->mc, key);
|
|
/* root offset is a special case */
|
|
if (!oe || (strlen(oe->key) - start) == 1)
|
|
continue;
|
|
@@ -2686,13 +2704,14 @@ int clean_stale_multi_triggers(struct autofs_point *ap,
|
|
char *root;
|
|
char mm_top[PATH_MAX + 1];
|
|
char path[PATH_MAX + 1];
|
|
- char buf[MAX_ERR_BUF];
|
|
char *offset;
|
|
struct mapent *oe;
|
|
struct list_head *mm_root, *pos;
|
|
const char o_root[] = "/";
|
|
const char *mm_base;
|
|
int left, start;
|
|
+ unsigned int root_len;
|
|
+ unsigned int mm_base_len;
|
|
time_t age;
|
|
|
|
if (top)
|
|
@@ -2720,14 +2739,30 @@ int clean_stale_multi_triggers(struct autofs_point *ap,
|
|
|
|
pos = NULL;
|
|
offset = path;
|
|
+ root_len = start;
|
|
+ mm_base_len = strlen(mm_base);
|
|
age = me->multi->age;
|
|
|
|
while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
|
|
+ char key[PATH_MAX + 1];
|
|
+ int key_len = root_len + strlen(offset);
|
|
char *oe_base;
|
|
- char *key;
|
|
int ret;
|
|
|
|
- oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
|
|
+ if (mm_base_len > 1)
|
|
+ key_len += mm_base_len;
|
|
+
|
|
+ if (key_len > PATH_MAX) {
|
|
+ warn(ap->logopt, "path loo long");
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ strcpy(key, root);
|
|
+ if (mm_base_len > 1)
|
|
+ strcat(key, mm_base);
|
|
+ strcat(key, offset);
|
|
+
|
|
+ oe = cache_lookup_distinct(me->mc, key);
|
|
/* root offset is a special case */
|
|
if (!oe || (strlen(oe->key) - start) == 1)
|
|
continue;
|
|
@@ -2778,14 +2813,6 @@ int clean_stale_multi_triggers(struct autofs_point *ap,
|
|
}
|
|
}
|
|
|
|
- key = strdup(oe->key);
|
|
- if (!key) {
|
|
- char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
|
|
- error(ap->logopt, "malloc: %s", estr);
|
|
- left++;
|
|
- continue;
|
|
- }
|
|
-
|
|
debug(ap->logopt, "umount offset %s", oe->key);
|
|
|
|
if (umount_autofs_offset(ap, oe)) {
|
|
@@ -2800,7 +2827,6 @@ int clean_stale_multi_triggers(struct autofs_point *ap,
|
|
if (cache_delete_offset(oe->mc, key) == CHE_FAIL)
|
|
error(ap->logopt,
|
|
"failed to delete offset key %s", key);
|
|
- free(key);
|
|
continue;
|
|
}
|
|
|
|
@@ -2816,7 +2842,6 @@ int clean_stale_multi_triggers(struct autofs_point *ap,
|
|
left++;
|
|
/* But we did origianlly create this */
|
|
oe->flags |= MOUNT_FLAG_DIR_CREATED;
|
|
- free(key);
|
|
continue;
|
|
}
|
|
/*
|
|
@@ -2834,7 +2859,6 @@ int clean_stale_multi_triggers(struct autofs_point *ap,
|
|
error(ap->logopt,
|
|
"failed to delete offset key %s", key);
|
|
}
|
|
- free(key);
|
|
}
|
|
|
|
return left;
|
|
diff --git a/modules/parse_sun.c b/modules/parse_sun.c
|
|
index 4b137f99..819d6adc 100644
|
|
--- a/modules/parse_sun.c
|
|
+++ b/modules/parse_sun.c
|
|
@@ -1086,6 +1086,8 @@ static void cleanup_multi_triggers(struct autofs_point *ap,
|
|
struct list_head *mm_root, *pos;
|
|
const char o_root[] = "/";
|
|
const char *mm_base;
|
|
+ unsigned int root_len;
|
|
+ unsigned int mm_base_len;
|
|
|
|
mm_root = &me->multi->multi_list;
|
|
|
|
@@ -1095,16 +1097,31 @@ static void cleanup_multi_triggers(struct autofs_point *ap,
|
|
mm_base = base;
|
|
|
|
pos = NULL;
|
|
+ root_len = strlen(root);
|
|
+ mm_base_len = strlen(mm_base);
|
|
|
|
/* Make sure "none" of the offsets have an active mount. */
|
|
while ((poffset = cache_get_offset(mm_base, poffset, start, mm_root, &pos))) {
|
|
- oe = cache_lookup_offset(mm_base, poffset, start, &me->multi_list);
|
|
- /* root offset is a special case */
|
|
- if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1)
|
|
+ unsigned int path_len = root_len + strlen(poffset);
|
|
+
|
|
+ if (mm_base_len > 1)
|
|
+ path_len += mm_base_len;
|
|
+
|
|
+ if (path_len > PATH_MAX) {
|
|
+ warn(ap->logopt, "path loo long");
|
|
continue;
|
|
+ }
|
|
|
|
strcpy(path, root);
|
|
+ if (mm_base_len > 1)
|
|
+ strcat(path, mm_base);
|
|
strcat(path, poffset);
|
|
+
|
|
+ oe = cache_lookup_distinct(me->mc, path);
|
|
+ /* root offset is a special case */
|
|
+ if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1)
|
|
+ continue;
|
|
+
|
|
if (umount(path)) {
|
|
error(ap->logopt, "error recovering from mount fail");
|
|
error(ap->logopt, "cannot umount offset %s", path);
|
|
@@ -1117,17 +1134,14 @@ static void cleanup_multi_triggers(struct autofs_point *ap,
|
|
static int mount_subtree(struct autofs_point *ap, struct mapent *me,
|
|
const char *name, char *loc, char *options, void *ctxt)
|
|
{
|
|
- struct mapent *mm;
|
|
struct mapent *ro;
|
|
char *mm_root, *mm_base, *mm_key;
|
|
- const char *mnt_root;
|
|
- unsigned int mm_root_len, mnt_root_len;
|
|
+ unsigned int mm_root_len;
|
|
int start, ret = 0, rv;
|
|
|
|
rv = 0;
|
|
|
|
- mm = me->multi;
|
|
- mm_key = mm->key;
|
|
+ mm_key = me->multi->key;
|
|
|
|
if (*mm_key == '/') {
|
|
mm_root = mm_key;
|
|
@@ -1141,20 +1155,26 @@ static int mount_subtree(struct autofs_point *ap, struct mapent *me,
|
|
}
|
|
mm_root_len = strlen(mm_root);
|
|
|
|
- mnt_root = mm_root;
|
|
- mnt_root_len = mm_root_len;
|
|
-
|
|
if (me == me->multi) {
|
|
+ char key[PATH_MAX + 1];
|
|
+
|
|
+ if (mm_root_len + 1 > PATH_MAX) {
|
|
+ warn(ap->logopt, "path loo long");
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
/* name = NULL */
|
|
/* destination = mm_root */
|
|
mm_base = "/";
|
|
|
|
+ strcpy(key, mm_root);
|
|
+ strcat(key, mm_base);
|
|
+
|
|
/* Mount root offset if it exists */
|
|
- ro = cache_lookup_offset(mm_base, mm_base, strlen(mm_root), &me->multi_list);
|
|
+ ro = cache_lookup_distinct(me->mc, key);
|
|
if (ro) {
|
|
- char *myoptions, *ro_loc, *tmp;
|
|
+ char *myoptions, *ro_loc;
|
|
int namelen = name ? strlen(name) : 0;
|
|
- const char *root;
|
|
int ro_len;
|
|
|
|
myoptions = NULL;
|
|
@@ -1172,13 +1192,7 @@ static int mount_subtree(struct autofs_point *ap, struct mapent *me,
|
|
if (ro_loc)
|
|
ro_len = strlen(ro_loc);
|
|
|
|
- tmp = alloca(mnt_root_len + 2);
|
|
- strcpy(tmp, mnt_root);
|
|
- tmp[mnt_root_len] = '/';
|
|
- tmp[mnt_root_len + 1] = '\0';
|
|
- root = tmp;
|
|
-
|
|
- rv = sun_mount(ap, root, name, namelen, ro_loc, ro_len, myoptions, ctxt);
|
|
+ rv = sun_mount(ap, key, name, namelen, ro_loc, ro_len, myoptions, ctxt);
|
|
|
|
free(myoptions);
|
|
if (ro_loc)
|
|
@@ -1186,11 +1200,11 @@ static int mount_subtree(struct autofs_point *ap, struct mapent *me,
|
|
}
|
|
|
|
if (ro && rv == 0) {
|
|
- ret = mount_multi_triggers(ap, me, mnt_root, start, mm_base);
|
|
+ ret = mount_multi_triggers(ap, me, mm_root, start, mm_base);
|
|
if (ret == -1) {
|
|
error(ap->logopt, MODPREFIX
|
|
"failed to mount offset triggers");
|
|
- cleanup_multi_triggers(ap, me, mnt_root, start, mm_base);
|
|
+ cleanup_multi_triggers(ap, me, mm_root, start, mm_base);
|
|
return 1;
|
|
}
|
|
} else if (rv <= 0) {
|
|
@@ -1206,24 +1220,29 @@ static int mount_subtree(struct autofs_point *ap, struct mapent *me,
|
|
int loclen = strlen(loc);
|
|
int namelen = strlen(name);
|
|
|
|
- mnt_root = name;
|
|
-
|
|
/* name = mm_root + mm_base */
|
|
/* destination = mm_root + mm_base = name */
|
|
mm_base = &me->key[start];
|
|
|
|
- rv = sun_mount(ap, mnt_root, name, namelen, loc, loclen, options, ctxt);
|
|
+ rv = sun_mount(ap, name, name, namelen, loc, loclen, options, ctxt);
|
|
if (rv == 0) {
|
|
- ret = mount_multi_triggers(ap, me->multi, mnt_root, start, mm_base);
|
|
+ ret = mount_multi_triggers(ap, me->multi, name, start, mm_base);
|
|
if (ret == -1) {
|
|
error(ap->logopt, MODPREFIX
|
|
"failed to mount offset triggers");
|
|
- cleanup_multi_triggers(ap, me, mnt_root, start, mm_base);
|
|
+ cleanup_multi_triggers(ap, me, name, start, mm_base);
|
|
return 1;
|
|
}
|
|
} else if (rv < 0) {
|
|
- char *mm_root_base = alloca(strlen(mm_root) + strlen(mm_base) + 1);
|
|
+ char mm_root_base[PATH_MAX + 1];
|
|
+ unsigned int mm_root_base_len = mm_root_len + strlen(mm_base) + 1;
|
|
|
|
+ if (mm_root_base_len > PATH_MAX) {
|
|
+ warn(ap->logopt, MODPREFIX "path too long");
|
|
+ cache_delete_offset_list(me->mc, name);
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
strcpy(mm_root_base, mm_root);
|
|
strcat(mm_root_base, mm_base);
|
|
|