Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / qa / workunits / direct_io / test_sync_io.c
1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <fcntl.h>
4 #include <unistd.h>
5 #include <stdio.h>
6 #include <inttypes.h>
7 #include <linux/types.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <sys/ioctl.h>
11 #include <errno.h>
12
13 //#include "../client/ioctl.h"
14
15 #include <linux/ioctl.h>
16 #define CEPH_IOCTL_MAGIC 0x97
17 #define CEPH_IOC_SYNCIO _IO(CEPH_IOCTL_MAGIC, 5)
18
19 void write_pattern()
20 {
21         printf("writing pattern\n");
22
23         uint64_t i;
24         int r;
25
26         int fd = open("foo", O_CREAT|O_WRONLY, 0644);
27         if (fd < 0) {
28            r = errno;
29            printf("write_pattern: error: open() failed with: %d (%s)\n", r, strerror(r));
30            exit(r);
31         }
32         for (i=0; i<1048576 * sizeof(i); i += sizeof(i)) {
33                 r = write(fd, &i, sizeof(i));
34                 if (r == -1) {
35                         r = errno;
36                         printf("write_pattern: error: write() failed with: %d (%s)\n", r, strerror(r));
37                         break;
38                 }
39         }
40
41         close(fd);
42 }
43
44 int verify_pattern(char *buf, size_t len, uint64_t off)
45 {
46         size_t i;
47
48         for (i = 0; i < len; i += sizeof(uint64_t)) {
49                 uint64_t expected = i + off;
50                 uint64_t actual = *(uint64_t*)(buf + i);
51                 if (expected != actual) {
52                         printf("error: offset %llu had %llu\n", (unsigned long long)expected,
53                                (unsigned long long)actual);
54                         exit(1);
55                 }
56         }
57         return 0;
58 }
59
60 void generate_pattern(void *buf, size_t len, uint64_t offset)
61 {
62         uint64_t *v = buf;
63         size_t i;
64
65         for (i=0; i<len / sizeof(v); i++)
66                 v[i] = i * sizeof(v) + offset;
67         verify_pattern(buf, len, offset);
68 }
69
70 int read_file(int buf_align, uint64_t offset, int len, int direct) {
71
72         printf("read_file buf_align %d offset %llu len %d\n", buf_align,
73                (unsigned long long)offset, len);
74         void *rawbuf;
75         int r;
76         int flags;
77         int err = 0;
78
79         if(direct)
80            flags = O_RDONLY|O_DIRECT;
81         else
82            flags = O_RDONLY;
83
84         int fd = open("foo", flags);
85         if (fd < 0) {
86            err = errno;
87            printf("read_file: error: open() failed with: %d (%s)\n", err, strerror(err));
88            exit(err);
89         }
90
91         if (!direct)
92            ioctl(fd, CEPH_IOC_SYNCIO);
93
94         if ((r = posix_memalign(&rawbuf, 4096, len + buf_align)) != 0) {
95            printf("read_file: error: posix_memalign failed with %d", r);
96            close(fd);
97            exit (r);
98         }
99
100         void *buf = (char *)rawbuf + buf_align;
101         memset(buf, 0, len);
102         r = pread(fd, buf, len, offset);
103         if (r == -1) {
104            err = errno;
105            printf("read_file: error: pread() failed with: %d (%s)\n", err, strerror(err));
106            goto out;
107         }
108         r = verify_pattern(buf, len, offset);
109
110 out:
111         close(fd);
112         free(rawbuf);
113         return r;
114 }
115
116 int read_direct(int buf_align, uint64_t offset, int len)
117 {
118         printf("read_direct buf_align %d offset %llu len %d\n", buf_align,
119                (unsigned long long)offset, len);
120         return read_file(buf_align, offset, len, 1);
121 }
122
123 int read_sync(int buf_align, uint64_t offset, int len)
124 {
125         printf("read_sync buf_align %d offset %llu len %d\n", buf_align,
126                (unsigned long long)offset, len);
127         return read_file(buf_align, offset, len, 0);
128 }
129
130 int write_file(int buf_align, uint64_t offset, int len, int direct)
131 {
132         printf("write_file buf_align %d offset %llu len %d\n", buf_align,
133                (unsigned long long)offset, len);
134         void *rawbuf;
135         int r;
136         int err = 0;
137         int flags;
138         if (direct)
139            flags = O_WRONLY|O_DIRECT|O_CREAT;
140         else
141            flags = O_WRONLY|O_CREAT;
142
143         int fd = open("foo", flags, 0644);
144         if (fd < 0) {
145            int err = errno;
146            printf("write_file: error: open() failed with: %d (%s)\n", err, strerror(err));
147            exit(err);
148         }
149
150         if ((r = posix_memalign(&rawbuf, 4096, len + buf_align)) != 0) {
151            printf("write_file: error: posix_memalign failed with %d", r);
152            err = r;
153            goto out_close;
154         }
155
156         if (!direct)
157            ioctl(fd, CEPH_IOC_SYNCIO);
158
159         void *buf = (char *)rawbuf + buf_align;
160
161         generate_pattern(buf, len, offset);
162
163         r = pwrite(fd, buf, len, offset);
164         close(fd);
165
166         fd = open("foo", O_RDONLY);
167         if (fd < 0) {
168            err = errno;
169            printf("write_file: error: open() failed with: %d (%s)\n", err, strerror(err));
170            free(rawbuf);
171            goto out_unlink;
172         }
173         void *buf2 = malloc(len);
174         if (!buf2) {
175            err = -ENOMEM;
176            printf("write_file: error: malloc failed\n");
177            goto out_free;
178         }
179
180         memset(buf2, 0, len);
181         r = pread(fd, buf2, len, offset);
182         if (r == -1) {
183            err = errno;
184            printf("write_file: error: pread() failed with: %d (%s)\n", err, strerror(err));
185            goto out_free_buf;
186         }
187         r = verify_pattern(buf2, len, offset);
188
189 out_free_buf:
190         free(buf2);
191 out_free:
192         free(rawbuf);
193 out_close:
194         close(fd);
195 out_unlink:
196         unlink("foo");
197         if (err)
198            exit(err);
199         return r;
200 }
201
202 int write_direct(int buf_align, uint64_t offset, int len)
203 {
204         printf("write_direct buf_align %d offset %llu len %d\n", buf_align,
205                (unsigned long long)offset, len);
206         return write_file (buf_align, offset, len, 1);
207 }
208
209 int write_sync(int buf_align, uint64_t offset, int len)
210 {
211         printf("write_sync buf_align %d offset %llu len %d\n", buf_align,
212                (unsigned long long)offset, len);
213         return write_file (buf_align, offset, len, 0);
214 }
215
216 int main(int argc, char **argv)
217 {
218         uint64_t i, j, k;
219         int read = 1;
220         int write = 1;
221
222         if (argc >= 2 && strcmp(argv[1], "read") == 0)
223                 write = 0;
224         if (argc >= 2 && strcmp(argv[1], "write") == 0)
225                 read = 0;
226
227         if (read) {
228                 write_pattern();
229                 
230                 for (i = 0; i < 4096; i += 512)
231                         for (j = 4*1024*1024 - 4096; j < 4*1024*1024 + 4096; j += 512)
232                                 for (k = 1024; k <= 16384; k *= 2) {
233                                         read_direct(i, j, k);
234                                         read_sync(i, j, k);
235                                 }
236                 
237         }
238         unlink("foo");
239         if (write) {
240                 for (i = 0; i < 4096; i += 512)
241                         for (j = 4*1024*1024 - 4096 + 512; j < 4*1024*1024 + 4096; j += 512)
242                                 for (k = 1024; k <= 16384; k *= 2) {
243                                         write_direct(i, j, k);
244                                         write_sync(i, j, k);
245                                 }
246         }
247         
248
249         return 0;
250 }