qemu-stable
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-stable] [Qemu-devel] [PATCH 2/2] ide: fix crash in IDE cdrom r


From: Denis V. Lunev
Subject: Re: [Qemu-stable] [Qemu-devel] [PATCH 2/2] ide: fix crash in IDE cdrom read
Date: Thu, 14 Dec 2017 14:29:09 +0300
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.5.0

On 12/13/2017 02:40 AM, John Snow wrote:
> Hi Den, the long email about IDE stuff:
>
> On 11/30/2017 07:01 AM, Denis V. Lunev wrote:
>> On 11/29/2017 02:50 AM, John Snow wrote:
>>> On 11/28/2017 07:10 AM, Denis V. Lunev wrote:
>>>> There is the following crash reported from the field in QEMU 2.9:
>>>>     bdrv_inc_in_flight (address@hidden)
>>>>     blk_aio_prwv
>>>>     blk_aio_preadv
>>>>     ide_buffered_readv
>>>>     cd_read_sector
>>> Is ide_atapi_cmd_reply_end missing from the call stack here for some
>>> reason? ide_data_readw /should/ have end_transfer_func set to that if it
>>> was processing an ATAPI command; otherwise it shouldn't be able to get
>>> here under normal circumstances...
>> this is my fault. I have lost this line while removing unnecessary into
>> from callstack. Here if the full one.
>>
> Well, at least we're back on terra firma here.
>
> I'm going to talk myself through what the problem looks like here, and I
> have some questions for you at the bottom of the email, so you can just
> skim if you're not interested in the details.
>
>> (gdb) bt
>> #0  bdrv_inc_in_flight (address@hidden) at block/io.c:561
>> #1  0x000055b224160d37 in blk_aio_prwv (blk=0x55b2265405a0,
>>     address@hidden, bytes=2048,
>> address@hidden,
>>     address@hidden <blk_aio_read_entry>,
>>     address@hidden, address@hidden
>> <ide_buffered_readv_cb>,
>>     address@hidden) at block/block-backend.c:1151
>> #2  0x000055b224160db5 in blk_aio_preadv (blk=<optimized out>,
>>     address@hidden, address@hidden,
>>     address@hidden, address@hidden
>> <ide_buffered_readv_cb>,
>>     address@hidden) at block/block-backend.c:1256
>> #3  0x000055b22404bd8d in ide_buffered_readv (address@hidden,
>>     sector_num=556880, address@hidden,
>>     address@hidden,
>>     address@hidden <cd_read_sector_cb>,
>>     address@hidden) at hw/ide/core.c:637
>> #4  0x000055b22404e2c1 in cd_read_sector (s=0x55b22a712a68)
>>     at hw/ide/atapi.c:198
>> #5  ide_atapi_cmd_reply_end (s=0x55b22a712a68) at hw/ide/atapi.c:272
>> #6  0x000055b224049704 in ide_data_readw (opaque=<optimized out>,
>>     addr=<optimized out>) at hw/ide/core.c:2263
>> #7  0x000055b223edd7f0 in portio_read (opaque=0x55b22a836000, addr=0,
>> size=2)
>>     at /usr/src/debug/qemu-2.9.0/ioport.c:180
>> #8  0x000055b223ee8e3b in memory_region_read_accessor (mr=0x55b22a836000,
>>     addr=0, value=0x7f843b5be7c0, size=2, shift=0, mask=65535, attrs=...)
>>     at /usr/src/debug/qemu-2.9.0/memory.c:435
>> #9  0x000055b223ee6369 in access_with_adjusted_size (address@hidden,
>>     address@hidden, address@hidden,
>>     access_size_min=<optimized out>, access_size_max=<optimized out>,
>>     address@hidden <memory_region_read_accessor>,
>>     address@hidden, address@hidden)
>>     at /usr/src/debug/qemu-2.9.0/memory.c:592
>> #10 0x000055b223ee9d36 in memory_region_dispatch_read1 (attrs=..., size=2,
>>     pval=0x7f843b5be7c0, addr=0, mr=0x55b22a836000)
>>     at /usr/src/debug/qemu-2.9.0/memory.c:1238
>> #11 memory_region_dispatch_read (address@hidden,
>>     address@hidden, address@hidden, address@hidden,
>>     address@hidden) at /usr/src/debug/qemu-2.9.0/memory.c:1269
>> #12 0x000055b223e9bdb2 in address_space_read_continue (
>>     address@hidden <address_space_io>, address@hidden,
>> ---Type <return> to continue, or q <return> to quit---
>>     attrs=..., address@hidden,
>>     address@hidden <Address 0x7f844dc103fe out of bounds>,
>>     address@hidden, addr1=0, l=2, mr=0x55b22a836000)
>>     at /usr/src/debug/qemu-2.9.0/exec.c:2844
>> #13 0x000055b223e9be67 in address_space_read_full (
>>     as=0x55b2247db8c0 <address_space_io>, address@hidden, attrs=...,
>>     address@hidden <Address 0x7f844dc103fe out of bounds>,
>>     len=2, address@hidden) at /usr/src/debug/qemu-2.9.0/exec.c:2895
>> #14 0x000055b223e9bfce in address_space_read (len=602521191,
>>     buf=0x7f844dc103fe <Address 0x7f844dc103fe out of bounds>, attrs=...,
>>     addr=496, as=<optimized out>)
>>     at /usr/src/debug/qemu-2.9.0/include/exec/memory.h:1718
>> #15 address_space_rw (as=<optimized out>, address@hidden, attrs=...,
>>     address@hidden,
>>     address@hidden <Address 0x7f844dc103fe out of bounds>,
>>     address@hidden, address@hidden)
>>     at /usr/src/debug/qemu-2.9.0/exec.c:2909
>> #16 0x000055b223ee5271 in kvm_handle_io (count=512, size=2,
>>     direction=<optimized out>, data=<optimized out>, attrs=..., port=496)
>>     at /usr/src/debug/qemu-2.9.0/kvm-all.c:1828
>> #17 kvm_cpu_exec (address@hidden)
>>     at /usr/src/debug/qemu-2.9.0/kvm-all.c:2058
>> #18 0x000055b223ed1c22 in qemu_kvm_cpu_thread_fn (arg=0x55b229032000)
>>     at /usr/src/debug/qemu-2.9.0/cpus.c:1119
>> #19 0x00007f8443993e25 in start_thread (arg=0x7f843b5bf700)
>>     at pthread_create.c:308
>> #20 0x00007f84436c134d in clone ()
>>     at ../sysdeps/unix/sysv/linux/x86_64/clone.S:113
>>
>>
>>
>>>>     ide_data_readw
>>> How do we get here? ide_is_pio_out ought to be false here; do you know
>>> what command was being processed? Do you have a reproducer?
>>>
>>> Knowing both the ATA and ATAPI commands under consideration here would
>>> be helpful.
>>>
>> if you prefer, I can upload core/binary to some storage.
>> Here is the state.
>>
> This might be helpful for me to poke around at, but unfortunately it
> looks like I can't see the ATAPI command that was being processed from
> the trace given. I don't think there's a way for me to retrieve it from
> a core, either.
>
>> (gdb) p *s
>> $3 = {bus = 0x55b22a7129f0, unit = 0 '\000', drive_kind = IDE_CD,
>>   cylinders = 0, heads = 0, sectors = 0, chs_trans = 0, nb_sectors =
>> 11588488,
>>   mult_sectors = 16, identify_set = 1,
>>   identify_data = "\300\205", '\000' <repeats 18 times>, "MQ0000 1", ' '
>> <repeats 12 times>, "\003\000\000\002\004\000.2+5    EQUMD DVR-MO", ' '
>> <repeats 28 times>,
>> "\000\000\001\000\000\003\000\000\000\000\000\000\a", '\000' <repeats 17
>> times>,
>> "\a\000\a\000\003\000\264\000\264\000,\001\264\000\000\000\000\000\036\000\036",
>> '\000' <repeats 15 times>, "\036", '\000' <repeats 15 times>, "? ",
>> '\000' <repeats 333 times>, drive_serial = 1,
>>   drive_serial_str = "QM00001", '\000' <repeats 13 times>,
>>   drive_model_str = "QEMU DVD-ROM", '\000' <repeats 28 times>, wwn = 0,
>>   feature = 0 '\000', error = 0 '\000', nsector = 2, sector = 0 '\000',
>>   lcyl = 0 '\000', hcyl = 8 '\b', hob_feature = 0 '\000',
>>   hob_nsector = 3 '\003', hob_sector = 0 '\000', hob_lcyl = 0 '\000',
>>   hob_hcyl = 8 '\b', select = 32 ' ', status = 80 'P', lba48 = 0 '\000',
> status = BUSY_STAT
> nsector = ATAPI_INT_REASON_IO (set in ide_atapi_cmd_reply_end)
> byte_count_limit = 2048 (hcyl << 8)
>
>>   blk = 0x55b2265405a0, version = "2.5+\000\000\000\000", events = {
>>     eject_request = false, new_media = false}, sense_key = 0 '\000',
>>   asc = 0 '\000', tray_open = false, tray_locked = false,
>>   cdrom_changed = 0 '\000', packet_transfer_size = 55296,
>>   elementary_transfer_size = 0, io_buffer_index = 2048, lba = 139220,
> packet_transfer_size = 55296, (27 cd sectors)
> elementary_transfer_size = 0,
> io_buffer_index = 2048,
> lba = 139220, or 0x021fd4
>
>
> This is either an initial read request, or a rebuffering.
> In the normative case, initial reads look like this:
>
> IDE:
> ide_ioport_write
>   ide_exec_cmd (0xA0)
>     cmd_packet
>       ide_transfer_start
>         s->end_transfer_func = ide_atapi_cmd
>         [data_ptr and data_end set to meaningful values]
> [Return to guest, await PIO write of scsi cdb]
> ide_data_writew
>   ide_atapi_cmd
>     [soft error if !blk->bs]
>     cmd_read_cd
>       ide_atapi_cmd_read
>         ide_atapi_cmd_read_pio
>           ide_atapi_cmd_reply_end
>             cd_read_sector
>               [segv if !blk->bs]
>
> AHCI:
> handle_reg_h2d_fis
>   [scsi CDB is copied into s->io_buffer]
>   ide_exec_cmd
>     cmd_packet
>       ide_transfer_start
>         [data_ptr and data_end set to transfer scsi cdb]
>           ahci_start_transfer
>             [shortcut, no transfer]
>             s->data_ptr set to s->data_end [*]
>               ide_atapi_cmd
>
> * (but data_end likely is still != s->io_buffer)
>
> from here the callback is the same as above: we'll wind up at
> cd_read_sector. Neither of these cases match your traceback.
>
> If it was the initial buffering, it would have occurred synchronously
> with receipt of the SCSI CDB, but your traces place it as a consequence
> of an attempt to read data, so that makes me suspect it's a rebuffering
> attempt, and the data in s->io_buffer is... cd data? I guess? did you
> have a CD in here at one point?
>
>>   cd_sector_size = 2048, atapi_dma = 0, acct = {bytes = 2048,
> So we're using PIO paths when applicable. The s->feature register being
> 0 seems to agree.
>
>>     start_time_ns = 433417215764666, type = BLOCK_ACCT_READ}, pio_aiocb
>> = 0x0,
>>   iov = {iov_base = 0x55b22a8ae000, iov_len = 2048}, qiov = {
>>     iov = 0x55b22a712d50, niov = 1, nalloc = -1, size = 2048},
>>   buffered_requests = {lh_first = 0x0}, io_buffer_offset = 0,
>>   io_buffer_size = 0, sg = {sg = 0x0, nsg = 0, nalloc = 0, size = 0,
>>     dev = 0x0, as = 0x0}, req_nb_sectors = 0,
>>   end_transfer_func = 0x55b22404e190 <ide_atapi_cmd_reply_end>,
>>   data_ptr = 0x55b22a8ae800 "", data_end = 0x55b22a8ae800 "",
>>   io_buffer = 0x55b22a8ae000
> s->data_ptr  = 0x55b22a8ae800
> s->data_end  = 0x55b22a8ae800
> s->io_buffer = 0x55b22a8ae000
> s->io_buffer_offset = 0
>
> Uh, hm. This does not look like an in-progress PIO transfer of any kind...
>
> This says to me that ide_dummy_transfer_stop was called at some point
> and nothing has started up in its place.
>
> This seems to conflict with the trace, which looks like a rebuffering.
> This looks like... undefined behavior entirely. I am not sure I have a
> good guess as to what's happening.
>
>> ")8\"\t\031\"\232\vx.\311l\301\270o$\335\025\257\064F\271\rI,R\342\032\315\nԆV\341od\251\023>\024\370\323\060A\256\337\300텋\024\233\201U\221T^\202\303\036\"E%\262\230\367ξ\fW\302\360\277\347\334\022\253\a\025\216\rj\334z\355>)\230/\021\255%a^\306\001\032",
> ... hmm
>
> 0x29 56 34 09 19
>
> 0x29 is... almost a read command (0x28) but it isn't. 0x29 shouldn't map
> to anything, actually. So this must be data we've buffered, or something
> left over from god knows what.
>
>>   io_buffer_total_len = 131076, cur_io_buffer_offset = 0,
>>   cur_io_buffer_len = 0, end_transfer_fn_idx = 0 '\000',
>>   sector_write_timer = 0x55b22a45d5c0, irq_count = 0, ext_error = 0 '\000',
>>   mdata_size = 0, mdata_storage = 0x0, media_changed = 0,
>>   dma_cmd = IDE_DMA_READ, smart_enabled = 1 '\001', smart_autosave = 1
>> '\001',
>>   smart_errors = 0, smart_selftest_count = 0 '\000',
>> ---Type <return> to continue, or q <return> to quit---
>>   smart_selftest_data = 0x55b22a827000 "", ncq_queues = 0}
>> (gdb)
>>
>> In general, I can upload the binary and core to the location
>> you want. Send it to me in person. By the way. I am staring to
>> receive these crashes in number. 2-3 in a day BUT from one
>> specific host. This could be important.
>>
>>>>     portio_read
>>>>     memory_region_read_accessor
>>>>     access_with_adjusted_size
>>>>     memory_region_dispatch_read1
>>>>     memory_region_dispatch_read
>>>>     address_space_read_continue
>>>>     address_space_read_full
>>>>     address_space_read
>>>>     address_space_rw
>>>>     kvm_handle_io
>>>>     kvm_cpu_exec
>>>>     qemu_kvm_cpu_thread_fn
>>>>     start_thread
>>>>     clone
>>> The thing that looks to be incongruent here is that we appear to be
>>> servicing a ATAPI reply; that reply is either the kind that uses
>>> preformatted data in a buffer, or the kind that buffers a read.
>>>
>>> If it buffers a read, it should require CHECK_READY which requires a medium.
>>>
>>> If it does not buffer a read, it should not be able to invoke
>>> cd_read_sector or any bdrv function from ide_data_readw.
>>>
>>> If it neither serves preformatted data nor buffers a read, it should not
>>> allow ide_data_readw to perform any action at all.
>> the guest could misbehave! This is not a reason to crash.
>> For example there is a race or something like this. What
>> if the guest will execute read from the device without
>> ANY sanity checks? QEMU should not crash. This is the point
>> and this is the approach taken in the original patch.
>>
> The stuff quoted above isn't participatory, it's mandatory. I don't know
> how we're bypassing CHECK_READY. I want to understand what's happening
> before I pepper in sanity checks.
>
> in 2.9.0, you have this code:
>
>     if ((cmd->flags & CHECK_READY) &&
>         (!media_present(s) || !blk_is_inserted(s->blk)))
>     {
>         ide_atapi_cmd_error(s, NOT_READY, ASC_MEDIUM_NOT_PRESENT);
>         return;
>     }
>
> with media_present defined as:
>
> static inline int media_present(IDEState *s)
> {
>     return !s->tray_open && s->nb_sectors > 0;
> }
>
> ... however, from your gdb output, we do have:
>
> tray_open = false
> nb_sectors = 11588488
>
> but blk_is_inserted is still going to check for the presence of 'bs'
> attached to the Block Backend, so this check should still prevent us
> from executing a read command out of the gate.
>
> Is the guest executing a read and then are we racing with the removal of
> the bds? Do you expect a CD to be inserted on this guest?
>
> nb_sectors I would expect to be 0; based on ide_cd_change_cb:
>
>     blk_get_geometry(s->blk, &nb_sectors);
>
> this should set nb_sectors to 0 if there's no blk->bs.
>
> I'm sort of lost, I can't really easily construct what exactly happened
> here.
>
>>>> Indeed, the CDROM device without media has blk->bs == NULL. We should
>>>> check that the media is really available for the device like has been done
>>>> in SCSI code.
>>>>
>>>> May be the patch adds a bit more check than necessary, but this is not be
>>>> the problem. We should always stay on the safe side.
>>>>
>>>> Signed-off-by: Denis V. Lunev <address@hidden>
>>>> CC: John Snow <address@hidden>
>>>> CC: Kevin Wolf <address@hidden>
>>>> CC: Stefan Hajnoczi <address@hidden>
>>>> ---
>>>>  hw/ide/atapi.c | 32 ++++++++++++++++++++++++++++----
>>>>  hw/ide/core.c  |  4 ++--
>>>>  2 files changed, 30 insertions(+), 6 deletions(-)
>>>>
>>>> diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
>>>> index c0509c8bf5..fa50c0ccf6 100644
>>>> --- a/hw/ide/atapi.c
>>>> +++ b/hw/ide/atapi.c
>>>> @@ -119,6 +119,11 @@ cd_read_sector_sync(IDEState *s)
>>>>  
>>>>      trace_cd_read_sector_sync(s->lba);
>>>>  
>>>> +    if (!blk_is_available(s->blk)) {
>>>> +        ret = -ENOMEDIUM;
>>>> +        goto fail;
>>>> +    }
>>>> +
>>>>      switch (s->cd_sector_size) {
>>>>      case 2048:
>>>>          ret = blk_pread(s->blk, (int64_t)s->lba << ATAPI_SECTOR_BITS,
>>>> @@ -132,8 +137,8 @@ cd_read_sector_sync(IDEState *s)
>>>>          }
>>>>          break;
>>>>      default:
>>>> -        block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_READ);
>>>> -        return -EIO;
>>>> +        ret = -EIO;
>>>> +        goto fail;
>>>>      }
>>>>  
>>>>      if (ret < 0) {
>>>> @@ -145,6 +150,10 @@ cd_read_sector_sync(IDEState *s)
>>>>      }
>>>>  
>>>>      return ret;
>>>> +
>>>> +fail:
>>>> +    block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_READ);
>>>> +    return ret;
>>>>  }
>>>>  
>>>>  static void cd_read_sector_cb(void *opaque, int ret)
>>>> @@ -174,9 +183,15 @@ static void cd_read_sector_cb(void *opaque, int ret)
>>>>  
>>>>  static int cd_read_sector(IDEState *s)
>>>>  {
>>>> +    int err;
>>>> +
>>>>      if (s->cd_sector_size != 2048 && s->cd_sector_size != 2352) {
>>>> -        block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_READ);
>>>> -        return -EINVAL;
>>>> +        err = -EINVAL;
>>>> +        goto fail;
>>>> +    }
>>>> +    if (!blk_is_available(s->blk)) {
>>>> +        err = -ENOMEDIUM;
>>>> +        goto fail;
>>>>      }
>>>>  
>>>>      s->iov.iov_base = (s->cd_sector_size == 2352) ?
>>>> @@ -195,6 +210,10 @@ static int cd_read_sector(IDEState *s)
>>>>  
>>>>      s->status |= BUSY_STAT;
>>>>      return 0;
>>>> +
>>>> +fail:
>>>> +    block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_READ);
>>>> +    return err;
>>>>  }
>>>>  
>>>>  void ide_atapi_cmd_ok(IDEState *s)
>>>> @@ -404,6 +423,11 @@ static void ide_atapi_cmd_read_dma_cb(void *opaque, 
>>>> int ret)
>>>>          goto eot;
>>>>      }
>>>>  
>>>> +    if (!blk_is_available(s->blk)) {
>>>> +        ide_atapi_cmd_read_dma_cb(s, -ENOMEDIUM);
>>>> +        return;
>>>> +    }
>>>> +
>>> I'm not sure this is OK, because it's an error but not setting the sense
>>> code or raising an IRQ; it's only calling ide_set_inactive, so this
>>> might be a problem. Normally the error code from the data read is
>>> handled earlier in the call by ide_handle_rw_error which can set the
>>> proper codes.
>>>
>> this follows the approach used by the error handling in this call.
>> I this code is not made worse. We can hit to the same processing
>> with the different error upper.
>>
>>>>      s->io_buffer_index = 0;
>>>>      if (s->cd_sector_size == 2352) {
>>>>          n = 1;
>>>> diff --git a/hw/ide/core.c b/hw/ide/core.c
>>>> index 471d0c928b..71780fc9d1 100644
>>>> --- a/hw/ide/core.c
>>>> +++ b/hw/ide/core.c
>>>> @@ -758,7 +758,7 @@ static void ide_sector_read(IDEState *s)
>>>>  
>>>>      trace_ide_sector_read(sector_num, n);
>>>>  
>>>> -    if (!ide_sect_range_ok(s, sector_num, n)) {
>>>> +    if (!ide_sect_range_ok(s, sector_num, n) || 
>>>> !blk_is_available(s->blk)) {
>>>>          ide_rw_error(s);
>>>>          block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_READ);
>>>>          return;
>>>> @@ -1023,7 +1023,7 @@ static void ide_sector_write(IDEState *s)
>>>>  
>>>>      trace_ide_sector_write(sector_num, n);
>>>>  
>>>> -    if (!ide_sect_range_ok(s, sector_num, n)) {
>>>> +    if (!ide_sect_range_ok(s, sector_num, n) || 
>>>> !blk_is_available(s->blk)) {
>>>>          ide_rw_error(s);
>>>>          block_acct_invalid(blk_get_stats(s->blk), BLOCK_ACCT_WRITE);
>>>>          return;
>>>>
>>> Since it's not a new regression (this is being reported against 2.9) I
>>> am somewhat hesitant to rush it into 2.11-rc3 without a little more info.
>>>
>>> That said, here's a list of the ATAPI commands we service that either
>>> return or CAN return data, but do not enforce CHECK_READY:
>>>
>>>     [ 0x03 ] = { cmd_request_sense,                 ALLOW_UA },
>>>     [ 0x12 ] = { cmd_inquiry,                       ALLOW_UA },
>>>     [ 0x46 ] = { cmd_get_configuration,             ALLOW_UA },
>>>     [ 0x4a ] = { cmd_get_event_status_notification, ALLOW_UA },
>>>     [ 0x5a ] = { cmd_mode_sense, /* (10) */         0 },
>>>     [ 0xbd ] = { cmd_mechanism_status,              0 },
>>>
>>> These six all invoke ide_atapi_cmd_reply in some way (which allows the
>>> guest to begin reading the reply via PIO mechanisms if DMA is not set):
>>>
>>> cmd_request_sense:     ide_atapi_cmd_reply(s, 18, max_len);
>>> cmd_inquiry:           ide_atapi_cmd_reply(s, idx, max_len);
>>> cmd_get_configuration: ide_atapi_cmd_reply(s, len, max_len);
>>> cmd_get_event_status_notification:
>>>                        ide_atapi_cmd_reply(s, used_len, max_len);
>>> cmd_mode_sense:        ide_atapi_cmd_reply(s, 16, max_len);
>>>                        ide_atapi_cmd_reply(s, 24, max_len);
>>>                        ide_atapi_cmd_reply(s, 30, max_len);
>>> cmd_mechanism_status:  ide_atapi_cmd_reply(s, 8, max_len);
>>>
>>> ide_atapi_cmd_reply itself sets lba to -1, which should inform
>>> ide_atapi_cmd_reply_end not to attempt to buffer any new data. These
>>> *should* be safe. The reply sizes are also all small enough that they
>>> are almost certainly getting buffered in one single transfer without
>>> attempting to buffer more data.
>>>
>>> In the normative PIO case then, reads will consume from this buffer
>>> until empty, then we'll call ide_atapi_cmd_reply_end through
>>> end_transfer_func and hit the end of transfer logic.
>>>
>>> I'm not sure I see how this crash is happening; it doesn't look like
>>> this path allows for invoking the block read functions and everything
>>> else is guarded by NONDATA or CHECK_READY.
>>>
>>> Unless this is an interesting interaction with ide_atapi_cmd_reply
>>> setting the DRQ bit which may trick the pio read function to allow PIO
>>> reads to come in during this time?
>>>
>>> Hypothetically:
>>>
>>> cmd_packet sets end_transfer_func to ide_atapi_cmd so it can process
>>> further once that PIO is completed. (The PIO may be emulated
>>> synchronously, in the case of AHCI.) In the true PIO case, it may be
>>> asynchronous.
>>>
>>> Now, in the AHCI case, the guest has control back and the CDROM is now
>>> executing a command to, perhaps, read data via DMA. Then,
>>> simultaneously, the guest issues a PIO read and because the DRQ bit is
>>> set for DMA, the PIO read also goes through.
>>>
>>> This still requires a media, though... and a very broken guest doing
>>> something naughty on purpose.
>>>
>>> I can't quite connect the dots to see how this crash is possible in
>>> general... it'd help to have:
>>>
>>> - The ATAPI command being processed at the time
>>> - The IDE command being processed at the time
>>> - s->status
>>>
>>> as a minimum, and then perhaps optionally some of the ATAPI loop
>>> variables, like packet_transfer_size, elementary_transfer_size, and
>>> io_buffer_index. Or a reproducer!
>>>
>>> Sorry I'm not more help and I wrote too much again :(
>> imho this does not matter. Once again - the guest can misbehave.
> I never said that if a guest acting out of spec was the problem I
> wouldn't fix it. I just want to find the root cause.
>
> If this has been broken since 2.9, 2.11-rc3 is too late for a bandaid
> applied to something I can't diagnose. Let's discuss this for 2.12 and I
> will keep trying to figure out what the root cause is.
I have read the entire letter in 2 subsequent attempts, but
unfortunately I can not say much more additionally :(

>
> Some questions for you:
>
> (1) Is the guest Linux? Do we know why this one machine might be
> tripping up QEMU? (Is it running a fuzzer, a weird OS, etc...?)
This is running by the end-user by our customer and we do not have
access to that machine and customer. This is anonymized crash report
from the node. This is not a single crash. We observe 1-2 reports with
this crash in a day.

> (2) Does the VM actually have a CDROM inserted at some point? Is it
> possible we're racing on some kind of eject or graph manipulation failure?
unclear but IMHO probable.

> (3) Is this using AHCI or IDE?
IDE. This is known 120%. We do not provide ability to enable AHCI
without manual tweaking.

>
> If I can't figure it out within a week or so from here I'll just check
> in the band-aid with some /* FIXME */ comments attached.
No prob. We are going to ship my band-aid and see to report statistics.

Thank you in advance,
    Den



reply via email to

[Prev in Thread] Current Thread [Next in Thread]