Whamcloud - gitweb
LU-2140 test: add fake nid with proper nettype
[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                                 len -= rc;
376                                 if (verbose >= 2)
377                                         printf("%.*s\n", rc, buf_align);
378                         }
379                         break;
380                 case 'R':
381                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
382                                 junk += mmap_ptr[i];
383                         break;
384                 case 's':
385                         if (stat(fname, &st) == -1) {
386                                 save_errno = errno;
387                                 perror("stat");
388                                 exit(save_errno);
389                         }
390                         break;
391                 case 'S':
392                         if (fstat(fd, &st) == -1) {
393                                 save_errno = errno;
394                                 perror("fstat");
395                                 exit(save_errno);
396                         }
397                         break;
398                 case 't':
399                         if (fchmod(fd, 0) == -1) {
400                                 save_errno = errno;
401                                 perror("fchmod");
402                                 exit(save_errno);
403                         }
404                         break;
405                 case 'T':
406                         len = atoi(commands+1);
407                         if (ftruncate(fd, len) == -1) {
408                                 save_errno = errno;
409                                 printf("ftruncate (%d,%d)\n", fd, len);
410                                 perror("ftruncate");
411                                 exit(save_errno);
412                         }
413                         break;
414                 case 'u':
415                         if (unlink(fname) == -1) {
416                                 save_errno = errno;
417                                 perror("unlink");
418                                 exit(save_errno);
419                         }
420                         break;
421                 case 'U':
422                         if (munmap(mmap_ptr, mmap_len)) {
423                                 save_errno = errno;
424                                 perror("munmap");
425                                 exit(save_errno);
426                         }
427                         break;
428                 case 'v':
429                         verbose++;
430                         break;
431                 case 'w':
432                         len = atoi(commands+1);
433                         if (len <= 0)
434                                 len = 1;
435                         if (bufsize < len) {
436                                 buf = realloc(buf, len + ALIGN);
437                                 if (buf == NULL) {
438                                         save_errno = errno;
439                                         perror("allocating buf for write\n");
440                                         exit(save_errno);
441                                 }
442                                 bufsize = len;
443                                 buf_align = (char *)((long)(buf + ALIGN) &
444                                                      ~ALIGN);
445                                 strncpy(buf_align, msg, bufsize);
446                         }
447                         while (len > 0) {
448                                 rc = write(fd, buf_align, len);
449                                 if (rc == -1) {
450                                         save_errno = errno;
451                                         perror("write");
452                                         exit(save_errno);
453                                 }
454                                 if (rc < len)
455                                         fprintf(stderr, "short write: %u/%u\n",
456                                                 rc, len);
457                                 len -= rc;
458                         }
459                         break;
460                 case 'W':
461                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
462                                 mmap_ptr[i] += junk++;
463                         break;
464                 case 'y':
465                         if (fsync(fd) == -1) {
466                                 save_errno = errno;
467                                 perror("fsync");
468                                 exit(save_errno);
469                         }
470                         break;
471                 case 'Y':
472                         if (fdatasync(fd) == -1) {
473                                 save_errno = errno;
474                                 perror("fdatasync");
475                                 exit(save_errno);
476                         }
477                 case 'z':
478                         len = atoi(commands+1);
479                         if (lseek(fd, len, SEEK_SET) == -1) {
480                                 save_errno = errno;
481                                 perror("lseek");
482                                 exit(save_errno);
483                         }
484                         break;
485                 case '0':
486                 case '1':
487                 case '2':
488                 case '3':
489                 case '4':
490                 case '5':
491                 case '6':
492                 case '7':
493                 case '8':
494                 case '9':
495                         break;
496                 default:
497                         fprintf(stderr, "unknown command \"%c\"\n", *commands);
498                         fprintf(stderr, usage, argv[0]);
499                         exit(1);
500                 }
501         }
502
503         if (buf)
504                 free(buf);
505
506         return 0;
507 }