Whamcloud - gitweb
b=16098
[fs/lustre-release.git] / lustre / tests / multiop.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * GPL HEADER START
5  *
6  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 only,
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License version 2 for more details (a copy is included
16  * in the LICENSE file that accompanied this code).
17  *
18  * You should have received a copy of the GNU General Public License
19  * version 2 along with this program; If not, see [sun.com URL with a
20  * copy of GPLv2].
21  *
22  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23  * CA 95054 USA or visit www.sun.com if you need additional information or
24  * have any questions.
25  *
26  * GPL HEADER END
27  */
28 /*
29  * Copyright  2008 Sun Microsystems, Inc. All rights reserved
30  * Use is subject to license terms.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36
37 #ifndef _GNU_SOURCE
38 #define _GNU_SOURCE /* pull in O_DIRECTORY in bits/fcntl.h */
39 #endif
40 #include <stdio.h>
41 #include <fcntl.h>
42 #include <string.h>
43 #include <errno.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <sys/mman.h>
47 #include <signal.h>
48 #include <stdlib.h>
49 #include <unistd.h>
50 #include <lustre/liblustreapi.h>
51
52 #define T1 "write data before unlink\n"
53 #define T2 "write data after unlink\n"
54 char msg[] = "yabba dabba doo, I'm coming for you, I live in a shoe, I don't know what to do.\n'Bigger, bigger,and bigger yet!' cried the Creator.  'You are not yet substantial enough for my boundless intents!'  And ever greater and greater the object became, until all was lost 'neath its momentus bulk.\n";
55 char *buf, *buf_align;
56 int bufsize = 0;
57 #define ALIGN 65535
58
59 char usage[] = 
60 "Usage: %s filename command-sequence\n"
61 "    command-sequence items:\n"
62 "        c  close\n"
63 "        C[num] create with optional stripes\n"
64 "        d  mkdir\n"
65 "        D  open(O_DIRECTORY)\n"
66 "        L  link\n"
67 "        l  symlink\n"
68 "        m  mknod\n"
69 "        M  rw mmap to EOF (must open and stat prior)\n"
70 "        N  rename\n"
71 "        o  open(O_RDONLY)\n"
72 "        O  open(O_CREAT|O_RDWR)\n"
73 "        r[num] read [optional length]\n"
74 "        R  reference entire mmap-ed region\n"
75 "        s  stat\n"
76 "        S  fstat\n"
77 "        t  fchmod\n"
78 "        T[num] ftruncate [optional position, default 0]\n"
79 "        u  unlink\n"
80 "        U  munmap\n"
81 "        w[num] write optional length\n"
82 "        W  write entire mmap-ed region\n"
83 "        y  fsync\n"
84 "        Y  fdatasync\n"
85 "        z[num] seek [optional position, default 0]\n"
86 "        _  wait for signal\n";
87
88 static int usr1_received;
89 void usr1_handler(int unused)
90 {
91         usr1_received = 1;
92 }
93
94 static const char *
95 pop_arg(int argc, char *argv[])
96 {
97         static int cur_arg = 3;
98
99         if (cur_arg >= argc)
100                 return NULL;
101
102         return argv[cur_arg++];
103 }
104
105 struct flag_mapping {
106        const char *string;
107        const int  flag;
108 } flag_table[] = {
109        {"O_RDONLY", O_RDONLY},
110        {"O_WRONLY", O_WRONLY},
111        {"O_RDWR", O_RDWR},
112        {"O_CREAT", O_CREAT},
113        {"O_EXCL", O_EXCL},
114        {"O_NOCTTY", O_NOCTTY},
115        {"O_TRUNC", O_TRUNC},
116        {"O_APPEND", O_APPEND},
117        {"O_NONBLOCK", O_NONBLOCK},
118        {"O_NDELAY", O_NDELAY},
119        {"O_SYNC", O_SYNC},
120 #ifdef O_DIRECT
121        {"O_DIRECT", O_DIRECT},
122 #endif
123        {"O_LARGEFILE", O_LARGEFILE},
124        {"O_DIRECTORY", O_DIRECTORY},
125        {"O_NOFOLLOW", O_NOFOLLOW},
126        {"", -1}
127 };
128
129 int get_flags(char *data, int *rflags)
130 {
131         char *cloned_flags;
132         char *tmp;
133         int flag_set = 0;
134         int flags = 0;
135         int size = 0;
136
137         cloned_flags = strdup(data);
138         if (cloned_flags == NULL) {
139                 fprintf(stderr, "Insufficient memory.\n");
140                 exit(-1);
141         }
142
143         for (tmp = strtok(cloned_flags, ":"); tmp;
144              tmp = strtok(NULL, ":")) {
145                 int i;
146
147                 size = tmp - cloned_flags;
148                 for (i = 0; flag_table[i].flag != -1; i++) {
149                         if (!strcmp(tmp, flag_table[i].string)){
150                                 flags |= flag_table[i].flag;
151                                 size += strlen(flag_table[i].string);
152                                 flag_set = 1;
153                                 break;
154                         }
155                 }
156         }
157         free(cloned_flags);
158
159         if (!flag_set) {
160                 *rflags = O_RDONLY;
161                 return 0;
162         }
163
164         *rflags = flags;
165         return size;
166 }
167
168 #define POP_ARG() (pop_arg(argc, argv))
169 #define min(a,b) ((a)>(b)?(b):(a))
170
171 int main(int argc, char **argv)
172 {
173         char *fname, *commands;
174         const char *newfile;
175         struct stat st;
176         size_t mmap_len = 0, i;
177         unsigned char *mmap_ptr = NULL, junk = 0;
178         int rc, len, fd = -1;
179         int flags;
180         int save_errno;
181         int verbose = 0;
182
183         if (argc < 3) {
184                 fprintf(stderr, usage, argv[0]);
185                 exit(1);
186         }
187
188         signal(SIGUSR1, usr1_handler);
189
190         fname = argv[1];
191
192         for (commands = argv[2]; *commands; commands++) {
193                 switch (*commands) {
194                 case '_':
195                         if (usr1_received == 0) {
196                                 if (verbose) {
197                                         printf("PAUSING\n");
198                                         fflush(stdout);
199                                 }
200                                 pause();
201                         }
202                         usr1_received = 0;
203                         signal(SIGUSR1, usr1_handler);
204                         break;
205                 case 'c':
206                         if (close(fd) == -1) {
207                                 save_errno = errno;
208                                 perror("close");
209                                 exit(save_errno);
210                         }
211                         fd = -1;
212                         break;
213                 case 'C':
214                         len = atoi(commands+1);
215                         fd = llapi_file_open(fname, O_CREAT | O_WRONLY, 0644,
216                                              0, 0, len, 0);
217                         if (fd == -1) {
218                                 save_errno = errno;
219                                 perror("create stripe file");
220                                 exit(save_errno);
221                         }
222                         break;
223                 case 'd':
224                         if (mkdir(fname, 0755) == -1) {
225                                 save_errno = errno;
226                                 perror("mkdir(0755)");
227                                 exit(save_errno);
228                         }
229                         break;
230                 case 'D':
231                         fd = open(fname, O_DIRECTORY);
232                         if (fd == -1) {
233                                 save_errno = errno;
234                                 perror("open(O_DIRECTORY)");
235                                 exit(save_errno);
236                         }
237                         break;
238                 case 'l':
239                         newfile = POP_ARG();
240                         if (!newfile)
241                                 newfile = fname;
242                         if (symlink(fname, newfile)) {
243                                 save_errno = errno;
244                                 perror("symlink()");
245                                 exit(save_errno);
246                         }
247                         break;
248                 case 'L':
249                         newfile = POP_ARG();
250                         if (!newfile)
251                                 newfile = fname;
252                         if (link(fname, newfile)) {
253                                 save_errno = errno;
254                                 perror("symlink()");
255                                 exit(save_errno);
256                         }
257                         break;
258                 case 'm':
259                         if (mknod(fname, S_IFREG | 0644, 0) == -1) {
260                                 save_errno = errno;
261                                 perror("mknod(S_IFREG|0644, 0)");
262                                 exit(save_errno);
263                         }
264                         break;
265                 case 'M':
266                         mmap_len = st.st_size;
267                         mmap_ptr = mmap(NULL, mmap_len, PROT_WRITE | PROT_READ,
268                                         MAP_SHARED, fd, 0);
269                         if (mmap_ptr == MAP_FAILED) {
270                                 save_errno = errno;
271                                 perror("mmap");
272                                 exit(save_errno);
273                         }
274                         break;
275                 case 'N':
276                         newfile = POP_ARG();
277                         if (!newfile)
278                                 newfile = fname;
279                         if (rename (fname, newfile)) {
280                                 save_errno = errno;
281                                 perror("rename()");
282                                 exit(save_errno);
283                         }
284                         break;
285                 case 'O':
286                         fd = open(fname, O_CREAT|O_RDWR, 0644);
287                         if (fd == -1) {
288                                 save_errno = errno;
289                                 perror("open(O_RDWR|O_CREAT)");
290                                 exit(save_errno);
291                         }
292                         break;
293                 case 'o':
294                         len = get_flags(commands+1, &flags);
295                         commands += len;
296                         fd = open(fname, flags);
297                         if (fd == -1) {
298                                 save_errno = errno;
299                                 perror("open");
300                                 exit(save_errno);
301                         }
302                         break;
303                 case 'r':
304                         len = atoi(commands+1);
305                         if (len <= 0)
306                                 len = 1;
307                         if (bufsize < len) {
308                                 buf = realloc(buf, len + ALIGN);
309                                 if (buf == NULL) {
310                                         save_errno = errno;
311                                         perror("allocating buf for read\n");
312                                         exit(save_errno);
313                                 }
314                                 bufsize = len;
315                                 buf_align = (char *)((long)(buf + ALIGN) &
316                                                      ~ALIGN);
317                         }
318                         while (len > 0) {
319                                 rc = read(fd, buf_align, len);
320                                 if (rc == -1) {
321                                         save_errno = errno;
322                                         perror("read");
323                                         exit(save_errno);
324                                 }
325                                 if (rc < len)
326                                         fprintf(stderr, "short read: %u/%u\n",
327                                                 rc, len);
328                                 len -= rc;
329                         }
330                         break;
331                 case 'R':
332                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
333                                 junk += mmap_ptr[i];
334                         break;
335                 case 's':
336                         if (stat(fname, &st) == -1) {
337                                 save_errno = errno;
338                                 perror("stat");
339                                 exit(save_errno);
340                         }
341                         break;
342                 case 'S':
343                         if (fstat(fd, &st) == -1) {
344                                 save_errno = errno;
345                                 perror("fstat");
346                                 exit(save_errno);
347                         }
348                         break;
349                 case 't':
350                         if (fchmod(fd, 0) == -1) {
351                                 save_errno = errno;
352                                 perror("fchmod");
353                                 exit(save_errno);
354                         }
355                         break;
356                 case 'T':
357                         len = atoi(commands+1);
358                         if (ftruncate(fd, len) == -1) {
359                                 save_errno = errno;
360                                 printf("ftruncate (%d,%d)\n", fd, len);
361                                 perror("ftruncate");
362                                 exit(save_errno);
363                         }
364                         break;
365                 case 'u':
366                         if (unlink(fname) == -1) {
367                                 save_errno = errno;
368                                 perror("unlink");
369                                 exit(save_errno);
370                         }
371                         break;
372                 case 'U':
373                         if (munmap(mmap_ptr, mmap_len)) {
374                                 save_errno = errno;
375                                 perror("munmap");
376                                 exit(save_errno);
377                         }
378                         break;
379                 case 'v':
380                         verbose = 1;
381                         break;
382                 case 'w':
383                         len = atoi(commands+1);
384                         if (len <= 0)
385                                 len = 1;
386                         if (bufsize < len) {
387                                 buf = realloc(buf, len + ALIGN);
388                                 if (buf == NULL) {
389                                         save_errno = errno;
390                                         perror("allocating buf for write\n");
391                                         exit(save_errno);
392                                 }
393                                 bufsize = len;
394                                 buf_align = (char *)((long)(buf + ALIGN) &
395                                                      ~ALIGN);
396                                 strncpy(buf_align, msg, bufsize);
397                         }
398                         while (len > 0) {
399                                 rc = write(fd, buf_align, len);
400                                 if (rc == -1) {
401                                         save_errno = errno;
402                                         perror("write");
403                                         exit(save_errno);
404                                 }
405                                 if (rc < len)
406                                         fprintf(stderr, "short write: %u/%u\n",
407                                                 rc, len);
408                                 len -= rc;
409                         }
410                         break;
411                 case 'W':
412                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
413                                 mmap_ptr[i] += junk++;
414                         break;
415                 case 'y':
416                         if (fsync(fd) == -1) {
417                                 save_errno = errno;
418                                 perror("fsync");
419                                 exit(save_errno);
420                         }
421                         break;
422                 case 'Y':
423                         if (fdatasync(fd) == -1) {
424                                 save_errno = errno;
425                                 perror("fdatasync");
426                                 exit(save_errno);
427                         }
428                 case 'z':
429                         len = atoi(commands+1);
430                         if (lseek(fd, len, SEEK_SET) == -1) {
431                                 save_errno = errno;
432                                 perror("lseek");
433                                 exit(save_errno);
434                         }
435                         break;
436                 case '0':
437                 case '1':
438                 case '2':
439                 case '3':
440                 case '4':
441                 case '5':
442                 case '6':
443                 case '7':
444                 case '8':
445                 case '9':
446                         break;
447                 default:
448                         fprintf(stderr, "unknown command \"%c\"\n", *commands);
449                         fprintf(stderr, usage, argv[0]);
450                         exit(1);
451                 }
452         }
453
454         if (buf)
455                 free(buf);
456
457         return 0;
458 }