Whamcloud - gitweb
LU-17705 ptlrpc: replace synchronize_rcu() with rcu_barrier()
[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.gnu.org/licenses/gpl-2.0.html
19  *
20  * GPL HEADER END
21  */
22 /*
23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright (c) 2012, 2017, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  */
31
32 #ifndef _GNU_SOURCE
33 #define _GNU_SOURCE /* pull in O_DIRECTORY in bits/fcntl.h */
34 #endif
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <limits.h>
38 #include <malloc.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <sys/mman.h>
44 #include <sys/vfs.h>
45 #include <sys/ioctl.h>
46 #include <sys/xattr.h>
47 #include <sys/file.h>
48 #include <signal.h>
49 #include <stdlib.h>
50 #include <unistd.h>
51 #include <semaphore.h>
52 #include <time.h>
53 #include <err.h>
54 #include <dirent.h>
55 #include <ctype.h>
56
57 #include <lustre/lustreapi.h>
58
59 #define T1 "write data before unlink\n"
60 #define T2 "write data after unlink\n"
61 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";
62 char *buf, *buf_align;
63 int bufsize;
64 sem_t sem;
65 #define ALIGN_LEN 65535
66 #define XATTR "user.multiop"
67
68 char usage[] =
69 "Usage: %s filename command-sequence [path...]\n"
70 "    command-sequence items:\n"
71 "        A  fsetxattr(\"user.multiop\")\n"
72 "        a[num] fgetxattr(\"user.multiop\") [optional buffer size, default 0]\n"
73 "        c  close\n"
74 "        B[num] call setstripe ioctl to create stripes\n"
75 "        C[num] create with optional stripes\n"
76 "        d  mkdir\n"
77 "        D  open(O_DIRECTORY)\n"
78 "        e[R|W|U] apply lease. R: Read; W: Write; U: Unlock\n"
79 "        E[+|-] get lease. +/-: expect lease to (not) exist\n"
80 "        f  statfs\n"
81 "        F  print FID\n"
82 "        G gid get grouplock\n"
83 "        g gid put grouplock\n"
84 "        H[num] create HSM released file with num stripes\n"
85 "        K  link path to filename\n"
86 "        L  link\n"
87 "        l  symlink filename to path\n"
88 "        m  mknod\n"
89 "        M  rw mmap to EOF (must open and stat prior)\n"
90 "        n  rename path to filename\n"
91 "        N  rename filename to path\n"
92 "        o  open(O_RDONLY)\n"
93 "        O  open(O_CREAT|O_RDWR)\n"
94 "        p  print return value of last command\n"
95 "        Q  open filename (should be dir), stat first entry to init statahead"
96 "        r[num] read [optional length]\n"
97 "        R  reference entire mmap-ed region\n"
98 "        s  stat\n"
99 "        S  fstat\n"
100 "        t  fchmod\n"
101 "        T[num] ftruncate [optional position, default 0]\n"
102 "        u  unlink\n"
103 "        U  munmap\n"
104 "        v  verbose\n"
105 "        V  open a volatile file\n"
106 "        w[num] write optional length\n"
107 "        P[num] like w, but only one write call\n"
108 "        x  get file data version\n"
109 "        W  write entire mmap-ed region\n"
110 "        y  fsync\n"
111 "        Y  fdatasync\n"
112 "        z[num] lseek(SEEK_SET) [optional offset, default 0]\n"
113 "        Z[num] lseek(SEEK_CUR) [optional offset, default 0]\n"
114 "        _  wait for signal\n";
115
116 static void usr1_handler(int unused)
117 {
118         int saved_errno = errno;
119
120         /*
121          * signal(7): POSIX.1-2004 ...requires an implementation to guarantee
122          * that the following functions can be safely called inside a signal
123          * handler:
124          *            sem_post()
125          */
126         sem_post(&sem);
127
128         errno = saved_errno;
129 }
130
131 static const char *
132 pop_arg(int argc, char *argv[])
133 {
134         static int cur_arg = 3;
135
136         if (cur_arg >= argc)
137                 return NULL;
138
139         return argv[cur_arg++];
140 }
141
142 struct flag_mapping {
143         const char *string;
144         const int  flag;
145 } flag_table[] = {
146         {"O_RDONLY", O_RDONLY},
147         {"O_WRONLY", O_WRONLY},
148         {"O_RDWR", O_RDWR},
149         {"O_CREAT", O_CREAT},
150         {"O_EXCL", O_EXCL},
151         {"O_NOCTTY", O_NOCTTY},
152         {"O_TRUNC", O_TRUNC},
153         {"O_APPEND", O_APPEND},
154         {"O_NONBLOCK", O_NONBLOCK},
155         {"O_NDELAY", O_NDELAY},
156         {"O_SYNC", O_SYNC},
157 #ifdef O_DIRECT
158         {"O_DIRECT", O_DIRECT},
159 #endif
160 #ifdef O_NOATIME
161         {"O_NOATIME", O_NOATIME},
162 #endif
163         {"O_LARGEFILE", O_LARGEFILE},
164         {"O_DIRECTORY", O_DIRECTORY},
165         {"O_NOFOLLOW", O_NOFOLLOW},
166         {"O_LOV_DELAY_CREATE", O_LOV_DELAY_CREATE},
167         {"", -1}
168 };
169
170 static int get_flags(char *data, int *rflags)
171 {
172         char *cloned_flags;
173         char *tmp;
174         int flag_set = 0;
175         int flags = 0;
176         int size = 0;
177
178         cloned_flags = strdup(data);
179         if (!cloned_flags) {
180                 fprintf(stderr, "Insufficient memory.\n");
181                 exit(-1);
182         }
183
184         for (tmp = strtok(cloned_flags, ":"); tmp;
185              tmp = strtok(NULL, ":")) {
186                 int i;
187
188                 size = tmp - cloned_flags;
189                 for (i = 0; flag_table[i].flag != -1; i++) {
190                         if (!strcmp(tmp, flag_table[i].string)) {
191                                 flags |= flag_table[i].flag;
192                                 size += strlen(flag_table[i].string);
193                                 flag_set = 1;
194                                 break;
195                         }
196                 }
197         }
198         free(cloned_flags);
199
200         if (!flag_set) {
201                 *rflags = O_RDONLY;
202                 return 0;
203         }
204
205         *rflags = flags;
206         return size;
207 }
208
209 static int statahead(char *dname)
210 {
211         DIR *d;
212         struct dirent *dent;
213         struct stat st;
214         char *buf;
215         int rc;
216
217         rc = 0;
218         d = opendir(dname);
219         if (!d)
220                 return errno;
221         dent = readdir(d);
222         if (!dent) {
223                 rc = errno;
224                 goto out_closedir;
225         }
226         if (asprintf(&buf, "%s/%s", dname, dent->d_name) == -1) {
227                 rc = errno;
228                 goto out_closedir;
229         }
230         if (stat(buf, &st))
231                 rc = errno;
232         free(buf);
233 out_closedir:
234         closedir(d);
235         return rc;
236 }
237
238 #define POP_ARG() (pop_arg(argc, argv))
239
240 int main(int argc, char **argv)
241 {
242         char *fname, *commands;
243         const char *newfile;
244         const char *oldpath;
245         struct stat st;
246         struct statfs stfs;
247         size_t mmap_len = 0, i;
248         unsigned char *mmap_ptr = NULL, junk = 1;
249         int len, fd = -1;
250         int flags;
251         int save_errno;
252         int verbose = 0;
253         int gid = 0;
254         struct lu_fid fid;
255         struct timespec ts;
256         struct lov_user_md_v3 lum;
257         char *xattr_buf = NULL;
258         size_t xattr_buf_size = 0;
259         long long rc = 0;
260         long long last_rc;
261         bool unaligned;
262         int msg_len = strlen(msg);
263         size_t total_bytes;
264
265         if (argc < 3) {
266                 fprintf(stderr, usage, argv[0]);
267                 exit(1);
268         }
269
270         memset(&st, 0, sizeof(st));
271         sem_init(&sem, 0, 0);
272         /* use sigaction instead of signal to avoid SA_ONESHOT semantics */
273         sigaction(SIGUSR1,
274                   &(const struct sigaction){.sa_handler = &usr1_handler}, NULL);
275
276         fname = argv[1];
277
278         for (commands = argv[2]; *commands; commands++) {
279                 /*
280                  * XXX Most commands return 0 or we exit so we only
281                  * update rc where really needed.
282                  */
283                 last_rc = rc;
284                 rc = 0;
285                 total_bytes = 0;
286                 unaligned = false;
287
288                 switch (*commands) {
289                 case '_':
290                         if (verbose) {
291                                 printf("PAUSING\n");
292                                 fflush(stdout);
293                         }
294                         len = atoi(commands + 1);
295                         if (len <= 0)
296                                 len = 3600; /* 1 hour */
297                         ts.tv_sec = time(NULL) + len;
298                         ts.tv_nsec = 0;
299                         while (sem_timedwait(&sem, &ts) < 0 && errno == EINTR)
300                                 ;
301                         break;
302                 case 'A':
303                         if (fsetxattr(fd, XATTR, "multiop", 8, 0)) {
304                                 save_errno = errno;
305                                 perror("fsetxattr");
306                                 exit(save_errno);
307                         }
308                         break;
309                 case 'a':
310                         len = atoi(commands + 1);
311                         if (xattr_buf_size < len) {
312                                 xattr_buf = realloc(xattr_buf, len);
313                                 if (!xattr_buf) {
314                                         save_errno = errno;
315                                         perror("allocating xattr buffer\n");
316                                         exit(save_errno);
317                                 }
318
319                                 xattr_buf_size = len;
320                         }
321
322                         rc = fgetxattr(fd, XATTR, xattr_buf, len);
323                         if (rc < 0) {
324                                 save_errno = errno;
325                                 perror("fgetxattr");
326                                 exit(save_errno);
327                         }
328                         break;
329                 case 'c':
330                         if (close(fd) == -1) {
331                                 save_errno = errno;
332                                 perror("close");
333                                 exit(save_errno);
334                         }
335                         fd = -1;
336                         break;
337                 case 'B':
338                         lum = (struct lov_user_md_v3) {
339                                 .lmm_magic = LOV_USER_MAGIC_V3,
340                                 .lmm_stripe_count = atoi(commands + 1),
341                         };
342
343                         if (ioctl(fd, LL_IOC_LOV_SETSTRIPE, &lum) < 0) {
344                                 save_errno = errno;
345                                 perror("LL_IOC_LOV_SETSTRIPE");
346                                 exit(save_errno);
347                         }
348                         break;
349                 case 'C':
350                         len = atoi(commands + 1);
351                         fd = llapi_file_open(fname, O_CREAT | O_WRONLY, 0644,
352                                              0, 0, len, 0);
353                         if (fd == -1) {
354                                 save_errno = errno;
355                                 perror("create stripe file");
356                                 exit(save_errno);
357                         }
358                         rc = fd;
359                         break;
360                 case 'd':
361                         if (mkdir(fname, 0755) == -1) {
362                                 save_errno = errno;
363                                 perror("mkdir(0755)");
364                                 exit(save_errno);
365                         }
366                         break;
367                 case 'D':
368                         fd = open(fname, O_DIRECTORY);
369                         if (fd == -1) {
370                                 save_errno = errno;
371                                 perror("open(O_DIRECTORY)");
372                                 exit(save_errno);
373                         }
374                         rc = fd;
375                         break;
376                 case 'e':
377                         commands++;
378                         switch (*commands) {
379                         case 'U':
380                                 rc = llapi_lease_release(fd);
381                                 break;
382                         case 'R':
383                                 rc = llapi_lease_acquire(fd, LL_LEASE_RDLCK);
384                                 break;
385                         case 'W':
386                                 rc = llapi_lease_acquire(fd, LL_LEASE_WRLCK);
387                                 break;
388                         default:
389                                 errx(-1, "unknown mode: %c", *commands);
390                         }
391                         if (rc < 0)
392                                 err(errno, "apply/unlock lease error");
393
394                         if (flags != LL_LEASE_UNLCK)
395                                 break;
396
397                         /* F_UNLCK, interpret return code */
398                         if (rc > 0) {
399                                 const char *str = "unknown";
400
401                                 if (rc == LL_LEASE_RDLCK)
402                                         str = "read";
403                                 else if (rc == LL_LEASE_WRLCK)
404                                         str = "write";
405                                 fprintf(stdout, "%s lease(%lld) released.\n",
406                                         str, rc);
407                         } else if (rc == 0) {
408                                 fprintf(stdout, "lease already broken.\n");
409                         }
410                         break;
411                 case 'E':
412                         commands++;
413                         if (*commands != '-' && *commands != '+')
414                                 errx(-1, "unknown mode: %c\n", *commands);
415
416                         rc = llapi_lease_check(fd);
417                         if (rc > 0) {
418                                 const char *str = "unknown";
419
420                                 if (rc == LL_LEASE_RDLCK)
421                                         str = "read";
422                                 else if (rc == LL_LEASE_WRLCK)
423                                         str = "write";
424                                 fprintf(stdout, "%s lease(%lld) has applied.\n",
425                                         str, rc);
426                                 if (*commands == '-')
427                                         errx(-1, "expect lease to not exist");
428                         } else if (rc == 0) {
429                                 fprintf(stdout, "no lease applied.\n");
430                                 if (*commands == '+')
431                                         errx(-1, "expect lease exists");
432                         } else {
433                                 err(errno, "free lease error");
434                         }
435                         break;
436                 case 'f':
437                         if (statfs(fname, &stfs) == -1)
438                                 errx(-1, "statfs()");
439                         break;
440                 case 'F':
441                         if (fd == -1)
442                                 rc = llapi_path2fid(fname, &fid);
443                         else
444                                 rc = llapi_fd2fid(fd, &fid);
445                         if (rc != 0)
446                                 fprintf(stderr,
447                                         "llapi_path/fd2fid() on %d, rc=%lld\n",
448                                         fd, rc);
449                         else
450                                 printf(DFID"\n", PFID(&fid));
451                         fflush(stdout);
452                         break;
453                 case 'G':
454                         gid = atoi(commands + 1);
455                         if (ioctl(fd, LL_IOC_GROUP_LOCK, gid) == -1) {
456                                 save_errno = errno;
457                                 perror("ioctl(GROUP_LOCK)");
458                                 exit(save_errno);
459                         }
460                         break;
461                 case 'g':
462                         gid = atoi(commands + 1);
463                         if (ioctl(fd, LL_IOC_GROUP_UNLOCK, gid) == -1) {
464                                 save_errno = errno;
465                                 perror("ioctl(GROUP_UNLOCK)");
466                                 exit(save_errno);
467                         }
468                         break;
469                 case 'H':
470                         len = atoi(commands + 1);
471                         fd = llapi_file_open(fname, O_CREAT | O_WRONLY, 0644,
472                                              0, 0, len, LOV_PATTERN_RAID0 |
473                                              LOV_PATTERN_F_RELEASED);
474                         if (fd == -1) {
475                                 save_errno = errno;
476                                 perror("create stripe file");
477                                 exit(save_errno);
478                         }
479                         rc = fd;
480                         break;
481                 case 'j':
482                         if (flock(fd, LOCK_EX) == -1)
483                                 errx(-1, "flock()");
484                         break;
485                 case 'K':
486                         oldpath = POP_ARG();
487                         if (!oldpath)
488                                 oldpath = fname;
489
490                         if (link(oldpath, fname)) {
491                                 save_errno = errno;
492                                 perror("link()");
493                                 exit(save_errno);
494                         }
495                         break;
496                 case 'l':
497                         newfile = POP_ARG();
498                         if (!newfile)
499                                 newfile = fname;
500                         if (symlink(fname, newfile)) {
501                                 save_errno = errno;
502                                 perror("symlink()");
503                                 exit(save_errno);
504                         }
505                         break;
506                 case 'L':
507                         newfile = POP_ARG();
508                         if (!newfile)
509                                 newfile = fname;
510
511                         if (link(fname, newfile)) {
512                                 save_errno = errno;
513                                 perror("link()");
514                                 exit(save_errno);
515                         }
516                         break;
517                 case 'm':
518                         if (mknod(fname, S_IFREG | 0644, 0) == -1) {
519                                 save_errno = errno;
520                                 perror("mknod(S_IFREG|0644, 0)");
521                                 exit(save_errno);
522                         }
523                         break;
524                 case 'M':
525                         if (st.st_size == 0) {
526                                 fprintf(stderr,
527                                         "mmap without preceeding stat, or on zero length file.\n");
528                                 exit(-1);
529                         }
530                         mmap_len = st.st_size;
531                         mmap_ptr = mmap(NULL, mmap_len, PROT_WRITE | PROT_READ,
532                                         MAP_SHARED, fd, 0);
533                         if (mmap_ptr == MAP_FAILED) {
534                                 save_errno = errno;
535                                 perror("mmap");
536                                 exit(save_errno);
537                         }
538                         break;
539                 case 'n':
540                         oldpath = POP_ARG();
541                         if (!oldpath)
542                                 oldpath = fname;
543
544                         if (rename(oldpath, fname) < 0) {
545                                 save_errno = errno;
546                                 perror("rename()");
547                                 exit(save_errno);
548                         }
549                         break;
550                 case 'N':
551                         newfile = POP_ARG();
552                         if (!newfile)
553                                 newfile = fname;
554                         if (rename(fname, newfile)) {
555                                 save_errno = errno;
556                                 perror("rename()");
557                                 exit(save_errno);
558                         }
559                         break;
560                 case 'O':
561                         fd = open(fname, O_CREAT | O_RDWR, 0644);
562                         if (fd == -1) {
563                                 save_errno = errno;
564                                 perror("open(O_RDWR|O_CREAT)");
565                                 exit(save_errno);
566                         }
567                         rc = fd;
568                         break;
569                 case 'o':
570                         len = get_flags(commands + 1, &flags);
571                         commands += len;
572                         if (flags & O_CREAT)
573                                 fd = open(fname, flags, 0666);
574                         else
575                                 fd = open(fname, flags);
576                         if (fd == -1) {
577                                 save_errno = errno;
578                                 perror("open");
579                                 exit(save_errno);
580                         }
581                         rc = fd;
582                         break;
583                 case 'p':
584                         printf("%lld\n", last_rc);
585                         break;
586                 case 'Q':
587                         save_errno = statahead(fname);
588                         if (save_errno) {
589                                 perror("statahead");
590                                 exit(save_errno);
591                         }
592                         break;
593                 case 'r':
594                         if (*(commands + 1) == 'u') {
595                                 unaligned = true;
596                                 commands++;
597                         }
598                         len = atoi(commands + 1);
599                         if (len <= 0)
600                                 len = 1;
601                         /* for unaligned, we realloc every time, so the
602                          * buffer alignment is variable
603                          *
604                          * the last condition is "if buf is unaligned", so when
605                          * unaligned is not set, we realloc if the buf is
606                          * unaligned to create an aligned buffer
607                          */
608                         if (bufsize < len || unaligned ||
609                             buf !=
610                             (char *)((long)(buf + ALIGN_LEN) & ~ALIGN_LEN)) {
611                                 void *tmp;
612
613                                 /* We add a margin of + ALIGN_LEN to let us
614                                  * unalign and stay in the buffer
615                                  */
616                                 tmp = realloc(buf, len + ALIGN_LEN*2);
617                                 if (!tmp) {
618                                         free(buf);
619                                         save_errno = errno;
620                                         perror("allocating buf for write\n");
621                                         exit(save_errno);
622                                 }
623                                 buf = tmp;
624                                 bufsize = len;
625                                 buf_align = (char *)((long)(buf + ALIGN_LEN) &
626                                                      ~ALIGN_LEN);
627                                 /* if the original buffer was aligned, we
628                                  * manually unalign it.  Otherwise, we use
629                                  * the unalignment from the allocator.
630                                  *
631                                  * Add + 1 to avoid ever hitting 0, and use
632                                  * mod 255 to avoid 255 + 1 = 256
633                                  */
634                                 if (unaligned && buf_align == buf)
635                                         buf_align += rand() % 255 + 1;
636                                 else if (unaligned)
637                                         buf_align = buf;
638                         }
639
640                         while (len > 0) {
641                                 off_t start, off;
642
643                                 start = lseek(fd, 0, SEEK_CUR);
644                                 rc = read(fd, buf_align, len);
645                                 if (rc == -1) {
646                                         save_errno = errno;
647                                         perror("read");
648                                         exit(save_errno);
649                                 }
650                                 if (rc < len) {
651                                         off = lseek(fd, 0, SEEK_CUR);
652                                         fprintf(stderr, "short read: %ld ->+ %u -> %ld %lld\n",
653                                                 start, len, off, rc);
654                                         if (rc == 0)
655                                                 break;
656                                 }
657                                 len -= rc;
658                                 if (verbose >= 2) {
659                                         printf("Buffer address %s: %p\n",
660                                                 unaligned ? "(unaligned)" : "",
661                                                 buf_align);
662                                         printf("Read this (%lld bytes):\n", rc);
663                                         printf("%.*s\n", (int)rc, buf_align);
664                                 }
665                         }
666                         break;
667                 case 'R':
668                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
669                                 junk += mmap_ptr[i];
670                         break;
671                 case 's':
672                         if (stat(fname, &st) == -1) {
673                                 save_errno = errno;
674                                 perror("stat");
675                                 exit(save_errno);
676                         }
677                         break;
678                 case 'S':
679                         if (fstat(fd, &st) == -1) {
680                                 save_errno = errno;
681                                 perror("fstat");
682                                 exit(save_errno);
683                         }
684                         break;
685                 case 't':
686                         if (fchmod(fd, 0) == -1) {
687                                 save_errno = errno;
688                                 perror("fchmod");
689                                 exit(save_errno);
690                         }
691                         break;
692                 case 'T':
693                         len = atoi(commands + 1);
694                         if (ftruncate(fd, len) == -1) {
695                                 save_errno = errno;
696                                 printf("ftruncate (%d,%d)\n", fd, len);
697                                 perror("ftruncate");
698                                 exit(save_errno);
699                         }
700                         break;
701                 case 'u':
702                         if (unlink(fname) == -1) {
703                                 save_errno = errno;
704                                 perror("unlink");
705                                 exit(save_errno);
706                         }
707                         break;
708                 case 'U':
709                         if (munmap(mmap_ptr, mmap_len)) {
710                                 save_errno = errno;
711                                 perror("munmap");
712                                 exit(save_errno);
713                         }
714                         break;
715                 case 'v':
716                         verbose++;
717                         break;
718                 case 'V':
719                         len = get_flags(commands + 1, &flags);
720                         commands += len;
721                         len = -1; /* mdt index */
722                         if (commands[1] >= '0' && commands[1] <= '9')
723                                 len = atoi(commands + 1);
724                         fd = llapi_create_volatile_idx(fname, len, flags);
725                         if (fd < 0) {
726                                 perror("llapi_create_volatile");
727                                 exit(fd);
728                         }
729                         rc = fd;
730                         break;
731                 case 'w':
732                 case 'P':
733                         if (*(commands + 1) == 'u') {
734                                 unaligned = true;
735                                 commands++;
736                         }
737                         len = atoi(commands + 1);
738                         if (len <= 0)
739                                 len = 1;
740                         /* for unaligned, we realloc every time, so the
741                          * buffer alignment is variable
742                          *
743                          * the last condition is "if buf is unaligned", so when
744                          * unaligned is not set, we realloc if the buf is
745                          * unaligned to create an aligned buffer
746                          */
747                         if (bufsize < len || unaligned ||
748                             buf !=
749                             (char *)((long)(buf + ALIGN_LEN) & ~ALIGN_LEN)) {
750                                 void *tmp;
751
752                                 /* We add a margin of + ALIGN_LEN to let us
753                                  * unalign and stay in the buffer
754                                  */
755                                 tmp = realloc(buf, len + ALIGN_LEN*2);
756                                 if (!tmp) {
757                                         free(buf);
758                                         save_errno = errno;
759                                         perror("allocating buf for write\n");
760                                         exit(save_errno);
761                                 }
762                                 buf = tmp;
763                                 bufsize = len;
764                                 buf_align = (char *)((long)(buf + ALIGN_LEN) &
765                                                      ~ALIGN_LEN);
766                                 /* if the original buffer was aligned, we
767                                  * manually unalign it.  Otherwise, we use
768                                  * the unalignment from the allocator.
769                                  *
770                                  * Add + 1 to avoid ever hitting 0, and use
771                                  * mod 255 to avoid 255 + 1 = 256
772                                  */
773                                 if (unaligned && buf_align == buf)
774                                         buf_align += rand() % 255 + 1;
775                                 else if (unaligned)
776                                         buf_align = buf;
777
778                                 /* fill the buffer with our string */
779                                 while (total_bytes < bufsize) {
780                                         /* msg_len does not include the
781                                          * terminating nul, deliberately,
782                                          * so all the additions are one string
783                                          */
784                                         strncpy(buf_align + total_bytes, msg,
785                                                 bufsize - total_bytes);
786                                         total_bytes += msg_len;
787                                 }
788                         }
789                         while (len > 0) {
790                                 rc = write(fd, buf_align, len);
791                                 if (rc == -1) {
792                                         save_errno = errno;
793                                         perror("write");
794                                         exit(save_errno);
795                                 }
796                                 if (rc < len)
797                                         fprintf(stderr,
798                                                 "short write: %lld/%u\n",
799                                                 rc, len);
800                                 if (commands[0] == 'P')
801                                         break;
802                                 len -= rc;
803                                 if (verbose >= 2) {
804                                         printf("Buffer address %s: %p\n",
805                                                 unaligned ? "(unaligned)" : "",
806                                                 buf_align);
807                                         printf("Wrote this (%lld bytes):\n",
808                                                rc);
809                                         printf("%.*s\n", (int)rc, buf_align);
810                                 }
811                         }
812                         break;
813                 case 'W':
814                         for (i = 0; i < mmap_len && mmap_ptr; i += 4096)
815                                 mmap_ptr[i] += junk++;
816                         break;
817                 case 'x': {
818                         __u64 dv;
819
820                         rc = llapi_get_data_version(fd, &dv, 0);
821                         if (rc) {
822                                 fprintf(stderr,
823                                         "cannot get file data version %lld\n",
824                                         rc);
825                                 exit(-rc);
826                         }
827                         printf("dataversion is %ju\n", (uintmax_t)dv);
828                         break;
829                 }
830                 case 'X': {
831                         __u32 layout_version;
832
833                         rc = llapi_get_ost_layout_version(fd, &layout_version);
834                         if (rc) {
835                                 fprintf(stderr,
836                                         "cannot get ost layout version %lld\n",
837                                         rc);
838                                 exit(-rc);
839                         }
840                         printf("ostlayoutversion: %u\n", layout_version);
841                         break;
842                 }
843                 case 'y':
844                         if (fsync(fd) == -1) {
845                                 save_errno = errno;
846                                 perror("fsync");
847                                 exit(save_errno);
848                         }
849                         break;
850                 case 'Y':
851                         if (fdatasync(fd) == -1) {
852                                 save_errno = errno;
853                                 perror("fdatasync");
854                                 exit(save_errno);
855                         }
856                         break;
857                 case 'z': {
858                         off_t off;
859
860                         len = atoi(commands + 1);
861                         off = lseek(fd, len, SEEK_SET);
862                         if (off == (off_t)-1) {
863                                 save_errno = errno;
864                                 perror("lseek");
865                                 exit(save_errno);
866                         }
867
868                         rc = off;
869                         break;
870                 }
871                 case 'Z': {
872                         off_t off;
873
874                         len = atoi(commands + 1);
875                         off = lseek(fd, len, SEEK_CUR);
876                         if (off == (off_t)-1) {
877                                 save_errno = errno;
878                                 perror("lseek");
879                                 exit(save_errno);
880                         }
881
882                         rc = off;
883                         break;
884                 }
885                 case '-':
886                 case '0':
887                 case '1':
888                 case '2':
889                 case '3':
890                 case '4':
891                 case '5':
892                 case '6':
893                 case '7':
894                 case '8':
895                 case '9':
896                         break;
897                 default:
898                         fprintf(stderr, "unknown command \"%c\"\n", *commands);
899                         fprintf(stderr, usage, argv[0]);
900                         exit(1);
901                 }
902         }
903
904         if (buf)
905                 free(buf);
906
907         return 0;
908 }