autofs-5.1.9 - improve handling of missing map entry for mount request From: Ian Kent If the map entry isn't found it must have been deleted from the map but a trigger mount is still mounted because it has sent us this request. Use the mount table for a brute force lookup to get the path and open a file handle for it so we can send a failure status to the kernel. Also remove the crit() log message following open_ioctlfd() as it already issues an appropriate error message on failure. Signed-off-by: Ian Kent --- CHANGELOG | 1 + daemon/direct.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index f9b6322ae..e28a991b4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -79,6 +79,7 @@ - refactor do_umount_autofs_direct(). - fix stale direct mount trigger not umounted on expire. - add function table_lookup_ino(). +- improve handling of missing map entry for mount request. 02/11/2023 autofs-5.1.9 - fix kernel mount status notification. diff --git a/daemon/direct.c b/daemon/direct.c index b8e5bb6ec..537dc46fa 100644 --- a/daemon/direct.c +++ b/daemon/direct.c @@ -1374,12 +1374,54 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_ } if (!me) { - /* - * Shouldn't happen as the kernel is telling us - * someone has walked on our mount point. + char tmp[PATH_MAX + 1]; + char *path; + + /* If the map entry wasn't found it must have been deleted + * from the map but a trigger mount is still mounted because + * it has sent us this request. So use the mount table for a + * brute force lookup to get the path and open a file handle + * for it so we can return a not found status to the kernel. */ - logerr("can't find map entry for (%lu,%lu)", - (unsigned long) pkt->dev, (unsigned long) pkt->ino); + path = table_lookup_ino(ap, pkt->dev, pkt->ino, tmp, PATH_MAX + 1, &ioctlfd); + if (!path) { + /* This could be cuased by an inability to open a file + * handle but generally that doesn't happen. The mount + * has to exist and be pinned becuase we got this request + * so it can't be umounted. Therefore it's very unlikely + * this case will happen. If it does happen it's fatal, + * the waiter will hang and there's nothing we can do + * about it. + */ + logerr("can't find mount for (%lu,%lu)", + (unsigned long) pkt->dev, (unsigned long) pkt->ino); + /* TODO: how do we clear wait q in kernel ?? */ + } else { + char buf[MAX_ERR_BUF]; + + /* Try and recover from this unexpecyedly missing map + * entry by detaching the direct mount trigger that + * sent the request so it's no longer visible to the + * VFS. + */ + info(ap->logopt, "forcing umount of direct mount %s", path); + if (umount2(path, MNT_DETACH) == -1) { + char *estr = strerror_r(errno, buf, MAX_ERR_BUF); + warn(ap->logopt, "failed to force umount %s: %s", + path, estr); + } + if (rmdir(path) == -1) { + char buf[MAX_ERR_BUF]; + char *estr; + + estr = strerror_r(errno, buf, MAX_ERR_BUF); + warn(ap->logopt, + "failed to remove dir %s: %s", path, estr); + } + ops->send_fail(ap->logopt, + ioctlfd, pkt->wait_queue_token, -EINVAL); + ops->close(ap->logopt, ioctlfd); + } master_source_unlock(ap->entry); master_mutex_unlock(); pthread_setcancelstate(state, NULL); @@ -1398,7 +1440,6 @@ int handle_packet_missing_direct(struct autofs_point *ap, autofs_packet_missing_ master_source_unlock(ap->entry); master_mutex_unlock(); pthread_setcancelstate(state, NULL); - crit(ap->logopt, "failed to create ioctl fd for %s", me->key); /* TODO: how do we clear wait q in kernel ?? */ return 1; }