Home | History | Annotate | Download | only in direct_io
      1 /*
      2  * Copyright (c) 2016 Oracle and/or its affiliates. All Rights Reserved.
      3  * Copyright (c) International Business Machines  Corp., 2002
      4  *
      5  * This program is free software; you can redistribute it and/or
      6  * modify it under the terms of the GNU General Public License as
      7  * published by the Free Software Foundation; either version 2 of
      8  * the License, or (at your option) any later version.
      9  *
     10  * This program is distributed in the hope that it would be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  * GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
     17  *
     18  * DESCRIPTION
     19  *	Copy the contents of the input file to output file using direct read
     20  *	and direct write. The input file size is numblks*bufsize.
     21  *	The read and write calls use bufsize to perform IO. Input and output
     22  *	files can be specified through commandline and is useful for running
     23  *	test with raw devices as files.
     24  *
     25  * USAGE
     26  *	diotest1 [-b bufsize] [-n numblks] [-i infile] [-o outfile]
     27  *
     28  * History
     29  *	04/22/2002	Narasimha Sharoff nsharoff (at) us.ibm.com
     30  */
     31 
     32 #include <stdio.h>
     33 #include <stdlib.h>
     34 #include <unistd.h>
     35 #include <signal.h>
     36 #include <string.h>
     37 #include <fcntl.h>
     38 #include <errno.h>
     39 
     40 #include "diotest_routines.h"
     41 
     42 #include "test.h"
     43 #include "safe_macros.h"
     44 
     45 char *TCID = "diotest01";	/* Test program identifier.    */
     46 int TST_TOTAL = 1;		/* Total number of test conditions */
     47 
     48 #ifdef O_DIRECT
     49 
     50 #define	BUFSIZE	8192
     51 #define	NBLKS	20
     52 #define	LEN	30
     53 #define	TRUE 1
     54 
     55 static char infile[LEN];	/* Input file. Default "infile" */
     56 static char outfile[LEN];	/* Output file. Default "outfile" */
     57 static int fd1, fd2;
     58 
     59 /*
     60  * prg_usage: display the program usage.
     61 */
     62 void prg_usage(void)
     63 {
     64 	fprintf(stderr,
     65 		"Usage: diotest1 [-b bufsize] [-n numblks] [-i infile] [-o outfile]\n");
     66 	tst_brkm(TBROK, NULL, "usage");
     67 }
     68 
     69 void cleanup(void)
     70 {
     71 	if (fd1 > 0)
     72 		close(fd1);
     73 	if (fd2 > 0)
     74 		close(fd2);
     75 
     76 	tst_rmdir();
     77 }
     78 
     79 int main(int argc, char *argv[])
     80 {
     81 	int bufsize = BUFSIZE;	/* Buffer size. Default 8k */
     82 	int numblks = NBLKS;	/* Number of blocks. Default 20 */
     83 	int i, n, offset;
     84 	char *buf;
     85 
     86 	/* Options */
     87 	strcpy(infile, "infile");	/* Default input file */
     88 	strcpy(outfile, "outfile");	/* Default outfile file */
     89 	while ((i = getopt(argc, argv, "b:n:i:o:")) != -1) {
     90 		switch (i) {
     91 		case 'b':
     92 			if ((bufsize = atoi(optarg)) <= 0) {
     93 				fprintf(stderr, "bufsize must be > 0\n");
     94 				prg_usage();
     95 			}
     96 			if (bufsize % 4096 != 0) {
     97 				fprintf(stderr,
     98 					"bufsize must be multiple of 4k\n");
     99 				prg_usage();
    100 			}
    101 			break;
    102 		case 'n':
    103 			if ((numblks = atoi(optarg)) <= 0) {
    104 				fprintf(stderr, "numblks must be > 0\n");
    105 				prg_usage();
    106 			}
    107 			break;
    108 		case 'i':
    109 			strcpy(infile, optarg);
    110 			break;
    111 		case 'o':
    112 			strcpy(outfile, optarg);
    113 			break;
    114 		default:
    115 			prg_usage();
    116 		}
    117 	}
    118 
    119 	tst_tmpdir();
    120 
    121 	/* Test for filesystem support of O_DIRECT */
    122 	int fd = open(infile, O_DIRECT | O_RDWR | O_CREAT, 0666);
    123 
    124 	if (fd < 0)
    125 		tst_brkm(TCONF, cleanup, "O_DIRECT not supported by FS");
    126 	SAFE_CLOSE(cleanup, fd);
    127 
    128 	/* Open files */
    129 	fd1 = SAFE_OPEN(cleanup, infile, O_DIRECT | O_RDWR | O_CREAT, 0666);
    130 	fd2 = SAFE_OPEN(cleanup, outfile, O_DIRECT | O_RDWR | O_CREAT, 0666);
    131 
    132 	/* Allocate for buf, Create input file */
    133 	buf = valloc(bufsize);
    134 
    135 	if (!buf)
    136 		tst_brkm(TFAIL | TERRNO, cleanup, "valloc() failed");
    137 
    138 	for (i = 0; i < numblks; i++) {
    139 		fillbuf(buf, bufsize, (char)(i % 256));
    140 		SAFE_WRITE(cleanup, 1, fd1, buf, bufsize);
    141 	}
    142 
    143 	/* Copy infile to outfile using direct read and direct write */
    144 	offset = 0;
    145 	SAFE_LSEEK(cleanup, fd1, offset, SEEK_SET);
    146 
    147 	while ((n = read(fd1, buf, bufsize)) > 0) {
    148 		SAFE_LSEEK(cleanup, fd2, offset, SEEK_SET);
    149 
    150 		SAFE_WRITE(cleanup, 1, fd2, buf, n);
    151 
    152 		offset += n;
    153 		SAFE_LSEEK(cleanup, fd1, offset, SEEK_SET);
    154 	}
    155 
    156 	/* Verify */
    157 	if (filecmp(infile, outfile) != 0) {
    158 		tst_brkm(TFAIL, cleanup, "file compare failed for %s and %s",
    159 			 infile, outfile);
    160 	}
    161 
    162 	tst_resm(TPASS, "Test passed");
    163 
    164 	cleanup();
    165 	tst_exit();
    166 }
    167 
    168 #else /* O_DIRECT */
    169 
    170 int main()
    171 {
    172 	tst_brkm(TCONF, NULL, "O_DIRECT is not defined.");
    173 }
    174 #endif /* O_DIRECT */
    175