Index: cddl/compat/opensolaris/misc/zmount.c =================================================================== --- cddl/compat/opensolaris/misc/zmount.c +++ cddl/compat/opensolaris/misc/zmount.c @@ -47,7 +47,7 @@ { int i; - if (*iovlen < 0) + if (*iovlen < 0 || *name == '\0') return; i = *iovlen; *iov = realloc(*iov, sizeof(**iov) * (i + 2)); Index: sbin/devd/devd.conf.5 =================================================================== --- sbin/devd/devd.conf.5 +++ sbin/devd/devd.conf.5 @@ -573,6 +573,20 @@ .Pp .Bl -column "System" "Subsystem" "1234567" -compact .Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description" +.It Li VFS Ta Ta Ta +Events from the vfs system. +.It Li VFS Ta Li FS Ta Ta +Events that change what is mounted to the system. +.It Li VFS Ta Li FS Ta Li MOUNT Ta +Notification of a filesystem is mounted for the first time. +.It Li VFS Ta Li FS Ta Li REMOUNT Ta +Notification of a filesystem is remounted (whether or not the options actually change). +.It Li VFS Ta Li FS Ta Li UNMOUNT Ta +Notification of a filesystem being unmounted. +.El +.Pp +.Bl -column "System" "Subsystem" "1234567" -compact +.Sy "System" Ta Sy "Subsystem" Ta Sy "Type" Ta Sy "Description" .It Li ZFS Ta ZFS Ta Ta Events about the ZFS subsystem. See Index: sbin/mount/mount.c =================================================================== --- sbin/mount/mount.c +++ sbin/mount/mount.c @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include +#define _WANT_MNTOPTNAMES #include #include #include @@ -92,36 +93,8 @@ char *flags2opts(int); /* Map from mount options to printable formats. */ -static struct opt { - uint64_t o_opt; - const char *o_name; -} optnames[] = { - { MNT_ASYNC, "asynchronous" }, - { MNT_EXPORTED, "NFS exported" }, - { MNT_LOCAL, "local" }, - { MNT_NOATIME, "noatime" }, - { MNT_NOEXEC, "noexec" }, - { MNT_NOSUID, "nosuid" }, - { MNT_NOSYMFOLLOW, "nosymfollow" }, - { MNT_QUOTA, "with quotas" }, - { MNT_RDONLY, "read-only" }, - { MNT_SYNCHRONOUS, "synchronous" }, - { MNT_UNION, "union" }, - { MNT_NOCLUSTERR, "noclusterr" }, - { MNT_NOCLUSTERW, "noclusterw" }, - { MNT_SUIDDIR, "suiddir" }, - { MNT_SOFTDEP, "soft-updates" }, - { MNT_SUJ, "journaled soft-updates" }, - { MNT_MULTILABEL, "multilabel" }, - { MNT_ACLS, "acls" }, - { MNT_NFS4ACLS, "nfsv4acls" }, - { MNT_GJOURNAL, "gjournal" }, - { MNT_AUTOMOUNTED, "automounted" }, - { MNT_VERIFIED, "verified" }, - { MNT_UNTRUSTED, "untrusted" }, - { MNT_NOCOVER, "nocover" }, - { MNT_EMPTYDIR, "emptydir" }, - { 0, NULL } +static struct mntoptnames optnames[] = { + MNTOPT_NAMES }; /* @@ -664,7 +637,7 @@ { uint64_t flags; unsigned int i; - struct opt *o; + struct mntoptnames *o; struct passwd *pw; (void)printf("%s on %s (%s", sfp->f_mntfromname, sfp->f_mntonname, Index: sys/amd64/conf/GENERIC =================================================================== --- sys/amd64/conf/GENERIC +++ sys/amd64/conf/GENERIC @@ -71,7 +71,7 @@ options SYSVMSG # SYSV-style message queues options SYSVSEM # SYSV-style semaphores options _KPOSIX_PRIORITY_SCHEDULING # POSIX P1003_1B real-time extensions -options PRINTF_BUFR_SIZE=128 # Prevent printf output being interspersed. +options PRINTF_BUFR_SIZE=512 # Prevent printf output being interspersed. options KBD_INSTALL_CDEV # install a CDEV entry in /dev options HWPMC_HOOKS # Necessary kernel hooks for hwpmc(4) options AUDIT # Security event auditing Index: sys/kern/vfs_mount.c =================================================================== --- sys/kern/vfs_mount.c +++ sys/kern/vfs_mount.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -101,6 +102,8 @@ EVENTHANDLER_LIST_DEFINE(vfs_mounted); EVENTHANDLER_LIST_DEFINE(vfs_unmounted); +static void mount_devctl_event(const char *type, struct mount *mp, bool donew); + /* * Global opts, taken by all filesystems */ @@ -1020,6 +1023,7 @@ VOP_UNLOCK(vp); EVENTHANDLER_DIRECT_INVOKE(vfs_mounted, mp, newdp, td); VOP_UNLOCK(newdp); + mount_devctl_event("MOUNT", mp, false); mountcheckdirs(vp, newdp); vn_seqc_write_end(vp); vn_seqc_write_end(newdp); @@ -1221,6 +1225,7 @@ if (error != 0) goto end; + mount_devctl_event("REMOUNT", mp, true); if (mp->mnt_opt != NULL) vfs_freeopts(mp->mnt_opt); mp->mnt_opt = mp->mnt_optnew; @@ -1842,6 +1847,7 @@ VOP_UNLOCK(coveredvp); vdrop(coveredvp); } + mount_devctl_event("UNMOUNT", mp, false); if (rootvp != NULL) { vn_seqc_write_end(rootvp); vdrop(rootvp); @@ -2423,3 +2429,71 @@ error = kernel_mount(ma, flags); return (error); } + +/* Map from mount options to printable formats. */ +static struct mntoptnames optnames[] = { + MNTOPT_NAMES +}; + +static void +mount_devctl_event_mntopt(struct sbuf *sb, const char *what, struct vfsoptlist *opts) +{ + struct vfsopt *opt; + + if (opts == NULL || TAILQ_EMPTY(opts)) + return; + sbuf_printf(sb, " %s=\"", what); + TAILQ_FOREACH(opt, opts, link) { + if (opt->name[0] == '\0' || (opt->len > 0 && *(char *)opt->value == '\0')) + continue; + devctl_safe_quote_sb(sb, opt->name); + if (opt->len > 0) { + sbuf_putc(sb, '='); + devctl_safe_quote_sb(sb, opt->value); + } + sbuf_putc(sb, ';'); + } + sbuf_putc(sb, '"'); +} + +#define DEVCTL_LEN 1024 +static void +mount_devctl_event(const char *type, struct mount *mp, bool donew) +{ + const uint8_t *cp; + struct mntoptnames *fp; + struct sbuf sb; + struct statfs *sfp = &mp->mnt_stat; + char *buf; + + buf = malloc(DEVCTL_LEN, M_MOUNT, M_WAITOK); + if (buf == NULL) + return; + sbuf_new(&sb, buf, DEVCTL_LEN, SBUF_FIXEDLEN); + sbuf_cpy(&sb, "mount-point=\""); + devctl_safe_quote_sb(&sb, sfp->f_mntonname); + sbuf_cat(&sb, "\" mount-dev=\""); + devctl_safe_quote_sb(&sb, sfp->f_mntfromname); + sbuf_cat(&sb, "\" mount-type=\""); + devctl_safe_quote_sb(&sb, sfp->f_fstypename); + sbuf_cat(&sb, "\" fsid=0x"); + cp = (const uint8_t *)&sfp->f_fsid.val[0]; + for (int i = 0; i < sizeof(sfp->f_fsid); i++) + sbuf_printf(&sb, "%02x", cp[i]); + sbuf_printf(&sb, " owner=%u flags=\"", sfp->f_owner); + for (fp = optnames; fp->o_opt != 0; fp++) { + if ((mp->mnt_flag & fp->o_opt) != 0) { + sbuf_cat(&sb, fp->o_name); + sbuf_putc(&sb, ';'); + } + } + sbuf_putc(&sb, '"'); + mount_devctl_event_mntopt(&sb, "opt", mp->mnt_opt); + if (donew) + mount_devctl_event_mntopt(&sb, "optnew", mp->mnt_optnew); + sbuf_finish(&sb); + + devctl_notify("VFS", "FS", type, sbuf_data(&sb)); + sbuf_delete(&sb); + free(buf, M_MOUNT); +} Index: sys/sys/mount.h =================================================================== --- sys/sys/mount.h +++ sys/sys/mount.h @@ -294,6 +294,45 @@ #endif /* _KERNEL */ +#if defined(_WANT_MNTOPTNAMES) || defined(_KERNEL) +struct mntoptnames { + uint64_t o_opt; + const char *o_name; +}; +#define MNTOPT_NAMES \ + { MNT_ASYNC, "asynchronous" }, \ + { MNT_EXPORTED, "NFS exported" }, \ + { MNT_LOCAL, "local" }, \ + { MNT_NOATIME, "noatime" }, \ + { MNT_NOEXEC, "noexec" }, \ + { MNT_NOSUID, "nosuid" }, \ + { MNT_NOSYMFOLLOW, "nosymfollow" }, \ + { MNT_QUOTA, "with quotas" }, \ + { MNT_RDONLY, "read-only" }, \ + { MNT_SYNCHRONOUS, "synchronous" }, \ + { MNT_UNION, "union" }, \ + { MNT_NOCLUSTERR, "noclusterr" }, \ + { MNT_NOCLUSTERW, "noclusterw" }, \ + { MNT_SUIDDIR, "suiddir" }, \ + { MNT_SOFTDEP, "soft-updates" }, \ + { MNT_SUJ, "journaled soft-updates" }, \ + { MNT_MULTILABEL, "multilabel" }, \ + { MNT_ACLS, "acls" }, \ + { MNT_NFS4ACLS, "nfsv4acls" }, \ + { MNT_GJOURNAL, "gjournal" }, \ + { MNT_AUTOMOUNTED, "automounted" }, \ + { MNT_VERIFIED, "verified" }, \ + { MNT_UNTRUSTED, "untrusted" }, \ + { MNT_NOCOVER, "nocover" }, \ + { MNT_EMPTYDIR, "emptydir" }, \ + { MNT_UPDATE, "update" }, \ + { MNT_DELEXPORT, "delexport" }, \ + { MNT_RELOAD, "reload" }, \ + { MNT_FORCE, "force" }, \ + { MNT_SNAPSHOT, "snapshot" }, \ + { 0, NULL } +#endif + /* * User specifiable flags, stored in mnt_flag. */