From: James Mckenzie Date: Fri, 11 Dec 2009 18:00:42 +0000 (+0000) Subject: fix race in async cdrom code X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=c719bdcbcc4d54fe46af532a659b33dbe873812f;p=xenclient%2Fioemu-pq.git fix race in async cdrom code --- diff --git a/master/series b/master/series index 9b12de0..90ecb79 100644 --- a/master/series +++ b/master/series @@ -32,3 +32,4 @@ dont-carp-about-a-missing-battery vga-clear-hw-fb-on-resize hide-msi-capability-for-igfx vga-edid +tidy-muticies-in-ata-pt diff --git a/master/tidy-muticies-in-ata-pt b/master/tidy-muticies-in-ata-pt new file mode 100644 index 0000000..c41dcfe --- /dev/null +++ b/master/tidy-muticies-in-ata-pt @@ -0,0 +1,621 @@ +diff --git a/hw/atapi-pt.c b/hw/atapi-pt.c +index 2d26983..7f59aca 100644 +--- a/hw/atapi-pt.c ++++ b/hw/atapi-pt.c +@@ -7,6 +7,8 @@ + #include + #include + #include ++#include ++#include + #include "xen.h" + + /* Even when defined debugging is only enabled if /etc/debugcdrom exists */ +@@ -395,6 +397,8 @@ static const struct { + + static int we_have_lock = 0; + ++static void ide_atapi_pt_ejected(void); ++ + static int get_lock_fd(void) + { + static int lock_fd=-1; +@@ -773,6 +777,9 @@ static uint32_t ide_atapi_pt_get_data_size(int size_select, uint8_t command, uin + + static void ide_atapi_pt_set_error(IDEState *s, int sense_key, int asc, int ascq, int error) + { ++ static uint32_t serial=0; ++ ++ DEBUG_PRINTF("ide_atapi_pt_set_error serial 0x%x\n",xerial++); + memset(&s->atapi_pt.sense, 0, 18); + s->atapi_pt.sense.sense_key = sense_key; + s->atapi_pt.sense.asc = asc; +@@ -807,16 +814,11 @@ static void ide_atapi_pt_error(IDEState *s) + * send our command. + * This is the BSG SG_IO v4 implementation. + */ +-static void *ide_atapi_pt_sgio_worker_thread(void *arg) ++static int ide_atapi_pt_do_dispatch(volatile IDEState *s) + { +- int r; + struct sg_io_v4 cmd; + BDRVRawState *raw_state; +- volatile IDEState *s = (volatile IDEState *)arg; +- +- for(;;) { +- pthread_mutex_lock(&s->atapi_pt.sgio_mutex); +- pthread_cond_wait(&s->atapi_pt.sgio_cv, &s->atapi_pt.sgio_mutex); ++ int r; + + /* Send command and wait for reply, SG_IO ioctl*/ + memset(&cmd, 0, sizeof(cmd)); +@@ -869,11 +871,215 @@ static void *ide_atapi_pt_sgio_worker_thread(void *arg) + s->atapi_pt.sense.asc, + s->atapi_pt.sense.ascq)); + } ++ return r; ++} ++ ++static int status_file_touched(const char *fn,time_t *t) ++{ ++ int fd; ++ struct stat buf; ++ ++ if (!t) return 0; ++ ++ if(stat(IDE_ATAPI_PT_NEW_CD_FILE, &buf)) { ++ DEBUG_PRINTF("Error stating %s\n",fn); ++ return 0; ++ } ++ ++ if (buf.st_ctime > *t) { ++ *t=buf.st_ctime; ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static void touch_status_file(const char *fn,time_t *t) ++{ ++ int fd; ++ struct stat buf; ++ ++ fd = open(fn, O_WRONLY | O_TRUNC | O_CREAT, 0666); ++ if(fd < 0) { ++ DEBUG_PRINTF("Error touching %s\n",fn); ++ } else { ++ close(fd); ++ utime(fn, NULL); ++ } ++ ++ if(stat(IDE_ATAPI_PT_NEW_CD_FILE, &buf)) { ++ DEBUG_PRINTF("Error stating %s\n",fn); ++ return; ++ } ++ ++ if (t) ++ *t = buf.st_ctime; ++} ++ ++static void ide_atapi_pt_cmd_complete(void *arg) /* Mop up result*/ ++{ ++ IDEState *s = (IDEState *)arg; ++ uint8_t cmd_code = s->atapi_pt.request[0]; ++ uint32_t din_desired; ++ static uint32_t serial = 0; ++ ++ assert(s); ++ ++ ++ { ++ /* Get return code of ioctl from worker thread's fd */ ++ int r; ++ recv(s->atapi_pt.sgio_dispatch_fd, &r, sizeof(int),0); ++ ++ DEBUG_PRINTF("ide_atapi_pt_cmd_complete serial 0x%x - code %d\n",serial++,r); ++ } ++ ++ if(s->atapi_pt.result) ++ { ++ if(s->atapi_pt.request[0] == GPCMD_TEST_UNIT_READY && ++ s->atapi_pt.sense.sense_key == 2 && s->atapi_pt.sense.asc == 0x3A) ++ /* No media, remove exclusivity lock */ ++ ide_atapi_pt_ejected(); ++ ++ ide_atapi_pt_error(s); ++ return; ++ } ++ ++ if(s->atapi_pt.request[0] == GPCMD_GET_EVENT_STATUS_NOTIFICATION) ++ { ++ ++ if(s->io_buffer[2] == 4 && s->io_buffer[4] == 2) ++ { ++ /* This is a "new media" message, tell any other VMs */ ++ DEBUG_PRINTF("[ATAPI] new media detected\n"); ++ ++ touch_status_file(IDE_ATAPI_PT_NEW_CD_FILE,&s->atapi_pt.new_cd_time); ++ } ++ ++ if(s->io_buffer[2] == 4 && s->io_buffer[4] == 3) ++ { ++ /* This is a "media removed" message, tell any other VMs */ ++ DEBUG_PRINTF("[ATAPI] media removed\n"); ++ ++ touch_status_file(IDE_ATAPI_PT_EJECT_CD_FILE,&s->atapi_pt.new_cd_time); ++ ++ /* Remove exclusivity lock */ ++ ide_atapi_pt_ejected(); ++ } ++ ++ if((s->io_buffer[2] == 4 && s->io_buffer[4] == 0 && s->io_buffer[5] == 2) || ++ (s->io_buffer[4] == 0 && s->io_buffer[5] == 0 && ++ s->io_buffer[6] == 0 && s->io_buffer[7] == 0)) ++ { ++ /* This is a no activity message we can hijack if we need to */ ++ ++ if(status_file_touched(IDE_ATAPI_PT_NEW_CD_FILE,&s->atapi_pt.new_cd_time)) { ++ DEBUG_PRINTF("[ATAPI] new media message spotted\n"); ++ ++ s->io_buffer[2] = 4; ++ s->io_buffer[4] = 2; ++ s->io_buffer[5] = 2; ++ s->io_buffer[6] = 0; ++ s->io_buffer[7] = 0; ++ } else if(status_file_touched(IDE_ATAPI_PT_EJECT_CD_FILE,&s->atapi_pt.eject_time)) ++ { ++ /* There's been an eject message that we haven't seen yet */ ++ DEBUG_PRINTF("[ATAPI] media removed message spotted\n"); ++ ++ s->io_buffer[2] = 4; ++ s->io_buffer[4] = 3; ++ s->io_buffer[5] = 1; ++ s->io_buffer[6] = 0; ++ s->io_buffer[7] = 0; ++ } ++ } ++ } ++ ++ if(s->atapi_pt.din_xfer_len == 0) ++ { ++ // Nothing else to do ++ ide_atapi_cmd_ok(s); ++ return; ++ } ++ ++ din_desired = ide_atapi_pt_get_data_size(ide_atapi_pt_size_din, cmd_code, s->io_buffer); ++ ++ /* din_xfer_len is the size of the buffer provided for the din data, ++ * din_desired in the size of the data the LU tried to send to us. Either one ++ * may be bigger. */ ++ ++ if(s->atapi_pt.request[0] == GPCMD_READ_BUFFER) ++ { ++ switch(s->atapi_pt.request[1] & 7) ++ { ++ case 0: // data with header, as specified in atapi_data_sizes table ++ break; ++ ++ case 2: // data only ++ din_desired = s->atapi_pt.din_xfer_len; ++ break; ++ ++ case 3: // header only ++ din_desired = 4; ++ break; ++ ++ case 1: // vendor specific ++ default: ++ DEBUG_PRINTF("\e[3;31mIllegal read buffer mode %d\e[m\n", ++ s->io_buffer[1] & 7); ++ ide_atapi_pt_set_error(s, SENSE_ILLEGAL_REQUEST, ++ ASC_INV_FIELD_IN_CMD_PACKET, 0, 0x70); ++ return; ++ } ++ } ++ ++ if(din_desired == (__u32)-1) ++ din_desired = s->atapi_pt.din_xfer_len; ++ ++ DEBUG_PRINTF("Read %d bytes of data (buffer size %d)\n", ++ din_desired, s->atapi_pt.din_xfer_len); ++ ++ if(s->atapi_pt.din_xfer_len >= 0x80 && din_desired >= 0x80) ++ DEBUG_HEXDUMP(s->io_buffer, 0x80); ++ else if(s->atapi_pt.din_xfer_len < din_desired) ++ DEBUG_HEXDUMP(s->io_buffer, s->atapi_pt.din_xfer_len); ++ else ++ DEBUG_HEXDUMP(s->io_buffer, din_desired); ++ ++ ide_atapi_cmd_reply(s, din_desired, s->atapi_pt.din_xfer_len); ++} ++ ++ ++static void *ide_atapi_pt_sgio_worker_thread(void *arg) ++{ ++ int r; ++ fd_set rfds; ++ sigset_t set; ++ static uint32_t serial=0; ++ volatile IDEState *s = (volatile IDEState *)arg; + +- /* Unlock _before_ signalling parent */ +- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex); +- write(s->atapi_pt.sgio_wfd, &r, sizeof(int)); ++ if (sigfillset(&set)) { DEBUG_PRINTF("sigfillset\n"); return NULL; } ++ if (pthread_sigmask(SIG_BLOCK, &set, NULL)) { DEBUG_PRINTF("sigprocmask"); return NULL; } ++ ++ FD_ZERO(&rfds); ++ ++ for(;;) { ++ struct timeval zero={0}; ++ recv(s->atapi_pt.sgio_worker_fd,&r,sizeof(int),0); ++ ++ FD_SET(s->atapi_pt.sgio_worker_fd,&rfds); ++ ++ while (select(s->atapi_pt.sgio_worker_fd+1,&rfds,NULL,NULL,&zero)==1) { ++ recv(s->atapi_pt.sgio_worker_fd,&r,sizeof(int),MSG_DONTWAIT); ++ } ++ ++ DEBUG_PRINTF("ide_atapi_pt_sgio_worker_thread: in serial 0x%x\n",serial++); ++ r=ide_atapi_pt_do_dispatch(s); ++ DEBUG_PRINTF("ide_atapi_pt_sgio_worker_thread: out serial 0x%x response %d\n",serial-1,r); ++ ++ write(s->atapi_pt.sgio_worker_fd, &r, sizeof(int)); + } ++return NULL; + } + + +@@ -884,49 +1090,45 @@ static int ide_atapi_pt_aio_flush(void *unused) + return 0; + } + +-static void ide_atapi_pt_cmd_complete(void *arg); + + static void ide_atapi_pt_setup_sgio_thread(IDEState *s) + { + int fds[2]; + +- if(pipe(fds) < 0) { +- DEBUG_PRINTF("atapi-pt failed to create pipe: %m\n"); ++ if(socketpair(PF_UNIX,SOCK_DGRAM,0,fds) < 0) { ++ DEBUG_PRINTF("atapi-pt failed to create socketpair: %m\n"); + exit(1); + } +- s->atapi_pt.sgio_rfd = fds[0]; +- s->atapi_pt.sgio_wfd = fds[1]; +- +- pthread_mutex_init(&s->atapi_pt.sgio_mutex, NULL); +- pthread_cond_init (&s->atapi_pt.sgio_cv, NULL); ++ s->atapi_pt.sgio_dispatch_fd = fds[0]; ++ s->atapi_pt.sgio_worker_fd = fds[1]; + + if (pthread_create(&s->atapi_pt.sgio_thread, NULL, ide_atapi_pt_sgio_worker_thread, (void *)s)) + { + DEBUG_PRINTF("Create CD-ROM worker thread failed\n"); + exit(1); + } +- qemu_aio_set_fd_handler(s->atapi_pt.sgio_rfd, ide_atapi_pt_cmd_complete, NULL, ide_atapi_pt_aio_flush, (void *)s); ++ qemu_aio_set_fd_handler(s->atapi_pt.sgio_dispatch_fd, ide_atapi_pt_cmd_complete, NULL, ide_atapi_pt_aio_flush, (void *)s); + } + +-/* Call with ide_atapi_sgio_mutex held */ + static void ide_atapi_pt_do_sg_io(IDEState *s) + { ++ static uint32_t serial=0; ++ int r='K'; ++ DEBUG_PRINTF("ide_atapi_pt_do_sg_io 0x%x\n",serial++); ++ + /* Poke worker thread to send command using SG_IO ioctl */ +- pthread_cond_signal(&s->atapi_pt.sgio_cv); +- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex); ++ send(s->atapi_pt.sgio_dispatch_fd,&r,sizeof(int),MSG_NOSIGNAL); + } + + + /* Functions to fetch dout data from where-ever it comes from */ + +-/* Call with ide_atapi_sgio_mutex held */ + static void ide_atapi_pt_dout_fetch_pio_done(IDEState *s) + { + ide_transfer_stop(s); + ide_atapi_pt_do_sg_io(s); + } + +-/* Call with ide_atapi_sgio_mutex held */ + static void ide_atapi_pt_dout_fetch_dma_done(void *opaque, int ret) + { + BMDMAState *bm = opaque; +@@ -935,7 +1137,6 @@ static void ide_atapi_pt_dout_fetch_dma_done(void *opaque, int ret) + + if (ret < 0) { + ide_atapi_io_error(s, ret); +- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex); + return; + } + +@@ -943,7 +1144,6 @@ static void ide_atapi_pt_dout_fetch_dma_done(void *opaque, int ret) + ide_atapi_pt_do_sg_io(s); + } + +-/* Call with ide_atapi_sgio_mutex held */ + static void ide_atapi_pt_wcmd(IDEState *s) + { + if (s->atapi_dma) +@@ -1107,11 +1307,6 @@ static void ide_atapi_pt_cmd(IDEState *s) + uint8_t cmd_code; + FILE *fp; + +- if(pthread_mutex_trylock(&s->atapi_pt.sgio_mutex)) { +- DEBUG_PRINTF("ide_atapi_pt_cmd() called with existing request processing - ignored!\n"); +- return; +- } +- + memcpy(s->atapi_pt.request, s->io_buffer, ATAPI_PACKET_SIZE); + cmd_code = s->atapi_pt.request[0]; + s->atapi_pt.timeout = 15000; +@@ -1148,8 +1343,8 @@ static void ide_atapi_pt_cmd(IDEState *s) + DEBUG_HEXDUMP(s->io_buffer, actual_size); + + ide_atapi_cmd_reply(s, size, max_size); +- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex); +- return; ++ return; ++ + } + + s->atapi_pt.dout_xfer_len = ide_atapi_pt_get_data_size(ide_atapi_pt_size_dout, +@@ -1178,8 +1373,8 @@ static void ide_atapi_pt_cmd(IDEState *s) + memcpy(s->io_buffer, inquiry_data, 96); + memset(&s->atapi_pt.sense, 0, sizeof(sense)); + ide_atapi_cmd_reply(s, 96, s->atapi_pt.din_xfer_len); +- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex); +- return; ++ return; ++ + } + + if(cmd_code == GPCMD_MODE_SENSE_10) +@@ -1192,8 +1387,7 @@ static void ide_atapi_pt_cmd(IDEState *s) + DEBUG_PRINTF("Blocking command due to exclusivity lock\n"); + memcpy(&s->atapi_pt.sense, sense, sizeof(sense)); + ide_atapi_pt_set_error(s, sense[2], sense[12], sense[13], 0x70); +- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex); +- return; ++ return; + } + + /* Claim exclusive use if we're doing any kind of writing */ +@@ -1210,8 +1404,7 @@ static void ide_atapi_pt_cmd(IDEState *s) + // FIXME XXX - make this throw an error + memcpy(&s->atapi_pt.sense, sense, 18); + ide_atapi_pt_set_error(s, sense[2], sense[12], sense[13], 0x70); +- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex); +- return; ++ return; + #endif + } + } +@@ -1225,8 +1418,8 @@ static void ide_atapi_pt_cmd(IDEState *s) + case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL: + // we don't allow locking, to prevent a VM from hogging the drive + ide_atapi_cmd_ok(s); +- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex); +- return; ++ return; ++ + + case GPCMD_FLUSH_CACHE: // bigger timeout while flushing write cache + s->atapi_pt.timeout = 1000 * 60; +@@ -1256,8 +1449,7 @@ static void ide_atapi_pt_cmd(IDEState *s) + s->io_buffer[1] & 7); + ide_atapi_pt_set_error(s, SENSE_ILLEGAL_REQUEST, + ASC_INV_FIELD_IN_CMD_PACKET, 0, 0x70); +- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex); +- return; ++ return; + } + + break; +@@ -1328,8 +1520,8 @@ static void ide_atapi_pt_cmd(IDEState *s) + s->io_buffer[10]); + ide_atapi_pt_set_error(s, SENSE_ILLEGAL_REQUEST, + ASC_INV_FIELD_IN_CMD_PACKET, 0, 0x70); +- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex); +- return; ++ return; ++ + } + + s->atapi_pt.din_xfer_len += 8; // 8 bytes of header +@@ -1352,8 +1544,7 @@ static void ide_atapi_pt_cmd(IDEState *s) + DEBUG_HEXDUMP(s->atapi_pt.request, ATAPI_PACKET_SIZE); + ide_atapi_pt_set_error(s, SENSE_ILLEGAL_REQUEST, + ASC_ILLEGAL_OPCODE, 0, 0x70); +- pthread_mutex_unlock(&s->atapi_pt.sgio_mutex); +- return; ++ return; + } + + if(s->atapi_pt.dout_xfer_len > 0) +@@ -1364,162 +1555,6 @@ static void ide_atapi_pt_cmd(IDEState *s) + } + + ide_atapi_pt_do_sg_io(s); +-} +- +-static void ide_atapi_pt_cmd_complete(void *arg) +-{ +- IDEState *s = (IDEState *)arg; +- int r; +- uint8_t cmd_code = s->atapi_pt.request[0]; +- uint32_t din_desired; +- +- assert(s); +- +- /* Get return code of ioctl from worker thread's fd */ +- read(s->atapi_pt.sgio_rfd, &r, sizeof(int)); +- +- if(s->atapi_pt.result) +- { +- if(s->atapi_pt.request[0] == GPCMD_TEST_UNIT_READY && +- s->atapi_pt.sense.sense_key == 2 && s->atapi_pt.sense.asc == 0x3A) +- /* No media, remove exclusivity lock */ +- ide_atapi_pt_ejected(); +- +- ide_atapi_pt_error(s); +- return; +- } +- +- if(s->atapi_pt.request[0] == GPCMD_GET_EVENT_STATUS_NOTIFICATION) +- { +- struct stat file_stat; +- int fd; +- +- if(s->io_buffer[2] == 4 && s->io_buffer[4] == 2) +- { +- /* This is a "new media" message, tell any other VMs */ +- DEBUG_PRINTF("[ATAPI] new media detected\n"); +- +- fd = open(IDE_ATAPI_PT_NEW_CD_FILE, O_WRONLY | O_TRUNC | O_CREAT, 0666); +- if(fd < 0) { +- DEBUG_PRINTF("Error touching new CD file\n"); +- } else { +- close(fd); +- utime(IDE_ATAPI_PT_NEW_CD_FILE, NULL); +- } +- +- if(stat(IDE_ATAPI_PT_NEW_CD_FILE, &file_stat) != 0) +- DEBUG_PRINTF("Error writing to new CD file\n"); +- else +- s->atapi_pt.new_cd_time = file_stat.st_ctime; +- } +- +- if(s->io_buffer[2] == 4 && s->io_buffer[4] == 3) +- { +- /* This is a "media removed" message, tell any other VMs */ +- DEBUG_PRINTF("[ATAPI] media removed\n"); +- +- fd = open(IDE_ATAPI_PT_EJECT_CD_FILE, O_WRONLY | O_TRUNC | O_CREAT, 0666); +- if(fd < 0) { +- DEBUG_PRINTF("Error touching eject CD file\n"); +- } else { +- close(fd); +- utime(IDE_ATAPI_PT_EJECT_CD_FILE, NULL); +- } +- +- if(stat(IDE_ATAPI_PT_EJECT_CD_FILE, &file_stat) != 0) +- DEBUG_PRINTF("Error writing to eject CD file\n"); +- else +- s->atapi_pt.eject_time = file_stat.st_ctime; +- +- /* Remove exclusivity lock */ +- ide_atapi_pt_ejected(); +- } +- +- if((s->io_buffer[2] == 4 && s->io_buffer[4] == 0 && s->io_buffer[5] == 2) || +- (s->io_buffer[4] == 0 && s->io_buffer[5] == 0 && +- s->io_buffer[6] == 0 && s->io_buffer[7] == 0)) +- { +- /* This is a no activity message we can hijack if we need to */ +- +- if(stat(IDE_ATAPI_PT_NEW_CD_FILE, &file_stat) == 0 && +- s->atapi_pt.new_cd_time < file_stat.st_ctime) +- { +- /* There's been a new media message that we haven't seen yet */ +- s->atapi_pt.new_cd_time = file_stat.st_ctime; +- DEBUG_PRINTF("[ATAPI] new media message spotted\n"); +- +- s->io_buffer[2] = 4; +- s->io_buffer[4] = 2; +- s->io_buffer[5] = 2; +- s->io_buffer[6] = 0; +- s->io_buffer[7] = 0; +- } +- else if(stat(IDE_ATAPI_PT_EJECT_CD_FILE, &file_stat) == 0 && +- s->atapi_pt.eject_time < file_stat.st_ctime) +- { +- /* There's been an eject message that we haven't seen yet */ +- DEBUG_PRINTF("[ATAPI] media removed message spotted\n"); +- s->atapi_pt.eject_time = file_stat.st_ctime; +- +- s->io_buffer[2] = 4; +- s->io_buffer[4] = 3; +- s->io_buffer[5] = 1; +- s->io_buffer[6] = 0; +- s->io_buffer[7] = 0; +- } +- } +- } +- +- if(s->atapi_pt.din_xfer_len == 0) +- { +- // Nothing else to do +- ide_atapi_cmd_ok(s); +- return; +- } +- +- din_desired = ide_atapi_pt_get_data_size(ide_atapi_pt_size_din, cmd_code, s->io_buffer); +- +- /* din_xfer_len is the size of the buffer provided for the din data, +- * din_desired in the size of the data the LU tried to send to us. Either one +- * may be bigger. */ +- +- if(s->atapi_pt.request[0] == GPCMD_READ_BUFFER) +- { +- switch(s->atapi_pt.request[1] & 7) +- { +- case 0: // data with header, as specified in atapi_data_sizes table +- break; +- +- case 2: // data only +- din_desired = s->atapi_pt.din_xfer_len; +- break; + +- case 3: // header only +- din_desired = 4; +- break; +- +- case 1: // vendor specific +- default: +- DEBUG_PRINTF("\e[3;31mIllegal read buffer mode %d\e[m\n", +- s->io_buffer[1] & 7); +- ide_atapi_pt_set_error(s, SENSE_ILLEGAL_REQUEST, +- ASC_INV_FIELD_IN_CMD_PACKET, 0, 0x70); +- return; +- } +- } +- +- if(din_desired == (__u32)-1) +- din_desired = s->atapi_pt.din_xfer_len; +- +- DEBUG_PRINTF("Read %d bytes of data (buffer size %d)\n", +- din_desired, s->atapi_pt.din_xfer_len); +- +- if(s->atapi_pt.din_xfer_len >= 0x80 && din_desired >= 0x80) +- DEBUG_HEXDUMP(s->io_buffer, 0x80); +- else if(s->atapi_pt.din_xfer_len < din_desired) +- DEBUG_HEXDUMP(s->io_buffer, s->atapi_pt.din_xfer_len); +- else +- DEBUG_HEXDUMP(s->io_buffer, din_desired); +- +- ide_atapi_cmd_reply(s, din_desired, s->atapi_pt.din_xfer_len); + } ++ +diff --git a/hw/ide.c b/hw/ide.c +index 37d0996..8a8c856 100644 +--- a/hw/ide.c ++++ b/hw/ide.c +@@ -437,8 +437,8 @@ typedef struct ATAPIPassThroughState + pthread_t sgio_thread; + pthread_mutex_t sgio_mutex; + pthread_cond_t sgio_cv; +- int sgio_rfd; +- int sgio_wfd; ++ int sgio_worker_fd; ++ int sgio_dispatch_fd; + } ATAPIPassThroughState; + #endif /* __linux__ */ +