- cp = errbuf;
- cp += sprintf(cp, "Request number %d\n", Reqno);
-
- cp += sprintf(cp, "syscall: listio(%s, %#o, %d)\n\n",
- cmd, list, nent);
-
- aio_strat = format_strat(liop->r_aio_strat);
-
- for (i = 0; i < nent; i++) {
- cp += sprintf(cp, "struct lioreq for request element %d\n", i);
- cp += sprintf(cp, "----------------------------------------\n");
-
- listreq = list + i;
-
- switch (listreq->li_opcode) {
- case LO_READ: opcode = "LO_READ"; break;
- case LO_WRITE: opcode = "LO_WRITE"; break;
- default: opcode = "???"; break;
- }
-
- cp += sprintf(cp, " li_opcode = %s\n", opcode);
- cp += sprintf(cp, " li_drvr = %#o\n", listreq->li_drvr);
- cp += sprintf(cp, " li_flags = %#o\n", listreq->li_flags);
- cp += sprintf(cp, " li_offset = %d\n", listreq->li_offset);
- cp += sprintf(cp, " li_fildes = %d\n", listreq->li_fildes);
- cp += sprintf(cp, " li_buf = %#o\n", listreq->li_buf);
- cp += sprintf(cp, " li_nbyte = %d\n", listreq->li_nbyte);
- cp += sprintf(cp, " li_status = %#o (%d, %d, %d)\n", listreq->li_status, listreq->li_status->sw_flag, listreq->li_status->sw_error, listreq->li_status->sw_count);
- cp += sprintf(cp, " li_signo = %d\n", listreq->li_signo);
- cp += sprintf(cp, " li_nstride = %d\n", listreq->li_nstride);
- cp += sprintf(cp, " li_filstride = %d\n", listreq->li_filstride);
- cp += sprintf(cp, " li_memstride = %d\n", listreq->li_memstride);
- cp += sprintf(cp, " io completion strategy is %s\n", aio_strat);
- }
- return errbuf;
-}
-#endif /* CRAY */
-
-int
-do_listio(req)
-struct io_req *req;
-{
-#ifdef CRAY
- struct listio_req *lio;
- int fd, oflags, signo, nb, i;
- int logged_write, rval, got_lock;
- int aio_strat, aio_id;
- int min_byte, max_byte;
- int mem_needed;
- int foffset, fstride, mstride, nstrides;
- char *moffset;
- long offset, woffset;
- char *addr, *msg;
- sigset_t block_mask, omask;
- struct wlog_rec wrec;
- struct aio_info *aiop;
- struct listreq lio_req;
-
- lio = &req->r_data.listio;
-
- /*
- * If bytes per stride is less than the stride size, drop the request
- * since it will cause overlapping strides, and we cannot predict
- * the order they will complete in.
- */
-
- if (lio->r_filestride && abs(lio->r_filestride) < lio->r_nbytes) {
- doio_fprintf(stderr, "do_listio(): Bogus listio request - abs(filestride) [%d] < nbytes [%d]\n",
- abs(lio->r_filestride), lio->r_nbytes);
- return -1;
- }
-
- /*
- * Allocate core memory. Initialize the data to be written. Make
- * sure we get enough, based on the memstride.
- */
-
- mem_needed =
- stride_bounds(0, lio->r_memstride, lio->r_nstrides,
- lio->r_nbytes, NULL, NULL);
-
- if ((rval = alloc_mem(mem_needed + wtob(1))) < 0) {
- return rval;
- }
-
- /*
- * Set the memory address pointer. If the io is not raw, adjust
- * addr by a random amount, so that non-raw io is not necessarily
- * word aligned.
- */
-
- addr = Memptr;
-
- if (! (lio->r_uflags & F_WORD_ALIGNED)) {
- addr += random_range(0, wtob(1) - 1, 1, NULL);
- }
-
- if (lio->r_opcode == LO_WRITE) {
- Pattern[0] = lio->r_pattern;
- (*Data_Fill)(Memptr, mem_needed, Pattern, Pattern_Length, 0);
- if( addr != Memptr )
- memmove( addr, Memptr, mem_needed);
- }
-
- /*
- * Get a descriptor to do the io on. No need to do an lseek, as this
- * is encoded in the listio request.
- */
-
- if ((fd = alloc_fd(lio->r_file, lio->r_oflags)) == -1) {
- return -1;
- }
-
- rval = -1;
- got_lock = 0;
- logged_write = 0;
-
- /*
- * If the opcode is LO_WRITE, lock all regions of the file that
- * are touched by this listio request. Currently, we use
- * stride_bounds() to figure out the min and max bytes affected, and
- * lock the entire region, regardless of the file stride.
- */
-
- if (lio->r_opcode == LO_WRITE && k_opt) {
- stride_bounds(lio->r_offset,
- lio->r_filestride, lio->r_nstrides,
- lio->r_nbytes, &min_byte, &max_byte);
-
- if (lock_file_region(lio->r_file, fd, F_WRLCK,
- min_byte, (max_byte-min_byte+1)) < 0) {
- doio_fprintf(stderr, "stride_bounds(%d, %d, %d, %d, ..., ...) set min_byte to %d, max_byte to %d\n",
- lio->r_offset, lio->r_filestride,
- lio->r_nstrides, lio->r_nbytes, min_byte,
- max_byte);
- return -1;
- } else {
- got_lock = 1;
- }
- }
-
- /*
- * async write
- */
-
- aio_strat = lio->r_aio_strat;
- signo = (aio_strat == A_SIGNAL) ? SIGUSR1 : 0;
-
- aio_id = aio_register(fd, aio_strat, signo);
- aiop = aio_slot(aio_id);
-
- /*
- * Form the listio request, and make the call.
- */
-
- lio_req.li_opcode = lio->r_opcode;
- lio_req.li_drvr = 0;
- lio_req.li_flags = LF_LSEEK;
- lio_req.li_offset = lio->r_offset;
- lio_req.li_fildes = fd;
-
- if (lio->r_memstride >= 0 || lio->r_nstrides <= 1) {
- lio_req.li_buf = addr;
- } else {
- lio_req.li_buf = addr + mem_needed - lio->r_nbytes;
- }
-
- lio_req.li_nbyte = lio->r_nbytes;
- lio_req.li_status = &aiop->iosw;
- lio_req.li_signo = signo;
- lio_req.li_nstride = lio->r_nstrides;
- lio_req.li_filstride = lio->r_filestride;
- lio_req.li_memstride = lio->r_memstride;
-
- /*
- * If signo != 0, block signo while we're in the system call, so that
- * we don't get interrupted syscall failures.
- */
-
- if (signo) {
- sigemptyset(&block_mask);
- sigaddset(&block_mask, signo);
- sigprocmask(SIG_BLOCK, &block_mask, &omask);
- }
-
- if (listio(lio->r_cmd, &lio_req, 1) < 0) {
- doio_fprintf(stderr,
- "listio() failed: %s (%d)\n%s\n",
- SYSERR, errno,
- format_listio(req, lio->r_cmd, &lio_req, 1, fd, Pattern));
- aio_unregister(aio_id);
- doio_upanic(U_RVAL);
- goto lio_done;
- }
-
- if (signo) {
- sigprocmask(SIG_SETMASK, &omask, NULL);
- }
-
- /*
- * Wait for io to complete
- */
-
- aio_wait(aio_id);
-
- nstrides = lio->r_nstrides ? lio->r_nstrides : 1;
- if (aiop->iosw.sw_count != lio->r_nbytes * nstrides) {
- doio_fprintf(stderr,
- "Bad iosw from listio()\nExpected (%d,%d,%d), got (%d,%d,%d)\n%s\n",
- 1, 0, lio->r_nbytes * lio->r_nstrides,
- aiop->iosw.sw_flag,
- aiop->iosw.sw_error, aiop->iosw.sw_count,
- format_listio(req, lio->r_cmd, &lio_req, 1, fd, Pattern));
- aio_unregister(aio_id);
- doio_upanic(U_IOSW);
- goto lio_done;
- }
-
- aio_unregister(aio_id);
-
- /*
- * Verify that the data was written correctly - check_file() returns
- * a non-null pointer which contains an error message if there are
- * problems.
- *
- * For listio, we basically have to make 1 call to check_file for each
- * stride.
- */
-
- if (v_opt && lio_req.li_opcode == LO_WRITE) {
- fstride = lio->r_filestride ? lio->r_filestride : lio->r_nbytes;
- mstride = lio->r_memstride ? lio->r_memstride : lio->r_nbytes;
- foffset = lio->r_offset;
-
- if (mstride> 0 || lio->r_nstrides <= 1) {
- moffset = addr;
- } else {
- moffset = addr + mem_needed - lio->r_nbytes;
- }
-
- for (i = 0; i < lio_req.li_nstride; i++) {
- msg = check_file(lio->r_file,
- foffset, lio->r_nbytes,
- Pattern, Pattern_Length,
- moffset - addr,
- lio->r_oflags & O_PARALLEL);
-
- if (msg != NULL) {
- doio_fprintf(stderr, "%s\n%s\n",
- msg,
- format_listio(req, lio->r_cmd, &lio_req, 1, fd, Pattern));
- doio_upanic(U_CORRUPTION);
- exit(E_COMPARE);
- }
-
- moffset += mstride;
- foffset += fstride;
- }
-
- }
-
- rval = 0;
-
- lio_done:
-
- /*
- * General cleanup ...
- *
- */
-
- /*
- * Release file locks if necessary
- */
-
- if (got_lock) {
- if (lock_file_region(lio->r_file, fd, F_UNLCK,
- min_byte, (max_byte-min_byte+1)) < 0) {
- return -1;
- }
- }
-
- return rval;
-#else
- return -1;
-#endif
-}
-
-/*
- * perform ssread/sswrite operations
- */
-
-#ifdef _CRAY1
-
-int
-do_ssdio(req)
-struct io_req *req;
-{
- int nbytes, nb;
- char errbuf[BSIZE];
-
- nbytes = req->r_data.ssread.r_nbytes;
-
- /*
- * Grab core and sds space
- */
-
- if ((nb = alloc_mem(nbytes)) < 0)
- return nb;
-
- if (alloc_sds(nbytes) == -1)
- return -1;
-
- if (req->r_type == SSWRITE) {
-
- /*
- * Init data and ship it to the ssd
- */
-
- Pattern[0] = req->r_data.sswrite.r_pattern;
- /*pattern_fill(Memptr, nbytes, Pattern, Pattern_Length, 0);*/
- (*Data_Fill)(Memptr, nbytes, Pattern, Pattern_Length, 0);
-
- if (sswrite((long)Memptr, (long)Sdsptr, btoc(nbytes)) == -1) {
- doio_fprintf(stderr, "sswrite() failed: %s (%d)\n%s\n",
- SYSERR, errno,
- format_sds(req, Memptr, Sdsptr, Pattern));
- doio_upanic(U_RVAL);
- return -1;
- }
- } else {
- /*
- * read from sds
- */
-
- if (ssread((long)Memptr, (long)Sdsptr, btoc(nbytes)) == -1) {
- doio_fprintf(stderr, "ssread() failed: %s (%d)\n%s\n",
- SYSERR, errno,
- format_sds(req, Memptr, Sdsptr, Pattern));
-
- doio_upanic(U_RVAL);
- return -1;
- }
- }
-
- /*
- * Verify data if SSWRITE and v_opt
- */
-
- if (v_opt && req->r_type == SSWRITE) {
- ssread((long)Memptr, (long)Sdsptr, btoc(nbytes));
-
- if (pattern_check(Memptr, nbytes, Pattern, Pattern_Length, 0) == -1) {
- doio_fprintf(stderr,
- "sds DATA COMPARE ERROR - ABORTING\n%s\n",
- format_sds(req, Memptr, Sdsptr, Pattern));
-
- doio_upanic(U_CORRUPTION);
- exit(E_COMPARE);
- }
- }
-}
-
-#else
-
-#ifdef CRAY
-
-int
-do_ssdio(req)
-struct io_req *req;
-{
- doio_fprintf(stderr,
- "Internal Error - do_ssdio() called on a non-cray1 system\n");
- alloc_mem(-1);
- exit(E_INTERNAL);
-}
-
-#endif
-
-#endif /* _CRAY1 */
-
-\f
-/* ---------------------------------------------------------------------------
- *
- * A new paradigm of doing the r/w system call where there is a "stub"
- * function that builds the info for the system call, then does the system
- * call; this is called by code that is common to all system calls and does
- * the syscall return checking, async I/O wait, iosw check, etc.
- *
- * Flags:
- * WRITE, ASYNC, SSD/SDS,
- * FILE_LOCK, WRITE_LOG, VERIFY_DATA,
- */
-
-struct status {
- int rval; /* syscall return */
- int err; /* errno */
- int *aioid; /* list of async I/O structures */
-};
-
-struct syscall_info {
- char *sy_name;
- int sy_type;
- struct status *(*sy_syscall)();
- int (*sy_buffer)();
- char *(*sy_format)();
- int sy_flags;
- int sy_bits;
-};
-
-#define SY_WRITE 00001
-#define SY_ASYNC 00010
-#define SY_IOSW 00020
-#define SY_SDS 00100
-
-char *
-fmt_ioreq(struct io_req *ioreq, struct syscall_info *sy, int fd)
-{
- static char *errbuf=NULL;
- char *cp;
- struct rw_req *io;
- struct smap *aname;
-#ifdef CRAY
- struct stat sbuf;
-#endif
-
- if(errbuf == NULL)
- errbuf = (char *)malloc(32768);
-
- io = &ioreq->r_data.io;