+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* doio - a general purpose io initiator with system call and
#include "global.h"
+#include <stdarg.h>
#include <sys/uio.h> /* for struct iovec (readv)*/
#include <sys/mman.h> /* for mmap(2) */
#include <sys/ipc.h> /* for i/o buffer in shared memory */
#include <sys/time.h> /* for delays */
#include <ctype.h>
-#ifndef NO_XFS
struct io_req;
int do_xfsctl(struct io_req *);
-#endif
#include "doio.h"
#include "pattern.h"
int c_oflags;
int c_fd;
long c_rtc;
-#ifndef NO_XFS
int c_memalign; /* from xfsctl(XFS_IOC_DIOINFO) */
int c_miniosz;
int c_maxiosz;
-#endif
void *c_memaddr; /* mmapped address */
int c_memlen; /* length of above region */
};
void cb_handler(); /* Posix aio callback handler. */
void noop_handler(); /* Delayop alarm, does nothing. */
-char *hms();
+char *hms(time_t t);
char *format_rw();
char *format_sds();
char *format_listio();
-char *check_file();
+char *check_file(char *file, int offset, int length, char *pattern,
+ int pattern_length, int patshift, int fsa);
int doio_fprintf(FILE *stream, char *format, ...);
-void doio_upanic();
+void doio_upanic(int mask);
void doio();
-void help();
+void help(FILE *stream);
void doio_delay();
int alloc_fd( char *, int );
int alloc_mem( int );
case SIGTSTP:
case SIGSTOP:
case SIGCONT:
- case SIGCLD:
+ case SIGCHLD:
case SIGBUS:
case SIGSEGV:
case SIGQUIT:
case LEWRITEA:
rval = do_rw(&ioreq);
break;
-#ifndef NO_XFS
case RESVSP:
case UNRESVSP:
rval = do_xfsctl(&ioreq);
break;
-#endif
case FSYNC2:
case FDATASYNC:
rval = do_sync(&ioreq);
{
int fd, offset, nbytes, oflags, rval;
char *addr, *file;
-#ifndef NO_XFS
struct fd_cache *fdc;
-#endif
/*
* Initialize common fields - assumes r_oflags, r_file, r_offset, and
#define wtob(x) (x * sizeof(UINT64_T))
#endif
-#ifndef NO_XFS
/* get memory alignment for using DIRECT I/O */
fdc = alloc_fdcache(file, oflags);
} else {
addr += random_range(0, wtob(1) - 1, 1, NULL);
}
-#else
- if ((rval = alloc_mem(nbytes + wtob(1) * 2)) < 0) {
- return rval;
- }
-
- addr = Memptr;
-#endif /* !NO_XFS */
-
switch (req->r_type) {
case READ:
static int pid = -1;
int fd, nbytes, oflags;
/* REFERENCED */
- int signo;
int logged_write, rval, got_lock;
long offset, woffset = 0;
char *addr, pattern, *file, *msg;
struct wlog_rec wrec;
-#ifndef NO_XFS
struct fd_cache *fdc;
-#endif
/*
* Misc variable setup
*/
- signo = 0;
nbytes = req->r_data.write.r_nbytes;
offset = req->r_data.write.r_offset;
pattern = req->r_data.write.r_pattern;
* Allocate SDS space for backdoor write if desired
*/
-#ifndef NO_XFS
/* get memory alignment for using DIRECT I/O */
fdc = alloc_fdcache(file, oflags);
if( addr != Memptr )
memmove( addr, Memptr, nbytes);
-#else /* sgi */
- if ((rval = alloc_mem(nbytes + wtob(1) * 2)) < 0) {
- return rval;
- }
-
- addr = Memptr;
-
- (*Data_Fill)(Memptr, nbytes, Pattern, Pattern_Length, 0);
- if( addr != Memptr )
- memmove( addr, Memptr, nbytes);
-#endif /* sgi */
-
rval = -1;
got_lock = 0;
logged_write = 0;
"write() failed: %s (%d)\n%s\n",
SYSERR, errno,
format_rw(req, fd, addr, -1, Pattern, NULL));
-#ifndef NO_XFS
doio_fprintf(stderr,
"write() failed: %s\n\twrite(%d, %#o, %d)\n\toffset %d, nbytes%%miniou(%d)=%d, oflags=%#o memalign=%d, addr%%memalign=%d\n",
strerror(errno),
offset,
fdc->c_miniosz, nbytes%fdc->c_miniosz,
oflags, fdc->c_memalign, (long)addr%fdc->c_memalign);
-#else
- doio_fprintf(stderr,
- "write() failed: %s\n\twrite(%d, %#o, %d)\n\toffset %d, nbytes%%1B=%d, oflags=%#o\n",
- strerror(errno),
- fd, addr, nbytes,
- offset, nbytes%4096, oflags);
-#endif
doio_upanic(U_RVAL);
} else if (rval != nbytes) {
doio_fprintf(stderr,
cp += sprintf(cp, " memory alignment is %s\n",
(io->r_uflags & F_WORD_ALIGNED) ? "aligned" : "unaligned");
-#ifndef NO_XFS
if(io->r_oflags & O_DIRECT) {
+ char *dio_env;
struct dioattr finfo;
if(xfsctl(io->r_file, fd, XFS_IOC_DIOINFO, &finfo) == -1) {
finfo.d_maxiosz = 1;
}
+ dio_env = getenv("XFS_DIO_MIN");
+ if (dio_env)
+ finfo.d_mem = finfo.d_miniosz = atoi(dio_env);
+
cp += sprintf(cp, " DIRECT I/O: offset %% %d = %d length %% %d = %d\n",
finfo.d_miniosz,
io->r_offset % finfo.d_miniosz,
cp += sprintf(cp, " mem alignment 0x%x xfer size: small: %d large: %d\n",
finfo.d_mem, finfo.d_miniosz, finfo.d_maxiosz);
}
-#endif
-
return(errbuf);
}
return(errbuf);
}
-struct status *
-sy_readv(req, sysc, fd, addr)
-struct io_req *req;
-struct syscall_info *sysc;
-int fd;
-char *addr;
-{
- struct status *sy_rwv();
- return sy_rwv(req, sysc, fd, addr, 0);
-}
-
-struct status *
-sy_writev(req, sysc, fd, addr)
-struct io_req *req;
-struct syscall_info *sysc;
-int fd;
-char *addr;
-{
- struct status *sy_rwv();
- return sy_rwv(req, sysc, fd, addr, 1);
-}
-
struct status *
sy_rwv(req, sysc, fd, addr, rw)
struct io_req *req;
return(status);
}
-char *
-fmt_readv(struct io_req *req, struct syscall_info *sy, int fd, char *addr)
-{
- static char errbuf[32768];
- char *cp;
-
- cp = errbuf;
- cp += sprintf(cp, "syscall: %s(%d, (iov on stack), 1)\n",
- sy->sy_name, fd);
- return(errbuf);
-}
-
struct status *
-sy_mmread(req, sysc, fd, addr)
-struct io_req *req;
+sy_readv(req, sysc, fd, addr)
+struct io_req *req;
struct syscall_info *sysc;
int fd;
char *addr;
{
- struct status *sy_mmrw();
- return sy_mmrw(req, sysc, fd, addr, 0);
+ return sy_rwv(req, sysc, fd, addr, 0);
}
struct status *
-sy_mmwrite(req, sysc, fd, addr)
-struct io_req *req;
+sy_writev(req, sysc, fd, addr)
+struct io_req *req;
struct syscall_info *sysc;
int fd;
char *addr;
{
- struct status *sy_mmrw();
- return sy_mmrw(req, sysc, fd, addr, 1);
+ return sy_rwv(req, sysc, fd, addr, 1);
+}
+
+char *
+fmt_readv(struct io_req *req, struct syscall_info *sy, int fd, char *addr)
+{
+ static char errbuf[32768];
+ char *cp;
+
+ cp = errbuf;
+ cp += sprintf(cp, "syscall: %s(%d, (iov on stack), 1)\n",
+ sy->sy_name, fd);
+ return(errbuf);
}
struct status *
return(status);
}
+struct status *
+sy_mmread(req, sysc, fd, addr)
+struct io_req *req;
+struct syscall_info *sysc;
+int fd;
+char *addr;
+{
+ return sy_mmrw(req, sysc, fd, addr, 0);
+}
+
+struct status *
+sy_mmwrite(req, sysc, fd, addr)
+struct io_req *req;
+struct syscall_info *sysc;
+int fd;
+char *addr;
+{
+ return sy_mmrw(req, sysc, fd, addr, 1);
+}
+
char *
fmt_mmrw(struct io_req *req, struct syscall_info *sy, int fd, char *addr)
{
struct status *s;
struct wlog_rec wrec;
struct syscall_info *sy;
-#ifndef NO_XFS
struct fd_cache *fdc;
-#endif
/*
* Initialize common fields - assumes r_oflags, r_file, r_offset, and
mem_needed = nbytes;
}
-#ifndef NO_XFS
/* get memory alignment for using DIRECT I/O */
fdc = alloc_fdcache(file, oflags);
if ((rval = alloc_mem(mem_needed + wtob(1) * 2 + fdc->c_memalign)) < 0) {
return rval;
}
-#else
- if ((rval = alloc_mem(mem_needed + wtob(1) * 2)) < 0) {
- return rval;
- }
-#endif
Pattern[0] = pattern;
addr += random_range(0, wtob(1) - 1, 1, NULL);
}
-#ifndef NO_XFS
/*
* Force memory alignment for Direct I/O
*/
if( (oflags & O_DIRECT) && ((long)addr % fdc->c_memalign != 0) ) {
addr += fdc->c_memalign - ((long)addr % fdc->c_memalign);
}
-#endif
/*
* FILL must be done on a word-aligned buffer.
* - XFS_IOC_RESVSP
* - XFS_IOC_UNRESVSP
*/
-#ifndef NO_XFS
int
do_xfsctl(req)
struct io_req *req;
return (rval == -1) ? -1 : 0;
}
-#endif
/*
* fsync(2) and fdatasync(2)
static char errbuf[4096];
int fd, nb, flags;
char *buf, *em, *ep;
-#ifndef NO_XFS
struct fd_cache *fdc;
-#endif
buf = Memptr;
return errbuf;
}
-#ifndef NO_XFS
/* Guarantee a properly aligned address on Direct I/O */
fdc = alloc_fdcache(file, flags);
if( (flags & O_DIRECT) && ((long)buf % fdc->c_memalign != 0) ) {
buf += fdc->c_memalign - ((long)buf % fdc->c_memalign);
}
-#endif
if ((nb = read(fd, buf, length)) == -1) {
-#ifndef NO_XFS
sprintf(errbuf,
"Could not read %d bytes from %s for verification: %s (%d)\n\tread(%d, 0x%p, %d)\n\tbuf %% alignment(%d) = %ld\n",
length, file, SYSERR, errno,
fd, buf, length,
fdc->c_memalign, (long)buf % fdc->c_memalign);
-#else
- sprintf(errbuf,
- "Could not read %d bytes from %s for verification: %s (%d)\n",
- length, file, SYSERR, errno);
-
-#endif
return errbuf;
}
struct fd_cache *free_slot, *oldest_slot, *cp;
static int cache_size = 0;
static struct fd_cache *cache = NULL;
-#ifndef NO_XFS
struct dioattr finfo;
-#endif
/*
* If file is NULL, it means to free up the fd cache.
strcpy(free_slot->c_file, file);
free_slot->c_rtc = Reqno;
-#ifndef NO_XFS
if (oflags & O_DIRECT) {
+ char *dio_env;
+
if (xfsctl(file, fd, XFS_IOC_DIOINFO, &finfo) == -1) {
finfo.d_mem = 1;
finfo.d_miniosz = 1;
finfo.d_maxiosz = 1;
}
+
+ dio_env = getenv("XFS_DIO_MIN");
+ if (dio_env)
+ finfo.d_mem = finfo.d_miniosz = atoi(dio_env);
+
} else {
finfo.d_mem = 1;
finfo.d_miniosz = 1;
free_slot->c_memalign = finfo.d_mem;
free_slot->c_miniosz = finfo.d_miniosz;
free_slot->c_maxiosz = finfo.d_maxiosz;
-#endif
free_slot->c_memaddr = NULL;
free_slot->c_memlen = 0;
break;
case 'N':
- sprintf( TagName, "(%.39s)", optarg );
+ sprintf( TagName, "(%.37s)", optarg );
break;
case 'n':