Whamcloud - gitweb
LU-1538 tests: fix test cases when OST is full
[fs/lustre-release.git] / lustre / tests / multiop.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.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  */
30 /*
31  * This file is part of Lustre, http://www.lustre.org/
32  * Lustre is a trademark of Sun Microsystems, Inc.
33  */
34
35 #ifndef _GNU_SOURCE
36 #define _GNU_SOURCE /* pull in O_DIRECTORY in bits/fcntl.h */
37 #endif
38 #include <stdio.h>
39 #include <fcntl.h>
40 #include <string.h>
41 #include <errno.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <sys/mman.h>
45 #include <sys/vfs.h>
46 #include <signal.h>
47 #include <stdlib.h>
48 #include <unistd.h>
49 #include <semaphore.h>
50
51 #include <lustre/lustreapi.h>
52
53 #define T1 "write data before unlink\n"
54 #define T2 "write data after unlink\n"
55 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";
56 char *buf, *buf_align;
57 int bufsize = 0;
58 sem_t sem;
59 #define ALIGN 65535
60
61 char usage[] =
62 "Usage: %s filename command-sequence\n"
63 "    command-sequence items:\n"
64 "        c  close\n"
65 "        C[num] create with optional stripes\n"
66 "        d  mkdir\n"
67 "        D  open(O_DIRECTORY)\n"
68 "        f  statfs\n"
69 "        G gid get grouplock\n"
70 "        g gid put grouplock\n"
71 "        L  link\n"
72 "        l  symlink\n"
73 "        m  mknod\n"
74 "        M  rw mmap to EOF (must open and stat prior)\n"
75 "        N  rename\n"
76 "        o  open(O_RDONLY)\n"
77 "        O  open(O_CREAT|O_RDWR)\n"
78 "        r[num] read [optional length]\n"
79 "        R  reference entire mmap-ed region\n"
80 "        s  stat\n"
81 "        S  fstat\n"
82 "        t  fchmod\n"
83 "        T[num] ftruncate [optional position, default 0]\n"
84 "        u  unlink\n"
85 "        U  munmap\n"
86 "        v  verbose\n"
87 "        w[num] write optional length\n"
88 "        W  write entire mmap-ed region\n"
89 "        y  fsync\n"
90 "        Y  fdatasync\n"
91 "        z[num] seek [optional position, default 0]\n"
92 "        _  wait for signal\n";
93
94 void usr1_handler(int unused)
95 {
96         int saved_errno = errno;
97
98         /*
99          * signal(7): POSIX.1-2004 ...requires an implementation to guarantee
100          * that the following functions can be safely called inside a signal
101          * handler:
102          *            sem_post()
103          */
104         sem_post(&sem);
105
106         errno = saved_errno;
107 }
108
109 static const char *
110 pop_arg(int argc, char *argv[])
111 {
112         static int cur_arg = 3;
113
114         if (cur_arg >= argc)
115                 return NULL;
116
117         return argv[cur_arg++];
118 }
119
120 struct flag_mapping {
121        const char *string;
122        const int  flag;
123 } flag_table[] = {
124        {"O_RDONLY", O_RDONLY},
125        {"O_WRONLY", O_WRONLY},
126        {"O_RDWR", O_RDWR},
127        {"O_CREAT", O_CREAT},
128        {"O_EXCL", O_EXCL},
129        {"O_NOCTTY", O_NOCTTY},
130        {"O_TRUNC", O_TRUNC},
131        {"O_APPEND", O_APPEND},
132        {"O_NONBLOCK", O_NONBLOCK},
133        {"O_NDELAY", O_NDELAY},
134        {"O_SYNC", O_SYNC},
135 #ifdef O_DIRECT
136        {"O_DIRECT", O_DIRECT},
137 #endif
138        {"O_LARGEFILE", O_LARGEFILE},
139        {"O_DIRECTORY", O_DIRECTORY},
140        {"O_NOFOLLOW", O_NOFOLLOW},
141        {"", -1}
142 };
143
144 int get_flags(char *data, int *rflags)
145 {
146         char *cloned_flags;
147         char *tmp;
148         int flag_set = 0;
149         int flags = 0;
150         int size = 0;
151
152         cloned_flags = strdup(data);
153         if (cloned_flags == NULL) {
154                 fprintf(stderr, "Insufficient memory.\n");
155                 exit(-1);
156         }
157
158         for (tmp = strtok(cloned_flags, ":"); tmp;
159              tmp = strtok(NULL, ":")) {
160                 int i;
161
162                 size = tmp - cloned_flags;
163                 for (i = 0; flag_table[i].flag != -1; i++) {
164                         if (!strcmp(tmp, flag_table[i].string)){
165                                 flags |= flag_table[i].flag;
166                                 size += strlen(flag_table[i].string);
167                                 flag_set = 1;
168                                 break;
169                         }
170                 }
171         }
172         free(cloned_flags);
173
174         if (!flag_set) {
175                 *rflags = O_RDONLY;
176                 return 0;
177         }
178
179         *rflags = flags;
180         return size;
181 }
182
183 #define POP_ARG() (pop_arg(argc, argv))
184
185 int main(int argc, char **argv)
186 {
187         char *fname, *commands;
188         const char *newfile;
189         struct stat st;
190         struct statfs stfs;
191         size_t mmap_len = 0, i;
192         unsigned char *mmap_ptr = NULL, junk = 0;
193         int rc, len, fd = -1;
194         int flags;
195         int save_errno;
196         int verbose = 0;
197         int gid = 0;
198
199         if (argc < 3) {
200                 fprintf(stderr, usage, argv[0]);
201                 exit(1);
202         }
203
204         memset(&st, 0, sizeof(st));
205         sem_init(&sem, 0, 0);
206         /* use sigaction instead of signal to avoid SA_ONESHOT semantics */
207         sigaction(SIGUSR1, &(const struct sigaction){.sa_handler = &usr1_handler},
208                   NULL);
209
210         fname = argv[1];
211
212         for (commands = argv[2]; *commands; commands++) {
213                 switch (*commands) {
214                 case '_':
215                         if (verbose) {
216                                 printf("PAUSING\n");
217                                 fflush(stdout);
218                         }
219                         while (sem_wait(&sem) == -1 && errno == EINTR);
220                         break;
221                 case 'c':
222                         if (close(fd) == -1) {
223                                 save_errno = errno;
224                                 perror("close");
225                                 exit(save_errno);
226                         }
227                         fd = -1;
228                         break;
229                 case 'C':
230                         len = atoi(commands+1);
231                         fd = llapi_file_open(fname, O_CREAT | O_WRONLY, 0644,
232                                              0, 0, len, 0);
233                         if (fd == -1) {
234                                 save_errno = errno;
235                                 perror("create stripe file");
236                                 exit(save_errno);
237                         }
238                         break;
239                 case 'd':
240                         if (mkdir(fname, 0755) == -1) {
241                                 save_errno = errno;
242                                 perror("mkdir(0755)");
243                                 exit(save_errno);
244                         }
245                         break;
246                 case 'D':
247                         fd = open(fname, O_DIRECTORY);
248                         if (fd == -1) {
249                                 save_errno = errno;
250                                 perror("open(O_DIRECTORY)");
251                                 exit(save_errno);
252                         }
253                         break;
254                 case 'f':
255                         if (statfs(fname, &stfs) == -1) {
256                                 save_errno = errno;
257                                 perror("statfs()");
258                                 exit(save_errno);
259                         }
260                         break;
261                 case 'G':
262                         gid = atoi(commands+1);
263                         if (ioctl(fd, LL_IOC_GROUP_LOCK, gid) == -1) {
264                                 save_errno = errno;
265                                 perror("ioctl(GROUP_LOCK)");
266                                 exit(save_errno);
267                         }
268                         break;
269                 case 'g':
270                         gid = atoi(commands+1);
271                         if (ioctl(fd, LL_IOC_GROUP_UNLOCK, gid) == -1) {
272                                 save_errno = errno;
273                                 perror("ioctl(GROUP_UNLOCK)");
274                                 exit(save_errno);
275                         }
276                         break;
277                 case 'l':
278                         newfile = POP_ARG();
279                         if (!newfile)
280                                 newfile = fname;
281                         if (symlink(fname, newfile)) {
282                                 save_errno = errno;
283                                 perror("symlink()");
284                                 exit(save_errno);
285                         }
286                         break;
287                 case 'L':
288                         newfile = POP_ARG();
289                         if (!newfile)
290                                 newfile = fname;
291                         if (link(fname, newfile)) {
292                                 save_errno = errno;
293                                 perror("symlink()");
294                                 exit(save_errno);
295                         }
296                         break;
297                 case 'm':
298                         if (mknod(fname, S_IFREG | 0644, 0) == -1) {
299                                 save_errno = errno;
300                                 perror("mknod(S_IFREG|0644, 0)");
301                                 exit(save_errno);
302                         }
303                         break;
304                 case 'M':
305                         if (st.st_size == 0) {
306                                 fprintf(stderr, "mmap without preceeding stat, or on"
307                                         " zero length file.\n");
308                                 exit(-1);
309                         }
310                         mmap_len = st.st_size;
311                         mmap_ptr = mmap(NULL, mmap_len, PROT_WRITE | PROT_READ,
312                                         MAP_SHARED, fd, 0);
313                         if (mmap_ptr == MAP_FAILED) {
314                                 save_errno = errno;
315                                 perror("mmap");
316                                 exit(save_errno);
317                         }
318                         break;
319                 case 'N':
320                         newfile = POP_ARG();
321                         if (!newfile)
322                                 newfile = fname;
323                         if (rename (fname, newfile)) {
324                                 save_errno = errno;
325                                 perror("rename()");
326                                 exit(save_errno);
327                         }
328                         break;
329                 case 'O':
330                         fd = open(fname, O_CREAT|O_RDWR, 0644);
331                         if (fd == -1) {
332                                 save_errno = errno;
333                                 perror("open(O_RDWR|O_CREAT)");
334                                 exit(save_errno);
335                         }
336                         break;
337                 case 'o':
338                         len = get_flags(commands+1, &flags);
339                         commands += len;
340                         if (flags & O_CREAT)
341                                 fd = open(fname, flags, 0666);
342                         else
343                                 fd = open(fname, flags);
344                         if (fd == -1) {
345                                 save_errno = errno;
346                                 perror("open");
347                                 exit(save_errno);
348                         }
349                         break;
350                 case 'r':
351                         len = atoi(commands+1);
352                         if (len <= 0)
353                                 len = 1;
354                         if (bufsize < len) {
355                                 buf = realloc(buf, len + ALIGN);
356                                 if (buf == NULL) {
357                                         save_errno = errno;
358                                         perror("allocating buf for read\n");
359                                         exit(save_errno);
360                                 }
361                                 bufsize = len;
362                                 buf_align = (char *)((long)(buf + ALIGN) &
363                                                      ~ALIGN);
364                         }
365                         while (len > 0) {
366                                 rc = read(fd, buf_align, len);
367                                 if (rc == -1) {
368                                         save_errno = errno;
369                                         perror("read");
370                                         exit(save_errno);
371                                 }
372                                 if (rc < len) {
373                                         fprintf(stderr, "short read: %u/%u\n",
374                                                 rc, len);
375                                         if (rc == 0)
376                                                 exit(ENODATA);
377                                 }
378                                 len -= rc;
379                                 if (verbose >= 2)
380                                         printf("%.*s\n", rc, buf_align);
381                         }
382                         break;
383                 case 'R':
384                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
385                                 junk += mmap_ptr[i];
386                         break;
387                 case 's':
388                         if (stat(fname, &st) == -1) {
389                                 save_errno = errno;
390                                 perror("stat");
391                                 exit(save_errno);
392                         }
393                         break;
394                 case 'S':
395                         if (fstat(fd, &st) == -1) {
396                                 save_errno = errno;
397                                 perror("fstat");
398                                 exit(save_errno);
399                         }
400                         break;
401                 case 't':
402                         if (fchmod(fd, 0) == -1) {
403                                 save_errno = errno;
404                                 perror("fchmod");
405                                 exit(save_errno);
406                         }
407                         break;
408                 case 'T':
409                         len = atoi(commands+1);
410                         if (ftruncate(fd, len) == -1) {
411                                 save_errno = errno;
412                                 printf("ftruncate (%d,%d)\n", fd, len);
413                                 perror("ftruncate");
414                                 exit(save_errno);
415                         }
416                         break;
417                 case 'u':
418                         if (unlink(fname) == -1) {
419                                 save_errno = errno;
420                                 perror("unlink");
421                                 exit(save_errno);
422                         }
423                         break;
424                 case 'U':
425                         if (munmap(mmap_ptr, mmap_len)) {
426                                 save_errno = errno;
427                                 perror("munmap");
428                                 exit(save_errno);
429                         }
430                         break;
431                 case 'v':
432                         verbose++;
433                         break;
434                 case 'w':
435                         len = atoi(commands+1);
436                         if (len <= 0)
437                                 len = 1;
438                         if (bufsize < len) {
439                                 buf = realloc(buf, len + ALIGN);
440                                 if (buf == NULL) {
441                                         save_errno = errno;
442                                         perror("allocating buf for write\n");
443                                         exit(save_errno);
444                                 }
445                                 bufsize = len;
446                                 buf_align = (char *)((long)(buf + ALIGN) &
447                                                      ~ALIGN);
448                                 strncpy(buf_align, msg, bufsize);
449                         }
450                         while (len > 0) {
451                                 rc = write(fd, buf_align, len);
452                                 if (rc == -1) {
453                                         save_errno = errno;
454                                         perror("write");
455                                         exit(save_errno);
456                                 }
457                                 if (rc < len)
458                                         fprintf(stderr, "short write: %u/%u\n",
459                                                 rc, len);
460                                 len -= rc;
461                         }
462                         break;
463                 case 'W':
464                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
465                                 mmap_ptr[i] += junk++;
466                         break;
467                 case 'y':
468                         if (fsync(fd) == -1) {
469                                 save_errno = errno;
470                                 perror("fsync");
471                                 exit(save_errno);
472                         }
473                         break;
474                 case 'Y':
475                         if (fdatasync(fd) == -1) {
476                                 save_errno = errno;
477                                 perror("fdatasync");
478                                 exit(save_errno);
479                         }
480                 case 'z':
481                         len = atoi(commands+1);
482                         if (lseek(fd, len, SEEK_SET) == -1) {
483                                 save_errno = errno;
484                                 perror("lseek");
485                                 exit(save_errno);
486                         }
487                         break;
488                 case '0':
489                 case '1':
490                 case '2':
491                 case '3':
492                 case '4':
493                 case '5':
494                 case '6':
495                 case '7':
496                 case '8':
497                 case '9':
498                         break;
499                 default:
500                         fprintf(stderr, "unknown command \"%c\"\n", *commands);
501                         fprintf(stderr, usage, argv[0]);
502                         exit(1);
503                 }
504         }
505
506         if (buf)
507                 free(buf);
508
509         return 0;
510 }