--- b/usr.sbin/autofs/automount.c +++ b/usr.sbin/autofs/automount.c @@ -63,24 +63,64 @@ __FBSDID("$FreeBSD$"); static int unmount_by_statfs(const struct statfs *sb, bool force) { + int error; + + if ((error = unmount_automount(&sb->f_fsid, force ? MNT_FORCE : 0)) != 0) + log_warn("cannot unmount %s (FSID:%d:%d)", + sb->f_mntonname, sb->f_fsid.val[0], sb->f_fsid.val[1]); + + return (error); +} + + +static int +unmount_by_umount(const fsid_t *fsid, int flags) +{ + FILE *f; + char fsid_str[sizeof(*fsid)*2+1]; + size_t i; + + /* umount(8) expects the file system ID to be in hexadecimal format */ + for (i = 0; i < sizeof(*fsid); i++) + snprintf(fsid_str+(i*2), sizeof(fsid_str) - (i*2), + "%02x", ((const u_char *)fsid)[i]); + + if (flags & MNT_FORCE) + f = auto_popen("umount", "-f", fsid_str, NULL); + else + f = auto_popen("umount", fsid_str, NULL); + + assert(f != NULL); + return (auto_pclose(f)); +} + +/* + * Unmount a filesystem. Default to umount(8) and fallback to unmount(3). + */ +int +unmount_automount(const fsid_t *fsid, int flags) +{ + int error; char *fsid_str; - int error, ret, flags; - ret = asprintf(&fsid_str, "FSID:%d:%d", - sb->f_fsid.val[0], sb->f_fsid.val[1]); - if (ret < 0) + /* need to find reference where FSID:0:0 is error */ + if (fsid->val[0] == 0 || fsid->val[1] == 0) + return (EACCES); + + /* any debug or warnings will be logged from auto_pclose() */ + if ((error = unmount_by_umount(fsid, flags)) == 0) + return (0); + + if (asprintf(&fsid_str, "FSID:%d:%d", fsid->val[0], fsid->val[1]) < 0) log_err(1, "asprintf"); - log_debugx("unmounting %s using %s", sb->f_mntonname, fsid_str); + flags |= MNT_BYFSID; + if ((error = unmount(fsid_str, flags)) == 0) + return (0); - flags = MNT_BYFSID; - if (force) - flags |= MNT_FORCE; - error = unmount(fsid_str, flags); - free(fsid_str); - if (error != 0) - log_warn("cannot unmount %s", sb->f_mntonname); + log_debugx("cannot unmount (%s): %s", fsid_str, strerror(errno)); + free(fsid_str); return (error); } --- b/usr.sbin/autofs/autounmountd.c +++ b/usr.sbin/autofs/autounmountd.c @@ -154,25 +154,11 @@ refresh_automounted(void) static int unmount_by_fsid(const fsid_t fsid, const char *mountpoint) { - char *fsid_str; - int error, ret; - - ret = asprintf(&fsid_str, "FSID:%d:%d", fsid.val[0], fsid.val[1]); - if (ret < 0) - log_err(1, "asprintf"); - - error = unmount(fsid_str, MNT_NONBUSY | MNT_BYFSID); - if (error != 0) { - if (errno == EBUSY) { - log_debugx("cannot unmount %s (%s): %s", - mountpoint, fsid_str, strerror(errno)); - } else { - log_warn("cannot unmount %s (%s)", - mountpoint, fsid_str); - } - } + int error; - free(fsid_str); + if ((error = unmount_automount(&fsid, MNT_NONBUSY)) != 0) + log_warn("cannot unmount %s (FSID:%d:%d)", + mountpoint, fsid.val[0], fsid.val[1]); return (error); } --- b/usr.sbin/autofs/common.h +++ b/usr.sbin/autofs/common.h @@ -33,6 +33,7 @@ #ifndef AUTOMOUNTD_H #define AUTOMOUNTD_H +#include #include #include @@ -104,6 +105,8 @@ int main_autounmountd(int argc, char **argv); FILE *auto_popen(const char *argv0, ...); int auto_pclose(FILE *iop); +int unmount_automount(const fsid_t *fsid, int flags); + /* * lex(1) stuff. */