Test for detecting unwritten extent related corruption reading+writing under swap.
[xfstests-dev.git] / src / resvtest.c
1 /*
2  * Copyright (c) 2004 Silicon Graphics, Inc.  All Rights Reserved.
3  * 
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  * 
8  * This program is distributed in the hope that it would be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11  * 
12  * Further, this software is distributed without any warranty that it is
13  * free of the rightful claim of any third person regarding infringement
14  * or the like.  Any license provided herein, whether implied or
15  * otherwise, applies only to this software file.  Patent licenses, if
16  * any, provided herein do not apply to combinations of this program with
17  * other software, or any other product whatsoever.
18  * 
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write the Free Software Foundation, Inc., 59
21  * Temple Place - Suite 330, Boston MA 02111-1307, USA.
22  * 
23  * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24  * Mountain View, CA  94043, or:
25  * 
26  * http://www.sgi.com 
27  * 
28  * For further information regarding this notice, see: 
29  * 
30  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31  */
32  
33 #include "global.h"
34
35 int
36 main(int argc, char **argv)
37 {
38         int             c, i, j, n, err = 0;
39         int             writefd, readfd;
40         long            iterations = 100;
41         long            psize, bsize, leaksize = 32 * 1024 * 1024;
42         char            *filename;
43         char            *readbuffer, *writebuffer;
44         off64_t         resvsize;
45         xfs_flock64_t   resvsp;
46
47         psize = bsize = getpagesize();
48         resvsize = bsize * (off64_t) 10000;
49
50         while ((c = getopt(argc, argv, "b:i:l:s:")) != EOF) {
51                 switch(c) {
52                 case 'b':
53                         bsize = atol(optarg);
54                         break;
55                 case 'i':
56                         iterations = atol(optarg);
57                         break;
58                 case 'l':
59                         leaksize = atol(optarg);
60                         break;
61                 case 's':
62                         resvsize = (off64_t) atoll(optarg);
63                         break;
64                 default:
65                         err++;
66                         break;
67                 }
68         }
69
70         if (optind > argc + 1)
71                 err++;
72
73         if (err) {
74                 printf("Usage: %s [-b blksize] [-l leaksize] [-r resvsize]\n",
75                         argv[0]);
76                 exit(0);
77         }
78
79         filename = argv[optind];
80
81         readbuffer = memalign(psize, bsize);
82         writebuffer = memalign(psize, bsize);
83         if (!readbuffer || !writebuffer) {
84                 perror("open");
85                 exit(1);
86         }
87         memset(writebuffer, 'A', sizeof(writebuffer));
88
89         unlink(filename);
90         writefd = open(filename, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
91         if (writefd < 0) {
92                 perror("open");
93                 exit(1);
94         }
95         readfd = open(filename, O_RDONLY);
96         if (readfd < 0) {
97                 perror("open");
98                 exit(1);
99         }
100
101         /* preallocate file space */
102         resvsp.l_whence = 0;
103         resvsp.l_start = 0;
104         resvsp.l_len = resvsize;
105         if (ioctl(writefd, XFS_IOC_RESVSP64, &resvsp) < 0) {
106                 fprintf(stdout, "attempt to reserve %lld bytes for %s "
107                                 "using %s failed: %s (%d)\n", 
108                                 resvsize, filename, "XFS_IOC_RESVSP64",
109                                 strerror(errno), errno);
110         } else {
111                 fprintf(stdout, "reserved %lld bytes for %s using %s\n",
112                                 resvsize, filename, "XFS_IOC_RESVSP64");
113         }
114
115         /* Space is now preallocated, start IO --
116          * write at current offset, pressurize, seek to zero on reader
117          * and read up to current write offset.
118          */
119
120         n = 0;
121         while (++n < iterations) {
122                 char *p;
123                 int numerrors;
124
125                 if (write(writefd, writebuffer, sizeof(writebuffer)) < 0) {
126                         perror("write");
127                         exit(1);
128                 }
129
130                 /* Apply some memory pressure 
131                  * (allocate another chunk and touch all pages)
132                  */
133                 for (i = 0; i < (leaksize / psize); i++) {
134                         p = malloc(psize);
135                         if (p)
136                                 p[7] = '7';
137                 }
138                 sleep(1);
139                 lseek(readfd, SEEK_SET, 0);
140                 numerrors = 0;
141                 for (j = 0; j < n; j++) {
142                         if (read(readfd, readbuffer, sizeof(readbuffer)) < 0) {
143                                 perror("read");
144                                 exit(1);
145                         }
146                         for (i = 0; i < sizeof(readbuffer); i++) {
147                                 if (readbuffer[i] != 'A') {
148                                         fprintf(stderr,
149 "errors detected in file, pos: %d (%lld+%d), nwrites: %d [val=0x%x].\n",
150                                                 j, (long long)j * 4096,
151                                                 i, n, readbuffer[i]);
152                                         numerrors++;
153                                         break;
154                                 }
155                         }
156                 }
157                 if (numerrors > 10) {
158                         exit(1);
159                 } else if (numerrors) {
160                         fprintf(stdout, "\n");
161                 }
162         }
163
164         return(0);
165 }