diff --git a/daemon/direct.c b/daemon/direct.c index a9dda87..86c817c 100644 --- a/daemon/direct.c +++ b/daemon/direct.c @@ -664,12 +664,12 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me) if (ap->state != ST_READMAP) warn(ap->logopt, "trigger %s already mounted", me->key); - return 0; + return MOUNT_OFFSET_OK; } if (me->ioctlfd != -1) { error(ap->logopt, "active offset mount %s", me->key); - return -1; + return MOUNT_OFFSET_FAIL; } status = pthread_once(&key_mnt_params_once, key_mnt_params_init); @@ -683,7 +683,7 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me) crit(ap->logopt, "mnt_params value create failed for offset mount %s", me->key); - return 0; + return MOUNT_OFFSET_OK; } mp->options = NULL; @@ -697,12 +697,22 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me) if (!mp->options) { mp->options = make_options_string(ap->path, ap->kpipefd, "offset"); if (!mp->options) - return 0; + return MOUNT_OFFSET_OK; } /* In case the directory doesn't exist, try to mkdir it */ if (mkdir_path(me->key, 0555) < 0) { if (errno == EEXIST) { + /* + * If the mount point directory is a real mount + * and it isn't the root offset then it must be + * a mount that has been automatically mounted by + * the kernel NFS client. + */ + if (me->multi != me && + is_mounted(_PROC_MOUNTS, me->key, MNTS_REAL)) + return MOUNT_OFFSET_IGNORE; + /* * If we recieve an error, and it's EEXIST * we know the directory was not created. @@ -721,13 +731,13 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me) debug(ap->logopt, "can't create mount directory: %s, %s", me->key, estr); - return -1; + return MOUNT_OFFSET_FAIL; } else { char *estr = strerror_r(errno, buf, MAX_ERR_BUF); crit(ap->logopt, "failed to create mount directory: %s, %s", me->key, estr); - return -1; + return MOUNT_OFFSET_FAIL; } } else { /* No errors so the directory was successfully created */ @@ -787,7 +797,7 @@ int mount_autofs_offset(struct autofs_point *ap, struct mapent *me) debug(ap->logopt, "mounted trigger %s", me->key); - return 0; + return MOUNT_OFFSET_OK; out_close: close(ioctlfd); @@ -797,7 +807,7 @@ out_err: if (stat(me->key, &st) == 0 && me->dir_created) rmdir_path(ap, me->key, st.st_dev); - return -1; + return MOUNT_OFFSET_FAIL; } static int expire_direct(int ioctlfd, const char *path, unsigned int when, unsigned int logopt) diff --git a/include/automount.h b/include/automount.h index cd8ce7b..d59be77 100644 --- a/include/automount.h +++ b/include/automount.h @@ -468,6 +468,10 @@ struct autofs_point { /* Standard functions used by daemon or modules */ +#define MOUNT_OFFSET_OK 0 +#define MOUNT_OFFSET_FAIL -1 +#define MOUNT_OFFSET_IGNORE -2 + void *handle_mounts(void *arg); int umount_multi(struct autofs_point *ap, const char *path, int incl); int send_ready(unsigned logopt, int ioctlfd, unsigned int wait_queue_token); diff --git a/lib/parse_subs.c b/lib/parse_subs.c index 5422fef..27cb0fc 100644 --- a/lib/parse_subs.c +++ b/lib/parse_subs.c @@ -390,7 +390,7 @@ int mount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, struct list_head *pos = NULL; unsigned int fs_path_len; unsigned int mounted; - int start; + int ret, start; fs_path_len = strlen(root) + strlen(base); if (fs_path_len > PATH_MAX) @@ -411,15 +411,25 @@ int mount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, } oe = cache_lookup_offset(base, offset, start, &me->multi_list); - if (!oe) + if (!oe || !oe->mapent) goto cont; debug(ap->logopt, "mount offset %s", oe->key); - if (mount_autofs_offset(ap, oe) < 0) - warn(ap->logopt, "failed to mount offset"); - else + ret = mount_autofs_offset(ap, oe); + if (ret >= MOUNT_OFFSET_OK) mounted++; + else { + if (ret != MOUNT_OFFSET_IGNORE) + warn(ap->logopt, "failed to mount offset"); + else { + debug(ap->logopt, + "ignoring \"nohide\" trigger %s", + oe->key); + free(oe->mapent); + oe->mapent = NULL; + } + } cont: offset = cache_get_offset(base, offset, start, &me->multi_list, &pos); @@ -457,7 +467,7 @@ int umount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list); /* root offset is a special case */ - if (!oe || (strlen(oe->key) - start) == 1) + if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1) continue; /* @@ -481,7 +491,7 @@ int umount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) { oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list); /* root offset is a special case */ - if (!oe || (strlen(oe->key) - start) == 1) + if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1) continue; debug(ap->logopt, "umount offset %s", oe->key); @@ -505,7 +515,7 @@ int umount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me if (is_mounted(_PATH_MOUNTED, root, MNTS_REAL)) { info(ap->logopt, "unmounting dir = %s", root); if (umount_ent(ap, root)) { - if (!mount_multi_triggers(ap, root, me, "/")) + if (mount_multi_triggers(ap, root, me, "/") < 0) warn(ap->logopt, "failed to remount offset triggers"); return left++;