2 * Copyright (c) 2000-2002 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #ifdef HAVE_ATTR_XATTR_H
22 #include <attr/xattr.h>
24 #ifdef HAVE_ATTR_ATTRIBUTES_H
25 #include <attr/attributes.h>
27 #ifdef HAVE_LINUX_FIEMAP_H
28 #include <linux/fiemap.h>
31 #include <linux/falloc.h>
32 #ifndef FALLOC_FL_PUNCH_HOLE
33 /* Copy-paste from linux/falloc.h */
34 #define FALLOC_FL_PUNCH_HOLE 0x02 /* de-allocates range */
37 #ifndef HAVE_ATTR_LIST
38 #define attr_list(path, buf, size, flags, cursor) (errno = -ENOSYS, -1)
40 #ifdef HAVE_SYS_PRCTL_H
41 #include <sys/prctl.h>
45 #ifndef FS_IOC_GETFLAGS
46 #define FS_IOC_GETFLAGS _IOR('f', 1, long)
48 #ifndef FS_IOC_SETFLAGS
49 #define FS_IOC_SETFLAGS _IOW('f', 2, long)
53 #define XFS_ERRTAG_MAX 17
54 #define XFS_IDMODULO_MAX 31 /* user/group IDs (1 << x) */
55 #define XFS_PROJIDMODULO_MAX 16 /* project IDs (1 << x) */
57 #define FILELEN_MAX (32*4096)
97 typedef void (*opfnc_t)(int, long);
99 typedef struct opdesc {
107 typedef struct fent {
112 typedef struct flist {
119 typedef struct pathname {
125 #define FT_DIRm (1 << FT_DIR)
127 #define FT_REGm (1 << FT_REG)
129 #define FT_SYMm (1 << FT_SYM)
131 #define FT_DEVm (1 << FT_DEV)
133 #define FT_RTFm (1 << FT_RTF)
135 #define FT_ANYm ((1 << FT_nft) - 1)
136 #define FT_REGFILE (FT_REGm | FT_RTFm)
137 #define FT_NOTDIR (FT_ANYm & ~FT_DIRm)
139 #define FLIST_SLOT_INCR 16
142 #define MAXFSIZE ((1ULL << 63) - 1ULL)
143 #define MAXFSIZE32 ((1ULL << 40) - 1ULL)
145 void allocsp_f(int, long);
146 void attr_remove_f(int, long);
147 void attr_set_f(int, long);
148 void bulkstat_f(int, long);
149 void bulkstat1_f(int, long);
150 void chown_f(int, long);
151 void creat_f(int, long);
152 void dread_f(int, long);
153 void dwrite_f(int, long);
154 void fallocate_f(int, long);
155 void fdatasync_f(int, long);
156 void fiemap_f(int, long);
157 void freesp_f(int, long);
158 void fsync_f(int, long);
159 void getattr_f(int, long);
160 void getdents_f(int, long);
161 void link_f(int, long);
162 void mkdir_f(int, long);
163 void mknod_f(int, long);
164 void punch_f(int, long);
165 void read_f(int, long);
166 void readlink_f(int, long);
167 void rename_f(int, long);
168 void resvsp_f(int, long);
169 void rmdir_f(int, long);
170 void setattr_f(int, long);
171 void setxattr_f(int, long);
172 void stat_f(int, long);
173 void symlink_f(int, long);
174 void sync_f(int, long);
175 void truncate_f(int, long);
176 void unlink_f(int, long);
177 void unresvsp_f(int, long);
178 void write_f(int, long);
181 /* { OP_ENUM, "name", function, freq, iswrite }, */
182 { OP_ALLOCSP, "allocsp", allocsp_f, 1, 1 },
183 { OP_ATTR_REMOVE, "attr_remove", attr_remove_f, /* 1 */ 0, 1 },
184 { OP_ATTR_SET, "attr_set", attr_set_f, /* 2 */ 0, 1 },
185 { OP_BULKSTAT, "bulkstat", bulkstat_f, 1, 0 },
186 { OP_BULKSTAT1, "bulkstat1", bulkstat1_f, 1, 0 },
187 { OP_CHOWN, "chown", chown_f, 3, 1 },
188 { OP_CREAT, "creat", creat_f, 4, 1 },
189 { OP_DREAD, "dread", dread_f, 4, 0 },
190 { OP_DWRITE, "dwrite", dwrite_f, 4, 1 },
191 { OP_FALLOCATE, "fallocate", fallocate_f, 1, 1 },
192 { OP_FDATASYNC, "fdatasync", fdatasync_f, 1, 1 },
193 { OP_FIEMAP, "fiemap", fiemap_f, 1, 1 },
194 { OP_FREESP, "freesp", freesp_f, 1, 1 },
195 { OP_FSYNC, "fsync", fsync_f, 1, 1 },
196 { OP_GETATTR, "getattr", getattr_f, 1, 0 },
197 { OP_GETDENTS, "getdents", getdents_f, 1, 0 },
198 { OP_LINK, "link", link_f, 1, 1 },
199 { OP_MKDIR, "mkdir", mkdir_f, 2, 1 },
200 { OP_MKNOD, "mknod", mknod_f, 2, 1 },
201 { OP_PUNCH, "punch", punch_f, 1, 1 },
202 { OP_READ, "read", read_f, 1, 0 },
203 { OP_READLINK, "readlink", readlink_f, 1, 0 },
204 { OP_RENAME, "rename", rename_f, 2, 1 },
205 { OP_RESVSP, "resvsp", resvsp_f, 1, 1 },
206 { OP_RMDIR, "rmdir", rmdir_f, 1, 1 },
207 { OP_SETATTR, "setattr", setattr_f, 0, 1 },
208 { OP_SETXATTR, "setxattr", setxattr_f, 1, 1 },
209 { OP_STAT, "stat", stat_f, 1, 0 },
210 { OP_SYMLINK, "symlink", symlink_f, 2, 1 },
211 { OP_SYNC, "sync", sync_f, 1, 1 },
212 { OP_TRUNCATE, "truncate", truncate_f, 2, 1 },
213 { OP_UNLINK, "unlink", unlink_f, 1, 1 },
214 { OP_UNRESVSP, "unresvsp", unresvsp_f, 1, 1 },
215 { OP_WRITE, "write", write_f, 4, 1 },
218 flist_t flist[FT_nft] = {
231 xfs_fsop_geom_t geom;
242 unsigned int idmodulo = XFS_IDMODULO_MAX;
243 unsigned int attr_mask = ~0;
246 unsigned long seed = 0;
249 sig_atomic_t should_stop = 0;
250 char *execute_cmd = NULL;
251 int execute_freq = 1;
253 void add_to_flist(int, int, int);
254 void append_pathname(pathname_t *, char *);
255 int attr_list_path(pathname_t *, char *, const int, int, attrlist_cursor_t *);
256 int attr_remove_path(pathname_t *, const char *, int);
257 int attr_set_path(pathname_t *, const char *, const char *, const int, int);
258 void check_cwd(void);
259 int creat_path(pathname_t *, mode_t);
260 void dcache_enter(int, int);
261 void dcache_init(void);
262 fent_t *dcache_lookup(int);
263 void dcache_purge(int);
264 void del_from_flist(int, int);
265 int dirid_to_name(char *, int);
267 int fent_to_name(pathname_t *, flist_t *, fent_t *);
268 void fix_parent(int, int);
269 void free_pathname(pathname_t *);
270 int generate_fname(fent_t *, int, pathname_t *, int *, int *);
271 int get_fname(int, long, pathname_t *, flist_t **, fent_t **, int *);
272 void init_pathname(pathname_t *);
273 int lchown_path(pathname_t *, uid_t, gid_t);
274 int link_path(pathname_t *, pathname_t *);
275 int lstat64_path(pathname_t *, struct stat64 *);
276 void make_freq_table(void);
277 int mkdir_path(pathname_t *, mode_t);
278 int mknod_path(pathname_t *, mode_t, dev_t);
279 void namerandpad(int, char *, int);
280 int open_path(pathname_t *, int);
281 DIR *opendir_path(pathname_t *);
282 void process_freq(char *);
283 int readlink_path(pathname_t *, char *, size_t);
284 int rename_path(pathname_t *, pathname_t *);
285 int rmdir_path(pathname_t *);
286 void separate_pathname(pathname_t *, char *, pathname_t *);
287 void show_ops(int, char *);
288 int stat64_path(pathname_t *, struct stat64 *);
289 int symlink_path(const char *, pathname_t *);
290 int truncate64_path(pathname_t *, off64_t);
291 int unlink_path(pathname_t *);
293 void write_freq(void);
294 void zero_freq(void);
296 void sg_handler(int signum)
301 int main(int argc, char **argv)
305 char *dirname = NULL;
306 char *logname = NULL;
307 char rpath[PATH_MAX];
316 xfs_error_injection_t err_inj;
317 struct sigaction action;
318 const char *allopts = "d:e:f:i:m:M:n:o:p:rs:S:vwx:X:zH";
320 errrange = errtag = 0;
322 nops = sizeof(ops) / sizeof(ops[0]);
323 ops_end = &ops[nops];
325 while ((c = getopt(argc, argv, allopts)) != -1) {
331 sscanf(optarg, "%d", &errtag);
335 } else if (errtag == 0)
337 if (errtag >= XFS_ERRTAG_MAX) {
339 "error tag %d too large (max %d)\n",
340 errtag, XFS_ERRTAG_MAX - 1);
345 process_freq(optarg);
348 ilist = realloc(ilist, ++ilistlen * sizeof(*ilist));
349 ilist[ilistlen - 1] = strtol(optarg, &p, 16);
352 idmodulo = strtoul(optarg, NULL, 0);
353 if (idmodulo > XFS_IDMODULO_MAX) {
355 "chown modulo %d too big (max %d)\n",
356 idmodulo, XFS_IDMODULO_MAX);
361 operations = atoi(optarg);
368 nproc = atoi(optarg);
374 seed = strtoul(optarg, NULL, 0);
383 execute_cmd = optarg;
389 attr_mask = strtoul(optarg, NULL, 0);
393 if (optarg[0] == 'c')
400 execute_freq = strtoul(optarg, NULL, 0);
403 fprintf(stderr, "%s - invalid parameters\n",
413 /* no directory specified */
414 if (!nousage) usage();
418 (void)mkdir(dirname, 0777);
419 if (logname && logname[0] != '/') {
420 if (getcwd(rpath, sizeof(rpath)) < 0){
421 perror("getcwd failed");
427 if (chdir(dirname) < 0) {
433 snprintf(path, sizeof(path), "%s/%s", rpath, logname);
434 if (freopen(path, "a", stdout) == NULL) {
435 perror("freopen logfile failed");
439 sprintf(buf, "fss%x", (unsigned int)getpid());
440 fd = creat(buf, 0666);
441 if (lseek64(fd, (off64_t)(MAXFSIZE32 + 1ULL), SEEK_SET) < 0)
442 maxfsize = (off64_t)MAXFSIZE32;
444 maxfsize = (off64_t)MAXFSIZE;
449 gettimeofday(&t, (void *)NULL);
450 seed = (int)t.tv_sec ^ (int)t.tv_usec;
451 printf("seed = %ld\n", seed);
453 i = xfsctl(buf, fd, XFS_IOC_FSGEOMETRY, &geom);
454 if (i >= 0 && geom.rtblocks)
455 rtpct = MIN(MAX(geom.rtblocks * 100 /
456 (geom.rtblocks + geom.datablocks), 1), 99);
465 for (i = 0; i < j; i++)
468 errtag = (random() % (XFS_ERRTAG_MAX-1)) + 1;
474 for (i = 0; i < j; i++)
477 errtag += (random() % (XFS_ERRTAG_MAX - errtag));
479 printf("Injecting failure on tag #%d\n", errtag);
480 err_inj.errtag = errtag;
482 srval = xfsctl(buf, fd, XFS_IOC_ERROR_INJECTION, &err_inj);
484 perror("fsstress - XFS_SYSSGI error injection call");
493 action.sa_handler = sg_handler;
494 sigemptyset(&action.sa_mask);
496 if (sigaction(SIGTERM, &action, 0)) {
497 perror("sigaction failed");
501 for (i = 0; i < nproc; i++) {
503 action.sa_handler = SIG_DFL;
504 sigemptyset(&action.sa_mask);
505 if (sigaction(SIGTERM, &action, 0))
507 #ifdef HAVE_SYS_PRCTL_H
508 prctl(PR_SET_PDEATHSIG, SIGKILL);
509 if (getppid() == 1) /* parent died already? */
514 snprintf(path, sizeof(path), "%s/%s.%d",
516 if (freopen(path, "a", stdout) == NULL) {
517 perror("freopen logfile failed");
526 while (wait(&stat) > 0 && !should_stop) {
529 action.sa_flags = SA_RESTART;
530 sigaction(SIGTERM, &action, 0);
531 kill(-getpid(), SIGTERM);
532 while (wait(&stat) > 0)
538 srval = xfsctl(buf, fd, XFS_IOC_ERROR_CLEARALL, &err_inj);
540 fprintf(stderr, "Bad ej clear on %s fd=%d (%d).\n",
542 perror("xfsctl(XFS_IOC_ERROR_CLEARALL)");
554 add_to_flist(int ft, int id, int parent)
560 if (ftp->nfiles == ftp->nslots) {
561 ftp->nslots += FLIST_SLOT_INCR;
562 ftp->fents = realloc(ftp->fents, ftp->nslots * sizeof(fent_t));
564 fep = &ftp->fents[ftp->nfiles++];
566 fep->parent = parent;
570 append_pathname(pathname_t *name, char *str)
576 /* attempting to append to a dir a zero length path */
577 if (len && *str == '/' && name->len == 0) {
578 fprintf(stderr, "fsstress: append_pathname failure\n");
584 name->path = realloc(name->path, name->len + 1 + len);
585 strcpy(&name->path[name->len], str);
590 attr_list_path(pathname_t *name,
592 const int buffersize,
594 attrlist_cursor_t *cursor)
596 char buf[NAME_MAX + 1];
600 if (flags != ATTR_DONTFOLLOW) {
605 rval = attr_list(name->path, buffer, buffersize, flags, cursor);
606 if (rval >= 0 || errno != ENAMETOOLONG)
608 separate_pathname(name, buf, &newname);
609 if (chdir(buf) == 0) {
610 rval = attr_list_path(&newname, buffer, buffersize, flags, cursor);
613 free_pathname(&newname);
618 attr_remove_path(pathname_t *name, const char *attrname, int flags)
620 char buf[NAME_MAX + 1];
624 rval = attr_remove(name->path, attrname, flags);
625 if (rval >= 0 || errno != ENAMETOOLONG)
627 separate_pathname(name, buf, &newname);
628 if (chdir(buf) == 0) {
629 rval = attr_remove_path(&newname, attrname, flags);
632 free_pathname(&newname);
637 attr_set_path(pathname_t *name, const char *attrname, const char *attrvalue,
638 const int valuelength, int flags)
640 char buf[NAME_MAX + 1];
644 rval = attr_set(name->path, attrname, attrvalue, valuelength, flags);
645 if (rval >= 0 || errno != ENAMETOOLONG)
647 separate_pathname(name, buf, &newname);
648 if (chdir(buf) == 0) {
649 rval = attr_set_path(&newname, attrname, attrvalue, valuelength,
653 free_pathname(&newname);
661 struct stat64 statbuf;
663 if (stat64(".", &statbuf) == 0 && statbuf.st_ino == top_ino)
666 fprintf(stderr, "fsstress: check_cwd failure\n");
673 creat_path(pathname_t *name, mode_t mode)
675 char buf[NAME_MAX + 1];
679 rval = creat(name->path, mode);
680 if (rval >= 0 || errno != ENAMETOOLONG)
682 separate_pathname(name, buf, &newname);
683 if (chdir(buf) == 0) {
684 rval = creat_path(&newname, mode);
687 free_pathname(&newname);
692 dcache_enter(int dirid, int slot)
694 dcache[dirid % NDCACHE] = slot;
702 for (i = 0; i < NDCACHE; i++)
707 dcache_lookup(int dirid)
712 i = dcache[dirid % NDCACHE];
713 if (i >= 0 && (fep = &flist[FT_DIR].fents[i])->id == dirid)
719 dcache_purge(int dirid)
723 dcp = &dcache[dirid % NDCACHE];
724 if (*dcp >= 0 && flist[FT_DIR].fents[*dcp].id == dirid)
729 * Delete the item from the list by
730 * moving last entry over the deleted one;
731 * unless deleted entry is the last one.
732 * Input: which file list array and which slot in array
735 del_from_flist(int ft, int slot)
741 dcache_purge(ftp->fents[slot].id);
742 if (slot != ftp->nfiles - 1) {
744 dcache_purge(ftp->fents[ftp->nfiles - 1].id);
745 ftp->fents[slot] = ftp->fents[--ftp->nfiles];
751 dirid_to_fent(int dirid)
757 if ((fep = dcache_lookup(dirid)))
759 flp = &flist[FT_DIR];
760 for (fep = flp->fents, efep = &fep[flp->nfiles]; fep < efep; fep++) {
761 if (fep->id == dirid) {
762 dcache_enter(dirid, fep - flp->fents);
772 struct stat64 statbuf;
779 dividend = (operations + execute_freq) / (execute_freq + 1);
780 sprintf(buf, "p%x", procid);
781 (void)mkdir(buf, 0777);
782 if (chdir(buf) < 0 || stat64(".", &statbuf) < 0) {
786 top_ino = statbuf.st_ino;
787 homedir = getcwd(NULL, -1);
792 for (opno = 0; opno < operations; opno++) {
793 if (execute_cmd && opno && opno % dividend == 0) {
795 printf("%d: execute command %s\n", opno,
797 rval = system(execute_cmd);
799 fprintf(stderr, "execute command failed with "
802 p = &ops[freq_table[random() % freq_table_size]];
803 p->func(opno, random());
805 * test for forced shutdown by stat'ing the test
806 * directory. If this stat returns EIO, assume
807 * the forced shutdown happened.
809 if (errtag != 0 && opno % 100 == 0) {
810 rval = stat64(".", &statbuf);
812 fprintf(stderr, "Detected EIO\n");
820 * build up a pathname going thru the file entry and all
822 * Return 0 on error, 1 on success;
825 fent_to_name(pathname_t *name, flist_t *flp, fent_t *fep)
827 char buf[NAME_MAX + 1];
835 /* build up parent directory name */
836 if (fep->parent != -1) {
837 pfep = dirid_to_fent(fep->parent);
840 fprintf(stderr, "%d: fent-id = %d: can't find parent id: %d\n",
841 procid, fep->id, fep->parent);
846 e = fent_to_name(name, &flist[FT_DIR], pfep);
849 append_pathname(name, "/");
852 i = sprintf(buf, "%c%x", flp->tag, fep->id);
853 namerandpad(fep->id, buf, i);
854 append_pathname(name, buf);
859 fix_parent(int oldid, int newid)
866 for (i = 0, flp = flist; i < FT_nft; i++, flp++) {
867 for (j = 0, fep = flp->fents; j < flp->nfiles; j++, fep++) {
868 if (fep->parent == oldid)
875 free_pathname(pathname_t *name)
885 * Generate a filename of type ft.
886 * If we have a fep which should be a directory then use it
887 * as the parent path for this new filename i.e. prepend with it.
890 generate_fname(fent_t *fep, int ft, pathname_t *name, int *idp, int *v)
892 char buf[NAME_MAX + 1];
901 len = sprintf(buf, "%c%x", flp->tag, id = nameseq++);
902 namerandpad(id, buf, len);
904 /* prepend fep parent dir-name to it */
906 e = fent_to_name(name, &flist[FT_DIR], fep);
909 append_pathname(name, "/");
911 append_pathname(name, buf);
915 for (j = 0; !*v && j < ilistlen; j++) {
916 if (ilist[j] == id) {
926 * Input: "which" to choose the file-types eg. non-directory
927 * Input: "r" to choose which file
928 * Output: file-list, file-entry, name for the chosen file.
929 * Output: verbose if chosen file is on the ilist.
932 get_fname(int which, long r, pathname_t *name, flist_t **flpp, fent_t **fepp,
935 int totalsum = 0; /* total number of matching files */
936 int partialsum = 0; /* partial sum of matching files */
942 int e = 1; /* success */
945 * go thru flist and add up number of files for each
946 * category that matches with <which>.
948 for (i = 0, flp = flist; i < FT_nft; i++, flp++) {
949 if (which & (1 << i))
950 totalsum += flp->nfiles;
962 * Now we have possible matches between 0..totalsum-1.
963 * And we use r to help us choose which one we want,
964 * which when bounded by totalsum becomes x.
966 x = (int)(r % totalsum);
967 for (i = 0, flp = flist; i < FT_nft; i++, flp++) {
968 if (which & (1 << i)) {
969 if (x < partialsum + flp->nfiles) {
971 /* found the matching file entry */
972 fep = &flp->fents[x - partialsum];
974 /* fill-in what we were asked for */
976 e = fent_to_name(name, flp, fep);
979 fprintf(stderr, "%d: failed to get path for entry:"
980 " id=%d,parent=%d\n",
981 procid, fep->id, fep->parent);
990 /* turn on verbose if its an ilisted file */
992 for (j = 0; !*v && j < ilistlen; j++) {
993 if (ilist[j] == fep->id) {
1000 partialsum += flp->nfiles;
1004 fprintf(stderr, "fsstress: get_fname failure\n");
1011 init_pathname(pathname_t *name)
1018 lchown_path(pathname_t *name, uid_t owner, gid_t group)
1020 char buf[NAME_MAX + 1];
1024 rval = lchown(name->path, owner, group);
1025 if (rval >= 0 || errno != ENAMETOOLONG)
1027 separate_pathname(name, buf, &newname);
1028 if (chdir(buf) == 0) {
1029 rval = lchown_path(&newname, owner, group);
1032 free_pathname(&newname);
1037 link_path(pathname_t *name1, pathname_t *name2)
1039 char buf1[NAME_MAX + 1];
1040 char buf2[NAME_MAX + 1];
1042 pathname_t newname1;
1043 pathname_t newname2;
1046 rval = link(name1->path, name2->path);
1047 if (rval >= 0 || errno != ENAMETOOLONG)
1049 separate_pathname(name1, buf1, &newname1);
1050 separate_pathname(name2, buf2, &newname2);
1051 if (strcmp(buf1, buf2) == 0) {
1052 if (chdir(buf1) == 0) {
1053 rval = link_path(&newname1, &newname2);
1057 if (strcmp(buf1, "..") == 0)
1059 else if (strcmp(buf2, "..") == 0)
1061 else if (strlen(buf1) == 0)
1063 else if (strlen(buf2) == 0)
1066 down1 = MAX(newname1.len, 3 + name2->len) <=
1067 MAX(3 + name1->len, newname2.len);
1069 free_pathname(&newname2);
1070 append_pathname(&newname2, "../");
1071 append_pathname(&newname2, name2->path);
1072 if (chdir(buf1) == 0) {
1073 rval = link_path(&newname1, &newname2);
1077 free_pathname(&newname1);
1078 append_pathname(&newname1, "../");
1079 append_pathname(&newname1, name1->path);
1080 if (chdir(buf2) == 0) {
1081 rval = link_path(&newname1, &newname2);
1086 free_pathname(&newname1);
1087 free_pathname(&newname2);
1092 lstat64_path(pathname_t *name, struct stat64 *sbuf)
1094 char buf[NAME_MAX + 1];
1098 rval = lstat64(name->path, sbuf);
1099 if (rval >= 0 || errno != ENAMETOOLONG)
1101 separate_pathname(name, buf, &newname);
1102 if (chdir(buf) == 0) {
1103 rval = lstat64_path(&newname, sbuf);
1106 free_pathname(&newname);
1111 make_freq_table(void)
1117 for (p = ops, f = 0; p < ops_end; p++)
1119 freq_table = malloc(f * sizeof(*freq_table));
1120 freq_table_size = f;
1121 for (p = ops, i = 0; p < ops_end; p++) {
1122 for (f = 0; f < p->freq; f++, i++)
1123 freq_table[i] = p->op;
1128 mkdir_path(pathname_t *name, mode_t mode)
1130 char buf[NAME_MAX + 1];
1134 rval = mkdir(name->path, mode);
1135 if (rval >= 0 || errno != ENAMETOOLONG)
1137 separate_pathname(name, buf, &newname);
1138 if (chdir(buf) == 0) {
1139 rval = mkdir_path(&newname, mode);
1142 free_pathname(&newname);
1147 mknod_path(pathname_t *name, mode_t mode, dev_t dev)
1149 char buf[NAME_MAX + 1];
1153 rval = mknod(name->path, mode, dev);
1154 if (rval >= 0 || errno != ENAMETOOLONG)
1156 separate_pathname(name, buf, &newname);
1157 if (chdir(buf) == 0) {
1158 rval = mknod_path(&newname, mode, dev);
1161 free_pathname(&newname);
1166 namerandpad(int id, char *buf, int i)
1169 static int buckets[] =
1170 { 2, 4, 8, 16, 32, 64, 128, NAME_MAX };
1176 bucket = (id ^ namerand) % (sizeof(buckets) / sizeof(buckets[0]));
1177 padmod = buckets[bucket] + 1 - i;
1180 padlen = (id ^ namerand) % padmod;
1182 memset(&buf[i], 'X', padlen);
1183 buf[i + padlen] = '\0';
1188 open_path(pathname_t *name, int oflag)
1190 char buf[NAME_MAX + 1];
1194 rval = open(name->path, oflag);
1195 if (rval >= 0 || errno != ENAMETOOLONG)
1197 separate_pathname(name, buf, &newname);
1198 if (chdir(buf) == 0) {
1199 rval = open_path(&newname, oflag);
1202 free_pathname(&newname);
1207 opendir_path(pathname_t *name)
1209 char buf[NAME_MAX + 1];
1213 rval = opendir(name->path);
1214 if (rval || errno != ENAMETOOLONG)
1216 separate_pathname(name, buf, &newname);
1217 if (chdir(buf) == 0) {
1218 rval = opendir_path(&newname);
1221 free_pathname(&newname);
1226 process_freq(char *arg)
1231 s = strchr(arg, '=');
1233 fprintf(stderr, "bad argument '%s'\n", arg);
1237 for (p = ops; p < ops_end; p++) {
1238 if (strcmp(arg, p->name) == 0) {
1243 fprintf(stderr, "can't find op type %s for -f\n", arg);
1248 readlink_path(pathname_t *name, char *lbuf, size_t lbufsiz)
1250 char buf[NAME_MAX + 1];
1254 rval = readlink(name->path, lbuf, lbufsiz);
1255 if (rval >= 0 || errno != ENAMETOOLONG)
1257 separate_pathname(name, buf, &newname);
1258 if (chdir(buf) == 0) {
1259 rval = readlink_path(&newname, lbuf, lbufsiz);
1262 free_pathname(&newname);
1267 rename_path(pathname_t *name1, pathname_t *name2)
1269 char buf1[NAME_MAX + 1];
1270 char buf2[NAME_MAX + 1];
1272 pathname_t newname1;
1273 pathname_t newname2;
1276 rval = rename(name1->path, name2->path);
1277 if (rval >= 0 || errno != ENAMETOOLONG)
1279 separate_pathname(name1, buf1, &newname1);
1280 separate_pathname(name2, buf2, &newname2);
1281 if (strcmp(buf1, buf2) == 0) {
1282 if (chdir(buf1) == 0) {
1283 rval = rename_path(&newname1, &newname2);
1287 if (strcmp(buf1, "..") == 0)
1289 else if (strcmp(buf2, "..") == 0)
1291 else if (strlen(buf1) == 0)
1293 else if (strlen(buf2) == 0)
1296 down1 = MAX(newname1.len, 3 + name2->len) <=
1297 MAX(3 + name1->len, newname2.len);
1299 free_pathname(&newname2);
1300 append_pathname(&newname2, "../");
1301 append_pathname(&newname2, name2->path);
1302 if (chdir(buf1) == 0) {
1303 rval = rename_path(&newname1, &newname2);
1307 free_pathname(&newname1);
1308 append_pathname(&newname1, "../");
1309 append_pathname(&newname1, name1->path);
1310 if (chdir(buf2) == 0) {
1311 rval = rename_path(&newname1, &newname2);
1316 free_pathname(&newname1);
1317 free_pathname(&newname2);
1322 rmdir_path(pathname_t *name)
1324 char buf[NAME_MAX + 1];
1328 rval = rmdir(name->path);
1329 if (rval >= 0 || errno != ENAMETOOLONG)
1331 separate_pathname(name, buf, &newname);
1332 if (chdir(buf) == 0) {
1333 rval = rmdir_path(&newname);
1336 free_pathname(&newname);
1341 separate_pathname(pathname_t *name, char *buf, pathname_t *newname)
1345 init_pathname(newname);
1346 slash = strchr(name->path, '/');
1347 if (slash == NULL) {
1352 strcpy(buf, name->path);
1354 append_pathname(newname, slash + 1);
1360 show_ops(int flag, char *lead_str)
1365 /* print in list form */
1368 for (p = ops; p < ops_end; p++) {
1369 if (lead_str != NULL && x+strlen(p->name)>=WIDTH-5)
1370 x=printf("%s%s", (p==ops)?"":"\n", lead_str);
1371 x+=printf("%s ", p->name);
1374 } else if (flag == 0) {
1375 /* Table view style */
1377 for (f = 0, p = ops; p < ops_end; p++)
1383 for (p = ops; p < ops_end; p++) {
1384 if (flag != 0 || p->freq > 0) {
1385 if (lead_str != NULL)
1386 printf("%s", lead_str);
1387 printf("%20s %d/%d %s\n",
1388 p->name, p->freq, f,
1389 (p->iswrite == 0) ? " " : "write op");
1393 /* Command line style */
1394 if (lead_str != NULL)
1395 printf("%s", lead_str);
1396 printf ("-z -s %ld -m %d -n %d -p %d \\\n", seed, idmodulo,
1398 for (p = ops; p < ops_end; p++)
1400 printf("-f %s=%d \\\n",p->name, p->freq);
1405 stat64_path(pathname_t *name, struct stat64 *sbuf)
1407 char buf[NAME_MAX + 1];
1411 rval = stat64(name->path, sbuf);
1412 if (rval >= 0 || errno != ENAMETOOLONG)
1414 separate_pathname(name, buf, &newname);
1415 if (chdir(buf) == 0) {
1416 rval = stat64_path(&newname, sbuf);
1419 free_pathname(&newname);
1424 symlink_path(const char *name1, pathname_t *name)
1426 char buf[NAME_MAX + 1];
1430 if (!strcmp(name1, name->path)) {
1431 printf("yikes! %s %s\n", name1, name->path);
1435 rval = symlink(name1, name->path);
1436 if (rval >= 0 || errno != ENAMETOOLONG)
1438 separate_pathname(name, buf, &newname);
1439 if (chdir(buf) == 0) {
1440 rval = symlink_path(name1, &newname);
1443 free_pathname(&newname);
1448 truncate64_path(pathname_t *name, off64_t length)
1450 char buf[NAME_MAX + 1];
1454 rval = truncate64(name->path, length);
1455 if (rval >= 0 || errno != ENAMETOOLONG)
1457 separate_pathname(name, buf, &newname);
1458 if (chdir(buf) == 0) {
1459 rval = truncate64_path(&newname, length);
1462 free_pathname(&newname);
1467 unlink_path(pathname_t *name)
1469 char buf[NAME_MAX + 1];
1473 rval = unlink(name->path);
1474 if (rval >= 0 || errno != ENAMETOOLONG)
1476 separate_pathname(name, buf, &newname);
1477 if (chdir(buf) == 0) {
1478 rval = unlink_path(&newname);
1481 free_pathname(&newname);
1488 printf("Usage: %s -H or\n", myprog);
1489 printf(" %s [-d dir][-e errtg][-f op_name=freq][-n nops]\n",
1491 printf(" [-p nproc][-r len][-s seed][-v][-w][-x cmd][-z][-S][-X ncmd]\n");
1493 printf(" -d dir specifies the base directory for operations\n");
1494 printf(" -e errtg specifies error injection stuff\n");
1495 printf(" -f op_name=freq changes the frequency of option name to freq\n");
1496 printf(" the valid operation names are:\n");
1497 printf(" -i filenum get verbose output for this nth file object\n");
1499 printf(" -m modulo uid/gid modulo for chown/chgrp (default 32)\n");
1500 printf(" -n nops specifies the no. of operations per process (default 1)\n");
1501 printf(" -p nproc specifies the no. of processes (default 1)\n");
1502 printf(" -r specifies random name padding\n");
1503 printf(" -s seed specifies the seed for the random generator (default random)\n");
1504 printf(" -v specifies verbose mode\n");
1505 printf(" -w zeros frequencies of non-write operations\n");
1506 printf(" -x cmd execute command in the middle of operations\n");
1507 printf(" -z zeros frequencies of all operations\n");
1508 printf(" -S [c,t] prints the list of operations (omitting zero frequency) in command line or table style\n");
1509 printf(" -X ncmd number of calls to the -x command (default 1)\n");
1510 printf(" -H prints usage and exits\n");
1518 for (p = ops; p < ops_end; p++) {
1529 for (p = ops; p < ops_end; p++)
1533 void inode_info(char *str, size_t sz, struct stat64 *s, int verbose)
1536 snprintf(str, sz, "[%ld %ld %d %d %lld %lld]", (long)s->st_ino,
1537 (long)s->st_nlink, s->st_uid, s->st_gid,
1538 (long long) s->st_blocks, (long long) s->st_size);
1542 allocsp_f(int opno, long r)
1547 struct xfs_flock64 fl;
1555 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
1557 printf("%d/%d: allocsp - no filename\n", procid, opno);
1561 fd = open_path(&f, O_RDWR);
1562 e = fd < 0 ? errno : 0;
1566 printf("%d/%d: allocsp - open %s failed %d\n",
1567 procid, opno, f.path, e);
1571 if (fstat64(fd, &stb) < 0) {
1573 printf("%d/%d: allocsp - fstat64 %s failed %d\n",
1574 procid, opno, f.path, errno);
1579 inode_info(st, sizeof(st), &stb, v);
1580 lr = ((__int64_t)random() << 32) + random();
1581 off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
1583 fl.l_whence = SEEK_SET;
1586 e = xfsctl(f.path, fd, XFS_IOC_ALLOCSP64, &fl) < 0 ? errno : 0;
1588 printf("%d/%d: xfsctl(XFS_IOC_ALLOCSP64) %s%s %lld 0 %d\n",
1589 procid, opno, f.path, st, (long long)off, e);
1596 attr_remove_f(int opno, long r)
1598 attrlist_ent_t *aep;
1602 attrlist_cursor_t cursor;
1611 if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
1612 append_pathname(&f, ".");
1614 bzero(&cursor, sizeof(cursor));
1616 bzero(buf, sizeof(buf));
1617 e = attr_list_path(&f, buf, sizeof(buf), ATTR_DONTFOLLOW, &cursor);
1621 alist = (attrlist_t *)buf;
1622 total += alist->al_count;
1623 } while (alist->al_more);
1626 printf("%d/%d: attr_remove - no attrs for %s\n",
1627 procid, opno, f.path);
1631 which = (int)(random() % total);
1632 bzero(&cursor, sizeof(cursor));
1636 bzero(buf, sizeof(buf));
1637 e = attr_list_path(&f, buf, sizeof(buf), ATTR_DONTFOLLOW, &cursor);
1641 alist = (attrlist_t *)buf;
1642 if (which < ent + alist->al_count) {
1643 aep = (attrlist_ent_t *)
1644 &buf[alist->al_offset[which - ent]];
1645 aname = aep->a_name;
1648 ent += alist->al_count;
1649 } while (alist->al_more);
1650 if (aname == NULL) {
1653 "%d/%d: attr_remove - name %d not found at %s\n",
1654 procid, opno, which, f.path);
1658 e = attr_remove_path(&f, aname, ATTR_DONTFOLLOW) < 0 ? errno : 0;
1661 printf("%d/%d: attr_remove %s %s %d\n",
1662 procid, opno, f.path, aname, e);
1667 attr_set_f(int opno, long r)
1674 static int lengths[] = { 10, 100, 1000, 10000 };
1679 if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
1680 append_pathname(&f, ".");
1681 sprintf(aname, "a%x", nameseq++);
1682 li = (int)(random() % (sizeof(lengths) / sizeof(lengths[0])));
1683 len = (int)(random() % lengths[li]);
1687 memset(aval, nameseq & 0xff, len);
1688 e = attr_set_path(&f, aname, aval, len, ATTR_DONTFOLLOW) < 0 ?
1693 printf("%d/%d: attr_set %s %s %d\n", procid, opno, f.path,
1699 bulkstat_f(int opno, long r)
1707 xfs_fsop_bulkreq_t bsr;
1710 nent = (r % 999) + 2;
1711 t = malloc(nent * sizeof(*t));
1712 fd = open(".", O_RDONLY);
1720 while (xfsctl(".", fd, XFS_IOC_FSBULKSTAT, &bsr) == 0 && count > 0)
1724 printf("%d/%d: bulkstat nent %d total %lld\n",
1725 procid, opno, nent, (long long)total);
1730 bulkstat1_f(int opno, long r)
1740 xfs_fsop_bulkreq_t bsr;
1743 good = random() & 1;
1745 /* use an inode we know exists */
1747 if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
1748 append_pathname(&f, ".");
1749 ino = stat64_path(&f, &s) < 0 ? (ino64_t)r : s.st_ino;
1754 * pick a random inode
1756 * note this can generate kernel warning messages
1757 * since bulkstat_one will read the disk block that
1758 * would contain a given inode even if that disk
1759 * block doesn't contain inodes.
1761 * this is detected later, but not until after the
1762 * warning is displayed.
1764 * "XFS: device 0x825- bad inode magic/vsn daddr 0x0 #0"
1770 fd = open(".", O_RDONLY);
1777 e = xfsctl(".", fd, XFS_IOC_FSBULKSTAT_SINGLE, &bsr) < 0 ? errno : 0;
1779 printf("%d/%d: bulkstat1 %s ino %lld %d\n",
1780 procid, opno, good?"real":"random", (long long)ino, e);
1785 chown_f(int opno, long r)
1795 if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
1796 append_pathname(&f, ".");
1797 u = (uid_t)random();
1798 g = (gid_t)random();
1799 nbits = (int)(random() % idmodulo);
1800 u &= (1 << nbits) - 1;
1801 g &= (1 << nbits) - 1;
1802 e = lchown_path(&f, u, g) < 0 ? errno : 0;
1805 printf("%d/%d: chown %s %d/%d %d\n", procid, opno, f.path, (int)u, (int)g, e);
1810 setxattr_f(int opno, long r)
1812 #ifdef XFS_XFLAG_EXTSIZE
1822 if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
1823 append_pathname(&f, ".");
1824 fd = open_path(&f, O_RDWR);
1825 e = fd < 0 ? errno : 0;
1830 e = MIN(idmodulo, XFS_PROJIDMODULO_MAX);
1831 nbits = (int)(random() % e);
1832 p &= (1 << nbits) - 1;
1834 if ((e = xfsctl(f.path, fd, XFS_IOC_FSGETXATTR, &fsx)) == 0) {
1836 e = xfsctl(f.path, fd, XFS_IOC_FSSETXATTR, &fsx);
1839 printf("%d/%d: setxattr %s %u %d\n", procid, opno, f.path, p, e);
1846 creat_f(int opno, long r)
1861 if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v1))
1866 e1 = (random() % 100);
1867 type = rtpct ? ((e1 > rtpct) ? FT_REG : FT_RTF) : FT_REG;
1869 if (type == FT_RTF) /* rt always gets an extsize */
1870 extsize = (random() % 10) + 1;
1871 else if (e1 < 10) /* one-in-ten get an extsize */
1872 extsize = random() % 1024;
1876 e = generate_fname(fep, type, &f, &id, &v);
1880 (void)fent_to_name(&f, &flist[FT_DIR], fep);
1881 printf("%d/%d: creat - no filename from %s\n",
1882 procid, opno, f.path);
1887 fd = creat_path(&f, 0666);
1888 e = fd < 0 ? errno : 0;
1893 xfsctl(f.path, fd, XFS_IOC_FSGETXATTR, &a) >= 0) {
1894 if (type == FT_RTF) {
1895 a.fsx_xflags |= XFS_XFLAG_REALTIME;
1896 a.fsx_extsize = extsize *
1897 geom.rtextsize * geom.blocksize;
1899 } else if (extsize) {
1900 a.fsx_xflags |= XFS_XFLAG_EXTSIZE;
1901 a.fsx_extsize = extsize * geom.blocksize;
1904 if (xfsctl(f.path, fd, XFS_IOC_FSSETXATTR, &a) < 0)
1907 add_to_flist(type, id, parid);
1911 printf("%d/%d: creat %s x:%d %d %d\n", procid, opno, f.path,
1912 extsize ? a.fsx_extsize : 0, e, e1);
1913 printf("%d/%d: creat add id=%d,parent=%d\n", procid, opno, id, parid);
1919 dread_f(int opno, long r)
1923 struct dioattr diob;
1935 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
1937 printf("%d/%d: dread - no filename\n", procid, opno);
1941 fd = open_path(&f, O_RDONLY|O_DIRECT);
1942 e = fd < 0 ? errno : 0;
1946 printf("%d/%d: dread - open %s failed %d\n",
1947 procid, opno, f.path, e);
1951 if (fstat64(fd, &stb) < 0) {
1953 printf("%d/%d: dread - fstat64 %s failed %d\n",
1954 procid, opno, f.path, errno);
1959 inode_info(st, sizeof(st), &stb, v);
1960 if (stb.st_size == 0) {
1962 printf("%d/%d: dread - %s%s zero size\n", procid, opno,
1968 if (xfsctl(f.path, fd, XFS_IOC_DIOINFO, &diob) < 0) {
1971 "%d/%d: dread - xfsctl(XFS_IOC_DIOINFO) %s%s failed %d\n",
1972 procid, opno, f.path, st, errno);
1977 align = (__int64_t)diob.d_miniosz;
1978 lr = ((__int64_t)random() << 32) + random();
1979 off = (off64_t)(lr % stb.st_size);
1980 off -= (off % align);
1981 lseek64(fd, off, SEEK_SET);
1982 len = (random() % FILELEN_MAX) + 1;
1983 len -= (len % align);
1986 else if (len > diob.d_maxiosz)
1987 len = diob.d_maxiosz;
1988 buf = memalign(diob.d_mem, len);
1989 e = read(fd, buf, len) < 0 ? errno : 0;
1992 printf("%d/%d: dread %s%s [%lld,%d] %d\n",
1993 procid, opno, f.path, st, (long long)off, (int)len, e);
1999 dwrite_f(int opno, long r)
2003 struct dioattr diob;
2015 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
2017 printf("%d/%d: dwrite - no filename\n", procid, opno);
2021 fd = open_path(&f, O_WRONLY|O_DIRECT);
2022 e = fd < 0 ? errno : 0;
2026 printf("%d/%d: dwrite - open %s failed %d\n",
2027 procid, opno, f.path, e);
2031 if (fstat64(fd, &stb) < 0) {
2033 printf("%d/%d: dwrite - fstat64 %s failed %d\n",
2034 procid, opno, f.path, errno);
2039 inode_info(st, sizeof(st), &stb, v);
2040 if (xfsctl(f.path, fd, XFS_IOC_DIOINFO, &diob) < 0) {
2042 printf("%d/%d: dwrite - xfsctl(XFS_IOC_DIOINFO)"
2043 " %s%s failed %d\n",
2044 procid, opno, f.path, st, errno);
2049 align = (__int64_t)diob.d_miniosz;
2050 lr = ((__int64_t)random() << 32) + random();
2051 off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
2052 off -= (off % align);
2053 lseek64(fd, off, SEEK_SET);
2054 len = (random() % FILELEN_MAX) + 1;
2055 len -= (len % align);
2058 else if (len > diob.d_maxiosz)
2059 len = diob.d_maxiosz;
2060 buf = memalign(diob.d_mem, len);
2062 lseek64(fd, off, SEEK_SET);
2063 memset(buf, nameseq & 0xff, len);
2064 e = write(fd, buf, len) < 0 ? errno : 0;
2067 printf("%d/%d: dwrite %s%s [%lld,%d] %d\n",
2068 procid, opno, f.path, st, (long long)off, (int)len, e);
2074 fallocate_f(int opno, long r)
2089 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
2091 printf("%d/%d: fallocate - no filename\n", procid, opno);
2095 fd = open_path(&f, O_RDWR);
2096 e = fd < 0 ? errno : 0;
2100 printf("%d/%d: fallocate - open %s failed %d\n",
2101 procid, opno, f.path, e);
2105 if (fstat64(fd, &stb) < 0) {
2107 printf("%d/%d: fallocate - fstat64 %s failed %d\n",
2108 procid, opno, f.path, errno);
2113 inode_info(st, sizeof(st), &stb, v);
2114 lr = ((__int64_t)random() << 32) + random();
2115 off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
2117 len = (off64_t)(random() % (1024 * 1024));
2118 mode |= FALLOC_FL_KEEP_SIZE & random();
2119 e = fallocate(fd, mode, (loff_t)off, (loff_t)len) < 0 ? errno : 0;
2121 printf("%d/%d: fallocate(%d) %s %st %lld %lld %d\n",
2123 f.path, st, (long long)off, (long long)len, e);
2131 fdatasync_f(int opno, long r)
2139 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
2141 printf("%d/%d: fdatasync - no filename\n",
2146 fd = open_path(&f, O_WRONLY);
2147 e = fd < 0 ? errno : 0;
2151 printf("%d/%d: fdatasync - open %s failed %d\n",
2152 procid, opno, f.path, e);
2156 e = fdatasync(fd) < 0 ? errno : 0;
2158 printf("%d/%d: fdatasync %s %d\n", procid, opno, f.path, e);
2163 fiemap_f(int opno, long r)
2165 #ifdef HAVE_LINUX_FIEMAP_H
2175 struct fiemap *fiemap;
2178 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
2180 printf("%d/%d: fiemap - no filename\n", procid, opno);
2184 fd = open_path(&f, O_RDWR);
2185 e = fd < 0 ? errno : 0;
2189 printf("%d/%d: fiemap - open %s failed %d\n",
2190 procid, opno, f.path, e);
2194 if (fstat64(fd, &stb) < 0) {
2196 printf("%d/%d: fiemap - fstat64 %s failed %d\n",
2197 procid, opno, f.path, errno);
2202 inode_info(st, sizeof(st), &stb, v);
2203 blocks_to_map = random() & 0xffff;
2204 fiemap = (struct fiemap *)malloc(sizeof(struct fiemap) +
2205 (blocks_to_map * sizeof(struct fiemap_extent)));
2208 printf("%d/%d: malloc failed \n", procid, opno);
2213 lr = ((__int64_t)random() << 32) + random();
2214 off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
2216 fiemap->fm_flags = random() & (FIEMAP_FLAGS_COMPAT | 0x10000);
2217 fiemap->fm_extent_count = blocks_to_map;
2218 fiemap->fm_mapped_extents = random() & 0xffff;
2219 fiemap->fm_start = off;
2220 fiemap->fm_length = ((__int64_t)random() << 32) + random();
2222 e = ioctl(fd, FS_IOC_FIEMAP, (unsigned long)fiemap);
2224 printf("%d/%d: ioctl(FIEMAP) %s%s %lld %lld %x %d\n",
2225 procid, opno, f.path, st, (long long)fiemap->fm_start,
2226 (long long) fiemap->fm_length, fiemap->fm_flags, e);
2234 freesp_f(int opno, long r)
2239 struct xfs_flock64 fl;
2247 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
2249 printf("%d/%d: freesp - no filename\n", procid, opno);
2253 fd = open_path(&f, O_RDWR);
2254 e = fd < 0 ? errno : 0;
2258 printf("%d/%d: freesp - open %s failed %d\n",
2259 procid, opno, f.path, e);
2263 if (fstat64(fd, &stb) < 0) {
2265 printf("%d/%d: freesp - fstat64 %s failed %d\n",
2266 procid, opno, f.path, errno);
2271 inode_info(st, sizeof(st), &stb, v);
2272 lr = ((__int64_t)random() << 32) + random();
2273 off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
2275 fl.l_whence = SEEK_SET;
2278 e = xfsctl(f.path, fd, XFS_IOC_FREESP64, &fl) < 0 ? errno : 0;
2280 printf("%d/%d: xfsctl(XFS_IOC_FREESP64) %s%s %lld 0 %d\n",
2281 procid, opno, f.path, st, (long long)off, e);
2287 fsync_f(int opno, long r)
2295 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
2297 printf("%d/%d: fsync - no filename\n", procid, opno);
2301 fd = open_path(&f, O_WRONLY);
2302 e = fd < 0 ? errno : 0;
2306 printf("%d/%d: fsync - open %s failed %d\n",
2307 procid, opno, f.path, e);
2311 e = fsync(fd) < 0 ? errno : 0;
2313 printf("%d/%d: fsync %s %d\n", procid, opno, f.path, e);
2319 getattr_f(int opno, long r)
2328 if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
2329 append_pathname(&f, ".");
2330 fd = open_path(&f, O_RDWR);
2331 e = fd < 0 ? errno : 0;
2334 e = ioctl(fd, FS_IOC_GETFLAGS, &fl);
2336 printf("%d/%d: getattr %s %u %d\n", procid, opno, f.path, fl, e);
2342 getdents_f(int opno, long r)
2349 if (!get_fname(FT_DIRm, r, &f, NULL, NULL, &v))
2350 append_pathname(&f, ".");
2351 dir = opendir_path(&f);
2355 printf("%d/%d: getdents - can't open %s\n",
2356 procid, opno, f.path);
2360 while (readdir64(dir) != NULL)
2363 printf("%d/%d: getdents %s 0\n", procid, opno, f.path);
2369 link_f(int opno, long r)
2382 if (!get_fname(FT_NOTDIR, r, &f, &flp, NULL, &v1)) {
2384 printf("%d/%d: link - no file\n", procid, opno);
2388 if (!get_fname(FT_DIRm, random(), NULL, NULL, &fep, &v))
2394 e = generate_fname(fep, flp - flist, &l, &id, &v1);
2398 (void)fent_to_name(&l, &flist[FT_DIR], fep);
2399 printf("%d/%d: link - no filename from %s\n",
2400 procid, opno, l.path);
2406 e = link_path(&f, &l) < 0 ? errno : 0;
2409 add_to_flist(flp - flist, id, parid);
2411 printf("%d/%d: link %s %s %d\n", procid, opno, f.path, l.path,
2413 printf("%d/%d: link add id=%d,parent=%d\n", procid, opno, id, parid);
2420 mkdir_f(int opno, long r)
2430 if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
2435 e = generate_fname(fep, FT_DIR, &f, &id, &v1);
2439 (void)fent_to_name(&f, &flist[FT_DIR], fep);
2440 printf("%d/%d: mkdir - no filename from %s\n",
2441 procid, opno, f.path);
2446 e = mkdir_path(&f, 0777) < 0 ? errno : 0;
2449 add_to_flist(FT_DIR, id, parid);
2451 printf("%d/%d: mkdir %s %d\n", procid, opno, f.path, e);
2452 printf("%d/%d: mkdir add id=%d,parent=%d\n", procid, opno, id, parid);
2458 mknod_f(int opno, long r)
2468 if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
2473 e = generate_fname(fep, FT_DEV, &f, &id, &v1);
2477 (void)fent_to_name(&f, &flist[FT_DIR], fep);
2478 printf("%d/%d: mknod - no filename from %s\n",
2479 procid, opno, f.path);
2484 e = mknod_path(&f, S_IFCHR|0444, 0) < 0 ? errno : 0;
2487 add_to_flist(FT_DEV, id, parid);
2489 printf("%d/%d: mknod %s %d\n", procid, opno, f.path, e);
2490 printf("%d/%d: mknod add id=%d,parent=%d\n", procid, opno, id, parid);
2496 punch_f(int opno, long r)
2508 int mode = FALLOC_FL_PUNCH_HOLE;
2511 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
2513 printf("%d/%d: punch hole - no filename\n", procid, opno);
2517 fd = open_path(&f, O_RDWR);
2518 e = fd < 0 ? errno : 0;
2522 printf("%d/%d: punch hole - open %s failed %d\n",
2523 procid, opno, f.path, e);
2527 if (fstat64(fd, &stb) < 0) {
2529 printf("%d/%d: punch hole - fstat64 %s failed %d\n",
2530 procid, opno, f.path, errno);
2535 inode_info(st, sizeof(st), &stb, v);
2536 lr = ((__int64_t)random() << 32) + random();
2537 off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
2539 len = (off64_t)(random() % (1024 * 1024));
2540 mode |= FALLOC_FL_KEEP_SIZE & random();
2541 e = fallocate(fd, mode, (loff_t)off, (loff_t)len) < 0 ? errno : 0;
2543 printf("%d/%d: punch hole(%d) %s %s %lld %lld %d\n",
2545 f.path, st, (long long)off, (long long)len, e);
2552 read_f(int opno, long r)
2566 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
2568 printf("%d/%d: read - no filename\n", procid, opno);
2572 fd = open_path(&f, O_RDONLY);
2573 e = fd < 0 ? errno : 0;
2577 printf("%d/%d: read - open %s failed %d\n",
2578 procid, opno, f.path, e);
2582 if (fstat64(fd, &stb) < 0) {
2584 printf("%d/%d: read - fstat64 %s failed %d\n",
2585 procid, opno, f.path, errno);
2590 inode_info(st, sizeof(st), &stb, v);
2591 if (stb.st_size == 0) {
2593 printf("%d/%d: read - %s%s zero size\n", procid, opno,
2599 lr = ((__int64_t)random() << 32) + random();
2600 off = (off64_t)(lr % stb.st_size);
2601 lseek64(fd, off, SEEK_SET);
2602 len = (random() % FILELEN_MAX) + 1;
2604 e = read(fd, buf, len) < 0 ? errno : 0;
2607 printf("%d/%d: read %s%s [%lld,%d] %d\n",
2608 procid, opno, f.path, st, (long long)off, (int)len, e);
2614 readlink_f(int opno, long r)
2622 if (!get_fname(FT_SYMm, r, &f, NULL, NULL, &v)) {
2624 printf("%d/%d: readlink - no filename\n", procid, opno);
2628 e = readlink_path(&f, buf, PATH_MAX) < 0 ? errno : 0;
2631 printf("%d/%d: readlink %s %d\n", procid, opno, f.path, e);
2636 rename_f(int opno, long r)
2650 /* get an existing path for the source of the rename */
2652 if (!get_fname(FT_ANYm, r, &f, &flp, &fep, &v1)) {
2654 printf("%d/%d: rename - no filename\n", procid, opno);
2659 /* get an existing directory for the destination parent directory name */
2660 if (!get_fname(FT_DIRm, random(), NULL, NULL, &dfep, &v))
2666 /* generate a new path using an existing parent directory in name */
2667 init_pathname(&newf);
2668 e = generate_fname(dfep, flp - flist, &newf, &id, &v1);
2672 (void)fent_to_name(&f, &flist[FT_DIR], dfep);
2673 printf("%d/%d: rename - no filename from %s\n",
2674 procid, opno, f.path);
2676 free_pathname(&newf);
2680 e = rename_path(&f, &newf) < 0 ? errno : 0;
2683 if (flp - flist == FT_DIR) {
2685 fix_parent(oldid, id);
2687 del_from_flist(flp - flist, fep - flp->fents);
2688 add_to_flist(flp - flist, id, parid);
2691 printf("%d/%d: rename %s to %s %d\n", procid, opno, f.path,
2694 printf("%d/%d: rename del entry: id=%d,parent=%d\n",
2695 procid, opno, fep->id, fep->parent);
2696 printf("%d/%d: rename add entry: id=%d,parent=%d\n",
2697 procid, opno, id, parid);
2700 free_pathname(&newf);
2705 resvsp_f(int opno, long r)
2710 struct xfs_flock64 fl;
2718 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
2720 printf("%d/%d: resvsp - no filename\n", procid, opno);
2724 fd = open_path(&f, O_RDWR);
2725 e = fd < 0 ? errno : 0;
2729 printf("%d/%d: resvsp - open %s failed %d\n",
2730 procid, opno, f.path, e);
2734 if (fstat64(fd, &stb) < 0) {
2736 printf("%d/%d: resvsp - fstat64 %s failed %d\n",
2737 procid, opno, f.path, errno);
2742 inode_info(st, sizeof(st), &stb, v);
2743 lr = ((__int64_t)random() << 32) + random();
2744 off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
2746 fl.l_whence = SEEK_SET;
2748 fl.l_len = (off64_t)(random() % (1024 * 1024));
2749 e = xfsctl(f.path, fd, XFS_IOC_RESVSP64, &fl) < 0 ? errno : 0;
2751 printf("%d/%d: xfsctl(XFS_IOC_RESVSP64) %s%s %lld %lld %d\n",
2752 procid, opno, f.path, st,
2753 (long long)off, (long long)fl.l_len, e);
2759 rmdir_f(int opno, long r)
2767 if (!get_fname(FT_DIRm, r, &f, NULL, &fep, &v)) {
2769 printf("%d/%d: rmdir - no directory\n", procid, opno);
2773 e = rmdir_path(&f) < 0 ? errno : 0;
2776 del_from_flist(FT_DIR, fep - flist[FT_DIR].fents);
2778 printf("%d/%d: rmdir %s %d\n", procid, opno, f.path, e);
2780 printf("%d/%d: rmdir del entry: id=%d,parent=%d\n",
2781 procid, opno, fep->id, fep->parent);
2787 setattr_f(int opno, long r)
2796 if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v))
2797 append_pathname(&f, ".");
2798 fd = open_path(&f, O_RDWR);
2799 e = fd < 0 ? errno : 0;
2802 fl = attr_mask & (uint)random();
2803 e = ioctl(fd, FS_IOC_SETFLAGS, &fl);
2805 printf("%d/%d: setattr %s %x %d\n", procid, opno, f.path, fl, e);
2811 stat_f(int opno, long r)
2819 if (!get_fname(FT_ANYm, r, &f, NULL, NULL, &v)) {
2821 printf("%d/%d: stat - no entries\n", procid, opno);
2825 e = lstat64_path(&f, &stb) < 0 ? errno : 0;
2828 printf("%d/%d: stat %s %d\n", procid, opno, f.path, e);
2833 symlink_f(int opno, long r)
2846 if (!get_fname(FT_DIRm, r, NULL, NULL, &fep, &v))
2851 e = generate_fname(fep, FT_SYM, &f, &id, &v1);
2855 (void)fent_to_name(&f, &flist[FT_DIR], fep);
2856 printf("%d/%d: symlink - no filename from %s\n",
2857 procid, opno, f.path);
2862 len = (int)(random() % PATH_MAX);
2863 val = malloc(len + 1);
2865 memset(val, 'x', len);
2867 for (i = 10; i < len - 1; i += 10)
2869 e = symlink_path(val, &f) < 0 ? errno : 0;
2872 add_to_flist(FT_SYM, id, parid);
2875 printf("%d/%d: symlink %s %d\n", procid, opno, f.path, e);
2876 printf("%d/%d: symlink add id=%d,parent=%d\n", procid, opno, id, parid);
2883 sync_f(int opno, long r)
2887 printf("%d/%d: sync\n", procid, opno);
2891 truncate_f(int opno, long r)
2902 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
2904 printf("%d/%d: truncate - no filename\n", procid, opno);
2908 e = stat64_path(&f, &stb) < 0 ? errno : 0;
2912 printf("%d/%d: truncate - stat64 %s failed %d\n",
2913 procid, opno, f.path, e);
2917 inode_info(st, sizeof(st), &stb, v);
2918 lr = ((__int64_t)random() << 32) + random();
2919 off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
2921 e = truncate64_path(&f, off) < 0 ? errno : 0;
2924 printf("%d/%d: truncate %s%s %lld %d\n", procid, opno, f.path,
2925 st, (long long)off, e);
2930 unlink_f(int opno, long r)
2939 if (!get_fname(FT_NOTDIR, r, &f, &flp, &fep, &v)) {
2941 printf("%d/%d: unlink - no file\n", procid, opno);
2945 e = unlink_path(&f) < 0 ? errno : 0;
2948 del_from_flist(flp - flist, fep - flp->fents);
2950 printf("%d/%d: unlink %s %d\n", procid, opno, f.path, e);
2952 printf("%d/%d: unlink del entry: id=%d,parent=%d\n",
2953 procid, opno, fep->id, fep->parent);
2959 unresvsp_f(int opno, long r)
2964 struct xfs_flock64 fl;
2972 if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
2974 printf("%d/%d: unresvsp - no filename\n", procid, opno);
2978 fd = open_path(&f, O_RDWR);
2979 e = fd < 0 ? errno : 0;
2983 printf("%d/%d: unresvsp - open %s failed %d\n",
2984 procid, opno, f.path, e);
2988 if (fstat64(fd, &stb) < 0) {
2990 printf("%d/%d: unresvsp - fstat64 %s failed %d\n",
2991 procid, opno, f.path, errno);
2996 inode_info(st, sizeof(st), &stb, v);
2997 lr = ((__int64_t)random() << 32) + random();
2998 off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
3000 fl.l_whence = SEEK_SET;
3002 fl.l_len = (off64_t)(random() % (1 << 20));
3003 e = xfsctl(f.path, fd, XFS_IOC_UNRESVSP64, &fl) < 0 ? errno : 0;
3005 printf("%d/%d: xfsctl(XFS_IOC_UNRESVSP64) %s%s %lld %lld %d\n",
3006 procid, opno, f.path, st,
3007 (long long)off, (long long)fl.l_len, e);
3013 write_f(int opno, long r)
3027 if (!get_fname(FT_REGm, r, &f, NULL, NULL, &v)) {
3029 printf("%d/%d: write - no filename\n", procid, opno);
3033 fd = open_path(&f, O_WRONLY);
3034 e = fd < 0 ? errno : 0;
3038 printf("%d/%d: write - open %s failed %d\n",
3039 procid, opno, f.path, e);
3043 if (fstat64(fd, &stb) < 0) {
3045 printf("%d/%d: write - fstat64 %s failed %d\n",
3046 procid, opno, f.path, errno);
3051 inode_info(st, sizeof(st), &stb, v);
3052 lr = ((__int64_t)random() << 32) + random();
3053 off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
3055 lseek64(fd, off, SEEK_SET);
3056 len = (random() % FILELEN_MAX) + 1;
3058 memset(buf, nameseq & 0xff, len);
3059 e = write(fd, buf, len) < 0 ? errno : 0;
3062 printf("%d/%d: write %s%s [%lld,%d] %d\n",
3063 procid, opno, f.path, st, (long long)off, (int)len, e);