xref: /dflybsd-src/usr.bin/dsynth/mount.c (revision 2b0cb81791f7cbae1a99aff6d697787b0372d28e)
18e25f19bSMatthew Dillon /*
23bd7e0a7SMatthew Dillon  * Copyright (c) 2019-2022 The DragonFly Project.  All rights reserved.
38e25f19bSMatthew Dillon  *
48e25f19bSMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
58e25f19bSMatthew Dillon  * by Matthew Dillon <dillon@backplane.com>
68e25f19bSMatthew Dillon  *
78e25f19bSMatthew Dillon  * This code uses concepts and configuration based on 'synth', by
88e25f19bSMatthew Dillon  * John R. Marino <draco@marino.st>, which was written in ada.
98e25f19bSMatthew Dillon  *
108e25f19bSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
118e25f19bSMatthew Dillon  * modification, are permitted provided that the following conditions
128e25f19bSMatthew Dillon  * are met:
138e25f19bSMatthew Dillon  *
148e25f19bSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
158e25f19bSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
168e25f19bSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
178e25f19bSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
188e25f19bSMatthew Dillon  *    the documentation and/or other materials provided with the
198e25f19bSMatthew Dillon  *    distribution.
208e25f19bSMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
218e25f19bSMatthew Dillon  *    contributors may be used to endorse or promote products derived
228e25f19bSMatthew Dillon  *    from this software without specific, prior written permission.
238e25f19bSMatthew Dillon  *
248e25f19bSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
258e25f19bSMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
268e25f19bSMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
278e25f19bSMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
288e25f19bSMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
298e25f19bSMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
308e25f19bSMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
318e25f19bSMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
328e25f19bSMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
338e25f19bSMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
348e25f19bSMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
358e25f19bSMatthew Dillon  * SUCH DAMAGE.
368e25f19bSMatthew Dillon  */
378e25f19bSMatthew Dillon #include "dsynth.h"
388e25f19bSMatthew Dillon 
398e25f19bSMatthew Dillon static void domount(worker_t *work, int type,
401d6e00cdSMatthew Dillon 			const char *spath, const char *dpath,
411d6e00cdSMatthew Dillon 			const char *discretefmt);
428e25f19bSMatthew Dillon static void dounmount(worker_t *work, const char *rpath);
431d6e00cdSMatthew Dillon static void makeDiscreteCopies(const char *spath, const char *discretefmt);
448e25f19bSMatthew Dillon 
458e25f19bSMatthew Dillon /*
468e25f19bSMatthew Dillon  * Called by the frontend to create a template which will be cpdup'd
478e25f19bSMatthew Dillon  * into fresh workers.
488e25f19bSMatthew Dillon  *
498e25f19bSMatthew Dillon  * Template must have been previously destroyed.  Errors are fatal
508e25f19bSMatthew Dillon  */
518e25f19bSMatthew Dillon int
DoCreateTemplate(int force)521d6e00cdSMatthew Dillon DoCreateTemplate(int force)
538e25f19bSMatthew Dillon {
541d6e00cdSMatthew Dillon 	struct stat st;
558ec23ca1SMatthew Dillon 	char *goodbuf;
568e25f19bSMatthew Dillon 	char *buf;
57753e4c44SMatthew Dillon 	const char *reason = "";
588e25f19bSMatthew Dillon 	int rc;
598ec23ca1SMatthew Dillon 	int fd;
602074bc97SMatthew Dillon 	int n;
618e25f19bSMatthew Dillon 
628e25f19bSMatthew Dillon 	rc = 0;
638ec23ca1SMatthew Dillon 	asprintf(&goodbuf, "%s/.template.good", BuildBase);
641d6e00cdSMatthew Dillon 
651d6e00cdSMatthew Dillon 	/*
661d6e00cdSMatthew Dillon 	 * Conditionally create the template and discrete copies of certain
671d6e00cdSMatthew Dillon 	 * directories if we think we are missing things.
681d6e00cdSMatthew Dillon 	 */
69753e4c44SMatthew Dillon 	if (force == 1)
70753e4c44SMatthew Dillon 		reason = " (Asked to force template creation)";
711d6e00cdSMatthew Dillon 	if (force == 0) {
722074bc97SMatthew Dillon 		time_t ls_mtime;
732074bc97SMatthew Dillon 
741d6e00cdSMatthew Dillon 		asprintf(&buf, "%s/Template", BuildBase);
75753e4c44SMatthew Dillon 		if (stat(buf, &st) < 0) {
761d6e00cdSMatthew Dillon 			force = 1;
77753e4c44SMatthew Dillon 			reason = " (Template file missing)";
78753e4c44SMatthew Dillon 		}
791d6e00cdSMatthew Dillon 		free(buf);
801d6e00cdSMatthew Dillon 
812074bc97SMatthew Dillon 		/*
822074bc97SMatthew Dillon 		 * Check to see if the worker count changed and some
832074bc97SMatthew Dillon 		 * template dirs are missing or out of date, and also if
842074bc97SMatthew Dillon 		 * a new world was installed (via /bin/ls mtime).
852074bc97SMatthew Dillon 		 */
862074bc97SMatthew Dillon 		asprintf(&buf, "%s/bin/ls", SystemPath);
872074bc97SMatthew Dillon 		if (stat(buf, &st) < 0)
882074bc97SMatthew Dillon 			dfatal_errno("Unable to locate %s", buf);
892074bc97SMatthew Dillon 		free(buf);
902074bc97SMatthew Dillon 		ls_mtime = st.st_mtime;
912074bc97SMatthew Dillon 
922074bc97SMatthew Dillon 		for (n = 0; n < MaxWorkers; ++n) {
932074bc97SMatthew Dillon 			asprintf(&buf, "%s/bin.%03d/ls", BuildBase, n);
94753e4c44SMatthew Dillon 			if (stat(buf, &st) < 0 || st.st_mtime != ls_mtime) {
952074bc97SMatthew Dillon 				force = 1;
96753e4c44SMatthew Dillon 				reason = " (/bin/ls mtime mismatch)";
97753e4c44SMatthew Dillon 			}
982074bc97SMatthew Dillon 			free(buf);
992074bc97SMatthew Dillon 		}
1002074bc97SMatthew Dillon 
101753e4c44SMatthew Dillon 		if (stat(goodbuf, &st) < 0) {
1021d6e00cdSMatthew Dillon 			force = 1;
103753e4c44SMatthew Dillon 			reason = " (.template.good file missing)";
104753e4c44SMatthew Dillon 		}
1051d6e00cdSMatthew Dillon 	}
1061d6e00cdSMatthew Dillon 
107753e4c44SMatthew Dillon 	dlog(DLOG_ALL, "Check Template: %s%s\n",
108753e4c44SMatthew Dillon 	     (force ? "Must-Create" : "Good"),
109753e4c44SMatthew Dillon 	     reason);
1106fd67931SMatthew Dillon 
1111d6e00cdSMatthew Dillon 	/*
1121d6e00cdSMatthew Dillon 	 * Create the template
1131d6e00cdSMatthew Dillon 	 */
1141d6e00cdSMatthew Dillon 	if (force) {
1158ec23ca1SMatthew Dillon 		remove(goodbuf);	/* ignore exit code */
1168ec23ca1SMatthew Dillon 
1171d6e00cdSMatthew Dillon 		rc = 0;
1188e25f19bSMatthew Dillon 		asprintf(&buf, "%s/mktemplate %s %s/Template",
1198e25f19bSMatthew Dillon 			 SCRIPTPATH(SCRIPTDIR), SystemPath, BuildBase);
1208e25f19bSMatthew Dillon 		rc = system(buf);
1218e25f19bSMatthew Dillon 		if (rc)
1228e25f19bSMatthew Dillon 			dfatal("Command failed: %s\n", buf);
123a574cbf0SMatthew Dillon 		dlog(DLOG_ALL | DLOG_FILTER,
124a574cbf0SMatthew Dillon 		     "Template - rc=%d running %s\n", rc, buf);
1258e25f19bSMatthew Dillon 		free(buf);
1261d6e00cdSMatthew Dillon 
1271d6e00cdSMatthew Dillon 		/*
1281d6e00cdSMatthew Dillon 		 * Make discrete copies of certain extremely heavily used
1291d6e00cdSMatthew Dillon 		 * but small directories.
1301d6e00cdSMatthew Dillon 		 */
1311d6e00cdSMatthew Dillon 		makeDiscreteCopies("$/bin", "/bin.%03d");
1321d6e00cdSMatthew Dillon 		makeDiscreteCopies("$/lib", "/lib.%03d");
1331d6e00cdSMatthew Dillon 		makeDiscreteCopies("$/libexec", "/libexec.%03d");
1341d6e00cdSMatthew Dillon 		makeDiscreteCopies("$/usr/bin", "/usr.bin.%03d");
1358e25f19bSMatthew Dillon 
1368ec23ca1SMatthew Dillon 		/*
1378ec23ca1SMatthew Dillon 		 * Mark the template good... ah, do a sync() to really
1388ec23ca1SMatthew Dillon 		 * be sure that it can't get corrupted.
1398ec23ca1SMatthew Dillon 		 */
1408ec23ca1SMatthew Dillon 		sync();
1418ec23ca1SMatthew Dillon 		fd = open(goodbuf, O_RDWR|O_CREAT|O_TRUNC, 0644);
1428ec23ca1SMatthew Dillon 		dassert_errno(fd >= 0, "could not create %s", goodbuf);
1438ec23ca1SMatthew Dillon 		close(fd);
1448ec23ca1SMatthew Dillon 
145a574cbf0SMatthew Dillon 		dlog(DLOG_ALL | DLOG_FILTER, "Template - done\n");
1468ec23ca1SMatthew Dillon 	}
1478ec23ca1SMatthew Dillon 	free(goodbuf);
1488ec23ca1SMatthew Dillon 
1496fd67931SMatthew Dillon 	return force;
1508e25f19bSMatthew Dillon }
1518e25f19bSMatthew Dillon 
1528e25f19bSMatthew Dillon void
DoDestroyTemplate(void)1538e25f19bSMatthew Dillon DoDestroyTemplate(void)
1548e25f19bSMatthew Dillon {
1558e25f19bSMatthew Dillon 	struct stat st;
1568e25f19bSMatthew Dillon 	char *path;
1578e25f19bSMatthew Dillon 	char *buf;
1588e25f19bSMatthew Dillon 	int rc;
1598e25f19bSMatthew Dillon 
1608e25f19bSMatthew Dillon 	/*
1618e25f19bSMatthew Dillon 	 * NOTE: rm -rf safety, use a fixed name 'Template' to ensure we
1628e25f19bSMatthew Dillon 	 *	 do not accidently blow something up.
1638e25f19bSMatthew Dillon 	 */
1648e25f19bSMatthew Dillon 	asprintf(&path, "%s/Template", BuildBase);
1658e25f19bSMatthew Dillon 	if (stat(path, &st) == 0) {
1668e25f19bSMatthew Dillon 		asprintf(&buf, "chflags -R noschg %s; /bin/rm -rf %s",
1678e25f19bSMatthew Dillon 			 path, path);
1688e25f19bSMatthew Dillon 		rc = system(buf);
1698e25f19bSMatthew Dillon 		if (rc)
1708e25f19bSMatthew Dillon 			dfatal("Command failed: %s (ignored)\n", buf);
1718e25f19bSMatthew Dillon 		free(buf);
1728e25f19bSMatthew Dillon 	}
1738e25f19bSMatthew Dillon 	free(path);
1748e25f19bSMatthew Dillon }
1758e25f19bSMatthew Dillon 
1768e25f19bSMatthew Dillon /*
1778e25f19bSMatthew Dillon  * Called by the worker support thread to install a new worker
1788e25f19bSMatthew Dillon  * filesystem topology.
1798e25f19bSMatthew Dillon  */
1808e25f19bSMatthew Dillon void
DoWorkerMounts(worker_t * work)1818e25f19bSMatthew Dillon DoWorkerMounts(worker_t *work)
1828e25f19bSMatthew Dillon {
1838e25f19bSMatthew Dillon 	char *buf;
1848e25f19bSMatthew Dillon 	int rc;
1858e25f19bSMatthew Dillon 
1868e25f19bSMatthew Dillon 	/*
1878e25f19bSMatthew Dillon 	 * Generate required mounts, domount() will mkdir() the target
1888e25f19bSMatthew Dillon 	 * directory if necessary and prefix spath with SystemPath if
1898e25f19bSMatthew Dillon 	 * it starts with $/
1908e25f19bSMatthew Dillon 	 */
1913bd7e0a7SMatthew Dillon 	setNumaDomain(work->index);
1921d6e00cdSMatthew Dillon 	domount(work, TMPFS_RW, "dummy", "", NULL);
1938e25f19bSMatthew Dillon 	asprintf(&buf, "%s/usr", work->basedir);
1948e25f19bSMatthew Dillon 	if (mkdir(buf, 0755) != 0) {
1958e25f19bSMatthew Dillon 		fprintf(stderr, "Command failed: mkdir %s\n", buf);
1968e25f19bSMatthew Dillon 		++work->mount_error;
1978e25f19bSMatthew Dillon 	}
19840dedc16SAntonio Huete Jimenez 	free(buf);
199*2b0cb817SMatthew Dillon 	asprintf(&buf, "%s/usr/packages", work->basedir);
200*2b0cb817SMatthew Dillon 	if (mkdir(buf, 0755) != 0) {
201*2b0cb817SMatthew Dillon 		fprintf(stderr, "Command failed: mkdir %s\n", buf);
202*2b0cb817SMatthew Dillon 		++work->mount_error;
203*2b0cb817SMatthew Dillon 	}
204*2b0cb817SMatthew Dillon 	free(buf);
20540dedc16SAntonio Huete Jimenez 
20649d2b1cbSMatthew Dillon 	domount(work, TMPFS_RW,  "dummy", "/boot", NULL);
20749d2b1cbSMatthew Dillon 
20849d2b1cbSMatthew Dillon 	asprintf(&buf, "%s/boot/modules.local", work->basedir);
20949d2b1cbSMatthew Dillon 	if (mkdir(buf, 0755) != 0) {
21049d2b1cbSMatthew Dillon 		fprintf(stderr, "Command failed: mkdir %s\n", buf);
21149d2b1cbSMatthew Dillon 		++work->mount_error;
21249d2b1cbSMatthew Dillon 	}
21349d2b1cbSMatthew Dillon 	free(buf);
21449d2b1cbSMatthew Dillon 
2151d6e00cdSMatthew Dillon 	domount(work, DEVFS_RW,  "dummy", "/dev", NULL);
2168ec23ca1SMatthew Dillon 	domount(work, PROCFS_RO, "dummy", "/proc", NULL);
2171d6e00cdSMatthew Dillon 	domount(work, NULLFS_RO, "$/bin", "/bin", "/bin.%03d");
2181d6e00cdSMatthew Dillon 	domount(work, NULLFS_RO, "$/sbin", "/sbin", NULL);
2191d6e00cdSMatthew Dillon 	domount(work, NULLFS_RO, "$/lib", "/lib", "/lib.%03d");
2201d6e00cdSMatthew Dillon 	domount(work, NULLFS_RO, "$/libexec", "/libexec", "/libexec.%03d");
2211d6e00cdSMatthew Dillon 	domount(work, NULLFS_RO, "$/usr/bin", "/usr/bin", "/usr.bin.%03d");
2221d6e00cdSMatthew Dillon 	domount(work, NULLFS_RO, "$/usr/include", "/usr/include", NULL);
2231d6e00cdSMatthew Dillon 	domount(work, NULLFS_RO, "$/usr/lib", "/usr/lib", NULL);
2241d6e00cdSMatthew Dillon 	domount(work, NULLFS_RO, "$/usr/libdata", "/usr/libdata", NULL);
2251d6e00cdSMatthew Dillon 	domount(work, NULLFS_RO, "$/usr/libexec", "/usr/libexec", NULL);
2261d6e00cdSMatthew Dillon 	domount(work, NULLFS_RO, "$/usr/sbin", "/usr/sbin", NULL);
2271d6e00cdSMatthew Dillon 	domount(work, NULLFS_RO, "$/usr/share", "/usr/share", NULL);
228a6361508SMatthew Dillon 	domount(work, TMPFS_RW_MED,  "dummy", "/usr/local", NULL);
2291d6e00cdSMatthew Dillon 	domount(work, NULLFS_RO, "$/usr/games", "/usr/games", NULL);
230f4094b20SMatthew Dillon 	if (UseUsrSrc)
231f4094b20SMatthew Dillon 		domount(work, NULLFS_RO, "$/usr/src", "/usr/src", NULL);
2321d6e00cdSMatthew Dillon 	domount(work, NULLFS_RO, DPortsPath, "/xports", NULL);
2331d6e00cdSMatthew Dillon 	domount(work, NULLFS_RW, OptionsPath, "/options", NULL);
2341d6e00cdSMatthew Dillon 	domount(work, NULLFS_RW, PackagesPath, "/packages", NULL);
2351d6e00cdSMatthew Dillon 	domount(work, NULLFS_RW, DistFilesPath, "/distfiles", NULL);
2361d6e00cdSMatthew Dillon 	domount(work, TMPFS_RW_BIG, "dummy", "/construction", NULL);
2376fd67931SMatthew Dillon 	if (UseCCache)
238f4094b20SMatthew Dillon 		domount(work, NULLFS_RW, CCachePath, "/ccache", NULL);
2398e25f19bSMatthew Dillon 
2408e25f19bSMatthew Dillon 	/*
2418e25f19bSMatthew Dillon 	 * NOTE: Uses blah/. to prevent cp from creating 'Template' under
2428e25f19bSMatthew Dillon 	 *	 work->basedir.  We want to start with the content.
2438e25f19bSMatthew Dillon 	 */
2448e25f19bSMatthew Dillon 	asprintf(&buf, "cp -Rp %s/Template/. %s", BuildBase, work->basedir);
2458e25f19bSMatthew Dillon 	rc = system(buf);
2468e25f19bSMatthew Dillon 	if (rc) {
2478e25f19bSMatthew Dillon 		fprintf(stderr, "Command failed: %s\n", buf);
2488e25f19bSMatthew Dillon 		++work->accum_error;
2498e25f19bSMatthew Dillon 		snprintf(work->status, sizeof(work->status),
2508e25f19bSMatthew Dillon 			 "Template copy failed");
2518e25f19bSMatthew Dillon 	}
2528e25f19bSMatthew Dillon 	free(buf);
2533bd7e0a7SMatthew Dillon 	setNumaDomain(-1);
2548e25f19bSMatthew Dillon }
2558e25f19bSMatthew Dillon 
2568e25f19bSMatthew Dillon /*
2578e25f19bSMatthew Dillon  * Called by the worker support thread to remove a worker
2588e25f19bSMatthew Dillon  * filesystem topology.
259f4094b20SMatthew Dillon  *
260f4094b20SMatthew Dillon  * NOTE: No need to conditionalize UseUsrSrc, it doesn't hurt to
261f4094b20SMatthew Dillon  *	 issue the umount() if it isn't mounted and it ensures that
262f4094b20SMatthew Dillon  *	 everything is unmounted properly on cleanup if the state
263f4094b20SMatthew Dillon  *	 changes.
2648e25f19bSMatthew Dillon  */
2658e25f19bSMatthew Dillon void
DoWorkerUnmounts(worker_t * work)2668e25f19bSMatthew Dillon DoWorkerUnmounts(worker_t *work)
2678e25f19bSMatthew Dillon {
2688e25f19bSMatthew Dillon 	int retries;
2698e25f19bSMatthew Dillon 
2703bd7e0a7SMatthew Dillon 	setNumaDomain(work->index);
2718e25f19bSMatthew Dillon 	work->mount_error = 0;
2728e25f19bSMatthew Dillon 	for (retries = 0; retries < 10; ++retries) {
2738ec23ca1SMatthew Dillon 		dounmount(work, "/proc");
2748e25f19bSMatthew Dillon 		dounmount(work, "/dev");
275f4094b20SMatthew Dillon 		dounmount(work, "/usr/src");
2768e25f19bSMatthew Dillon 		dounmount(work, "/usr/games");
2778e25f19bSMatthew Dillon 		dounmount(work, "/boot");
2788e25f19bSMatthew Dillon 		dounmount(work, "/usr/local");
2798e25f19bSMatthew Dillon 		dounmount(work, "/construction");
2806fd67931SMatthew Dillon 		dounmount(work, "/ccache");	/* in case of config change */
2818e25f19bSMatthew Dillon 		dounmount(work, "/distfiles");
2828e25f19bSMatthew Dillon 		dounmount(work, "/packages");
2838e25f19bSMatthew Dillon 		dounmount(work, "/options");
2848e25f19bSMatthew Dillon 		dounmount(work, "/xports");
2858e25f19bSMatthew Dillon 		dounmount(work, "/usr/share");
2868e25f19bSMatthew Dillon 		dounmount(work, "/usr/sbin");
2878e25f19bSMatthew Dillon 		dounmount(work, "/usr/libexec");
2888e25f19bSMatthew Dillon 		dounmount(work, "/usr/libdata");
2898e25f19bSMatthew Dillon 		dounmount(work, "/usr/lib");
2908e25f19bSMatthew Dillon 		dounmount(work, "/usr/include");
2918e25f19bSMatthew Dillon 		dounmount(work, "/usr/bin");
2928e25f19bSMatthew Dillon 		dounmount(work, "/libexec");
2938e25f19bSMatthew Dillon 		dounmount(work, "/lib");
2948e25f19bSMatthew Dillon 		dounmount(work, "/sbin");
2958e25f19bSMatthew Dillon 		dounmount(work, "/bin");
2968e25f19bSMatthew Dillon 		dounmount(work, "");
2978e25f19bSMatthew Dillon 		if (work->mount_error == 0)
2988e25f19bSMatthew Dillon 			break;
2998e25f19bSMatthew Dillon 		sleep(5);
3008e25f19bSMatthew Dillon 		work->mount_error = 0;
3018e25f19bSMatthew Dillon 	}
3028e25f19bSMatthew Dillon 	if (work->mount_error) {
3038e25f19bSMatthew Dillon 		++work->accum_error;
3048e25f19bSMatthew Dillon 		snprintf(work->status, sizeof(work->status),
3058e25f19bSMatthew Dillon 			 "Unable to unmount slot");
3068e25f19bSMatthew Dillon 	}
3073bd7e0a7SMatthew Dillon 	setNumaDomain(-1);
3088e25f19bSMatthew Dillon }
3098e25f19bSMatthew Dillon 
3108e25f19bSMatthew Dillon static
3118e25f19bSMatthew Dillon void
domount(worker_t * work,int type,const char * spath,const char * dpath,const char * discretefmt)3121d6e00cdSMatthew Dillon domount(worker_t *work, int type, const char *spath, const char *dpath,
3131d6e00cdSMatthew Dillon 	const char *discretefmt)
3148e25f19bSMatthew Dillon {
3158e25f19bSMatthew Dillon 	const char *sbase;
3168e25f19bSMatthew Dillon 	const char *rwstr;
3178e25f19bSMatthew Dillon 	const char *optstr;
318223eb4a7SAntonio Huete Jimenez 	const char *typestr;
319aeecca07SMatthew Dillon 	const char *debug;
3208e25f19bSMatthew Dillon 	struct stat st;
3218e25f19bSMatthew Dillon 	char *buf;
3221d6e00cdSMatthew Dillon 	char *tmp;
3238e25f19bSMatthew Dillon 	int rc;
3248e25f19bSMatthew Dillon 
3258e25f19bSMatthew Dillon 	/*
3268e25f19bSMatthew Dillon 	 * Make target directory if necessary.  This must occur in-order
3278e25f19bSMatthew Dillon 	 * since directories may have to be created under prior mounts
3288e25f19bSMatthew Dillon 	 * in the sequence.
3298e25f19bSMatthew Dillon 	 */
3308e25f19bSMatthew Dillon 	asprintf(&buf, "%s%s", work->basedir, dpath);
3318e25f19bSMatthew Dillon 	if (stat(buf, &st) != 0) {
3328e25f19bSMatthew Dillon 		if (mkdir(buf, 0755) != 0) {
3338e25f19bSMatthew Dillon 			fprintf(stderr, "Command failed: mkdir %s\n", buf);
3348e25f19bSMatthew Dillon 			++work->mount_error;
3358e25f19bSMatthew Dillon 		}
3368e25f19bSMatthew Dillon 	}
3378e25f19bSMatthew Dillon 	free(buf);
3388e25f19bSMatthew Dillon 
3398e25f19bSMatthew Dillon 	/*
3408e25f19bSMatthew Dillon 	 * Setup for mount arguments
3418e25f19bSMatthew Dillon 	 */
3428e25f19bSMatthew Dillon 	rwstr = (type & MOUNT_TYPE_RW) ? "rw" : "ro";
3438e25f19bSMatthew Dillon 	optstr = "";
344223eb4a7SAntonio Huete Jimenez 	typestr = "";
3458e25f19bSMatthew Dillon 
3468e25f19bSMatthew Dillon 	switch(type & MOUNT_TYPE_MASK) {
3478e25f19bSMatthew Dillon 	case MOUNT_TYPE_TMPFS:
348aeecca07SMatthew Dillon 		/*
349aeecca07SMatthew Dillon 		 * When creating a tmpfs filesystem, make sure the big ones
350aeecca07SMatthew Dillon 		 * requested are big enough for the worst-case dport (which
351aeecca07SMatthew Dillon 		 * is usually chromium).  If debugging is turned on, its even
352aeecca07SMatthew Dillon 		 * worse.  You'd better have enough swap!
353aeecca07SMatthew Dillon 		 */
354aeecca07SMatthew Dillon 		debug = getbuildenv("WITH_DEBUG");
355223eb4a7SAntonio Huete Jimenez 		typestr = "tmpfs";
3568e25f19bSMatthew Dillon 		if (type & MOUNT_TYPE_BIG)
357aeecca07SMatthew Dillon 			optstr = debug ? " -o size=128g" : " -o size=64g";
358a6361508SMatthew Dillon 		else if (type & MOUNT_TYPE_MED)
359a6361508SMatthew Dillon 			optstr = debug ? " -o size=32g" : " -o size=16g";
3608e25f19bSMatthew Dillon 		else
361223eb4a7SAntonio Huete Jimenez 			optstr = " -o size=16g";
3628e25f19bSMatthew Dillon 		break;
3638e25f19bSMatthew Dillon 	case MOUNT_TYPE_NULLFS:
364223eb4a7SAntonio Huete Jimenez #if defined(__DragonFly__)
365223eb4a7SAntonio Huete Jimenez 		typestr = "null";
366223eb4a7SAntonio Huete Jimenez #else
367223eb4a7SAntonio Huete Jimenez 		typestr = "nullfs";
368223eb4a7SAntonio Huete Jimenez #endif
3698e25f19bSMatthew Dillon 		break;
3708e25f19bSMatthew Dillon 	case MOUNT_TYPE_DEVFS:
371223eb4a7SAntonio Huete Jimenez 		typestr = "devfs";
3728e25f19bSMatthew Dillon 		break;
3738ec23ca1SMatthew Dillon 	case MOUNT_TYPE_PROCFS:
374223eb4a7SAntonio Huete Jimenez 		typestr = "procfs";
3758ec23ca1SMatthew Dillon 		break;
3768e25f19bSMatthew Dillon 	default:
3778e25f19bSMatthew Dillon 		dfatal("Illegal mount type: %08x", type);
3788e25f19bSMatthew Dillon 		/* NOT REACHED */
3798e25f19bSMatthew Dillon 		break;
3808e25f19bSMatthew Dillon 	}
3818e25f19bSMatthew Dillon 
3828e25f19bSMatthew Dillon 	/*
3838e25f19bSMatthew Dillon 	 * Prefix spath
3848e25f19bSMatthew Dillon 	 */
3851d6e00cdSMatthew Dillon 	if (discretefmt) {
3861d6e00cdSMatthew Dillon 		sbase = BuildBase;
3871d6e00cdSMatthew Dillon 		asprintf(&tmp, discretefmt, work->index);
3881d6e00cdSMatthew Dillon 		spath = tmp;
3891d6e00cdSMatthew Dillon 	} else {
3908e25f19bSMatthew Dillon 		if (spath[0] == '$') {
3918e25f19bSMatthew Dillon 			++spath;
3928e25f19bSMatthew Dillon 			sbase = SystemPath;
3931d6e00cdSMatthew Dillon 			if (strcmp(sbase, "/") == 0)
3941d6e00cdSMatthew Dillon 				++sbase;
3958e25f19bSMatthew Dillon 		} else {
3968e25f19bSMatthew Dillon 			sbase = "";
3978e25f19bSMatthew Dillon 		}
3981d6e00cdSMatthew Dillon 		tmp = NULL;
3991d6e00cdSMatthew Dillon 	}
400223eb4a7SAntonio Huete Jimenez 	asprintf(&buf, "%s%s -t %s -o %s %s%s %s%s",
401223eb4a7SAntonio Huete Jimenez 		MOUNT_BINARY, optstr, typestr, rwstr,
4028e25f19bSMatthew Dillon 		sbase, spath, work->basedir, dpath);
4038e25f19bSMatthew Dillon 	rc = system(buf);
4048e25f19bSMatthew Dillon 	if (rc) {
4058e25f19bSMatthew Dillon 		fprintf(stderr, "Command failed: %s\n", buf);
4068e25f19bSMatthew Dillon 		++work->mount_error;
4078e25f19bSMatthew Dillon 	}
4088e25f19bSMatthew Dillon 	free(buf);
4091d6e00cdSMatthew Dillon 	if (tmp)
4101d6e00cdSMatthew Dillon 		free(tmp);
4118e25f19bSMatthew Dillon }
4128e25f19bSMatthew Dillon 
4138e25f19bSMatthew Dillon static
4148e25f19bSMatthew Dillon void
dounmount(worker_t * work,const char * rpath)4158e25f19bSMatthew Dillon dounmount(worker_t *work, const char *rpath)
4168e25f19bSMatthew Dillon {
4178e25f19bSMatthew Dillon 	char *buf;
4188e25f19bSMatthew Dillon 
4198e25f19bSMatthew Dillon 	asprintf(&buf, "%s%s", work->basedir, rpath);
4208e25f19bSMatthew Dillon 	if (unmount(buf, 0) < 0) {
4218e25f19bSMatthew Dillon 		switch(errno) {
42268dc2eeaSMatthew Dillon 		case EPERM:	/* This is probably fatal later on in mount */
42368dc2eeaSMatthew Dillon 		case ENOENT:	/* Expected if mount already gone */
42468dc2eeaSMatthew Dillon 		case EINVAL:	/* Expected if mount already gone (maybe) */
4258e25f19bSMatthew Dillon 			break;
4268e25f19bSMatthew Dillon 		default:
4271d6e00cdSMatthew Dillon 			fprintf(stderr, "Cannot umount %s (%s)\n",
4281d6e00cdSMatthew Dillon 				buf, strerror(errno));
4298e25f19bSMatthew Dillon 			++work->mount_error;
4308e25f19bSMatthew Dillon 			break;
4318e25f19bSMatthew Dillon 		}
4328e25f19bSMatthew Dillon 	}
4338e25f19bSMatthew Dillon 	free(buf);
4348e25f19bSMatthew Dillon }
4351d6e00cdSMatthew Dillon 
4361d6e00cdSMatthew Dillon static
4371d6e00cdSMatthew Dillon void
makeDiscreteCopies(const char * spath,const char * discretefmt)4381d6e00cdSMatthew Dillon makeDiscreteCopies(const char *spath, const char *discretefmt)
4391d6e00cdSMatthew Dillon {
4401d6e00cdSMatthew Dillon 	char *src;
4411d6e00cdSMatthew Dillon 	char *dst;
4421d6e00cdSMatthew Dillon 	char *buf;
4431d6e00cdSMatthew Dillon 	struct stat st;
4441d6e00cdSMatthew Dillon 	int i;
4451d6e00cdSMatthew Dillon 	int rc;
4461d6e00cdSMatthew Dillon 
4471d6e00cdSMatthew Dillon 	for (i = 0; i < MaxWorkers; ++i) {
4483bd7e0a7SMatthew Dillon 		setNumaDomain(i);
4491d6e00cdSMatthew Dillon 		if (spath[0] == '$') {
4501d6e00cdSMatthew Dillon 			if (strcmp(SystemPath, "/") == 0)
4511d6e00cdSMatthew Dillon 				asprintf(&src, "%s%s",
4521d6e00cdSMatthew Dillon 					 SystemPath + 1, spath + 1);
4531d6e00cdSMatthew Dillon 			else
4541d6e00cdSMatthew Dillon 				asprintf(&src, "%s%s",
4551d6e00cdSMatthew Dillon 					 SystemPath, spath + 1);
4561d6e00cdSMatthew Dillon 		} else {
4571d6e00cdSMatthew Dillon 			src = strdup(spath);
4581d6e00cdSMatthew Dillon 		}
4591d6e00cdSMatthew Dillon 		asprintf(&buf, discretefmt, i);
4601d6e00cdSMatthew Dillon 		asprintf(&dst, "%s%s", BuildBase, buf);
4611d6e00cdSMatthew Dillon 		free(buf);
4628d9409b8SMatthew Dillon 
4631d6e00cdSMatthew Dillon 		if (stat(dst, &st) < 0) {
4646fd67931SMatthew Dillon 			if (mkdir(dst, 0555) < 0) {
4656fd67931SMatthew Dillon 				dlog(DLOG_ALL, "Template - mkdir %s failed\n",
4666fd67931SMatthew Dillon 				     dst);
4678d9409b8SMatthew Dillon 				dfatal_errno("Cannot mkdir %s:", dst);
4686fd67931SMatthew Dillon 			}
4696fd67931SMatthew Dillon 		}
4708ec23ca1SMatthew Dillon 		asprintf(&buf, "chflags -R noschg %s; "
4718ec23ca1SMatthew Dillon 			       "rm -rf %s; "
4728ec23ca1SMatthew Dillon 			       "cp -Rp %s/. %s",
4738ec23ca1SMatthew Dillon 			       dst, dst, src, dst);
4741d6e00cdSMatthew Dillon 		rc = system(buf);
475a574cbf0SMatthew Dillon 		dlog(DLOG_ALL | DLOG_FILTER,
476a574cbf0SMatthew Dillon 		     "Template - rc=%d running %s\n", rc, buf);
4771d6e00cdSMatthew Dillon 		if (rc)
4781d6e00cdSMatthew Dillon 			dfatal("Command failed: %s", buf);
4791d6e00cdSMatthew Dillon 		free(buf);
4801d6e00cdSMatthew Dillon 		free(src);
4811d6e00cdSMatthew Dillon 		free(dst);
4823bd7e0a7SMatthew Dillon 		setNumaDomain(-1);
4831d6e00cdSMatthew Dillon 	}
4841d6e00cdSMatthew Dillon }
485