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