196c8483aSYuri Pankov /*
296c8483aSYuri Pankov  * This file and its contents are supplied under the terms of the
396c8483aSYuri Pankov  * Common Development and Distribution License ("CDDL"), version 1.0.
496c8483aSYuri Pankov  * You may only use this file in accordance with the terms of version
596c8483aSYuri Pankov  * 1.0 of the CDDL.
696c8483aSYuri Pankov  *
796c8483aSYuri Pankov  * A full copy of the text of the CDDL should have accompanied this
896c8483aSYuri Pankov  * source.  A copy of the CDDL is also available via the Internet at
996c8483aSYuri Pankov  * http://www.illumos.org/license/CDDL.
1096c8483aSYuri Pankov  */
1196c8483aSYuri Pankov 
1296c8483aSYuri Pankov /*
1396c8483aSYuri Pankov  * Copyright 2012 Jilin Xpd <jilinxpd@gmail.com>
1496c8483aSYuri Pankov  * Copyright 2018 Nexenta Systems, Inc.
15*dc5e7685SJohn Levon  * Copyright (c) 2018, Joyent, Inc.
1696c8483aSYuri Pankov  */
1796c8483aSYuri Pankov 
1896c8483aSYuri Pankov /*
1996c8483aSYuri Pankov  * Using mmap, make a file and padding it with random chars.
2096c8483aSYuri Pankov  */
2196c8483aSYuri Pankov 
2296c8483aSYuri Pankov #include <sys/mman.h>
2396c8483aSYuri Pankov #include <sys/types.h>
2496c8483aSYuri Pankov #include <sys/stat.h>
2596c8483aSYuri Pankov #include <fcntl.h>
2696c8483aSYuri Pankov #include <stdio.h>
2796c8483aSYuri Pankov #include <stdlib.h>
2896c8483aSYuri Pankov #include <unistd.h>
2996c8483aSYuri Pankov #include <string.h>
3096c8483aSYuri Pankov #include <errno.h>
3196c8483aSYuri Pankov #include <time.h>
3296c8483aSYuri Pankov 
3396c8483aSYuri Pankov void
usage(void)3496c8483aSYuri Pankov usage(void)
3596c8483aSYuri Pankov {
3696c8483aSYuri Pankov 	fprintf(stderr,
3796c8483aSYuri Pankov 	    "usage: mkfile_mmap -n <size>[b|k|m|g] -f <filename>\n");
3896c8483aSYuri Pankov 	exit(1);
3996c8483aSYuri Pankov }
4096c8483aSYuri Pankov 
4196c8483aSYuri Pankov int
main(int argc,char ** argv)4296c8483aSYuri Pankov main(int argc, char **argv)
4396c8483aSYuri Pankov {
4496c8483aSYuri Pankov 	char *suffix;
4596c8483aSYuri Pankov 	char *filename = NULL;
4696c8483aSYuri Pankov 	char *file_addr;
4796c8483aSYuri Pankov 	char *p, *q;
4896c8483aSYuri Pankov 	off_t offset;
4996c8483aSYuri Pankov 	size_t filesize;
5096c8483aSYuri Pankov 	size_t blksize;
5196c8483aSYuri Pankov 	size_t numblks;
5296c8483aSYuri Pankov 	size_t cnt = 1;
5396c8483aSYuri Pankov 	size_t mul = 1;
5496c8483aSYuri Pankov 	size_t i;
5596c8483aSYuri Pankov 	int mret = 0;
5696c8483aSYuri Pankov 	int c, fid;
5796c8483aSYuri Pankov 
5896c8483aSYuri Pankov 	/*
5996c8483aSYuri Pankov 	 * parse arguments
6096c8483aSYuri Pankov 	 */
6196c8483aSYuri Pankov 	while ((c = getopt(argc, argv, "n:f:")) != -1) {
6296c8483aSYuri Pankov 		switch (c) {
6396c8483aSYuri Pankov 		case 'n':
6496c8483aSYuri Pankov 			cnt = (size_t)strtoul(optarg, &suffix, 0);
6596c8483aSYuri Pankov 			if (cnt == 0)
6696c8483aSYuri Pankov 				goto bad_n_arg;
6796c8483aSYuri Pankov 			switch (*suffix) {
6896c8483aSYuri Pankov 			case '\0':
6996c8483aSYuri Pankov 			case 'b':
7096c8483aSYuri Pankov 				mul = 1;
7196c8483aSYuri Pankov 				break;
7296c8483aSYuri Pankov 			case 'k':
7396c8483aSYuri Pankov 				mul = 1024;
7496c8483aSYuri Pankov 				break;
7596c8483aSYuri Pankov 			case 'm':
7696c8483aSYuri Pankov 				mul = (1024 * 1024);
7796c8483aSYuri Pankov 				break;
7896c8483aSYuri Pankov 			case 'g':
7996c8483aSYuri Pankov 				mul = (1024 * 1024 * 1024);
8096c8483aSYuri Pankov 				break;
8196c8483aSYuri Pankov 			default:
8296c8483aSYuri Pankov 			bad_n_arg:
8396c8483aSYuri Pankov 				fprintf(stderr, "-n %s: invalid size\n",
8496c8483aSYuri Pankov 				    optarg);
8596c8483aSYuri Pankov 				return (1);
8696c8483aSYuri Pankov 			}
8796c8483aSYuri Pankov 			cnt = cnt * mul;
8896c8483aSYuri Pankov 			break;
8996c8483aSYuri Pankov 
9096c8483aSYuri Pankov 		case 'f': /* target file */
9196c8483aSYuri Pankov 			filename = optarg;
9296c8483aSYuri Pankov 			break;
9396c8483aSYuri Pankov 
9496c8483aSYuri Pankov 		case ':':   /* missing optarg */
9596c8483aSYuri Pankov 			fprintf(stderr,
9696c8483aSYuri Pankov 			    "Option -%c requires an arg\n", optopt);
9796c8483aSYuri Pankov 			usage();
9896c8483aSYuri Pankov 			break;
9996c8483aSYuri Pankov 		case '?':
10096c8483aSYuri Pankov 			fprintf(stderr,
10196c8483aSYuri Pankov 			    "Unrecognized option: -%c\n", optopt);
10296c8483aSYuri Pankov 			usage();
10396c8483aSYuri Pankov 			break;
10496c8483aSYuri Pankov 		}
10596c8483aSYuri Pankov 	}
10696c8483aSYuri Pankov 
10796c8483aSYuri Pankov 	/* open test file */
10896c8483aSYuri Pankov 	fid = open(filename, O_RDWR | O_CREAT | O_TRUNC,
10996c8483aSYuri Pankov 	    S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH);
11096c8483aSYuri Pankov 	if (fid == -1) {
11196c8483aSYuri Pankov 		fprintf(stderr, "open %s error=%d\n", filename, errno);
11296c8483aSYuri Pankov 		mret = 1;
11396c8483aSYuri Pankov 		goto exit3;
11496c8483aSYuri Pankov 	}
11596c8483aSYuri Pankov 
11696c8483aSYuri Pankov 	/* extend file */
11796c8483aSYuri Pankov 	filesize = cnt;
11896c8483aSYuri Pankov 	if (ftruncate(fid, filesize) == -1) {
11996c8483aSYuri Pankov 		fprintf(stderr, "ftrunc %s error=%d\n", filename, errno);
12096c8483aSYuri Pankov 		mret = 1;
12196c8483aSYuri Pankov 		goto exit2;
12296c8483aSYuri Pankov 	}
12396c8483aSYuri Pankov 
12496c8483aSYuri Pankov #define	K 1024
12596c8483aSYuri Pankov 
12696c8483aSYuri Pankov 	blksize = 64 * K * K;
12796c8483aSYuri Pankov 	numblks = (filesize + blksize - 1) / blksize;
12896c8483aSYuri Pankov 	for (i = 0; i < numblks && mret == 0; i++) {
12996c8483aSYuri Pankov 
13096c8483aSYuri Pankov 		offset = i*blksize;
13196c8483aSYuri Pankov 		if (offset + blksize > filesize)
13296c8483aSYuri Pankov 			blksize = filesize - offset;
13396c8483aSYuri Pankov 
13496c8483aSYuri Pankov 		/* map file */
13596c8483aSYuri Pankov 		file_addr = mmap(NULL, blksize,
13696c8483aSYuri Pankov 		    PROT_READ | PROT_WRITE, MAP_SHARED, fid, offset);
13796c8483aSYuri Pankov 		if (file_addr == MAP_FAILED) {
13896c8483aSYuri Pankov 			fprintf(stderr, "mmap %s error=%d\n", filename, errno);
13996c8483aSYuri Pankov 			mret = 1;
14096c8483aSYuri Pankov 			break;
14196c8483aSYuri Pankov 		}
14296c8483aSYuri Pankov 
143*dc5e7685SJohn Levon 		/* tag each block (to aid debug) */
144*dc5e7685SJohn Levon 		p = file_addr;
145*dc5e7685SJohn Levon 		q = file_addr + blksize - K;
14696c8483aSYuri Pankov 		memset(p, ' ', K);
147*dc5e7685SJohn Levon 		snprintf(p, K, "\nblk=%d\n\n", i);
14896c8483aSYuri Pankov 		p += K;
149*dc5e7685SJohn Levon 
150*dc5e7685SJohn Levon 		/* fill something into mapped addr */
151*dc5e7685SJohn Levon 		while (p < q) {
152*dc5e7685SJohn Levon 			memset(p, ' ', K);
153*dc5e7685SJohn Levon 			snprintf(p, K, "\noff=0x%x\n\n",
154*dc5e7685SJohn Levon 			    (i * blksize) + (p - file_addr));
155*dc5e7685SJohn Levon 			p += K;
156*dc5e7685SJohn Levon 		}
15796c8483aSYuri Pankov 
15896c8483aSYuri Pankov 		/* sync mapped pages to file */
15996c8483aSYuri Pankov 		if (msync(file_addr, blksize, MS_SYNC) == -1) {
16096c8483aSYuri Pankov 			fprintf(stderr, "msync %s error=%d\n", filename, errno);
16196c8483aSYuri Pankov 			mret = 1;
16296c8483aSYuri Pankov 		}
16396c8483aSYuri Pankov 
16496c8483aSYuri Pankov 		/* unmap file */
16596c8483aSYuri Pankov 		if (munmap(file_addr, blksize) == -1) {
16696c8483aSYuri Pankov 			fprintf(stderr, "unmap %s error=%d\n", filename, errno);
16796c8483aSYuri Pankov 			mret = 1;
16896c8483aSYuri Pankov 		}
16996c8483aSYuri Pankov 	}
17096c8483aSYuri Pankov 
17196c8483aSYuri Pankov 	/* close file */
17296c8483aSYuri Pankov exit2:
17396c8483aSYuri Pankov 	close(fid);
17496c8483aSYuri Pankov exit3:
17596c8483aSYuri Pankov 	return (mret);
17696c8483aSYuri Pankov }
177