Module Name: src
Committed By: maxv
Date: Thu Dec 19 07:14:07 UTC 2019
Modified Files:
src/usr.bin/make: Makefile compat.c make.1 meta.c
Log Message:
Revert the filemon removal in bmake, as pointed out by maya we do care
about not introducing divergence with FreeBSD, and the cost of unused
is acceptable here.
To generate a diff of this commit:
cvs rdiff -u -r1.64 -r1.65 src/usr.bin/make/Makefile
cvs rdiff -u -r1.108 -r1.109 src/usr.bin/make/compat.c
cvs rdiff -u -r1.275 -r1.276 src/usr.bin/make/make.1
cvs rdiff -u -r1.72 -r1.73 src/usr.bin/make/meta.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/usr.bin/make/Makefile
diff -u src/usr.bin/make/Makefile:1.64 src/usr.bin/make/Makefile:1.65
--- src/usr.bin/make/Makefile:1.64 Wed Dec 18 07:37:19 2019
+++ src/usr.bin/make/Makefile Thu Dec 19 07:14:07 2019
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.64 2019/12/18 07:37:19 maxv Exp $
+# $NetBSD: Makefile,v 1.65 2019/12/19 07:14:07 maxv Exp $
# @(#)Makefile 5.2 (Berkeley) 12/28/90
PROG= make
@@ -17,6 +17,10 @@ USE_META ?= yes
.if ${USE_META:tl} != "no"
SRCS+= meta.c
CPPFLAGS+= -DUSE_META
+FILEMON_H ?= ${.CURDIR:H:H}/sys/dev/filemon/filemon.h
+.if exists(${FILEMON_H}) && ${FILEMON_H:T} == "filemon.h"
+COPTS.meta.c += -DHAVE_FILEMON_H -I${FILEMON_H:H}
+.endif
.endif
.PATH: ${.CURDIR}/lst.lib
Index: src/usr.bin/make/compat.c
diff -u src/usr.bin/make/compat.c:1.108 src/usr.bin/make/compat.c:1.109
--- src/usr.bin/make/compat.c:1.108 Wed Dec 18 07:37:19 2019
+++ src/usr.bin/make/compat.c Thu Dec 19 07:14:07 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: compat.c,v 1.108 2019/12/18 07:37:19 maxv Exp $ */
+/* $NetBSD: compat.c,v 1.109 2019/12/19 07:14:07 maxv Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -70,14 +70,14 @@
*/
#ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: compat.c,v 1.108 2019/12/18 07:37:19 maxv Exp $";
+static char rcsid[] = "$NetBSD: compat.c,v 1.109 2019/12/19 07:14:07 maxv Exp $";
#else
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "@(#)compat.c 8.2 (Berkeley) 3/19/94";
#else
-__RCSID("$NetBSD: compat.c,v 1.108 2019/12/18 07:37:19 maxv Exp $");
+__RCSID("$NetBSD: compat.c,v 1.109 2019/12/19 07:14:07 maxv Exp $");
#endif
#endif /* not lint */
#endif
@@ -426,6 +426,11 @@ again:
status = WSTOPSIG(reason); /* stopped */
} else if (WIFEXITED(reason)) {
status = WEXITSTATUS(reason); /* exited */
+#if defined(USE_META) && defined(USE_FILEMON_ONCE)
+ if (useMeta) {
+ meta_cmd_finish(NULL);
+ }
+#endif
if (status != 0) {
if (DEBUG(ERROR)) {
fprintf(debug_file, "\n*** Failed target: %s\n*** Failed command: ",
Index: src/usr.bin/make/make.1
diff -u src/usr.bin/make/make.1:1.275 src/usr.bin/make/make.1:1.276
--- src/usr.bin/make/make.1:1.275 Wed Dec 18 07:37:19 2019
+++ src/usr.bin/make/make.1 Thu Dec 19 07:14:07 2019
@@ -1,4 +1,4 @@
-.\" $NetBSD: make.1,v 1.275 2019/12/18 07:37:19 maxv Exp $
+.\" $NetBSD: make.1,v 1.276 2019/12/19 07:14:07 maxv Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -29,7 +29,7 @@
.\"
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
.\"
-.Dd December 17, 2019
+.Dd February 16, 2019
.Dt MAKE 1
.Os
.Sh NAME
@@ -883,7 +883,10 @@ into "compat" mode.
Puts
.Nm
into "meta" mode, where meta files are created for each target
-to capture the command run.
+to capture the command run, the output generated and if
+.Xr filemon 4
+is available, the system calls which are of interest to
+.Nm .
The captured output can be very useful when diagnosing errors.
.It Pa curdirOk= Ar bf
Normally
@@ -971,6 +974,13 @@ by appending their names to
is re-exported whenever
.Ql Va .MAKEOVERRIDES
is modified.
+.It Va .MAKE.PATH_FILEMON
+If
+.Nm
+was built with
+.Xr filemon 4
+support, this is set to the path of the device node.
+This allows makefiles to test for this support.
.It Va .MAKE.PID
The process-id of
.Nm .
Index: src/usr.bin/make/meta.c
diff -u src/usr.bin/make/meta.c:1.72 src/usr.bin/make/meta.c:1.73
--- src/usr.bin/make/meta.c:1.72 Wed Dec 18 10:30:23 2019
+++ src/usr.bin/make/meta.c Thu Dec 19 07:14:07 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: meta.c,v 1.72 2019/12/18 10:30:23 martin Exp $ */
+/* $NetBSD: meta.c,v 1.73 2019/12/19 07:14:07 maxv Exp $ */
/*
* Implement 'meta' mode.
@@ -46,6 +46,13 @@
#include "make.h"
#include "job.h"
+#ifdef HAVE_FILEMON_H
+# include <filemon.h>
+#endif
+#if !defined(USE_FILEMON) && defined(FILEMON_SET_FD)
+# define USE_FILEMON
+#endif
+
static BuildMon Mybm; /* for compat */
static Lst metaBailiwick; /* our scope of control */
static char *metaBailiwickStr; /* string storage for the list */
@@ -93,6 +100,100 @@ extern char **environ;
#endif
/*
+ * Filemon is a kernel module which snoops certain syscalls.
+ *
+ * C chdir
+ * E exec
+ * F [v]fork
+ * L [sym]link
+ * M rename
+ * R read
+ * W write
+ * S stat
+ *
+ * See meta_oodate below - we mainly care about 'E' and 'R'.
+ *
+ * We can still use meta mode without filemon, but
+ * the benefits are more limited.
+ */
+#ifdef USE_FILEMON
+# ifndef _PATH_FILEMON
+# define _PATH_FILEMON "/dev/filemon"
+# endif
+
+/*
+ * Open the filemon device.
+ */
+static void
+filemon_open(BuildMon *pbm)
+{
+ int retry;
+
+ pbm->mon_fd = pbm->filemon_fd = -1;
+ if (!useFilemon)
+ return;
+
+ for (retry = 5; retry >= 0; retry--) {
+ if ((pbm->filemon_fd = open(_PATH_FILEMON, O_RDWR)) >= 0)
+ break;
+ }
+
+ if (pbm->filemon_fd < 0) {
+ useFilemon = FALSE;
+ warn("Could not open %s", _PATH_FILEMON);
+ return;
+ }
+
+ /*
+ * We use a file outside of '.'
+ * to avoid a FreeBSD kernel bug where unlink invalidates
+ * cwd causing getcwd to do a lot more work.
+ * We only care about the descriptor.
+ */
+ pbm->mon_fd = mkTempFile("filemon.XXXXXX", NULL);
+ if (ioctl(pbm->filemon_fd, FILEMON_SET_FD, &pbm->mon_fd) < 0) {
+ err(1, "Could not set filemon file descriptor!");
+ }
+ /* we don't need these once we exec */
+ (void)fcntl(pbm->mon_fd, F_SETFD, FD_CLOEXEC);
+ (void)fcntl(pbm->filemon_fd, F_SETFD, FD_CLOEXEC);
+}
+
+/*
+ * Read the build monitor output file and write records to the target's
+ * metadata file.
+ */
+static int
+filemon_read(FILE *mfp, int fd)
+{
+ char buf[BUFSIZ];
+ int n;
+ int error;
+
+ /* Check if we're not writing to a meta data file.*/
+ if (mfp == NULL) {
+ if (fd >= 0)
+ close(fd); /* not interested */
+ return 0;
+ }
+ /* rewind */
+ (void)lseek(fd, (off_t)0, SEEK_SET);
+
+ error = 0;
+ fprintf(mfp, "\n-- filemon acquired metadata --\n");
+
+ while ((n = read(fd, buf, sizeof(buf))) > 0) {
+ if ((int)fwrite(buf, 1, n, mfp) < n)
+ error = EIO;
+ }
+ fflush(mfp);
+ if (close(fd) < 0)
+ error = errno;
+ return error;
+}
+#endif
+
+/*
* when realpath() fails,
* we use this, to clean up ./ and ../
*/
@@ -467,6 +568,10 @@ boolValue(char *s)
void
meta_init(void)
{
+#ifdef USE_FILEMON
+ /* this allows makefiles to test if we have filemon support */
+ Var_Set(".MAKE.PATH_FILEMON", _PATH_FILEMON, VAR_GLOBAL, 0);
+#endif
}
@@ -568,6 +673,18 @@ meta_job_start(Job *job, GNode *gn)
pbm = &Mybm;
}
pbm->mfp = meta_create(pbm, gn);
+#ifdef USE_FILEMON_ONCE
+ /* compat mode we open the filemon dev once per command */
+ if (job == NULL)
+ return;
+#endif
+#ifdef USE_FILEMON
+ if (pbm->mfp != NULL && useFilemon) {
+ filemon_open(pbm);
+ } else {
+ pbm->mon_fd = pbm->filemon_fd = -1;
+ }
+#endif
}
/*
@@ -577,6 +694,26 @@ meta_job_start(Job *job, GNode *gn)
void
meta_job_child(Job *job)
{
+#ifdef USE_FILEMON
+ BuildMon *pbm;
+
+ if (job != NULL) {
+ pbm = &job->bm;
+ } else {
+ pbm = &Mybm;
+ }
+ if (pbm->mfp != NULL) {
+ close(fileno(pbm->mfp));
+ if (useFilemon) {
+ pid_t pid;
+
+ pid = getpid();
+ if (ioctl(pbm->filemon_fd, FILEMON_SET_PID, &pid) < 0) {
+ err(1, "Could not set filemon pid!");
+ }
+ }
+ }
+#endif
}
void
@@ -649,11 +786,24 @@ meta_cmd_finish(void *pbmp)
{
int error = 0;
BuildMon *pbm = pbmp;
+#ifdef USE_FILEMON
+ int x;
+#endif
if (!pbm)
pbm = &Mybm;
- fprintf(pbm->mfp, "\n"); /* ensure end with newline */
+#ifdef USE_FILEMON
+ if (pbm->filemon_fd >= 0) {
+ if (close(pbm->filemon_fd) < 0)
+ error = errno;
+ x = filemon_read(pbm->mfp, pbm->mon_fd);
+ if (error == 0 && x != 0)
+ error = x;
+ pbm->filemon_fd = pbm->mon_fd = -1;
+ } else
+#endif
+ fprintf(pbm->mfp, "\n"); /* ensure end with newline */
return error;
}
@@ -1442,6 +1592,18 @@ static int childPipe[2];
void
meta_compat_start(void)
{
+#ifdef USE_FILEMON_ONCE
+ /*
+ * We need to re-open filemon for each cmd.
+ */
+ BuildMon *pbm = &Mybm;
+
+ if (pbm->mfp != NULL && useFilemon) {
+ filemon_open(pbm);
+ } else {
+ pbm->mon_fd = pbm->filemon_fd = -1;
+ }
+#endif
if (pipe(childPipe) < 0)
Punt("Cannot create pipe: %s", strerror(errno));
/* Set close-on-exec flag for both */