3 * Copyright (c) 2004 Daniel McNeil <daniel@osdl.org>
4 * 2004 Open Source Development Lab
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * 2/2004 Marty Ridgeway (mridge@us.ibm.com) Changes to adapt to LTP
31 #include <sys/types.h>
42 #define NUM_CHILDREN 1000
46 const char* filename1
=NULL
;
47 const char* filename2
=NULL
;
49 static void setup(void);
50 static void cleanup(void);
52 #define barrier() __asm__ __volatile__("": : :"memory")
53 #define WITH_SIGNALS_BLOCKED(code) { \
54 sigset_t held_sigs_; \
55 sigfillset(&held_sigs_); \
56 sigprocmask(SIG_SETMASK, &held_sigs_, &held_sigs_); \
60 sigprocmask(SIG_SETMASK, &held_sigs_, NULL); \
63 char *TCID
="dio_sparse"; /* Test program identifier. */
64 int TST_TOTAL
=1; /* Total number of test cases. */
66 * dio_sparse - issue O_DIRECT writes to holes is a file while concurrently
67 * reading the file and checking that the read never reads uninitailized
71 char *check_zero(unsigned char *buf
, int size
)
79 fprintf(stderr
, "non zero buffer at buf[%d] => 0x%02x,%02x,%02x,%02x\n",
80 buf
- p
, (unsigned int)buf
[0],
81 size
> 1 ? (unsigned int)buf
[1] : 0,
82 size
> 2 ? (unsigned int)buf
[2] : 0,
83 size
> 3 ? (unsigned int)buf
[3] : 0);
89 return 0; /* all zeros */
92 int read_sparse(char *filename
, int filesize
)
100 while ((fd
= open(filename
, O_RDONLY
)) < 0) {
101 sleep(1); /* wait for file to be created */
104 for (i
= 0 ; i
< 100000000; i
++) {
108 if (debug
> 1 && (i
% 10) == 0) {
109 fprintf(stderr
, "child %d, read loop count %d\n",
112 lseek(fd
, SEEK_SET
, 0);
113 for (j
= 0; j
< filesize
+1; j
+= sizeof(buf
)) {
114 r
= read(fd
, buf
, sizeof(buf
));
116 if ((badbuf
= check_zero(buf
, r
))) {
117 fprintf(stderr
, "non-zero read at offset %d\n",
118 offset
+ badbuf
- buf
);
119 kill(getppid(), SIGTERM
);
129 volatile int got_signal
;
132 sig_term_func(int i
, siginfo_t
*si
, void *p
)
135 fprintf(stderr
, "sig(%d, %p, %p)\n", i
, si
, p
);
140 * do DIO writes to a sparse file
142 void dio_sparse(char *filename
, int align
, int writesize
, int filesize
)
148 static struct sigaction s
;
150 s
.sa_sigaction
= sig_term_func
;
151 s
.sa_flags
= SA_SIGINFO
;
152 sigaction(SIGTERM
, &s
, 0);
154 WITH_SIGNALS_BLOCKED(
155 fd
= open(filename
, O_DIRECT
|O_WRONLY
|O_CREAT
|O_EXCL
, 0600);
157 filename1
= filename
;
161 perror("cannot create file");
165 ftruncate(fd
, filesize
);
167 if (posix_memalign(&bufptr
, align
, writesize
)) {
168 perror("cannot malloc aligned memory");
170 WITH_SIGNALS_BLOCKED(
177 memset(bufptr
, 0, writesize
);
178 for (i
= 0; i
< filesize
; ) {
179 if (debug
> 1 && ((i
% writesize
) % 100)) {
180 fprintf(stderr
, "DIO write # %d\n", i
);
182 if ((w
= write(fd
, bufptr
, writesize
)) != writesize
) {
183 fprintf(stderr
, "write %d returned %d\n", i
, w
);
189 fprintf(stderr
, "signal -- stop at %d\n", i
);
194 fprintf(stderr
, "DIO write done unlinking file\n");
196 WITH_SIGNALS_BLOCKED(
203 void dirty_freeblocks(int size
)
211 size
= ((size
+ pg
- 1) / pg
) * pg
;
212 sprintf(filename
, "file.xx.%d", getpid());
214 WITH_SIGNALS_BLOCKED(
215 fd
= open(filename
, O_CREAT
|O_RDWR
|O_EXCL
, 0600);
220 perror("cannot open file");
224 p
= mmap(0, size
, PROT_WRITE
|PROT_READ
, MAP_SHARED
|MAP_FILE
, fd
, 0);
225 if (p
== MAP_FAILED
) {
226 perror("cannot mmap");
228 WITH_SIGNALS_BLOCKED(
234 memset(p
, 0xaa, size
);
235 msync(p
, size
, MS_SYNC
);
238 WITH_SIGNALS_BLOCKED(
246 fprintf(stderr
, "usage: dio_sparse [-n children] [-s filesize]"
247 " [-w writesize] [-r readsize] \n");
252 * Scale value by kilo, mega, or giga.
254 long long scale_by_kmg(long long value
, char scale
)
277 * usage: dio_sparse [-r readsize] [-w writesize] [-n chilren] [-a align]
280 int main(int argc
, char **argv
)
282 int pid
[NUM_CHILDREN
];
283 int num_children
= 1;
285 char *filename
= "/test/aiodio/file";
286 long alignment
= 512;
287 int readsize
= 65536;
288 int writesize
= 65536;
289 int filesize
= 100*1024*1024;
291 int children_errors
= 0;
293 extern int optind
, optopt
, opterr
;
295 while ((c
= getopt(argc
, argv
, "dr:w:n:a:s:")) != -1) {
302 alignment
= strtol(optarg
, &endp
, 0);
303 alignment
= (int)scale_by_kmg((long long)alignment
,
307 readsize
= strtol(optarg
, &endp
, 0);
308 readsize
= (int)scale_by_kmg((long long)readsize
, *endp
);
311 writesize
= strtol(optarg
, &endp
, 0);
312 writesize
= (int)scale_by_kmg((long long)writesize
, *endp
);
315 filesize
= strtol(optarg
, &endp
, 0);
316 filesize
= (int)scale_by_kmg((long long)filesize
, *endp
);
319 num_children
= atoi(optarg
);
320 if (num_children
> NUM_CHILDREN
) {
322 "number of children limited to %d\n",
324 num_children
= NUM_CHILDREN
;
335 * Create some dirty free blocks by allocating, writing, syncing,
336 * and then unlinking and freeing.
338 dirty_freeblocks(filesize
);
340 for (i
= 0; i
< num_children
; i
++) {
341 if ((pid
[i
] = fork()) == 0) {
343 return read_sparse(filename
, filesize
);
344 } else if (pid
[i
] < 0) {
346 perror("fork error");
355 * Parent write to a hole in a file using direct i/o
358 dio_sparse(filename
, alignment
, writesize
, filesize
);
361 fprintf(stderr
, "dio_sparse done writing, kill children\n");
362 for (i
= 0; i
< num_children
; i
++) {
363 kill(pid
[i
], SIGTERM
);
366 for (i
= 0; i
< num_children
; i
++) {
370 p
= waitpid(pid
[i
], &status
, 0);
374 if (WIFEXITED(status
) && WEXITSTATUS(status
) == 10) {
377 fprintf(stderr
, "child %d bad exit\n", p
);
383 fprintf(stderr
, "dio_sparse %d children had errors\n",
390 static void setup(void)
392 tst_sig(FORK
, DEF_HANDLER
, cleanup
);
393 signal(SIGTERM
, SIG_DFL
);
396 static void cleanup(void)