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