autofs/autofs-5.1.7-eliminate-cache_lookup_offset-usage.patch
DistroBaker a5adb69dac Merged update from upstream sources
This is an automated DistroBaker update from upstream sources.
If you do not know what this is about or would like to opt out,
contact the OSCI team.

Source: https://src.fedoraproject.org/rpms/autofs.git#25aaf0b69441b4e7370a195cbf1c7988d0abef3d
2021-03-26 02:05:45 +00:00

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);