1 /*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
33 #include "global.h"
34 #include <limits.h>
35
36 #define XFS_ERRTAG_MAX 17
37
38 typedef enum {
39 #ifndef NO_XFS
40 OP_ALLOCSP,
41 OP_ATTR_REMOVE,
42 OP_ATTR_SET,
43 OP_BULKSTAT,
44 OP_BULKSTAT1,
45 #endif
46 OP_CHOWN,
47 OP_CREAT,
48 OP_DREAD,
49 OP_DWRITE,
50 OP_FDATASYNC,
51 #ifndef NO_XFS
52 OP_FREESP,
53 #endif
54 OP_FSYNC,
55 OP_GETDENTS,
56 OP_LINK,
57 OP_MKDIR,
58 OP_MKNOD,
59 OP_READ,
60 OP_READLINK,
61 OP_RENAME,
62 #ifndef NO_XFS
63 OP_RESVSP,
64 #endif
65 OP_RMDIR,
66 OP_STAT,
67 OP_SYMLINK,
68 OP_SYNC,
69 OP_TRUNCATE,
70 OP_UNLINK,
71 #ifndef NO_XFS
72 OP_UNRESVSP,
73 #endif
74 OP_WRITE,
75 OP_LAST
76 } opty_t;
77
78 typedef void (*opfnc_t) (int, long);
79
80 typedef struct opdesc {
81 opty_t op;
82 char *name;
83 opfnc_t func;
84 int freq;
85 int iswrite;
86 int isxfs;
87 } opdesc_t;
88
89 typedef struct fent {
90 int id;
91 int parent;
92 } fent_t;
93
94 typedef struct flist {
95 int nfiles;
96 int nslots;
97 int tag;
98 fent_t *fents;
99 } flist_t;
100
101 typedef struct pathname {
102 int len;
103 char *path;
104 } pathname_t;
105
106 #define FT_DIR 0
107 #define FT_DIRm (1 << FT_DIR)
108 #define FT_REG 1
109 #define FT_REGm (1 << FT_REG)
110 #define FT_SYM 2
111 #define FT_SYMm (1 << FT_SYM)
112 #define FT_DEV 3
113 #define FT_DEVm (1 << FT_DEV)
114 #define FT_RTF 4
115 #define FT_RTFm (1 << FT_RTF)
116 #define FT_nft 5
117 #define FT_ANYm ((1 << FT_nft) - 1)
118 #define FT_REGFILE (FT_REGm | FT_RTFm)
119 #define FT_NOTDIR (FT_ANYm & ~FT_DIRm)
120
121 #define FLIST_SLOT_INCR 16
122 #define NDCACHE 64
123
124 #define MAXFSIZE ((1ULL << 63) - 1ULL)
125 #define MAXFSIZE32 ((1ULL << 40) - 1ULL)
126
127 void allocsp_f(int, long);
128 void attr_remove_f(int, long);
129 void attr_set_f(int, long);
130 void bulkstat_f(int, long);
131 void bulkstat1_f(int, long);
132 void chown_f(int, long);
133 void creat_f(int, long);
134 void dread_f(int, long);
135 void dwrite_f(int, long);
136 void fdatasync_f(int, long);
137 void freesp_f(int, long);
138 void fsync_f(int, long);
139 void getdents_f(int, long);
140 void link_f(int, long);
141 void mkdir_f(int, long);
142 void mknod_f(int, long);
143 void read_f(int, long);
144 void readlink_f(int, long);
145 void rename_f(int, long);
146 void resvsp_f(int, long);
147 void rmdir_f(int, long);
148 void stat_f(int, long);
149 void symlink_f(int, long);
150 void sync_f(int, long);
151 void truncate_f(int, long);
152 void unlink_f(int, long);
153 void unresvsp_f(int, long);
154 void write_f(int, long);
155
156 opdesc_t ops[] = {
157 #ifndef NO_XFS
158 {OP_ALLOCSP, "allocsp", allocsp_f, 1, 1, 1},
159 {OP_ATTR_REMOVE, "attr_remove", attr_remove_f, /* 1 */ 0, 1, 1},
160 {OP_ATTR_SET, "attr_set", attr_set_f, /* 2 */ 0, 1, 1},
161 {OP_BULKSTAT, "bulkstat", bulkstat_f, 1, 0, 1},
162 {OP_BULKSTAT1, "bulkstat1", bulkstat1_f, 1, 0, 1},
163 #endif
164 {OP_CHOWN, "chown", chown_f, 3, 1},
165 {OP_CREAT, "creat", creat_f, 4, 1},
166 {OP_DREAD, "dread", dread_f, 4, 0},
167 {OP_DWRITE, "dwrite", dwrite_f, 4, 1},
168 {OP_FDATASYNC, "fdatasync", fdatasync_f, 1, 1},
169 #ifndef NO_XFS
170 {OP_FREESP, "freesp", freesp_f, 1, 1, 1},
171 #endif
172 {OP_FSYNC, "fsync", fsync_f, 1, 1},
173 {OP_GETDENTS, "getdents", getdents_f, 1, 0},
174 {OP_LINK, "link", link_f, 1, 1},
175 {OP_MKDIR, "mkdir", mkdir_f, 2, 1},
176 {OP_MKNOD, "mknod", mknod_f, 2, 1},
177 {OP_READ, "read", read_f, 1, 0},
178 {OP_READLINK, "readlink", readlink_f, 1, 0},
179 {OP_RENAME, "rename", rename_f, 2, 1},
180 #ifndef NO_XFS
181 {OP_RESVSP, "resvsp", resvsp_f, 1, 1, 1},
182 #endif
183 {OP_RMDIR, "rmdir", rmdir_f, 1, 1},
184 {OP_STAT, "stat", stat_f, 1, 0},
185 {OP_SYMLINK, "symlink", symlink_f, 2, 1},
186 {OP_SYNC, "sync", sync_f, 1, 0},
187 {OP_TRUNCATE, "truncate", truncate_f, 2, 1},
188 {OP_UNLINK, "unlink", unlink_f, 1, 1},
189 #ifndef NO_XFS
190 {OP_UNRESVSP, "unresvsp", unresvsp_f, 1, 1, 1},
191 #endif
192 {OP_WRITE, "write", write_f, 4, 1},
193 }, *ops_end;
194
195 flist_t flist[FT_nft] = {
196 {0, 0, 'd', NULL},
197 {0, 0, 'f', NULL},
198 {0, 0, 'l', NULL},
199 {0, 0, 'c', NULL},
200 {0, 0, 'r', NULL},
201 };
202
203 int dcache[NDCACHE];
204 int errrange;
205 int errtag;
206 opty_t *freq_table;
207 int freq_table_size;
208 #ifndef NO_XFS
209 xfs_fsop_geom_t geom;
210 #endif
211 char *homedir;
212 int *ilist;
213 int ilistlen;
214 off64_t maxfsize;
215 char *myprog;
216 int namerand;
217 int nameseq;
218 int nops;
219 int nproc = 1;
220 int operations = 1;
221 int procid;
222 int rtpct;
223 unsigned long seed = 0;
224 ino_t top_ino;
225 int verbose = 0;
226 #ifndef NO_XFS
227 int no_xfs = 0;
228 #else
229 int no_xfs = 1;
230 #endif
231
232 void add_to_flist(int, int, int);
233 void append_pathname(pathname_t *, char *);
234 #ifndef NO_XFS
235 int attr_list_path(pathname_t *, char *, const int, int, attrlist_cursor_t *);
236 int attr_remove_path(pathname_t *, const char *, int);
237 int attr_set_path(pathname_t *, const char *, const char *, const int, int);
238 #endif
239 void check_cwd(void);
240 int creat_path(pathname_t *, mode_t);
241 void dcache_enter(int, int);
242 void dcache_init(void);
243 fent_t *dcache_lookup(int);
244 void dcache_purge(int);
245 void del_from_flist(int, int);
246 int dirid_to_name(char *, int);
247 void doproc(void);
248 void fent_to_name(pathname_t *, flist_t *, fent_t *);
249 void fix_parent(int, int);
250 void free_pathname(pathname_t *);
251 int generate_fname(fent_t *, int, pathname_t *, int *, int *);
252 int get_fname(int, long, pathname_t *, flist_t **, fent_t **, int *);
253 void init_pathname(pathname_t *);
254 int lchown_path(pathname_t *, uid_t, gid_t);
255 int link_path(pathname_t *, pathname_t *);
256 int lstat64_path(pathname_t *, struct stat64 *);
257 void make_freq_table(void);
258 int mkdir_path(pathname_t *, mode_t);
259 int mknod_path(pathname_t *, mode_t, dev_t);
260 void namerandpad(int, char *, int);
261 int open_path(pathname_t *, int);
262 DIR *opendir_path(pathname_t *);
263 void process_freq(char *);
264 int readlink_path(pathname_t *, char *, size_t);
265 int rename_path(pathname_t *, pathname_t *);
266 int rmdir_path(pathname_t *);
267 void separate_pathname(pathname_t *, char *, pathname_t *);
268 void show_ops(int, char *);
269 int stat64_path(pathname_t *, struct stat64 *);
270 int symlink_path(const char *, pathname_t *);
271 int truncate64_path(pathname_t *, off64_t);
272 int unlink_path(pathname_t *);
273 void usage(void);
274 void write_freq(void);
275 void zero_freq(void);
276
main(int argc,char ** argv)277 int main(int argc, char **argv)
278 {
279 char buf[10];
280 int c;
281 char *dirname = NULL;
282 int fd;
283 int i;
284 int cleanup = 0;
285 int loops = 1;
286 int loopcntr = 1;
287 char cmd[256];
288 #ifndef NO_XFS
289 int j;
290 #endif
291 char *p;
292 int stat;
293 struct timeval t;
294 #ifndef NO_XFS
295 ptrdiff_t srval;
296 #endif
297 int nousage = 0;
298 #ifndef NO_XFS
299 xfs_error_injection_t err_inj;
300 #endif
301
302 errrange = errtag = 0;
303 umask(0);
304 nops = sizeof(ops) / sizeof(ops[0]);
305 ops_end = &ops[nops];
306 myprog = argv[0];
307 while ((c = getopt(argc, argv, "cd:e:f:i:l:n:p:rs:vwzHSX")) != -1) {
308 switch (c) {
309 case 'c':
310 /*Don't cleanup */
311 cleanup = 1;
312 break;
313 case 'd':
314 dirname = optarg;
315 break;
316 case 'e':
317 sscanf(optarg, "%d", &errtag);
318 if (errtag < 0) {
319 errtag = -errtag;
320 errrange = 1;
321 } else if (errtag == 0)
322 errtag = -1;
323 if (errtag >= XFS_ERRTAG_MAX) {
324 fprintf(stderr,
325 "error tag %d too large (max %d)\n",
326 errtag, XFS_ERRTAG_MAX - 1);
327 exit(1);
328 }
329 break;
330 case 'f':
331 process_freq(optarg);
332 break;
333 case 'i':
334 ilist = realloc(ilist, ++ilistlen * sizeof(*ilist));
335 ilist[ilistlen - 1] = strtol(optarg, &p, 16);
336 break;
337 case 'l':
338 loops = atoi(optarg);
339 break;
340 case 'n':
341 operations = atoi(optarg);
342 break;
343 case 'p':
344 nproc = atoi(optarg);
345 break;
346 case 'r':
347 namerand = 1;
348 break;
349 case 's':
350 seed = strtoul(optarg, NULL, 0);
351 break;
352 case 'v':
353 verbose = 1;
354 break;
355 case 'w':
356 write_freq();
357 break;
358 case 'z':
359 zero_freq();
360 break;
361 case 'S':
362 show_ops(0, NULL);
363 printf("\n");
364 nousage = 1;
365 break;
366 case '?':
367 fprintf(stderr, "%s - invalid parameters\n", myprog);
368 /* fall through */
369 case 'H':
370 usage();
371 exit(1);
372 case 'X':
373 no_xfs = 1;
374 break;
375 }
376 }
377 while ((loopcntr <= loops) || (loops == 0)) {
378 if (no_xfs && errtag) {
379 fprintf(stderr, "error injection only works on XFS\n");
380 exit(1);
381 }
382
383 if (no_xfs) {
384 int i;
385 for (i = 0; ops + i < ops_end; ++i) {
386 if (ops[i].isxfs)
387 ops[i].freq = 0;
388 }
389 }
390
391 if (!dirname) {
392 /* no directory specified */
393 if (!nousage)
394 usage();
395 exit(1);
396 }
397
398 (void)mkdir(dirname, 0777);
399 if (chdir(dirname) < 0) {
400 perror(dirname);
401 exit(1);
402 }
403 sprintf(buf, "fss%x", getpid());
404 fd = creat(buf, 0666);
405 if (lseek64(fd, (off64_t) (MAXFSIZE32 + 1ULL), SEEK_SET) < 0)
406 maxfsize = (off64_t) MAXFSIZE32;
407 else
408 maxfsize = (off64_t) MAXFSIZE;
409 make_freq_table();
410 dcache_init();
411 setlinebuf(stdout);
412 if (!seed) {
413 gettimeofday(&t, NULL);
414 seed = (int)t.tv_sec ^ (int)t.tv_usec;
415 printf("seed = %ld\n", seed);
416 }
417 #ifndef NO_XFS
418 if (!no_xfs) {
419 i = ioctl(fd, XFS_IOC_FSGEOMETRY, &geom);
420 if (i >= 0 && geom.rtblocks)
421 rtpct = MIN(MAX(geom.rtblocks * 100 /
422 (geom.rtblocks +
423 geom.datablocks), 1), 99);
424 else
425 rtpct = 0;
426 }
427 if (errtag != 0) {
428 if (errrange == 0) {
429 if (errtag <= 0) {
430 srandom(seed);
431 j = random() % 100;
432
433 for (i = 0; i < j; i++)
434 (void)random();
435
436 errtag =
437 (random() % (XFS_ERRTAG_MAX - 1)) +
438 1;
439 }
440 } else {
441 srandom(seed);
442 j = random() % 100;
443
444 for (i = 0; i < j; i++)
445 (void)random();
446
447 errtag +=
448 (random() % (XFS_ERRTAG_MAX - errtag));
449 }
450 printf("Injecting failure on tag #%d\n", errtag);
451 err_inj.errtag = errtag;
452 err_inj.fd = fd;
453 srval = ioctl(fd, XFS_IOC_ERROR_INJECTION, &err_inj);
454 if (srval < -1) {
455 perror
456 ("fsstress - XFS_SYSSGI error injection call");
457 close(fd);
458 unlink(buf);
459 exit(1);
460 }
461 } else
462 #endif
463 close(fd);
464 unlink(buf);
465 if (nproc == 1) {
466 procid = 0;
467 doproc();
468 } else {
469 for (i = 0; i < nproc; i++) {
470 if (fork() == 0) {
471 procid = i;
472 doproc();
473 return 0;
474 }
475 }
476 while (wait(&stat) > 0)
477 continue;
478 }
479 #ifndef NO_XFS
480 if (errtag != 0) {
481 err_inj.errtag = 0;
482 err_inj.fd = fd;
483 if ((srval =
484 ioctl(fd, XFS_IOC_ERROR_CLEARALL,
485 &err_inj)) != 0) {
486 fprintf(stderr, "Bad ej clear on %d (%d).\n",
487 fd, errno);
488 perror
489 ("fsstress - XFS_SYSSGI clear error injection call");
490 close(fd);
491 exit(1);
492 }
493 close(fd);
494 }
495 #endif
496 if (cleanup == 0) {
497 sprintf(cmd, "rm -rf %s/*", dirname);
498 system(cmd);
499 }
500 loopcntr++;
501 }
502 return 0;
503 }
504
add_to_flist(int ft,int id,int parent)505 void add_to_flist(int ft, int id, int parent)
506 {
507 fent_t *fep;
508 flist_t *ftp;
509
510 ftp = &flist[ft];
511 if (ftp->nfiles == ftp->nslots) {
512 ftp->nslots += FLIST_SLOT_INCR;
513 ftp->fents = realloc(ftp->fents, ftp->nslots * sizeof(fent_t));
514 }
515 fep = &ftp->fents[ftp->nfiles++];
516 fep->id = id;
517 fep->parent = parent;
518 }
519
append_pathname(pathname_t * name,char * str)520 void append_pathname(pathname_t * name, char *str)
521 {
522 int len;
523
524 len = strlen(str);
525 #ifdef DEBUG
526 if (len && *str == '/' && name->len == 0) {
527 fprintf(stderr, "fsstress: append_pathname failure\n");
528 chdir(homedir);
529 abort();
530
531 }
532 #endif
533 name->path = realloc(name->path, name->len + 1 + len);
534 strcpy(&name->path[name->len], str);
535 name->len += len;
536 }
537
538 #ifndef NO_XFS
539 int
attr_list_path(pathname_t * name,char * buffer,const int buffersize,int flags,attrlist_cursor_t * cursor)540 attr_list_path(pathname_t * name, char *buffer, const int buffersize, int flags,
541 attrlist_cursor_t * cursor)
542 {
543 char buf[MAXNAMELEN];
544 pathname_t newname;
545 int rval;
546
547 rval = attr_list(name->path, buffer, buffersize, flags, cursor);
548 if (rval >= 0 || errno != ENAMETOOLONG)
549 return rval;
550 separate_pathname(name, buf, &newname);
551 if (chdir(buf) == 0) {
552 rval = attr_list_path(&newname, buffer, buffersize, flags,
553 cursor);
554 chdir("..");
555 }
556 free_pathname(&newname);
557 return rval;
558 }
559
attr_remove_path(pathname_t * name,const char * attrname,int flags)560 int attr_remove_path(pathname_t * name, const char *attrname, int flags)
561 {
562 char buf[MAXNAMELEN];
563 pathname_t newname;
564 int rval;
565
566 rval = attr_remove(name->path, attrname, flags);
567 if (rval >= 0 || errno != ENAMETOOLONG)
568 return rval;
569 separate_pathname(name, buf, &newname);
570 if (chdir(buf) == 0) {
571 rval = attr_remove_path(&newname, attrname, flags);
572 chdir("..");
573 }
574 free_pathname(&newname);
575 return rval;
576 }
577
578 int
attr_set_path(pathname_t * name,const char * attrname,const char * attrvalue,const int valuelength,int flags)579 attr_set_path(pathname_t * name, const char *attrname, const char *attrvalue,
580 const int valuelength, int flags)
581 {
582 char buf[MAXNAMELEN];
583 pathname_t newname;
584 int rval;
585
586 rval = attr_set(name->path, attrname, attrvalue, valuelength, flags);
587 if (rval >= 0 || errno != ENAMETOOLONG)
588 return rval;
589 separate_pathname(name, buf, &newname);
590 if (chdir(buf) == 0) {
591 rval = attr_set_path(&newname, attrname, attrvalue, valuelength,
592 flags);
593 chdir("..");
594 }
595 free_pathname(&newname);
596 return rval;
597 }
598 #endif
599
check_cwd(void)600 void check_cwd(void)
601 {
602 #ifdef DEBUG
603 struct stat64 statbuf;
604
605 if (stat64(".", &statbuf) == 0 && statbuf.st_ino == top_ino)
606 return;
607 chdir(homedir);
608 fprintf(stderr, "fsstress: check_cwd failure\n");
609 abort();
610
611 #endif
612 }
613
creat_path(pathname_t * name,mode_t mode)614 int creat_path(pathname_t * name, mode_t mode)
615 {
616 char buf[MAXNAMELEN];
617 pathname_t newname;
618 int rval;
619
620 rval = creat(name->path, mode);
621 if (rval >= 0 || errno != ENAMETOOLONG)
622 return rval;
623 separate_pathname(name, buf, &newname);
624 if (chdir(buf) == 0) {
625 rval = creat_path(&newname, mode);
626 chdir("..");
627 }
628 free_pathname(&newname);
629 return rval;
630 }
631
dcache_enter(int dirid,int slot)632 void dcache_enter(int dirid, int slot)
633 {
634 dcache[dirid % NDCACHE] = slot;
635 }
636
dcache_init(void)637 void dcache_init(void)
638 {
639 int i;
640
641 for (i = 0; i < NDCACHE; i++)
642 dcache[i] = -1;
643 }
644
dcache_lookup(int dirid)645 fent_t *dcache_lookup(int dirid)
646 {
647 fent_t *fep;
648 int i;
649
650 i = dcache[dirid % NDCACHE];
651 if (i >= 0 && (fep = &flist[FT_DIR].fents[i])->id == dirid)
652 return fep;
653 return NULL;
654 }
655
dcache_purge(int dirid)656 void dcache_purge(int dirid)
657 {
658 int *dcp;
659
660 dcp = &dcache[dirid % NDCACHE];
661 if (*dcp >= 0 && flist[FT_DIR].fents[*dcp].id == dirid)
662 *dcp = -1;
663 }
664
del_from_flist(int ft,int slot)665 void del_from_flist(int ft, int slot)
666 {
667 flist_t *ftp;
668
669 ftp = &flist[ft];
670 if (ft == FT_DIR)
671 dcache_purge(ftp->fents[slot].id);
672 if (slot != ftp->nfiles - 1) {
673 if (ft == FT_DIR)
674 dcache_purge(ftp->fents[ftp->nfiles - 1].id);
675 ftp->fents[slot] = ftp->fents[--ftp->nfiles];
676 } else
677 ftp->nfiles--;
678 }
679
dirid_to_fent(int dirid)680 fent_t *dirid_to_fent(int dirid)
681 {
682 fent_t *efep;
683 fent_t *fep;
684 flist_t *flp;
685
686 if ((fep = dcache_lookup(dirid)))
687 return fep;
688 flp = &flist[FT_DIR];
689 for (fep = flp->fents, efep = &fep[flp->nfiles]; fep < efep; fep++) {
690 if (fep->id == dirid) {
691 dcache_enter(dirid, fep - flp->fents);
692 return fep;
693 }
694 }
695 return NULL;
696 }
697
doproc(void)698 void doproc(void)
699 {
700 struct stat64 statbuf;
701 char buf[10];
702 int opno;
703 int rval;
704 opdesc_t *p;
705
706 sprintf(buf, "p%x", procid);
707 (void)mkdir(buf, 0777);
708 if (chdir(buf) < 0 || stat64(".", &statbuf) < 0) {
709 perror(buf);
710 _exit(1);
711 }
712 top_ino = statbuf.st_ino;
713 homedir = getcwd(NULL, -1);
714 seed += procid;
715 srandom(seed);
716 if (namerand)
717 namerand = random();
718 for (opno = 0; opno < operations; opno++) {
719 p = &ops[freq_table[random() % freq_table_size]];
720 if ((unsigned long)p->func < 4096)
721 abort();
722
723 p->func(opno, random());
724 /*
725 * test for forced shutdown by stat'ing the test
726 * directory. If this stat returns EIO, assume
727 * the forced shutdown happened.
728 */
729 if (errtag != 0 && opno % 100 == 0) {
730 rval = stat64(".", &statbuf);
731 if (rval == EIO) {
732 fprintf(stderr, "Detected EIO\n");
733 return;
734 }
735 }
736 }
737 }
738
fent_to_name(pathname_t * name,flist_t * flp,fent_t * fep)739 void fent_to_name(pathname_t * name, flist_t * flp, fent_t * fep)
740 {
741 char buf[MAXNAMELEN];
742 int i;
743 fent_t *pfep;
744
745 if (fep == NULL)
746 return;
747 if (fep->parent != -1) {
748 pfep = dirid_to_fent(fep->parent);
749 fent_to_name(name, &flist[FT_DIR], pfep);
750 append_pathname(name, "/");
751 }
752 i = sprintf(buf, "%c%x", flp->tag, fep->id);
753 namerandpad(fep->id, buf, i);
754 append_pathname(name, buf);
755 }
756
fix_parent(int oldid,int newid)757 void fix_parent(int oldid, int newid)
758 {
759 fent_t *fep;
760 flist_t *flp;
761 int i;
762 int j;
763
764 for (i = 0, flp = flist; i < FT_nft; i++, flp++) {
765 for (j = 0, fep = flp->fents; j < flp->nfiles; j++, fep++) {
766 if (fep->parent == oldid)
767 fep->parent = newid;
768 }
769 }
770 }
771
free_pathname(pathname_t * name)772 void free_pathname(pathname_t * name)
773 {
774 if (name->path) {
775 free(name->path);
776 name->path = NULL;
777 name->len = 0;
778 }
779 }
780
generate_fname(fent_t * fep,int ft,pathname_t * name,int * idp,int * v)781 int generate_fname(fent_t * fep, int ft, pathname_t * name, int *idp, int *v)
782 {
783 char buf[MAXNAMELEN];
784 flist_t *flp;
785 int id;
786 int j;
787 int len;
788
789 flp = &flist[ft];
790 len = sprintf(buf, "%c%x", flp->tag, id = nameseq++);
791 namerandpad(id, buf, len);
792 if (fep) {
793 fent_to_name(name, &flist[FT_DIR], fep);
794 append_pathname(name, "/");
795 }
796 append_pathname(name, buf);
797 *idp = id;
798 *v = verbose;
799 for (j = 0; !*v && j < ilistlen; j++) {
800 if (ilist[j] == id) {
801 *v = 1;
802 break;
803 }
804 }
805 return 1;
806 }
807
808 int
get_fname(int which,long r,pathname_t * name,flist_t ** flpp,fent_t ** fepp,int * v)809 get_fname(int which, long r, pathname_t * name, flist_t ** flpp, fent_t ** fepp,
810 int *v)
811 {
812 int c;
813 fent_t *fep;
814 flist_t *flp;
815 int i;
816 int j;
817 int x;
818
819 for (i = 0, c = 0, flp = flist; i < FT_nft; i++, flp++) {
820 if (which & (1 << i))
821 c += flp->nfiles;
822 }
823 if (c == 0) {
824 if (flpp)
825 *flpp = NULL;
826 if (fepp)
827 *fepp = NULL;
828 *v = verbose;
829 return 0;
830 }
831 x = (int)(r % c);
832 for (i = 0, c = 0, flp = flist; i < FT_nft; i++, flp++) {
833 if (which & (1 << i)) {
834 if (x < c + flp->nfiles) {
835 fep = &flp->fents[x - c];
836 if (name)
837 fent_to_name(name, flp, fep);
838 if (flpp)
839 *flpp = flp;
840 if (fepp)
841 *fepp = fep;
842 *v = verbose;
843 for (j = 0; !*v && j < ilistlen; j++) {
844 if (ilist[j] == fep->id) {
845 *v = 1;
846 break;
847 }
848 }
849 return 1;
850 }
851 c += flp->nfiles;
852 }
853 }
854 #ifdef DEBUG
855 fprintf(stderr, "fsstress: get_fname failure\n");
856 abort();
857 #endif
858 return -1;
859
860 }
861
init_pathname(pathname_t * name)862 void init_pathname(pathname_t * name)
863 {
864 name->len = 0;
865 name->path = NULL;
866 }
867
lchown_path(pathname_t * name,uid_t owner,gid_t group)868 int lchown_path(pathname_t * name, uid_t owner, gid_t group)
869 {
870 char buf[MAXNAMELEN];
871 pathname_t newname;
872 int rval;
873
874 rval = lchown(name->path, owner, group);
875 if (rval >= 0 || errno != ENAMETOOLONG)
876 return rval;
877 separate_pathname(name, buf, &newname);
878 if (chdir(buf) == 0) {
879 rval = lchown_path(&newname, owner, group);
880 chdir("..");
881 }
882 free_pathname(&newname);
883 return rval;
884 }
885
link_path(pathname_t * name1,pathname_t * name2)886 int link_path(pathname_t * name1, pathname_t * name2)
887 {
888 char buf1[MAXNAMELEN];
889 char buf2[MAXNAMELEN];
890 int down1;
891 pathname_t newname1;
892 pathname_t newname2;
893 int rval;
894
895 rval = link(name1->path, name2->path);
896 if (rval >= 0 || errno != ENAMETOOLONG)
897 return rval;
898 separate_pathname(name1, buf1, &newname1);
899 separate_pathname(name2, buf2, &newname2);
900 if (strcmp(buf1, buf2) == 0) {
901 if (chdir(buf1) == 0) {
902 rval = link_path(&newname1, &newname2);
903 chdir("..");
904 }
905 } else {
906 if (strcmp(buf1, "..") == 0)
907 down1 = 0;
908 else if (strcmp(buf2, "..") == 0)
909 down1 = 1;
910 else if (strlen(buf1) == 0)
911 down1 = 0;
912 else if (strlen(buf2) == 0)
913 down1 = 1;
914 else
915 down1 = MAX(newname1.len, 3 + name2->len) <=
916 MAX(3 + name1->len, newname2.len);
917 if (down1) {
918 free_pathname(&newname2);
919 append_pathname(&newname2, "../");
920 append_pathname(&newname2, name2->path);
921 if (chdir(buf1) == 0) {
922 rval = link_path(&newname1, &newname2);
923 chdir("..");
924 }
925 } else {
926 free_pathname(&newname1);
927 append_pathname(&newname1, "../");
928 append_pathname(&newname1, name1->path);
929 if (chdir(buf2) == 0) {
930 rval = link_path(&newname1, &newname2);
931 chdir("..");
932 }
933 }
934 }
935 free_pathname(&newname1);
936 free_pathname(&newname2);
937 return rval;
938 }
939
lstat64_path(pathname_t * name,struct stat64 * sbuf)940 int lstat64_path(pathname_t * name, struct stat64 *sbuf)
941 {
942 char buf[MAXNAMELEN];
943 pathname_t newname;
944 int rval;
945
946 rval = lstat64(name->path, sbuf);
947 if (rval >= 0 || errno != ENAMETOOLONG)
948 return rval;
949 separate_pathname(name, buf, &newname);
950 if (chdir(buf) == 0) {
951 rval = lstat64_path(&newname, sbuf);
952 chdir("..");
953 }
954 free_pathname(&newname);
955 return rval;
956 }
957
make_freq_table(void)958 void make_freq_table(void)
959 {
960 int f;
961 int i;
962 opdesc_t *p;
963
964 for (p = ops, f = 0; p < ops_end; p++)
965 f += p->freq;
966 freq_table = malloc(f * sizeof(*freq_table));
967 freq_table_size = f;
968 for (p = ops, i = 0; p < ops_end; p++) {
969 for (f = 0; f < p->freq; f++, i++)
970 freq_table[i] = p->op;
971 }
972 }
973
mkdir_path(pathname_t * name,mode_t mode)974 int mkdir_path(pathname_t * name, mode_t mode)
975 {
976 char buf[MAXNAMELEN];
977 pathname_t newname;
978 int rval;
979
980 rval = mkdir(name->path, mode);
981 if (rval >= 0 || errno != ENAMETOOLONG)
982 return rval;
983 separate_pathname(name, buf, &newname);
984 if (chdir(buf) == 0) {
985 rval = mkdir_path(&newname, mode);
986 chdir("..");
987 }
988 free_pathname(&newname);
989 return rval;
990 }
991
mknod_path(pathname_t * name,mode_t mode,dev_t dev)992 int mknod_path(pathname_t * name, mode_t mode, dev_t dev)
993 {
994 char buf[MAXNAMELEN];
995 pathname_t newname;
996 int rval;
997
998 rval = mknod(name->path, mode, dev);
999 if (rval >= 0 || errno != ENAMETOOLONG)
1000 return rval;
1001 separate_pathname(name, buf, &newname);
1002 if (chdir(buf) == 0) {
1003 rval = mknod_path(&newname, mode, dev);
1004 chdir("..");
1005 }
1006 free_pathname(&newname);
1007 return rval;
1008 }
1009
namerandpad(int id,char * buf,int i)1010 void namerandpad(int id, char *buf, int i)
1011 {
1012 int bucket;
1013 static int buckets[] = { 2, 4, 8, 16, 32, 64, 128, MAXNAMELEN - 1 };
1014 int padlen;
1015 int padmod;
1016
1017 if (namerand == 0)
1018 return;
1019 bucket = (id ^ namerand) % (sizeof(buckets) / sizeof(buckets[0]));
1020 padmod = buckets[bucket] + 1 - i;
1021 if (padmod <= 0)
1022 return;
1023 padlen = (id ^ namerand) % padmod;
1024 if (padlen) {
1025 memset(&buf[i], 'X', padlen);
1026 buf[i + padlen] = '\0';
1027 }
1028 }
1029
open_path(pathname_t * name,int oflag)1030 int open_path(pathname_t * name, int oflag)
1031 {
1032 char buf[MAXNAMELEN];
1033 pathname_t newname;
1034 int rval;
1035
1036 rval = open(name->path, oflag);
1037 if (rval >= 0 || errno != ENAMETOOLONG)
1038 return rval;
1039 separate_pathname(name, buf, &newname);
1040 if (chdir(buf) == 0) {
1041 rval = open_path(&newname, oflag);
1042 chdir("..");
1043 }
1044 free_pathname(&newname);
1045 return rval;
1046 }
1047
opendir_path(pathname_t * name)1048 DIR *opendir_path(pathname_t * name)
1049 {
1050 char buf[MAXNAMELEN];
1051 pathname_t newname;
1052 DIR *rval;
1053
1054 rval = opendir(name->path);
1055 if (rval || errno != ENAMETOOLONG)
1056 return rval;
1057 separate_pathname(name, buf, &newname);
1058 if (chdir(buf) == 0) {
1059 rval = opendir_path(&newname);
1060 chdir("..");
1061 }
1062 free_pathname(&newname);
1063 return rval;
1064 }
1065
process_freq(char * arg)1066 void process_freq(char *arg)
1067 {
1068 opdesc_t *p;
1069 char *s;
1070
1071 s = strchr(arg, '=');
1072 if (s == NULL) {
1073 fprintf(stderr, "bad argument '%s'\n", arg);
1074 exit(1);
1075 }
1076 *s++ = '\0';
1077 for (p = ops; p < ops_end; p++) {
1078 if (strcmp(arg, p->name) == 0) {
1079 p->freq = atoi(s);
1080 return;
1081 }
1082 }
1083 fprintf(stderr, "can't find op type %s for -f\n", arg);
1084 exit(1);
1085 }
1086
readlink_path(pathname_t * name,char * lbuf,size_t lbufsiz)1087 int readlink_path(pathname_t * name, char *lbuf, size_t lbufsiz)
1088 {
1089 char buf[MAXNAMELEN];
1090 pathname_t newname;
1091 int rval;
1092
1093 rval = readlink(name->path, lbuf, lbufsiz);
1094 if (rval >= 0 || errno != ENAMETOOLONG)
1095 return rval;
1096 separate_pathname(name, buf, &newname);
1097 if (chdir(buf) == 0) {
1098 rval = readlink_path(&newname, lbuf, lbufsiz);
1099 chdir("..");
1100 }
1101 free_pathname(&newname);
1102 return rval;
1103 }
1104
rename_path(pathname_t * name1,pathname_t * name2)1105 int rename_path(pathname_t * name1, pathname_t * name2)
1106 {
1107 char buf1[MAXNAMELEN];
1108 char buf2[MAXNAMELEN];
1109 int down1;
1110 pathname_t newname1;
1111 pathname_t newname2;
1112 int rval;
1113
1114 rval = rename(name1->path, name2->path);
1115 if (rval >= 0 || errno != ENAMETOOLONG)
1116 return rval;
1117 separate_pathname(name1, buf1, &newname1);
1118 separate_pathname(name2, buf2, &newname2);
1119 if (strcmp(buf1, buf2) == 0) {
1120 if (chdir(buf1) == 0) {
1121 rval = rename_path(&newname1, &newname2);
1122 chdir("..");
1123 }
1124 } else {
1125 if (strcmp(buf1, "..") == 0)
1126 down1 = 0;
1127 else if (strcmp(buf2, "..") == 0)
1128 down1 = 1;
1129 else if (strlen(buf1) == 0)
1130 down1 = 0;
1131 else if (strlen(buf2) == 0)
1132 down1 = 1;
1133 else
1134 down1 = MAX(newname1.len, 3 + name2->len) <=
1135 MAX(3 + name1->len, newname2.len);
1136 if (down1) {
1137 free_pathname(&newname2);
1138 append_pathname(&newname2, "../");
1139 append_pathname(&newname2, name2->path);
1140 if (chdir(buf1) == 0) {
1141 rval = rename_path(&newname1, &newname2);
1142 chdir("..");
1143 }
1144 } else {
1145 free_pathname(&newname1);
1146 append_pathname(&newname1, "../");
1147 append_pathname(&newname1, name1->path);
1148 if (chdir(buf2) == 0) {
1149 rval = rename_path(&newname1, &newname2);
1150 chdir("..");
1151 }
1152 }
1153 }
1154 free_pathname(&newname1);
1155 free_pathname(&newname2);
1156 return rval;
1157 }
1158
rmdir_path(pathname_t * name)1159 int rmdir_path(pathname_t * name)
1160 {
1161 char buf[MAXNAMELEN];
1162 pathname_t newname;
1163 int rval;
1164
1165 rval = rmdir(name->path);
1166 if (rval >= 0 || errno != ENAMETOOLONG)
1167 return rval;
1168 separate_pathname(name, buf, &newname);
1169 if (chdir(buf) == 0) {
1170 rval = rmdir_path(&newname);
1171 chdir("..");
1172 }
1173 free_pathname(&newname);
1174 return rval;
1175 }
1176
separate_pathname(pathname_t * name,char * buf,pathname_t * newname)1177 void separate_pathname(pathname_t * name, char *buf, pathname_t * newname)
1178 {
1179 char *slash;
1180
1181 init_pathname(newname);
1182 slash = strchr(name->path, '/');
1183 if (slash == NULL) {
1184 buf[0] = '\0';
1185 return;
1186 }
1187 *slash = '\0';
1188 strcpy(buf, name->path);
1189 *slash = '/';
1190 append_pathname(newname, slash + 1);
1191 }
1192
1193 #define WIDTH 80
1194
show_ops(int flag,char * lead_str)1195 void show_ops(int flag, char *lead_str)
1196 {
1197 opdesc_t *p;
1198
1199 if (flag < 0) {
1200 /* print in list form */
1201 int x = WIDTH;
1202
1203 for (p = ops; p < ops_end; p++) {
1204 if (lead_str != NULL
1205 && x + strlen(p->name) >= WIDTH - 5)
1206 x = printf("%s%s", (p == ops) ? "" : "\n",
1207 lead_str);
1208 x += printf("%s ", p->name);
1209 }
1210 printf("\n");
1211 } else {
1212 int f;
1213 for (f = 0, p = ops; p < ops_end; p++)
1214 f += p->freq;
1215
1216 if (f == 0)
1217 flag = 1;
1218
1219 for (p = ops; p < ops_end; p++) {
1220 if (flag != 0 || p->freq > 0) {
1221 if (lead_str != NULL)
1222 printf("%s", lead_str);
1223 printf("%20s %d/%d %s\n",
1224 p->name, p->freq, f,
1225 (p->iswrite == 0) ? " " : "write op");
1226 }
1227 }
1228 }
1229 }
1230
stat64_path(pathname_t * name,struct stat64 * sbuf)1231 int stat64_path(pathname_t * name, struct stat64 *sbuf)
1232 {
1233 char buf[MAXNAMELEN];
1234 pathname_t newname;
1235 int rval;
1236
1237 rval = stat64(name->path, sbuf);
1238 if (rval >= 0 || errno != ENAMETOOLONG)
1239 return rval;
1240 separate_pathname(name, buf, &newname);
1241 if (chdir(buf) == 0) {
1242 rval = stat64_path(&newname, sbuf);
1243 chdir("..");
1244 }
1245 free_pathname(&newname);
1246 return rval;
1247 }
1248
symlink_path(const char * name1,pathname_t * name)1249 int symlink_path(const char *name1, pathname_t * name)
1250 {
1251 char buf[MAXNAMELEN];
1252 pathname_t newname;
1253 int rval;
1254
1255 if (!strcmp(name1, name->path)) {
1256 printf("yikes! %s %s\n", name1, name->path);
1257 return 0;
1258 }
1259
1260 rval = symlink(name1, name->path);
1261 if (rval >= 0 || errno != ENAMETOOLONG)
1262 return rval;
1263 separate_pathname(name, buf, &newname);
1264 if (chdir(buf) == 0) {
1265 rval = symlink_path(name1, &newname);
1266 chdir("..");
1267 }
1268 free_pathname(&newname);
1269 return rval;
1270 }
1271
truncate64_path(pathname_t * name,off64_t length)1272 int truncate64_path(pathname_t * name, off64_t length)
1273 {
1274 char buf[MAXNAMELEN];
1275 pathname_t newname;
1276 int rval;
1277
1278 rval = truncate64(name->path, length);
1279 if (rval >= 0 || errno != ENAMETOOLONG)
1280 return rval;
1281 separate_pathname(name, buf, &newname);
1282 if (chdir(buf) == 0) {
1283 rval = truncate64_path(&newname, length);
1284 chdir("..");
1285 }
1286 free_pathname(&newname);
1287 return rval;
1288 }
1289
unlink_path(pathname_t * name)1290 int unlink_path(pathname_t * name)
1291 {
1292 char buf[MAXNAMELEN];
1293 pathname_t newname;
1294 int rval;
1295
1296 rval = unlink(name->path);
1297 if (rval >= 0 || errno != ENAMETOOLONG)
1298 return rval;
1299 separate_pathname(name, buf, &newname);
1300 if (chdir(buf) == 0) {
1301 rval = unlink_path(&newname);
1302 chdir("..");
1303 }
1304 free_pathname(&newname);
1305 return rval;
1306 }
1307
usage(void)1308 void usage(void)
1309 {
1310 printf("Usage: %s -H or\n", myprog);
1311 printf
1312 (" %s [-c][-d dir][-e errtg][-f op_name=freq][-l loops][-n nops]\n",
1313 myprog);
1314 printf(" [-p nproc][-r len][-s seed][-v][-w][-z][-S]\n");
1315 printf("where\n");
1316 printf
1317 (" -c specifies not to remove files(cleanup) after execution\n");
1318 printf
1319 (" -d dir specifies the base directory for operations\n");
1320 printf(" -e errtg specifies error injection stuff\n");
1321 printf
1322 (" -f op_name=freq changes the frequency of option name to freq\n");
1323 printf(" the valid operation names are:\n");
1324 show_ops(-1, " ");
1325 printf
1326 (" -l loops specifies the no. of times the testrun should loop.\n");
1327 printf(" *use 0 for infinite (default 1)\n");
1328 printf
1329 (" -n nops specifies the no. of operations per process (default 1)\n");
1330 printf
1331 (" -p nproc specifies the no. of processes (default 1)\n");
1332 printf(" -r specifies random name padding\n");
1333 printf
1334 (" -s seed specifies the seed for the random generator (default random)\n");
1335 printf(" -v specifies verbose mode\n");
1336 printf
1337 (" -w zeros frequencies of non-write operations\n");
1338 printf(" -z zeros frequencies of all operations\n");
1339 printf
1340 (" -S prints the table of operations (omitting zero frequency)\n");
1341 printf(" -H prints usage and exits\n");
1342 printf
1343 (" -X don't do anything XFS specific (default with -DNO_XFS)\n");
1344 }
1345
write_freq(void)1346 void write_freq(void)
1347 {
1348 opdesc_t *p;
1349
1350 for (p = ops; p < ops_end; p++) {
1351 if (!p->iswrite)
1352 p->freq = 0;
1353 }
1354 }
1355
zero_freq(void)1356 void zero_freq(void)
1357 {
1358 opdesc_t *p;
1359
1360 for (p = ops; p < ops_end; p++)
1361 p->freq = 0;
1362 }
1363
1364 #ifndef NO_XFS
1365
allocsp_f(int opno,long r)1366 void allocsp_f(int opno, long r)
1367 {
1368 int e;
1369 pathname_t f;
1370 int fd;
1371 struct flock64 fl;
1372 int64_t lr;
1373 off64_t off;
1374 struct stat64 stb;
1375 int v;
1376
1377 init_pathname(&f);
1378 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
1379 if (v)
1380 printf("%d/%d: allocsp - no filename\n", procid, opno);
1381 free_pathname(&f);
1382 return;
1383 }
1384 fd = open_path(&f, O_RDWR);
1385 e = fd < 0 ? errno : 0;
1386 check_cwd();
1387 if (fd < 0) {
1388 if (v)
1389 printf("%d/%d: allocsp - open %s failed %d\n",
1390 procid, opno, f.path, e);
1391 free_pathname(&f);
1392 return;
1393 }
1394 if (fstat64(fd, &stb) < 0) {
1395 if (v)
1396 printf("%d/%d: allocsp - fstat64 %s failed %d\n",
1397 procid, opno, f.path, errno);
1398 free_pathname(&f);
1399 close(fd);
1400 return;
1401 }
1402 lr = ((int64_t) random() << 32) + random();
1403 off = (off64_t) (lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
1404 off %= maxfsize;
1405 fl.l_whence = SEEK_SET;
1406 fl.l_start = off;
1407 fl.l_len = 0;
1408 e = ioctl(fd, XFS_IOC_ALLOCSP64, &fl) < 0 ? errno : 0;
1409 if (v)
1410 printf("%d/%d: ioctl(XFS_IOC_ALLOCSP64) %s %lld 0 %d\n",
1411 procid, opno, f.path, off, e);
1412 free_pathname(&f);
1413 close(fd);
1414 }
1415
attr_remove_f(int opno,long r)1416 void attr_remove_f(int opno, long r)
1417 {
1418 attrlist_ent_t *aep;
1419 attrlist_t *alist;
1420 char *aname;
1421 char buf[4096];
1422 attrlist_cursor_t cursor;
1423 int e;
1424 int ent;
1425 pathname_t f;
1426 int total;
1427 int v;
1428 int which;
1429
1430 init_pathname(&f);
1431 if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
1432 append_pathname(&f, ".");
1433 total = 0;
1434 memset(&cursor, 0x00, sizeof(cursor));
1435 do {
1436 e = attr_list_path(&f, buf, sizeof(buf), ATTR_DONTFOLLOW,
1437 &cursor);
1438 check_cwd();
1439 if (e)
1440 break;
1441 alist = (attrlist_t *) buf;
1442 total += alist->al_count;
1443 } while (alist->al_more);
1444 if (total == 0) {
1445 if (v)
1446 printf("%d/%d: attr_remove - no attrs for %s\n",
1447 procid, opno, f.path);
1448 free_pathname(&f);
1449 return;
1450 }
1451 which = (int)(random() % total);
1452 memset(&cursor, 0x00, sizeof(cursor));
1453 ent = 0;
1454 aname = NULL;
1455 do {
1456 e = attr_list_path(&f, buf, sizeof(buf), ATTR_DONTFOLLOW,
1457 &cursor);
1458 check_cwd();
1459 if (e)
1460 break;
1461 alist = (attrlist_t *) buf;
1462 if (which < ent + alist->al_count) {
1463 aep = (attrlist_ent_t *)
1464 & buf[alist->al_offset[which - ent]];
1465 aname = aep->a_name;
1466 break;
1467 }
1468 ent += alist->al_count;
1469 } while (alist->al_more);
1470 if (aname == NULL) {
1471 if (v)
1472 printf("%d/%d: attr_remove - name %d not found at %s\n",
1473 procid, opno, which, f.path);
1474 free_pathname(&f);
1475 return;
1476 }
1477 e = attr_remove_path(&f, aname, ATTR_DONTFOLLOW) < 0 ? errno : 0;
1478 check_cwd();
1479 if (v)
1480 printf("%d/%d: attr_remove %s %s %d\n",
1481 procid, opno, f.path, aname, e);
1482 free_pathname(&f);
1483 }
1484
attr_set_f(int opno,long r)1485 void attr_set_f(int opno, long r)
1486 {
1487 char aname[10];
1488 char *aval;
1489 int e;
1490 pathname_t f;
1491 int len;
1492 static int lengths[] = { 10, 100, 1000, 10000 };
1493 int li;
1494 int v;
1495
1496 init_pathname(&f);
1497 if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
1498 append_pathname(&f, ".");
1499 sprintf(aname, "a%x", nameseq++);
1500 li = (int)(random() % (sizeof(lengths) / sizeof(lengths[0])));
1501 len = (int)(random() % lengths[li]);
1502 if (len == 0)
1503 len = 1;
1504 aval = malloc(len);
1505 memset(aval, nameseq & 0xff, len);
1506 e = attr_set_path(&f, aname, aval, len, ATTR_DONTFOLLOW) < 0 ?
1507 errno : 0;
1508 check_cwd();
1509 free(aval);
1510 if (v)
1511 printf("%d/%d: attr_set %s %s %d\n", procid, opno, f.path,
1512 aname, e);
1513 free_pathname(&f);
1514 }
1515
bulkstat_f(int opno,long r)1516 void bulkstat_f(int opno, long r)
1517 {
1518 int count;
1519 int fd;
1520 __uint64_t last;
1521 int nent;
1522 xfs_bstat_t *t;
1523 int64_t total;
1524 xfs_fsop_bulkreq_t bsr;
1525
1526 last = 0;
1527 nent = (r % 999) + 2;
1528 t = malloc(nent * sizeof(*t));
1529 fd = open(".", O_RDONLY);
1530 total = 0;
1531
1532 bsr.lastip = &last;
1533 bsr.icount = nent;
1534 bsr.ubuffer = t;
1535 bsr.ocount = &count;
1536
1537 while (ioctl(fd, XFS_IOC_FSBULKSTAT, &bsr) == 0 && count > 0)
1538 total += count;
1539 free(t);
1540 if (verbose)
1541 printf("%d/%d: bulkstat nent %d total %lld\n",
1542 procid, opno, nent, total);
1543 close(fd);
1544 }
1545
bulkstat1_f(int opno,long r)1546 void bulkstat1_f(int opno, long r)
1547 {
1548 int e;
1549 pathname_t f;
1550 int fd;
1551 int good;
1552 __uint64_t ino;
1553 struct stat64 s;
1554 xfs_bstat_t t;
1555 int v;
1556 xfs_fsop_bulkreq_t bsr;
1557
1558 good = random() & 1;
1559 if (good) {
1560 /* use an inode we know exists */
1561 init_pathname(&f);
1562 if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
1563 append_pathname(&f, ".");
1564 ino = stat64_path(&f, &s) < 0 ? (ino64_t) r : s.st_ino;
1565 check_cwd();
1566 free_pathname(&f);
1567 } else {
1568 /*
1569 * pick a random inode
1570 *
1571 * note this can generate kernel warning messages
1572 * since bulkstat_one will read the disk block that
1573 * would contain a given inode even if that disk
1574 * block doesn't contain inodes.
1575 *
1576 * this is detected later, but not until after the
1577 * warning is displayed.
1578 *
1579 * "XFS: device 0x825- bad inode magic/vsn daddr 0x0 #0"
1580 *
1581 */
1582 ino = (ino64_t) r;
1583 v = verbose;
1584 }
1585 fd = open(".", O_RDONLY);
1586
1587 bsr.lastip = &ino;
1588 bsr.icount = 1;
1589 bsr.ubuffer = &t;
1590 bsr.ocount = NULL;
1591
1592 e = ioctl(fd, XFS_IOC_FSBULKSTAT_SINGLE, &bsr) < 0 ? errno : 0;
1593 if (v)
1594 printf("%d/%d: bulkstat1 %s ino %lld %d\n",
1595 procid, opno, good ? "real" : "random", (int64_t) ino,
1596 e);
1597 close(fd);
1598 }
1599
1600 #endif
1601
chown_f(int opno,long r)1602 void chown_f(int opno, long r)
1603 {
1604 int e;
1605 pathname_t f;
1606 int nbits;
1607 uid_t u;
1608 int v;
1609
1610 init_pathname(&f);
1611 if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
1612 append_pathname(&f, ".");
1613 u = (uid_t) random();
1614 nbits = (int)(random() % 32);
1615 u &= (1 << nbits) - 1;
1616 e = lchown_path(&f, u, -1) < 0 ? errno : 0;
1617 check_cwd();
1618 if (v)
1619 printf("%d/%d: chown %s %d %d\n", procid, opno, f.path, u, e);
1620 free_pathname(&f);
1621 }
1622
creat_f(int opno,long r)1623 void creat_f(int opno, long r)
1624 {
1625 int e;
1626 int e1;
1627 int extsize;
1628 pathname_t f;
1629 int fd;
1630 fent_t *fep;
1631 int id;
1632 int parid;
1633 int type;
1634 int v;
1635 int v1;
1636 int esz = 0;
1637
1638 if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v1))
1639 parid = -1;
1640 else
1641 parid = fep->id;
1642 init_pathname(&f);
1643 type = rtpct ? ((random() % 100) > rtpct ? FT_REG : FT_RTF) : FT_REG;
1644 if (type == FT_RTF)
1645 extsize = (random() % 10) + 1;
1646 else
1647 extsize = 0;
1648 e = generate_fname(fep, type, &f, &id, &v);
1649 v |= v1;
1650 if (!e) {
1651 if (v) {
1652 fent_to_name(&f, &flist[FT_DIR], fep);
1653 printf("%d/%d: creat - no filename from %s\n",
1654 procid, opno, f.path);
1655 }
1656 free_pathname(&f);
1657 return;
1658 }
1659 fd = creat_path(&f, 0666);
1660 e = fd < 0 ? errno : 0;
1661 e1 = 0;
1662 check_cwd();
1663 esz = 0;
1664 if (fd >= 0) {
1665 #ifndef NO_XFS
1666 struct fsxattr a;
1667 if (extsize && ioctl(fd, XFS_IOC_FSGETXATTR, &a) >= 0) {
1668 a.fsx_xflags |= XFS_XFLAG_REALTIME;
1669 a.fsx_extsize =
1670 geom.rtextsize * geom.blocksize * extsize;
1671 if (ioctl(fd, XFS_IOC_FSSETXATTR, &a) < 0)
1672 e1 = errno;
1673 esz = a.fsx_estsize;
1674
1675 }
1676 #endif
1677 add_to_flist(type, id, parid);
1678 close(fd);
1679 }
1680 if (v)
1681 printf("%d/%d: creat %s x:%d %d %d\n", procid, opno, f.path,
1682 esz, e, e1);
1683 free_pathname(&f);
1684 }
1685
setdirect(int fd)1686 int setdirect(int fd)
1687 {
1688 static int no_direct;
1689 int flags;
1690
1691 if (no_direct)
1692 return 0;
1693
1694 flags = fcntl(fd, F_GETFL, 0);
1695 if (flags < 0)
1696 return 0;
1697
1698 if (fcntl(fd, F_SETFL, flags | O_DIRECT) < 0) {
1699 if (no_xfs) {
1700 no_direct = 1;
1701 return 0;
1702 }
1703 printf("cannot set O_DIRECT: %s\n", strerror(errno));
1704 return 0;
1705 }
1706
1707 return 1;
1708 }
1709
dread_f(int opno,long r)1710 void dread_f(int opno, long r)
1711 {
1712 int64_t align;
1713 char *buf;
1714 struct dioattr diob;
1715 int e;
1716 pathname_t f;
1717 int fd;
1718 size_t len;
1719 int64_t lr;
1720 off64_t off;
1721 struct stat64 stb;
1722 int v;
1723
1724 init_pathname(&f);
1725 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
1726 if (v)
1727 printf("%d/%d: dread - no filename\n", procid, opno);
1728 free_pathname(&f);
1729 return;
1730 }
1731 fd = open_path(&f, O_RDONLY);
1732
1733 if (!setdirect(fd)) {
1734 return;
1735 }
1736
1737 e = fd < 0 ? errno : 0;
1738 check_cwd();
1739 if (fd < 0) {
1740 if (v)
1741 printf("%d/%d: dread - open %s failed %d\n",
1742 procid, opno, f.path, e);
1743 free_pathname(&f);
1744 return;
1745 }
1746 if (fstat64(fd, &stb) < 0) {
1747 if (v)
1748 printf("%d/%d: dread - fstat64 %s failed %d\n",
1749 procid, opno, f.path, errno);
1750 free_pathname(&f);
1751 close(fd);
1752 return;
1753 }
1754 if (stb.st_size == 0) {
1755 if (v)
1756 printf("%d/%d: dread - %s zero size\n", procid, opno,
1757 f.path);
1758 free_pathname(&f);
1759 close(fd);
1760 return;
1761 }
1762
1763 if (no_xfs) {
1764 diob.d_miniosz = stb.st_blksize;
1765 diob.d_maxiosz = stb.st_blksize * 256; /* good number ? */
1766 diob.d_mem = stb.st_blksize;
1767 }
1768 #ifndef NO_XFS
1769 else if (ioctl(fd, XFS_IOC_DIOINFO, &diob) < 0) {
1770 if (v)
1771 printf
1772 ("%d/%d: dread - ioctl(fd, XFS_IOC_DIOINFO) %s failed %d\n",
1773 procid, opno, f.path, errno);
1774 free_pathname(&f);
1775 close(fd);
1776 return;
1777 }
1778 #endif
1779 align = (int64_t) diob.d_miniosz;
1780 lr = ((int64_t) random() << 32) + random();
1781 off = (off64_t) (lr % stb.st_size);
1782 off -= (off % align);
1783 lseek64(fd, off, SEEK_SET);
1784 len = (random() % (getpagesize() * 32)) + 1;
1785 len -= (len % align);
1786 if (len <= 0)
1787 len = align;
1788 else if (len > diob.d_maxiosz)
1789 len = diob.d_maxiosz;
1790 posix_memalign((void **)&buf, diob.d_mem, len);
1791 e = read(fd, buf, len) < 0 ? errno : 0;
1792 free(buf);
1793 if (v)
1794 printf("%d/%d: dread %s [%lld,%ld] %d\n",
1795 procid, opno, f.path, (long long int)off, (long)len, e);
1796 free_pathname(&f);
1797 close(fd);
1798 }
1799
dwrite_f(int opno,long r)1800 void dwrite_f(int opno, long r)
1801 {
1802 int64_t align;
1803 char *buf;
1804 struct dioattr diob;
1805 int e;
1806 pathname_t f;
1807 int fd;
1808 size_t len;
1809 int64_t lr;
1810 off64_t off;
1811 struct stat64 stb;
1812 int v;
1813
1814 init_pathname(&f);
1815 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
1816 if (v)
1817 printf("%d/%d: dwrite - no filename\n", procid, opno);
1818 free_pathname(&f);
1819 return;
1820 }
1821 fd = open_path(&f, O_WRONLY);
1822 e = fd < 0 ? errno : 0;
1823 check_cwd();
1824 if (fd < 0) {
1825 if (v)
1826 printf("%d/%d: dwrite - open %s failed %d\n",
1827 procid, opno, f.path, e);
1828 free_pathname(&f);
1829 return;
1830 }
1831
1832 if (!setdirect(fd))
1833 return;
1834 if (fstat64(fd, &stb) < 0) {
1835 if (v)
1836 printf("%d/%d: dwrite - fstat64 %s failed %d\n",
1837 procid, opno, f.path, errno);
1838 free_pathname(&f);
1839 close(fd);
1840 return;
1841 }
1842 if (no_xfs) {
1843 diob.d_miniosz = stb.st_blksize;
1844 diob.d_maxiosz = stb.st_blksize * 256; /* good number ? */
1845 diob.d_mem = stb.st_blksize;
1846 }
1847 #ifndef NO_XFS
1848 else if (ioctl(fd, XFS_IOC_DIOINFO, &diob) < 0) {
1849 if (v)
1850 printf
1851 ("%d/%d: dwrite - ioctl(fd, XFS_IOC_DIOINFO) %s failed %d\n",
1852 procid, opno, f.path, errno);
1853 free_pathname(&f);
1854 close(fd);
1855 return;
1856 }
1857 #endif
1858 align = (int64_t) diob.d_miniosz;
1859 lr = ((int64_t) random() << 32) + random();
1860 off = (off64_t) (lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
1861 off -= (off % align);
1862 lseek64(fd, off, SEEK_SET);
1863 len = (random() % (getpagesize() * 32)) + 1;
1864 len -= (len % align);
1865 if (len <= 0)
1866 len = align;
1867 else if (len > diob.d_maxiosz)
1868 len = diob.d_maxiosz;
1869 posix_memalign((void **)&buf, diob.d_mem, len);
1870 off %= maxfsize;
1871 lseek64(fd, off, SEEK_SET);
1872 memset(buf, nameseq & 0xff, len);
1873 e = write(fd, buf, len) < 0 ? errno : 0;
1874 free(buf);
1875 if (v)
1876 printf("%d/%d: dwrite %s [%lld,%ld] %d\n",
1877 procid, opno, f.path, (long long)off, (long int)len, e);
1878 free_pathname(&f);
1879 close(fd);
1880 }
1881
fdatasync_f(int opno,long r)1882 void fdatasync_f(int opno, long r)
1883 {
1884 int e;
1885 pathname_t f;
1886 int fd;
1887 int v;
1888
1889 init_pathname(&f);
1890 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
1891 if (v)
1892 printf("%d/%d: fdatasync - no filename\n",
1893 procid, opno);
1894 free_pathname(&f);
1895 return;
1896 }
1897 fd = open_path(&f, O_WRONLY);
1898 e = fd < 0 ? errno : 0;
1899 check_cwd();
1900 if (fd < 0) {
1901 if (v)
1902 printf("%d/%d: fdatasync - open %s failed %d\n",
1903 procid, opno, f.path, e);
1904 free_pathname(&f);
1905 return;
1906 }
1907 e = fdatasync(fd) < 0 ? errno : 0;
1908 if (v)
1909 printf("%d/%d: fdatasync %s %d\n", procid, opno, f.path, e);
1910 free_pathname(&f);
1911 close(fd);
1912 }
1913
1914 #ifndef NO_XFS
freesp_f(int opno,long r)1915 void freesp_f(int opno, long r)
1916 {
1917 int e;
1918 pathname_t f;
1919 int fd;
1920 struct flock64 fl;
1921 int64_t lr;
1922 off64_t off;
1923 struct stat64 stb;
1924 int v;
1925
1926 init_pathname(&f);
1927 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
1928 if (v)
1929 printf("%d/%d: freesp - no filename\n", procid, opno);
1930 free_pathname(&f);
1931 return;
1932 }
1933 fd = open_path(&f, O_RDWR);
1934 e = fd < 0 ? errno : 0;
1935 check_cwd();
1936 if (fd < 0) {
1937 if (v)
1938 printf("%d/%d: freesp - open %s failed %d\n",
1939 procid, opno, f.path, e);
1940 free_pathname(&f);
1941 return;
1942 }
1943 if (fstat64(fd, &stb) < 0) {
1944 if (v)
1945 printf("%d/%d: freesp - fstat64 %s failed %d\n",
1946 procid, opno, f.path, errno);
1947 free_pathname(&f);
1948 close(fd);
1949 return;
1950 }
1951 lr = ((int64_t) random() << 32) + random();
1952 off = (off64_t) (lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
1953 off %= maxfsize;
1954 fl.l_whence = SEEK_SET;
1955 fl.l_start = off;
1956 fl.l_len = 0;
1957 e = ioctl(fd, XFS_IOC_FREESP64, &fl) < 0 ? errno : 0;
1958 if (v)
1959 printf("%d/%d: ioctl(XFS_IOC_FREESP64) %s %lld 0 %d\n",
1960 procid, opno, f.path, off, e);
1961 free_pathname(&f);
1962 close(fd);
1963 }
1964
1965 #endif
1966
fsync_f(int opno,long r)1967 void fsync_f(int opno, long r)
1968 {
1969 int e;
1970 pathname_t f;
1971 int fd;
1972 int v;
1973
1974 init_pathname(&f);
1975 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
1976 if (v)
1977 printf("%d/%d: fsync - no filename\n", procid, opno);
1978 free_pathname(&f);
1979 return;
1980 }
1981 fd = open_path(&f, O_WRONLY);
1982 e = fd < 0 ? errno : 0;
1983 check_cwd();
1984 if (fd < 0) {
1985 if (v)
1986 printf("%d/%d: fsync - open %s failed %d\n",
1987 procid, opno, f.path, e);
1988 free_pathname(&f);
1989 return;
1990 }
1991 e = fsync(fd) < 0 ? errno : 0;
1992 if (v)
1993 printf("%d/%d: fsync %s %d\n", procid, opno, f.path, e);
1994 free_pathname(&f);
1995 close(fd);
1996 }
1997
getdents_f(int opno,long r)1998 void getdents_f(int opno, long r)
1999 {
2000 DIR *dir;
2001 pathname_t f;
2002 int v;
2003
2004 init_pathname(&f);
2005 if (!get_fname(FT_DIRm, r, &f, NULL, NULL, &v))
2006 append_pathname(&f, ".");
2007 dir = opendir_path(&f);
2008 check_cwd();
2009 if (dir == NULL) {
2010 if (v)
2011 printf("%d/%d: getdents - can't open %s\n",
2012 procid, opno, f.path);
2013 free_pathname(&f);
2014 return;
2015 }
2016 while (readdir64(dir) != NULL)
2017 continue;
2018 if (v)
2019 printf("%d/%d: getdents %s 0\n", procid, opno, f.path);
2020 free_pathname(&f);
2021 closedir(dir);
2022 }
2023
link_f(int opno,long r)2024 void link_f(int opno, long r)
2025 {
2026 int e;
2027 pathname_t f;
2028 fent_t *fep;
2029 flist_t *flp;
2030 int id;
2031 pathname_t l;
2032 int parid;
2033 int v;
2034 int v1;
2035
2036 init_pathname(&f);
2037 if (!get_fname(FT_NOTDIR, r, &f, &flp, NULL, &v1)) {
2038 if (v1)
2039 printf("%d/%d: link - no file\n", procid, opno);
2040 free_pathname(&f);
2041 return;
2042 }
2043 if (!get_fname(FT_DIRm, random(), NULL, NULL, &fep, &v))
2044 parid = -1;
2045 else
2046 parid = fep->id;
2047 v |= v1;
2048 init_pathname(&l);
2049 e = generate_fname(fep, flp - flist, &l, &id, &v1);
2050 v |= v1;
2051 if (!e) {
2052 if (v) {
2053 fent_to_name(&l, &flist[FT_DIR], fep);
2054 printf("%d/%d: link - no filename from %s\n",
2055 procid, opno, l.path);
2056 }
2057 free_pathname(&l);
2058 free_pathname(&f);
2059 return;
2060 }
2061 e = link_path(&f, &l) < 0 ? errno : 0;
2062 check_cwd();
2063 if (e == 0)
2064 add_to_flist(flp - flist, id, parid);
2065 if (v)
2066 printf("%d/%d: link %s %s %d\n", procid, opno, f.path, l.path,
2067 e);
2068 free_pathname(&l);
2069 free_pathname(&f);
2070 }
2071
mkdir_f(int opno,long r)2072 void mkdir_f(int opno, long r)
2073 {
2074 int e;
2075 pathname_t f;
2076 fent_t *fep;
2077 int id;
2078 int parid;
2079 int v;
2080 int v1;
2081
2082 if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
2083 parid = -1;
2084 else
2085 parid = fep->id;
2086 init_pathname(&f);
2087 e = generate_fname(fep, FT_DIR, &f, &id, &v1);
2088 v |= v1;
2089 if (!e) {
2090 if (v) {
2091 fent_to_name(&f, &flist[FT_DIR], fep);
2092 printf("%d/%d: mkdir - no filename from %s\n",
2093 procid, opno, f.path);
2094 }
2095 free_pathname(&f);
2096 return;
2097 }
2098 e = mkdir_path(&f, 0777) < 0 ? errno : 0;
2099 check_cwd();
2100 if (e == 0)
2101 add_to_flist(FT_DIR, id, parid);
2102 if (v)
2103 printf("%d/%d: mkdir %s %d\n", procid, opno, f.path, e);
2104 free_pathname(&f);
2105 }
2106
mknod_f(int opno,long r)2107 void mknod_f(int opno, long r)
2108 {
2109 int e;
2110 pathname_t f;
2111 fent_t *fep;
2112 int id;
2113 int parid;
2114 int v;
2115 int v1;
2116
2117 if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
2118 parid = -1;
2119 else
2120 parid = fep->id;
2121 init_pathname(&f);
2122 e = generate_fname(fep, FT_DEV, &f, &id, &v1);
2123 v |= v1;
2124 if (!e) {
2125 if (v) {
2126 fent_to_name(&f, &flist[FT_DIR], fep);
2127 printf("%d/%d: mknod - no filename from %s\n",
2128 procid, opno, f.path);
2129 }
2130 free_pathname(&f);
2131 return;
2132 }
2133 e = mknod_path(&f, S_IFCHR | 0444, 0) < 0 ? errno : 0;
2134 check_cwd();
2135 if (e == 0)
2136 add_to_flist(FT_DEV, id, parid);
2137 if (v)
2138 printf("%d/%d: mknod %s %d\n", procid, opno, f.path, e);
2139 free_pathname(&f);
2140 }
2141
read_f(int opno,long r)2142 void read_f(int opno, long r)
2143 {
2144 char *buf;
2145 int e;
2146 pathname_t f;
2147 int fd;
2148 size_t len;
2149 int64_t lr;
2150 off64_t off;
2151 struct stat64 stb;
2152 int v;
2153
2154 init_pathname(&f);
2155 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
2156 if (v)
2157 printf("%d/%d: read - no filename\n", procid, opno);
2158 free_pathname(&f);
2159 return;
2160 }
2161 fd = open_path(&f, O_RDONLY);
2162 e = fd < 0 ? errno : 0;
2163 check_cwd();
2164 if (fd < 0) {
2165 if (v)
2166 printf("%d/%d: read - open %s failed %d\n",
2167 procid, opno, f.path, e);
2168 free_pathname(&f);
2169 return;
2170 }
2171 if (fstat64(fd, &stb) < 0) {
2172 if (v)
2173 printf("%d/%d: read - fstat64 %s failed %d\n",
2174 procid, opno, f.path, errno);
2175 free_pathname(&f);
2176 close(fd);
2177 return;
2178 }
2179 if (stb.st_size == 0) {
2180 if (v)
2181 printf("%d/%d: read - %s zero size\n", procid, opno,
2182 f.path);
2183 free_pathname(&f);
2184 close(fd);
2185 return;
2186 }
2187 lr = ((int64_t) random() << 32) + random();
2188 off = (off64_t) (lr % stb.st_size);
2189 lseek64(fd, off, SEEK_SET);
2190 len = (random() % (getpagesize() * 32)) + 1;
2191 buf = malloc(len);
2192 e = read(fd, buf, len) < 0 ? errno : 0;
2193 free(buf);
2194 if (v)
2195 printf("%d/%d: read %s [%lld,%ld] %d\n",
2196 procid, opno, f.path, (long long)off, (long int)len, e);
2197 free_pathname(&f);
2198 close(fd);
2199 }
2200
readlink_f(int opno,long r)2201 void readlink_f(int opno, long r)
2202 {
2203 char buf[PATH_MAX];
2204 int e;
2205 pathname_t f;
2206 int v;
2207
2208 init_pathname(&f);
2209 if (!get_fname(FT_SYMm, r, &f, NULL, NULL, &v)) {
2210 if (v)
2211 printf("%d/%d: readlink - no filename\n", procid, opno);
2212 free_pathname(&f);
2213 return;
2214 }
2215 e = readlink_path(&f, buf, PATH_MAX) < 0 ? errno : 0;
2216 check_cwd();
2217 if (v)
2218 printf("%d/%d: readlink %s %d\n", procid, opno, f.path, e);
2219 free_pathname(&f);
2220 }
2221
rename_f(int opno,long r)2222 void rename_f(int opno, long r)
2223 {
2224 fent_t *dfep;
2225 int e;
2226 pathname_t f;
2227 fent_t *fep;
2228 flist_t *flp;
2229 int id;
2230 pathname_t newf;
2231 int oldid;
2232 int parid;
2233 int v;
2234 int v1;
2235
2236 init_pathname(&f);
2237 if (!get_fname(FT_ANYm, r, &f, &flp, &fep, &v1)) {
2238 if (v1)
2239 printf("%d/%d: rename - no filename\n", procid, opno);
2240 free_pathname(&f);
2241 return;
2242 }
2243 if (!get_fname(FT_DIRm, random(), NULL, NULL, &dfep, &v))
2244 parid = -1;
2245 else
2246 parid = dfep->id;
2247 v |= v1;
2248 init_pathname(&newf);
2249 e = generate_fname(dfep, flp - flist, &newf, &id, &v1);
2250 v |= v1;
2251 if (!e) {
2252 if (v) {
2253 fent_to_name(&f, &flist[FT_DIR], dfep);
2254 printf("%d/%d: rename - no filename from %s\n",
2255 procid, opno, f.path);
2256 }
2257 free_pathname(&newf);
2258 free_pathname(&f);
2259 return;
2260 }
2261 e = rename_path(&f, &newf) < 0 ? errno : 0;
2262 check_cwd();
2263 if (e == 0) {
2264 if (flp - flist == FT_DIR) {
2265 oldid = fep->id;
2266 fix_parent(oldid, id);
2267 }
2268 del_from_flist(flp - flist, fep - flp->fents);
2269 add_to_flist(flp - flist, id, parid);
2270 }
2271 if (v)
2272 printf("%d/%d: rename %s to %s %d\n", procid, opno, f.path,
2273 newf.path, e);
2274 free_pathname(&newf);
2275 free_pathname(&f);
2276 }
2277
2278 #ifndef NO_XFS
resvsp_f(int opno,long r)2279 void resvsp_f(int opno, long r)
2280 {
2281 int e;
2282 pathname_t f;
2283 int fd;
2284 struct flock64 fl;
2285 int64_t lr;
2286 off64_t off;
2287 struct stat64 stb;
2288 int v;
2289
2290 init_pathname(&f);
2291 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
2292 if (v)
2293 printf("%d/%d: resvsp - no filename\n", procid, opno);
2294 free_pathname(&f);
2295 return;
2296 }
2297 fd = open_path(&f, O_RDWR);
2298 e = fd < 0 ? errno : 0;
2299 check_cwd();
2300 if (fd < 0) {
2301 if (v)
2302 printf("%d/%d: resvsp - open %s failed %d\n",
2303 procid, opno, f.path, e);
2304 free_pathname(&f);
2305 return;
2306 }
2307 if (fstat64(fd, &stb) < 0) {
2308 if (v)
2309 printf("%d/%d: resvsp - fstat64 %s failed %d\n",
2310 procid, opno, f.path, errno);
2311 free_pathname(&f);
2312 close(fd);
2313 return;
2314 }
2315 lr = ((int64_t) random() << 32) + random();
2316 off = (off64_t) (lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
2317 off %= maxfsize;
2318 fl.l_whence = SEEK_SET;
2319 fl.l_start = off;
2320 fl.l_len = (off64_t) (random() % (1024 * 1024));
2321 e = ioctl(fd, XFS_IOC_RESVSP64, &fl) < 0 ? errno : 0;
2322 if (v)
2323 printf("%d/%d: ioctl(XFS_IOC_RESVSP64) %s %lld %lld %d\n",
2324 procid, opno, f.path, off, fl.l_len, e);
2325 free_pathname(&f);
2326 close(fd);
2327 }
2328 #endif
2329
rmdir_f(int opno,long r)2330 void rmdir_f(int opno, long r)
2331 {
2332 int e;
2333 pathname_t f;
2334 fent_t *fep;
2335 int v;
2336
2337 init_pathname(&f);
2338 if (!get_fname(FT_DIRm, r, &f, NULL, &fep, &v)) {
2339 if (v)
2340 printf("%d/%d: rmdir - no directory\n", procid, opno);
2341 free_pathname(&f);
2342 return;
2343 }
2344 e = rmdir_path(&f) < 0 ? errno : 0;
2345 check_cwd();
2346 if (e == 0)
2347 del_from_flist(FT_DIR, fep - flist[FT_DIR].fents);
2348 if (v)
2349 printf("%d/%d: rmdir %s %d\n", procid, opno, f.path, e);
2350 free_pathname(&f);
2351 }
2352
stat_f(int opno,long r)2353 void stat_f(int opno, long r)
2354 {
2355 int e;
2356 pathname_t f;
2357 struct stat64 stb;
2358 int v;
2359
2360 init_pathname(&f);
2361 if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v)) {
2362 if (v)
2363 printf("%d/%d: stat - no entries\n", procid, opno);
2364 free_pathname(&f);
2365 return;
2366 }
2367 e = lstat64_path(&f, &stb) < 0 ? errno : 0;
2368 check_cwd();
2369 if (v)
2370 printf("%d/%d: stat %s %d\n", procid, opno, f.path, e);
2371 free_pathname(&f);
2372 }
2373
symlink_f(int opno,long r)2374 void symlink_f(int opno, long r)
2375 {
2376 int e;
2377 pathname_t f;
2378 fent_t *fep;
2379 int i;
2380 int id;
2381 int len;
2382 int parid;
2383 int v;
2384 int v1;
2385 char *val;
2386
2387 if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
2388 parid = -1;
2389 else
2390 parid = fep->id;
2391 init_pathname(&f);
2392 e = generate_fname(fep, FT_SYM, &f, &id, &v1);
2393 v |= v1;
2394 if (!e) {
2395 if (v) {
2396 fent_to_name(&f, &flist[FT_DIR], fep);
2397 printf("%d/%d: symlink - no filename from %s\n",
2398 procid, opno, f.path);
2399 }
2400 free_pathname(&f);
2401 return;
2402 }
2403 len = (int)(random() % PATH_MAX);
2404 val = malloc(len + 1);
2405 if (len)
2406 memset(val, 'x', len);
2407 val[len] = '\0';
2408 for (i = 10; i < len - 1; i += 10)
2409 val[i] = '/';
2410 e = symlink_path(val, &f) < 0 ? errno : 0;
2411 check_cwd();
2412 if (e == 0)
2413 add_to_flist(FT_SYM, id, parid);
2414 free(val);
2415 if (v)
2416 printf("%d/%d: symlink %s %d\n", procid, opno, f.path, e);
2417 free_pathname(&f);
2418 }
2419
2420 /* ARGSUSED */
sync_f(int opno,long r)2421 void sync_f(int opno, long r)
2422 {
2423 sync();
2424 if (verbose)
2425 printf("%d/%d: sync\n", procid, opno);
2426 }
2427
truncate_f(int opno,long r)2428 void truncate_f(int opno, long r)
2429 {
2430 int e;
2431 pathname_t f;
2432 int64_t lr;
2433 off64_t off;
2434 struct stat64 stb;
2435 int v;
2436
2437 init_pathname(&f);
2438 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
2439 if (v)
2440 printf("%d/%d: truncate - no filename\n", procid, opno);
2441 free_pathname(&f);
2442 return;
2443 }
2444 e = stat64_path(&f, &stb) < 0 ? errno : 0;
2445 check_cwd();
2446 if (e > 0) {
2447 if (v)
2448 printf("%d/%d: truncate - stat64 %s failed %d\n",
2449 procid, opno, f.path, e);
2450 free_pathname(&f);
2451 return;
2452 }
2453 lr = ((int64_t) random() << 32) + random();
2454 off = (off64_t) (lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
2455 off %= maxfsize;
2456 e = truncate64_path(&f, off) < 0 ? errno : 0;
2457 check_cwd();
2458 if (v)
2459 printf("%d/%d: truncate %s %lld %d\n", procid, opno, f.path,
2460 (long long)off, e);
2461 free_pathname(&f);
2462 }
2463
unlink_f(int opno,long r)2464 void unlink_f(int opno, long r)
2465 {
2466 int e;
2467 pathname_t f;
2468 fent_t *fep;
2469 flist_t *flp;
2470 int v;
2471
2472 init_pathname(&f);
2473 if (!get_fname(FT_NOTDIR, r, &f, &flp, &fep, &v)) {
2474 if (v)
2475 printf("%d/%d: unlink - no file\n", procid, opno);
2476 free_pathname(&f);
2477 return;
2478 }
2479 e = unlink_path(&f) < 0 ? errno : 0;
2480 check_cwd();
2481 if (e == 0)
2482 del_from_flist(flp - flist, fep - flp->fents);
2483 if (v)
2484 printf("%d/%d: unlink %s %d\n", procid, opno, f.path, e);
2485 free_pathname(&f);
2486 }
2487
2488 #ifndef NO_XFS
unresvsp_f(int opno,long r)2489 void unresvsp_f(int opno, long r)
2490 {
2491 int e;
2492 pathname_t f;
2493 int fd;
2494 struct flock64 fl;
2495 int64_t lr;
2496 off64_t off;
2497 struct stat64 stb;
2498 int v;
2499
2500 init_pathname(&f);
2501 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
2502 if (v)
2503 printf("%d/%d: unresvsp - no filename\n", procid, opno);
2504 free_pathname(&f);
2505 return;
2506 }
2507 fd = open_path(&f, O_RDWR);
2508 e = fd < 0 ? errno : 0;
2509 check_cwd();
2510 if (fd < 0) {
2511 if (v)
2512 printf("%d/%d: unresvsp - open %s failed %d\n",
2513 procid, opno, f.path, e);
2514 free_pathname(&f);
2515 return;
2516 }
2517 if (fstat64(fd, &stb) < 0) {
2518 if (v)
2519 printf("%d/%d: unresvsp - fstat64 %s failed %d\n",
2520 procid, opno, f.path, errno);
2521 free_pathname(&f);
2522 close(fd);
2523 return;
2524 }
2525 lr = ((int64_t) random() << 32) + random();
2526 off = (off64_t) (lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
2527 off %= maxfsize;
2528 fl.l_whence = SEEK_SET;
2529 fl.l_start = off;
2530 fl.l_len = (off64_t) (random() % (1 << 20));
2531 e = ioctl(fd, XFS_IOC_UNRESVSP64, &fl) < 0 ? errno : 0;
2532 if (v)
2533 printf("%d/%d: ioctl(XFS_IOC_UNRESVSP64) %s %lld %lld %d\n",
2534 procid, opno, f.path, off, fl.l_len, e);
2535 free_pathname(&f);
2536 close(fd);
2537 }
2538 #endif
2539
write_f(int opno,long r)2540 void write_f(int opno, long r)
2541 {
2542 char *buf;
2543 int e;
2544 pathname_t f;
2545 int fd;
2546 size_t len;
2547 int64_t lr;
2548 off64_t off;
2549 struct stat64 stb;
2550 int v;
2551
2552 init_pathname(&f);
2553 if (!get_fname(FT_REGm, r, &f, NULL, NULL, &v)) {
2554 if (v)
2555 printf("%d/%d: write - no filename\n", procid, opno);
2556 free_pathname(&f);
2557 return;
2558 }
2559 fd = open_path(&f, O_WRONLY);
2560 e = fd < 0 ? errno : 0;
2561 check_cwd();
2562 if (fd < 0) {
2563 if (v)
2564 printf("%d/%d: write - open %s failed %d\n",
2565 procid, opno, f.path, e);
2566 free_pathname(&f);
2567 return;
2568 }
2569 if (fstat64(fd, &stb) < 0) {
2570 if (v)
2571 printf("%d/%d: write - fstat64 %s failed %d\n",
2572 procid, opno, f.path, errno);
2573 free_pathname(&f);
2574 close(fd);
2575 return;
2576 }
2577 lr = ((int64_t) random() << 32) + random();
2578 off = (off64_t) (lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
2579 off %= maxfsize;
2580 lseek64(fd, off, SEEK_SET);
2581 len = (random() % (getpagesize() * 32)) + 1;
2582 buf = malloc(len);
2583 memset(buf, nameseq & 0xff, len);
2584 e = write(fd, buf, len) < 0 ? errno : 0;
2585 free(buf);
2586 if (v)
2587 printf("%d/%d: write %s [%lld,%ld] %d\n",
2588 procid, opno, f.path, (long long)off, (long int)len, e);
2589 free_pathname(&f);
2590 close(fd);
2591 }
2592