Home | History | Annotate | Download | only in ltp-aiodio
      1 /*
      2  *   Copyright (c) 2004 Daniel McNeil <daniel (at) osdl.org>
      3  *                 2004 Open Source Development Lab
      4  *
      5  *   Copyright (c) 2004 Marty Ridgeway <mridge (at) us.ibm.com>
      6  *
      7  *   Copyright (c) 2011 Cyril Hrubis <chrubis (at) suse.cz>
      8  *
      9  *   This program is free software;  you can redistribute it and/or modify
     10  *   it under the terms of the GNU General Public License as published by
     11  *   the Free Software Foundation; either version 2 of the License, or
     12  *   (at your option) any later version.
     13  *
     14  *   This program is distributed in the hope that it will be useful,
     15  *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
     16  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
     17  *   the GNU General Public License for more details.
     18  *
     19  *   You should have received a copy of the GNU General Public License
     20  *   along with this program;  if not, write to the Free Software
     21  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     22  */
     23 
     24 #define _GNU_SOURCE
     25 
     26 #include <stdlib.h>
     27 #include <sys/types.h>
     28 #include <signal.h>
     29 #include <fcntl.h>
     30 #include <stdio.h>
     31 #include <unistd.h>
     32 #include <memory.h>
     33 #include <sys/mman.h>
     34 #include <sys/wait.h>
     35 #include <limits.h>
     36 #include <getopt.h>
     37 
     38 #include "test.h"
     39 #include "safe_macros.h"
     40 
     41 #define NUM_CHILDREN 1000
     42 
     43 static void setup(void);
     44 static void cleanup(void);
     45 static void usage(void);
     46 static int debug = 0;
     47 
     48 char *TCID = "dio_sparse";
     49 int TST_TOTAL = 1;
     50 
     51 #include "common_sparse.h"
     52 
     53 /*
     54  * Write zeroes using O_DIRECT into sparse file.
     55  */
     56 int dio_sparse(char *filename, int align, int writesize, int filesize)
     57 {
     58 	int fd;
     59 	void *bufptr;
     60 	int i, w;
     61 
     62 	fd = open(filename, O_DIRECT | O_WRONLY | O_CREAT | O_EXCL, 0600);
     63 
     64 	if (fd < 0) {
     65 		tst_resm(TBROK | TERRNO, "open()");
     66 		return 1;
     67 	}
     68 
     69 	SAFE_FTRUNCATE(cleanup, fd, filesize);
     70 
     71 	if (posix_memalign(&bufptr, align, writesize)) {
     72 		close(fd);
     73 		tst_resm(TBROK | TERRNO, "posix_memalign()");
     74 		return 1;
     75 	}
     76 
     77 	memset(bufptr, 0, writesize);
     78 	for (i = 0; i < filesize;) {
     79 		if ((w = write(fd, bufptr, writesize)) != writesize) {
     80 			tst_resm(TBROK | TERRNO, "write() returned %d", w);
     81 			close(fd);
     82 			return 1;
     83 		}
     84 
     85 		i += w;
     86 	}
     87 
     88 	close(fd);
     89 	unlink(filename);
     90 
     91 	return 0;
     92 }
     93 
     94 void usage(void)
     95 {
     96 	fprintf(stderr, "usage: dio_sparse [-d] [-n children] [-s filesize]"
     97 		" [-w writesize]\n");
     98 	exit(1);
     99 }
    100 
    101 int main(int argc, char **argv)
    102 {
    103 	char *filename = "dio_sparse";
    104 	int pid[NUM_CHILDREN];
    105 	int num_children = 1;
    106 	int i;
    107 	long alignment = 512;
    108 	int writesize = 65536;
    109 	int filesize = 100 * 1024 * 1024;
    110 	int c;
    111 	int children_errors = 0;
    112 	int ret;
    113 
    114 	while ((c = getopt(argc, argv, "dw:n:a:s:")) != -1) {
    115 		char *endp;
    116 		switch (c) {
    117 		case 'd':
    118 			debug++;
    119 			break;
    120 		case 'a':
    121 			alignment = strtol(optarg, &endp, 0);
    122 			alignment = scale_by_kmg(alignment, *endp);
    123 			break;
    124 		case 'w':
    125 			writesize = strtol(optarg, &endp, 0);
    126 			writesize = scale_by_kmg(writesize, *endp);
    127 			break;
    128 		case 's':
    129 			filesize = strtol(optarg, &endp, 0);
    130 			filesize = scale_by_kmg(filesize, *endp);
    131 			break;
    132 		case 'n':
    133 			num_children = atoi(optarg);
    134 			if (num_children > NUM_CHILDREN) {
    135 				fprintf(stderr,
    136 					"number of children limited to %d\n",
    137 					NUM_CHILDREN);
    138 				num_children = NUM_CHILDREN;
    139 			}
    140 			break;
    141 		case '?':
    142 			usage();
    143 			break;
    144 		}
    145 	}
    146 
    147 	setup();
    148 	tst_resm(TINFO, "Dirtying free blocks");
    149 	dirty_freeblocks(filesize);
    150 
    151 	tst_resm(TINFO, "Starting I/O tests");
    152 	signal(SIGTERM, SIG_DFL);
    153 	for (i = 0; i < num_children; i++) {
    154 		switch (pid[i] = fork()) {
    155 		case 0:
    156 			read_sparse(filename, filesize);
    157 			break;
    158 		case -1:
    159 			while (i-- > 0)
    160 				kill(pid[i], SIGTERM);
    161 
    162 			tst_brkm(TBROK | TERRNO, cleanup, "fork()");
    163 		default:
    164 			continue;
    165 		}
    166 	}
    167 	tst_sig(FORK, DEF_HANDLER, cleanup);
    168 
    169 	ret = dio_sparse(filename, alignment, writesize, filesize);
    170 
    171 	tst_resm(TINFO, "Killing childrens(s)");
    172 
    173 	for (i = 0; i < num_children; i++)
    174 		kill(pid[i], SIGTERM);
    175 
    176 	for (i = 0; i < num_children; i++) {
    177 		int status;
    178 		pid_t p;
    179 
    180 		p = waitpid(pid[i], &status, 0);
    181 		if (p < 0) {
    182 			tst_resm(TBROK | TERRNO, "waitpid()");
    183 		} else {
    184 			if (WIFEXITED(status) && WEXITSTATUS(status) == 10)
    185 				children_errors++;
    186 		}
    187 	}
    188 
    189 	if (children_errors)
    190 		tst_resm(TFAIL, "%i children(s) exited abnormally",
    191 			 children_errors);
    192 
    193 	if (!children_errors && !ret)
    194 		tst_resm(TPASS, "Test passed");
    195 
    196 	cleanup();
    197 	tst_exit();
    198 }
    199 
    200 static void setup(void)
    201 {
    202 	tst_sig(FORK, DEF_HANDLER, cleanup);
    203 	tst_tmpdir();
    204 }
    205 
    206 static void cleanup(void)
    207 {
    208 	tst_rmdir();
    209 }
    210