| autofs 5.0.3 - check for exported mounts automatically mounted by kernel |
| |
| From: Ian Kent <raven@themaw.net> |
| |
| If a server exports file systems that are automatically mounted by |
| the kernel client autofs will mistakenly over mount them when it |
| constructs and mounts its multi-mount triggers. |
| |
| This patch makes autofs check for this case and ignores them if the |
| kernel mounts them while it mounts multi-mount triggers. |
| |
| We don't want to fight with NFS over mounting these because it |
| confuses autofs and they magically go away when the owner mount is |
| umounted. This isn't ideal because autofs will mount these mounts |
| while constructing its multi-mount triggers but it is unavoidable |
| at the moment. |
| |
| |
| CHANGELOG | 1 + |
| daemon/direct.c | 26 ++++++++++++++++++-------- |
| include/automount.h | 4 ++++ |
| lib/parse_subs.c | 26 ++++++++++++++++++-------- |
| 4 files changed, 41 insertions(+), 16 deletions(-) |
| |
| |
| |
| |
| @@ -12,6 +12,7 @@ |
| - init SASL callbacks on every ldap lookup library load. |
| - fix incorrect match of map type name when included in map name. |
| - fix incorrect pthreads condition handling for mount requests. |
| +- add check for exports automatically mounted by NFS kernel client. |
| |
| 14/01/2008 autofs-5.0.3 |
| ----------------------- |
| |
| |
| @@ -664,12 +664,12 @@ int mount_autofs_offset(struct autofs_po |
| 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_po |
| 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_po |
| 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_po |
| 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_po |
| |
| 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) |
| |
| |
| @@ -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); |
| |
| |
| @@ -390,7 +390,7 @@ int mount_multi_triggers(struct autofs_p |
| 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_p |
| } |
| |
| 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_ |
| |
| 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_ |
| 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_ |
| 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++; |