diff --git a/CHANGELOG b/CHANGELOG index bf5195d..438e182 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -52,6 +52,7 @@ - update master map tokenizer to admit "slasify-colons" option (Capelle Bonoit). - update location validation to accept "_" (Fabio Olive Leite). - set close-on-exec flag on open sockets. +- fix nonstrict multi-mount handling. 1/9/2006 autofs-5.0.1 rc2 ------------------------- diff --git a/daemon/direct.c b/daemon/direct.c index 7af8721..070e614 100644 --- a/daemon/direct.c +++ b/daemon/direct.c @@ -1405,11 +1405,19 @@ cont: pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state); if (status) { struct mapent *me; + int real_mount, set_fd; cache_readlock(mt->mc); me = cache_lookup_distinct(mt->mc, mt->name); - me->ioctlfd = mt->ioctlfd; + real_mount = is_mounted(_PATH_MOUNTED, me->key, MNTS_REAL); + set_fd = (real_mount || me->multi == me); cache_unlock(mt->mc); - send_ready(mt->ioctlfd, mt->wait_queue_token); + if (set_fd) { + me->ioctlfd = mt->ioctlfd; + send_ready(mt->ioctlfd, mt->wait_queue_token); + } else { + send_ready(mt->ioctlfd, mt->wait_queue_token); + close(mt->ioctlfd); + } msg("mounted %s", mt->name); } else { send_fail(mt->ioctlfd, mt->wait_queue_token); diff --git a/lib/parse_subs.c b/lib/parse_subs.c index fbbc515..c98989c 100644 --- a/lib/parse_subs.c +++ b/lib/parse_subs.c @@ -358,12 +358,12 @@ int mount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, unsigned int fs_path_len; struct statfs fs; struct stat st; - unsigned int is_autofs_fs; + unsigned int mounted, is_autofs_fs; int ret, start; fs_path_len = strlen(root) + strlen(base); if (fs_path_len > PATH_MAX) - return 0; + return -1; strcpy(path, root); strcat(path, base); @@ -373,10 +373,11 @@ int mount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, if (errno == ENOENT) is_autofs_fs = 1; else - return 0; + return -1; } else is_autofs_fs = fs.f_type == AUTOFS_SUPER_MAGIC ? 1 : 0; + mounted = 0; start = strlen(root); offset = cache_get_offset(base, offset, start, &me->multi_list, &pos); while (offset) { @@ -406,12 +407,14 @@ int mount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, if (mount_autofs_offset(ap, oe, is_autofs_fs) < 0) warn(ap->logopt, "failed to mount offset"); + else + mounted++; cont: offset = cache_get_offset(base, offset, start, &me->multi_list, &pos); } - return 1; + return mounted; } int umount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, const char *base) @@ -439,11 +442,20 @@ int umount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me /* Make sure "none" of the offsets have an active mount. */ while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) { + char *oe_base; + oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list); /* root offset is a special case */ if (!oe || (strlen(oe->key) - start) == 1) continue; + /* + * Check for and umount subtree offsets resulting from + * nonstrict mount fail. + */ + oe_base = oe->key + strlen(root); + left = umount_multi_triggers(ap, root, oe, oe_base); + if (oe->ioctlfd != -1) left++; } diff --git a/modules/parse_sun.c b/modules/parse_sun.c index c849ff3..6b2a640 100644 --- a/modules/parse_sun.c +++ b/modules/parse_sun.c @@ -458,10 +458,10 @@ static int sun_mount(struct autofs_point *ap, const char *root, fstype = alloca(typelen + 1); memcpy(fstype, cp + 7, typelen); fstype[typelen] = '\0'; - } else if (strncmp("strict", cp, 6) == 0) { - nonstrict = 0; } else if (strncmp("nonstrict", cp, 9) == 0) { nonstrict = 1; + } else if (strncmp("strict", cp, 6) == 0) { + nonstrict = 0; } else if (strncmp("nobrowse", cp, 8) == 0 || strncmp("browse", cp, 6) == 0 || strncmp("timeout=", cp, 8) == 0) { @@ -837,14 +837,14 @@ static int mount_subtree_offsets(struct autofs_point *ap, struct mapent_cache *m { struct mapent *mm; char *m_key; - int start; + int ret, start; char *base, *m_root; char buf[MAX_ERR_BUF]; mm = me->multi; if (!mm) - return 1; + return 0; cache_multi_lock(me->parent); @@ -861,7 +861,7 @@ static int mount_subtree_offsets(struct autofs_point *ap, struct mapent_cache *m cache_multi_unlock(me->parent); estr = strerror_r(errno, buf, MAX_ERR_BUF); error(ap->logopt, MODPREFIX "alloca: %s", estr); - return 0; + return -1; } strcpy(m_root, ap->path); strcat(m_root, "/"); @@ -870,15 +870,16 @@ static int mount_subtree_offsets(struct autofs_point *ap, struct mapent_cache *m base = &me->key[start]; - if (!mount_multi_triggers(ap, m_root, me->multi, base)) { + ret = mount_multi_triggers(ap, m_root, me->multi, base); + if (ret == -1) { cache_multi_unlock(me->parent); error(ap->logopt, MODPREFIX "failed to mount offset triggers"); - return 0; + return -1; } cache_multi_unlock(me->parent); - return 1; + return ret; } /* @@ -998,7 +999,7 @@ int parse_mount(struct autofs_point *ap, const char *name, char *m_root = NULL; int m_root_len; time_t age = time(NULL); - int l; + int l, ret; /* If name starts with "/" it's a direct mount */ if (*name == '/') { @@ -1169,21 +1170,10 @@ int parse_mount(struct autofs_point *ap, const char *name, free(myoptions); free(loc); - - if (rv < 0) { - warn(ap->logopt, - MODPREFIX - "mount multi-mount root %s failed", name); - cache_delete_offset_list(mc, name); - cache_multi_unlock(me); - cache_unlock(mc); - free(options); - pthread_setcancelstate(cur_state, NULL); - return rv; - } } - if (!mount_multi_triggers(ap, m_root, me, "/")) { + ret = mount_multi_triggers(ap, m_root, me, "/"); + if (ret == -1) { warn(ap->logopt, MODPREFIX "failed to mount offset triggers"); cache_multi_unlock(me); @@ -1193,6 +1183,13 @@ int parse_mount(struct autofs_point *ap, const char *name, return 1; } + /* + * Convert fail on nonstrict, non-empty multi-mount + * to success + */ + if (rv < 0 && ret > 0) + rv = 0; + cache_multi_unlock(me); cache_unlock(mc); @@ -1293,15 +1290,9 @@ int parse_mount(struct autofs_point *ap, const char *name, rv = sun_mount(ap, ap->path, name, name_len, loc, loclen, options, ctxt); - /* non-strict failure to normal failure for ordinary mount */ - if (rv < 0) - rv = -rv; - free(loc); free(options); - if (rv) - return rv; /* * If it's a multi-mount insert the triggers * These are always direct mount triggers so root = "" @@ -1310,7 +1301,10 @@ int parse_mount(struct autofs_point *ap, const char *name, cache_readlock(mc); me = cache_lookup_distinct(mc, name); if (me) { - mount_subtree_offsets(ap, mc, me); + int ret = mount_subtree_offsets(ap, mc, me); + /* Convert fail on nonstrict, non-empty multi-mount to success */ + if (rv < 0 && ret > 0) + rv = 0; } cache_unlock(mc); pthread_setcancelstate(cur_state, NULL);