>   s390irq_spin_lock_irqsave (...);
>   dasd_chanq_enq (...);
>   dasd_schedule_bh (...);
>   do {
>     s390irq_spin_unlock_irqrestore (...);
>     wait_event ( device->wait_q,
>                  (((cs = req->status) == CQR_STATUS_DONE) ...);
>     s390irq_spin_lock_irqsave (...);
>   } while (cs != CQR_STATUS_DONE ...);

> For example, immediately after the `SSM' instruction in the unlock
> is executed an external interrupt could occur.  The first bottom
> half routine is then dispatched scheduling the i/o (dasd_run_bh ->
> dasd_start_IO -> do_IO -> SSCH).  before the instruction after the SSM
> instruction can be executed, the i/o interrupt could occur.
> `dasd_int_handler' sets the cqr status to DONE and schedules the
> second bottom half routine.  Now `dasd_sleep_on_req' doesn't
> wait at all because `wait_event' doesn't wait if the specified
> condition is true.  Control returns back to `dasd_format',
> which calls `dasd_free_request', then `dasd_eckd_format_device' which
> zeroes the cqr (effectively setting the status to EMPTY).  If an
> external interrupt now occurs then the second bottom half routine
> runs and the bug occurs because it doesn't expect an EMPTY status.

I see a great deal of similarity between the above and a bug
in USB that I fixed. Basically, the waiter must not check the
status of the request (in USB case it was URB), but instead,
poll a flag set by the last callback (in our case the second
bottom half).

-- Pete

Reply via email to