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 */

Reply via email to