scsi_target.c (157009) | scsi_target.c (162704) |
---|---|
1/* 2 * SCSI Disk Emulator 3 * 4 * Copyright (c) 2002 Nate Lawson. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions --- 11 unchanged lines hidden (view full) --- 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * | 1/* 2 * SCSI Disk Emulator 3 * 4 * Copyright (c) 2002 Nate Lawson. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions --- 11 unchanged lines hidden (view full) --- 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * |
28 * $FreeBSD: head/share/examples/scsi_target/scsi_target.c 157009 2006-03-22 17:00:14Z mjacob $ | 28 * $FreeBSD: head/share/examples/scsi_target/scsi_target.c 162704 2006-09-27 15:38:13Z mjacob $ |
29 */ 30 31#include <sys/types.h> 32#include <ctype.h> 33#include <errno.h> 34#include <err.h> 35#include <fcntl.h> 36#include <signal.h> --- 14 unchanged lines hidden (view full) --- 51#include <cam/scsi/scsi_all.h> 52#include <cam/scsi/scsi_targetio.h> 53#include <cam/scsi/scsi_message.h> 54#include "scsi_target.h" 55 56/* Maximum amount to transfer per CTIO */ 57#define MAX_XFER MAXPHYS 58/* Maximum number of allocated CTIOs */ | 29 */ 30 31#include <sys/types.h> 32#include <ctype.h> 33#include <errno.h> 34#include <err.h> 35#include <fcntl.h> 36#include <signal.h> --- 14 unchanged lines hidden (view full) --- 51#include <cam/scsi/scsi_all.h> 52#include <cam/scsi/scsi_targetio.h> 53#include <cam/scsi/scsi_message.h> 54#include "scsi_target.h" 55 56/* Maximum amount to transfer per CTIO */ 57#define MAX_XFER MAXPHYS 58/* Maximum number of allocated CTIOs */ |
59#define MAX_CTIOS 32 | 59#define MAX_CTIOS 64 |
60/* Maximum sector size for emulated volume */ 61#define MAX_SECTOR 32768 62 63/* Global variables */ 64int debug; | 60/* Maximum sector size for emulated volume */ 61#define MAX_SECTOR 32768 62 63/* Global variables */ 64int debug; |
65int notaio = 0; |
|
65off_t volume_size; 66u_int sector_size; 67size_t buf_size; 68 69/* Local variables */ 70static int targ_fd; 71static int kq_fd; 72static int file_fd; --- 8 unchanged lines hidden (view full) --- 81 82/* Local functions */ 83static void cleanup(void); 84static int init_ccbs(void); 85static void request_loop(void); 86static void handle_read(void); 87/* static int work_atio(struct ccb_accept_tio *); */ 88static void queue_io(struct ccb_scsiio *); | 66off_t volume_size; 67u_int sector_size; 68size_t buf_size; 69 70/* Local variables */ 71static int targ_fd; 72static int kq_fd; 73static int file_fd; --- 8 unchanged lines hidden (view full) --- 82 83/* Local functions */ 84static void cleanup(void); 85static int init_ccbs(void); 86static void request_loop(void); 87static void handle_read(void); 88/* static int work_atio(struct ccb_accept_tio *); */ 89static void queue_io(struct ccb_scsiio *); |
89static void run_queue(struct ccb_accept_tio *); | 90static int run_queue(struct ccb_accept_tio *); |
90static int work_inot(struct ccb_immed_notify *); 91static struct ccb_scsiio * 92 get_ctio(void); 93/* static void free_ccb(union ccb *); */ 94static cam_status get_sim_flags(u_int16_t *); 95static void rel_simq(void); 96static void abort_all_pending(void); 97static void usage(void); --- 14 unchanged lines hidden (view full) --- 112 num_ctios = 0; 113 sector_size = SECTOR_SIZE; 114 buf_size = DFLTPHYS; 115 116 /* Prepare resource pools */ 117 TAILQ_INIT(&pending_queue); 118 TAILQ_INIT(&work_queue); 119 | 91static int work_inot(struct ccb_immed_notify *); 92static struct ccb_scsiio * 93 get_ctio(void); 94/* static void free_ccb(union ccb *); */ 95static cam_status get_sim_flags(u_int16_t *); 96static void rel_simq(void); 97static void abort_all_pending(void); 98static void usage(void); --- 14 unchanged lines hidden (view full) --- 113 num_ctios = 0; 114 sector_size = SECTOR_SIZE; 115 buf_size = DFLTPHYS; 116 117 /* Prepare resource pools */ 118 TAILQ_INIT(&pending_queue); 119 TAILQ_INIT(&work_queue); 120 |
120 while ((ch = getopt(argc, argv, "AdSTb:c:s:W:")) != -1) { | 121 while ((ch = getopt(argc, argv, "AdSTYb:c:s:W:")) != -1) { |
121 switch(ch) { 122 case 'A': 123 req_flags |= SID_Addr16; 124 break; 125 case 'd': 126 debug = 1; 127 break; 128 case 'S': --- 59 unchanged lines hidden (view full) --- 188 req_flags |= SID_WBus32; 189 break; 190 default: 191 warnx("Width %s not supported", optarg); 192 usage(); 193 /* NOTREACHED */ 194 } 195 break; | 122 switch(ch) { 123 case 'A': 124 req_flags |= SID_Addr16; 125 break; 126 case 'd': 127 debug = 1; 128 break; 129 case 'S': --- 59 unchanged lines hidden (view full) --- 189 req_flags |= SID_WBus32; 190 break; 191 default: 192 warnx("Width %s not supported", optarg); 193 usage(); 194 /* NOTREACHED */ 195 } 196 break; |
197 case 'Y': 198 notaio = 1; 199 break; |
|
196 default: 197 usage(); 198 /* NOTREACHED */ 199 } 200 } 201 argc -= optind; 202 argv += optind; 203 --- 37 unchanged lines hidden (view full) --- 241 volume_size = mediasize / sector_size; 242 } else 243#endif 244 volume_size = st.st_size / sector_size; 245 } else { 246 volume_size = user_size / sector_size; 247 } 248 if (debug) | 200 default: 201 usage(); 202 /* NOTREACHED */ 203 } 204 } 205 argc -= optind; 206 argv += optind; 207 --- 37 unchanged lines hidden (view full) --- 245 volume_size = mediasize / sector_size; 246 } else 247#endif 248 volume_size = st.st_size / sector_size; 249 } else { 250 volume_size = user_size / sector_size; 251 } 252 if (debug) |
249#if __FreeBSD_version >= 500000 250 warnx("volume_size: %d bytes x %jd sectors", 251#else 252 warnx("volume_size: %d bytes x %lld sectors", 253#endif | 253 warnx("volume_size: %d bytes x " OFF_FMT " sectors", |
254 sector_size, volume_size); 255 256 if (volume_size <= 0) 257 errx(1, "volume must be larger than %d", sector_size); 258 | 254 sector_size, volume_size); 255 256 if (volume_size <= 0) 257 errx(1, "volume must be larger than %d", sector_size); 258 |
259 { | 259 if (notaio == 0) { |
260 struct aiocb aio, *aiop; 261 | 260 struct aiocb aio, *aiop; 261 |
262 /* Make sure we have working AIO support */ | 262 /* See if we have we have working AIO support */ |
263 memset(&aio, 0, sizeof(aio)); 264 aio.aio_buf = malloc(sector_size); 265 if (aio.aio_buf == NULL) 266 err(1, "malloc"); 267 aio.aio_fildes = file_fd; 268 aio.aio_offset = 0; 269 aio.aio_nbytes = sector_size; 270 signal(SIGSYS, SIG_IGN); 271 if (aio_read(&aio) != 0) { | 263 memset(&aio, 0, sizeof(aio)); 264 aio.aio_buf = malloc(sector_size); 265 if (aio.aio_buf == NULL) 266 err(1, "malloc"); 267 aio.aio_fildes = file_fd; 268 aio.aio_offset = 0; 269 aio.aio_nbytes = sector_size; 270 signal(SIGSYS, SIG_IGN); 271 if (aio_read(&aio) != 0) { |
272 printf("You must enable VFS_AIO in your kernel " 273 "or load the aio(4) module.\n"); 274 err(1, "aio_read"); | 272 printf("AIO support is not available- switchin to" 273 " single-threaded mode.\n"); 274 notaio = 1; 275 } else { 276 if (aio_waitcomplete(&aiop, NULL) != sector_size) 277 err(1, "aio_waitcomplete"); 278 assert(aiop == &aio); 279 signal(SIGSYS, SIG_DFL); |
275 } | 280 } |
276 if (aio_waitcomplete(&aiop, NULL) != sector_size) 277 err(1, "aio_waitcomplete"); 278 assert(aiop == &aio); 279 signal(SIGSYS, SIG_DFL); | |
280 free((void *)aio.aio_buf); | 281 free((void *)aio.aio_buf); |
281 if (debug) | 282 if (debug && notaio == 0) |
282 warnx("aio support tested ok"); 283 } 284 285 /* Go through all the control devices and find one that isn't busy. */ 286 unit = 0; 287 do { 288 snprintf(targname, sizeof(targname), "/dev/targ%d", unit++); 289 targ_fd = open(targname, O_RDWR); --- 16 unchanged lines hidden (view full) --- 306 307 /* Enable listening on the specified LUN */ 308 if (ioctl(targ_fd, TARGIOCENABLE, &ioc_enlun) != 0) 309 err(1, "TARGIOCENABLE"); 310 311 /* Enable debugging if requested */ 312 if (debug) { 313 if (ioctl(targ_fd, TARGIOCDEBUG, &debug) != 0) | 283 warnx("aio support tested ok"); 284 } 285 286 /* Go through all the control devices and find one that isn't busy. */ 287 unit = 0; 288 do { 289 snprintf(targname, sizeof(targname), "/dev/targ%d", unit++); 290 targ_fd = open(targname, O_RDWR); --- 16 unchanged lines hidden (view full) --- 307 308 /* Enable listening on the specified LUN */ 309 if (ioctl(targ_fd, TARGIOCENABLE, &ioc_enlun) != 0) 310 err(1, "TARGIOCENABLE"); 311 312 /* Enable debugging if requested */ 313 if (debug) { 314 if (ioctl(targ_fd, TARGIOCDEBUG, &debug) != 0) |
314 err(1, "TARGIOCDEBUG"); | 315 warnx("TARGIOCDEBUG"); |
315 } 316 317 /* Set up inquiry data according to what SIM supports */ 318 if (get_sim_flags(&sim_flags) != CAM_REQ_CMP) 319 errx(1, "get_sim_flags"); 320 if (tcmd_init(req_flags, sim_flags) != 0) 321 errx(1, "Initializing tcmd subsystem failed"); 322 --- 93 unchanged lines hidden (view full) --- 416 417 ts.tv_sec = 0; 418 ts.tv_nsec = 0; 419 tptr = NULL; 420 quit = 0; 421 422 /* Loop until user signal */ 423 while (quit == 0) { | 316 } 317 318 /* Set up inquiry data according to what SIM supports */ 319 if (get_sim_flags(&sim_flags) != CAM_REQ_CMP) 320 errx(1, "get_sim_flags"); 321 if (tcmd_init(req_flags, sim_flags) != 0) 322 errx(1, "Initializing tcmd subsystem failed"); 323 --- 93 unchanged lines hidden (view full) --- 417 418 ts.tv_sec = 0; 419 ts.tv_nsec = 0; 420 tptr = NULL; 421 quit = 0; 422 423 /* Loop until user signal */ 424 while (quit == 0) { |
424 int retval, i; | 425 int retval, i, oo; |
425 struct ccb_hdr *ccb_h; 426 427 /* Check for the next signal, read ready, or AIO completion */ 428 retval = kevent(kq_fd, NULL, 0, events, MAX_EVENTS, tptr); 429 if (retval < 0) { 430 if (errno == EINTR) { 431 if (debug) 432 warnx("EINTR, looping"); 433 continue; 434 } 435 else { 436 err(1, "kevent failed"); 437 } 438 } else if (retval > MAX_EVENTS) { 439 errx(1, "kevent returned more events than allocated?"); 440 } 441 442 /* Process all received events. */ | 426 struct ccb_hdr *ccb_h; 427 428 /* Check for the next signal, read ready, or AIO completion */ 429 retval = kevent(kq_fd, NULL, 0, events, MAX_EVENTS, tptr); 430 if (retval < 0) { 431 if (errno == EINTR) { 432 if (debug) 433 warnx("EINTR, looping"); 434 continue; 435 } 436 else { 437 err(1, "kevent failed"); 438 } 439 } else if (retval > MAX_EVENTS) { 440 errx(1, "kevent returned more events than allocated?"); 441 } 442 443 /* Process all received events. */ |
443 for (i = 0; i < retval; i++) { | 444 for (oo = i = 0; i < retval; i++) { |
444 if ((events[i].flags & EV_ERROR) != 0) 445 errx(1, "kevent registration failed"); 446 447 switch (events[i].filter) { 448 case EVFILT_READ: 449 if (debug) 450 warnx("read ready"); 451 handle_read(); --- 7 unchanged lines hidden (view full) --- 459 460 ctio = (struct ccb_scsiio *)events[i].udata; 461 c_descr = (struct ctio_descr *) 462 ctio->ccb_h.targ_descr; 463 c_descr->event = AIO_DONE; 464 /* Queue on the appropriate ATIO */ 465 queue_io(ctio); 466 /* Process any queued completions. */ | 445 if ((events[i].flags & EV_ERROR) != 0) 446 errx(1, "kevent registration failed"); 447 448 switch (events[i].filter) { 449 case EVFILT_READ: 450 if (debug) 451 warnx("read ready"); 452 handle_read(); --- 7 unchanged lines hidden (view full) --- 460 461 ctio = (struct ccb_scsiio *)events[i].udata; 462 c_descr = (struct ctio_descr *) 463 ctio->ccb_h.targ_descr; 464 c_descr->event = AIO_DONE; 465 /* Queue on the appropriate ATIO */ 466 queue_io(ctio); 467 /* Process any queued completions. */ |
467 run_queue(c_descr->atio); | 468 oo += run_queue(c_descr->atio); |
468 break; 469 } 470 case EVFILT_SIGNAL: 471 if (debug) 472 warnx("signal ready, setting quit"); 473 quit = 1; 474 break; 475 default: | 469 break; 470 } 471 case EVFILT_SIGNAL: 472 if (debug) 473 warnx("signal ready, setting quit"); 474 quit = 1; 475 break; 476 default: |
476 warnx("unknown event %#x", events[i].filter); | 477 warnx("unknown event %d", events[i].filter); |
477 break; 478 } 479 480 if (debug) | 478 break; 479 } 480 481 if (debug) |
481 warnx("event done"); | 482 warnx("event %d done", events[i].filter); |
482 } 483 | 483 } 484 |
485 if (oo) { 486 tptr = &ts; 487 continue; 488 } 489 |
|
484 /* Grab the first CCB and perform one work unit. */ 485 if ((ccb_h = TAILQ_FIRST(&work_queue)) != NULL) { 486 union ccb *ccb; 487 488 ccb = (union ccb *)ccb_h; 489 switch (ccb_h->func_code) { 490 case XPT_ACCEPT_TARGET_IO: 491 /* Start one more transfer. */ --- 37 unchanged lines hidden (view full) --- 529 } 530} 531 532/* CCBs are ready from the kernel */ 533static void 534handle_read() 535{ 536 union ccb *ccb_array[MAX_INITIATORS], *ccb; | 490 /* Grab the first CCB and perform one work unit. */ 491 if ((ccb_h = TAILQ_FIRST(&work_queue)) != NULL) { 492 union ccb *ccb; 493 494 ccb = (union ccb *)ccb_h; 495 switch (ccb_h->func_code) { 496 case XPT_ACCEPT_TARGET_IO: 497 /* Start one more transfer. */ --- 37 unchanged lines hidden (view full) --- 535 } 536} 537 538/* CCBs are ready from the kernel */ 539static void 540handle_read() 541{ 542 union ccb *ccb_array[MAX_INITIATORS], *ccb; |
537 int ccb_count, i; | 543 int ccb_count, i, oo; |
538 539 ccb_count = read(targ_fd, ccb_array, sizeof(ccb_array)); 540 if (ccb_count <= 0) { 541 warn("read ccb ptrs"); 542 return; 543 } 544 ccb_count /= sizeof(union ccb *); 545 if (ccb_count < 1) { --- 35 unchanged lines hidden (view full) --- 581 struct ctio_descr *c_descr; 582 583 ctio = &ccb->ctio; 584 c_descr = (struct ctio_descr *)ctio->ccb_h.targ_descr; 585 c_descr->event = CTIO_DONE; 586 /* Queue on the appropriate ATIO */ 587 queue_io(ctio); 588 /* Process any queued completions. */ | 544 545 ccb_count = read(targ_fd, ccb_array, sizeof(ccb_array)); 546 if (ccb_count <= 0) { 547 warn("read ccb ptrs"); 548 return; 549 } 550 ccb_count /= sizeof(union ccb *); 551 if (ccb_count < 1) { --- 35 unchanged lines hidden (view full) --- 587 struct ctio_descr *c_descr; 588 589 ctio = &ccb->ctio; 590 c_descr = (struct ctio_descr *)ctio->ccb_h.targ_descr; 591 c_descr->event = CTIO_DONE; 592 /* Queue on the appropriate ATIO */ 593 queue_io(ctio); 594 /* Process any queued completions. */ |
589 run_queue(c_descr->atio); | 595 oo += run_queue(c_descr->atio); |
590 break; 591 } 592 case XPT_IMMED_NOTIFY: 593 /* INOTs are handled with priority */ 594 TAILQ_INSERT_HEAD(&work_queue, &ccb->ccb_h, 595 periph_links.tqe); 596 break; 597 default: --- 16 unchanged lines hidden (view full) --- 614 615 if (debug) 616 warnx("Working on ATIO %p", atio); 617 618 a_descr = (struct atio_descr *)atio->ccb_h.targ_descr; 619 620 /* Get a CTIO and initialize it according to our known parameters */ 621 ctio = get_ctio(); | 596 break; 597 } 598 case XPT_IMMED_NOTIFY: 599 /* INOTs are handled with priority */ 600 TAILQ_INSERT_HEAD(&work_queue, &ccb->ccb_h, 601 periph_links.tqe); 602 break; 603 default: --- 16 unchanged lines hidden (view full) --- 620 621 if (debug) 622 warnx("Working on ATIO %p", atio); 623 624 a_descr = (struct atio_descr *)atio->ccb_h.targ_descr; 625 626 /* Get a CTIO and initialize it according to our known parameters */ 627 ctio = get_ctio(); |
622 if (ctio == NULL) | 628 if (ctio == NULL) { |
623 return (1); | 629 return (1); |
630 } |
|
624 ret = 0; 625 ctio->ccb_h.flags = a_descr->flags; 626 ctio->tag_id = atio->tag_id; 627 ctio->init_id = atio->init_id; 628 /* XXX priority needs to be added to a_descr */ 629 c_descr = (struct ctio_descr *)ctio->ccb_h.targ_descr; 630 c_descr->atio = atio; 631 if ((a_descr->flags & CAM_DIR_IN) != 0) --- 22 unchanged lines hidden (view full) --- 654 } 655 656 status = atio->ccb_h.status & CAM_STATUS_MASK; 657 switch (status) { 658 case CAM_CDB_RECVD: 659 ret = tcmd_handle(atio, ctio, ATIO_WORK); 660 break; 661 case CAM_REQ_ABORTED: | 631 ret = 0; 632 ctio->ccb_h.flags = a_descr->flags; 633 ctio->tag_id = atio->tag_id; 634 ctio->init_id = atio->init_id; 635 /* XXX priority needs to be added to a_descr */ 636 c_descr = (struct ctio_descr *)ctio->ccb_h.targ_descr; 637 c_descr->atio = atio; 638 if ((a_descr->flags & CAM_DIR_IN) != 0) --- 22 unchanged lines hidden (view full) --- 661 } 662 663 status = atio->ccb_h.status & CAM_STATUS_MASK; 664 switch (status) { 665 case CAM_CDB_RECVD: 666 ret = tcmd_handle(atio, ctio, ATIO_WORK); 667 break; 668 case CAM_REQ_ABORTED: |
669 warn("ATIO %p aborted", a_descr); |
|
662 /* Requeue on HBA */ 663 TAILQ_REMOVE(&work_queue, &atio->ccb_h, periph_links.tqe); 664 send_ccb((union ccb *)atio, /*priority*/1); 665 ret = 1; 666 break; 667 default: 668 warnx("ATIO completed with unhandled status %#x", status); 669 abort(); --- 4 unchanged lines hidden (view full) --- 674 return (ret); 675} 676 677static void 678queue_io(struct ccb_scsiio *ctio) 679{ 680 struct ccb_hdr *ccb_h; 681 struct io_queue *ioq; | 670 /* Requeue on HBA */ 671 TAILQ_REMOVE(&work_queue, &atio->ccb_h, periph_links.tqe); 672 send_ccb((union ccb *)atio, /*priority*/1); 673 ret = 1; 674 break; 675 default: 676 warnx("ATIO completed with unhandled status %#x", status); 677 abort(); --- 4 unchanged lines hidden (view full) --- 682 return (ret); 683} 684 685static void 686queue_io(struct ccb_scsiio *ctio) 687{ 688 struct ccb_hdr *ccb_h; 689 struct io_queue *ioq; |
682 struct ctio_descr *c_descr, *curr_descr; | 690 struct ctio_descr *c_descr; |
683 684 c_descr = (struct ctio_descr *)ctio->ccb_h.targ_descr; | 691 692 c_descr = (struct ctio_descr *)ctio->ccb_h.targ_descr; |
685 /* If the completion is for a specific ATIO, queue in order */ 686 if (c_descr->atio != NULL) { 687 struct atio_descr *a_descr; 688 689 a_descr = (struct atio_descr *)c_descr->atio->ccb_h.targ_descr; 690 ioq = &a_descr->cmplt_io; 691 } else { | 693 if (c_descr->atio == NULL) { |
692 errx(1, "CTIO %p has NULL ATIO", ctio); 693 } | 694 errx(1, "CTIO %p has NULL ATIO", ctio); 695 } |
696 ioq = &((struct atio_descr *)c_descr->atio->ccb_h.targ_descr)->cmplt_io; |
|
694 | 697 |
695 /* Insert in order, sorted by offset */ 696 if (!TAILQ_EMPTY(ioq)) { 697 TAILQ_FOREACH_REVERSE(ccb_h, ioq, io_queue, periph_links.tqe) { 698 curr_descr = (struct ctio_descr *)ccb_h->targ_descr; 699 if (curr_descr->offset <= c_descr->offset) { 700 TAILQ_INSERT_AFTER(ioq, ccb_h, &ctio->ccb_h, 701 periph_links.tqe); 702 break; 703 } 704 if (TAILQ_PREV(ccb_h, io_queue, periph_links.tqe) 705 == NULL) { 706 TAILQ_INSERT_BEFORE(ccb_h, &ctio->ccb_h, 707 periph_links.tqe); 708 break; 709 } | 698 if (TAILQ_EMPTY(ioq)) { 699 TAILQ_INSERT_HEAD(ioq, &ctio->ccb_h, periph_links.tqe); 700 return; 701 } 702 703 TAILQ_FOREACH_REVERSE(ccb_h, ioq, io_queue, periph_links.tqe) { 704 struct ctio_descr *curr_descr = 705 (struct ctio_descr *)ccb_h->targ_descr; 706 if (curr_descr->offset <= c_descr->offset) { 707 break; |
710 } | 708 } |
709 } 710 711 if (ccb_h) { 712 TAILQ_INSERT_AFTER(ioq, ccb_h, &ctio->ccb_h, periph_links.tqe); |
|
711 } else { 712 TAILQ_INSERT_HEAD(ioq, &ctio->ccb_h, periph_links.tqe); 713 } 714} 715 716/* 717 * Go through all completed AIO/CTIOs for a given ATIO and advance data 718 * counts, start continuation IO, etc. 719 */ | 713 } else { 714 TAILQ_INSERT_HEAD(ioq, &ctio->ccb_h, periph_links.tqe); 715 } 716} 717 718/* 719 * Go through all completed AIO/CTIOs for a given ATIO and advance data 720 * counts, start continuation IO, etc. 721 */ |
720static void | 722static int |
721run_queue(struct ccb_accept_tio *atio) 722{ 723 struct atio_descr *a_descr; 724 struct ccb_hdr *ccb_h; 725 int sent_status, event; 726 727 if (atio == NULL) | 723run_queue(struct ccb_accept_tio *atio) 724{ 725 struct atio_descr *a_descr; 726 struct ccb_hdr *ccb_h; 727 int sent_status, event; 728 729 if (atio == NULL) |
728 return; | 730 return (0); |
729 730 a_descr = (struct atio_descr *)atio->ccb_h.targ_descr; 731 732 while ((ccb_h = TAILQ_FIRST(&a_descr->cmplt_io)) != NULL) { 733 struct ccb_scsiio *ctio; 734 struct ctio_descr *c_descr; 735 736 ctio = (struct ccb_scsiio *)ccb_h; --- 19 unchanged lines hidden (view full) --- 756 periph_links.tqe); 757 tcmd_handle(atio, ctio, c_descr->event); 758 759 /* If entire transfer complete, send back ATIO */ 760 if (sent_status != 0 && event == CTIO_DONE) 761 send_ccb((union ccb *)atio, /*priority*/1); 762 } else { 763 /* Gap in offsets so wait until later callback */ | 731 732 a_descr = (struct atio_descr *)atio->ccb_h.targ_descr; 733 734 while ((ccb_h = TAILQ_FIRST(&a_descr->cmplt_io)) != NULL) { 735 struct ccb_scsiio *ctio; 736 struct ctio_descr *c_descr; 737 738 ctio = (struct ccb_scsiio *)ccb_h; --- 19 unchanged lines hidden (view full) --- 758 periph_links.tqe); 759 tcmd_handle(atio, ctio, c_descr->event); 760 761 /* If entire transfer complete, send back ATIO */ 762 if (sent_status != 0 && event == CTIO_DONE) 763 send_ccb((union ccb *)atio, /*priority*/1); 764 } else { 765 /* Gap in offsets so wait until later callback */ |
764 if (debug) 765 warnx("IO %p out of order", ccb_h); 766 break; | 766 if (/* debug */ 1) 767 warnx("IO %p:%p out of order %s", ccb_h, 768 a_descr, c_descr->event == AIO_DONE? 769 "aio" : "ctio"); 770 return (1); |
767 } 768 } | 771 } 772 } |
773 return (0); |
|
769} 770 771static int 772work_inot(struct ccb_immed_notify *inot) 773{ 774 cam_status status; 775 int sense; 776 --- 74 unchanged lines hidden (view full) --- 851/* Return a CTIO/descr/buf combo from the freelist or malloc one */ 852static struct ccb_scsiio * 853get_ctio() 854{ 855 struct ccb_scsiio *ctio; 856 struct ctio_descr *c_descr; 857 struct sigevent *se; 858 | 774} 775 776static int 777work_inot(struct ccb_immed_notify *inot) 778{ 779 cam_status status; 780 int sense; 781 --- 74 unchanged lines hidden (view full) --- 856/* Return a CTIO/descr/buf combo from the freelist or malloc one */ 857static struct ccb_scsiio * 858get_ctio() 859{ 860 struct ccb_scsiio *ctio; 861 struct ctio_descr *c_descr; 862 struct sigevent *se; 863 |
859 if (num_ctios == MAX_CTIOS) | 864 if (num_ctios == MAX_CTIOS) { 865 warnx("at CTIO max"); |
860 return (NULL); | 866 return (NULL); |
867 } |
|
861 862 ctio = (struct ccb_scsiio *)malloc(sizeof(*ctio)); 863 if (ctio == NULL) { 864 warn("malloc CTIO"); 865 return (NULL); 866 } 867 c_descr = (struct ctio_descr *)malloc(sizeof(*c_descr)); 868 if (c_descr == NULL) { --- 113 unchanged lines hidden (view full) --- 982 } 983 } 984} 985 986static void 987usage() 988{ 989 fprintf(stderr, | 868 869 ctio = (struct ccb_scsiio *)malloc(sizeof(*ctio)); 870 if (ctio == NULL) { 871 warn("malloc CTIO"); 872 return (NULL); 873 } 874 c_descr = (struct ctio_descr *)malloc(sizeof(*c_descr)); 875 if (c_descr == NULL) { --- 113 unchanged lines hidden (view full) --- 989 } 990 } 991} 992 993static void 994usage() 995{ 996 fprintf(stderr, |
990 "Usage: scsi_target [-AdST] [-b bufsize] [-c sectorsize]\n" | 997 "Usage: scsi_target [-AdSTY] [-b bufsize] [-c sectorsize]\n" |
991 "\t\t[-r numbufs] [-s volsize] [-W 8,16,32]\n" 992 "\t\tbus:target:lun filename\n"); 993 exit(1); 994} | 998 "\t\t[-r numbufs] [-s volsize] [-W 8,16,32]\n" 999 "\t\tbus:target:lun filename\n"); 1000 exit(1); 1001} |