Whamcloud - gitweb
LU-11997 ptlrpc: Properly swab ll_fiemap_info_key
[fs/lustre-release.git] / lustre / tests / directio.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  */
26 /*
27  * This file is part of Lustre, http://www.lustre.org/
28  * Lustre is a trademark of Sun Microsystems, Inc.
29  */
30
31 #ifndef _GNU_SOURCE
32 #define  _GNU_SOURCE
33 #endif
34 #include <stdio.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38 #include <stdlib.h>
39 #include <errno.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <sys/mman.h>
43
44 /*
45  * return index of the first byte not matching given byte
46  * or buffer size if all bytes are matching
47  */
48 static size_t check_bytes(const char *buf, int byte, size_t len)
49 {
50         const char *p;
51
52         for (p = buf; p < buf + len; p++)
53                 if (*p != byte)
54                         break;
55         return p - buf;
56 }
57
58 int main(int argc, char **argv)
59 {
60 #ifdef O_DIRECT
61         int fd;
62         char *buf, *fname;
63         int blocks, seek_blocks;
64         long len;
65         off64_t seek;
66         struct stat64 st;
67         char pad = 0xba;
68         int action;
69         int rc;
70
71         if (argc < 5 || argc > 6) {
72                 printf("Usage: %s <read/write/rdwr/readhole> file seek nr_blocks [blocksize]\n",
73                        argv[0]);
74                 return 1;
75         }
76
77         if (!strcmp(argv[1], "read")) {
78                 action = O_RDONLY;
79         } else if (!strcmp(argv[1], "write")) {
80                 action = O_WRONLY;
81         } else if (!strcmp(argv[1], "rdwr")) {
82                 action = O_RDWR;
83         } else if (!strcmp(argv[1], "readhole")) {
84                 action = O_RDONLY;
85                 pad = 0;
86         } else {
87                 printf("Usage: %s <read/write/rdwr> file seek nr_blocks [blocksize]\n",
88                        argv[0]);
89                 return 1;
90         }
91
92         fname = argv[2];
93         seek_blocks = strtoul(argv[3], 0, 0);
94         blocks = strtoul(argv[4], 0, 0);
95         if (!blocks) {
96                 printf("Usage: %s <read/write/rdwr> file seek nr_blocks [blocksize]\n",
97                        argv[0]);
98                 return 1;
99         }
100
101         fd = open(fname, O_LARGEFILE | O_DIRECT | O_RDWR | O_CREAT, 0644);
102         if (fd == -1) {
103                 printf("Cannot open %s:  %s\n", fname, strerror(errno));
104                 return 1;
105         }
106
107         if (argc >= 6) {
108                 st.st_blksize = strtoul(argv[5], 0, 0);
109         } else if (fstat64(fd, &st) < 0) {
110                 printf("Cannot stat %s:  %s\n", fname, strerror(errno));
111                 return 1;
112         }
113
114         printf("directio on %s for %dx%lu bytes\n", fname, blocks,
115                (unsigned long)st.st_blksize);
116
117         seek = (off64_t)seek_blocks * (off64_t)st.st_blksize;
118         len = blocks * st.st_blksize;
119
120         buf = mmap(0, len,
121                    PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, 0, 0);
122         if (buf == MAP_FAILED) {
123                 printf("No memory %s\n", strerror(errno));
124                 return 1;
125         }
126         memset(buf, pad, len);
127
128         if (action == O_WRONLY || action == O_RDWR) {
129                 if (lseek64(fd, seek, SEEK_SET) < 0) {
130                         printf("lseek64 failed: %s\n", strerror(errno));
131                         return 1;
132                 }
133
134                 rc = write(fd, buf, len);
135                 if (rc != len) {
136                         printf("Write error %s (rc = %d, len = %ld)\n",
137                                strerror(errno), rc, len);
138                         return 1;
139                 }
140         }
141
142         if (action == O_RDONLY || action == O_RDWR) {
143                 if (lseek64(fd, seek, SEEK_SET) < 0) {
144                         printf("Cannot seek %s\n", strerror(errno));
145                         return 1;
146                 }
147                 /* reset all bytes to something nor 0x0 neither 0xab */
148                 memset(buf, 0x5e, len);
149                 rc = read(fd, buf, len);
150                 if (rc != len) {
151                         printf("Read error: %s rc = %d\n", strerror(errno), rc);
152                         return 1;
153                 }
154
155                 if (check_bytes(buf, pad, len) != len) {
156                         printf("Data mismatch\n");
157                         return 1;
158                 }
159         }
160
161         printf("PASS\n");
162         return 0;
163 #else /* !O_DIRECT */
164 #warning O_DIRECT not defined, directio test will fail
165         printf("O_DIRECT not defined\n");
166         return 1;
167 #endif /* !O_DIRECT */
168 }