Bug 154443 - kernel dm-multipath: can device be destroyed while outstanding pg_init I/O?
kernel dm-multipath: can device be destroyed while outstanding pg_init I/O?
Status: CLOSED DUPLICATE of bug 154442
Product: Red Hat Enterprise Linux 4
Classification: Red Hat
Component: device-mapper-multipath (Show other bugs)
All Linux
medium Severity medium
: ---
: ---
Assigned To: Alasdair Kergon
Depends On:
  Show dependency treegraph
Reported: 2005-04-11 14:28 EDT by Alasdair Kergon
Modified: 2010-01-11 21:20 EST (History)
4 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Last Closed: 2005-07-02 15:55:02 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---

Attachments (Terms of Use)

  None (edit)
Description Alasdair Kergon 2005-04-11 14:28:24 EDT
Need to re-check the logic in the existing code.


> Suspend cannot complete until there is no I/O outstanding, including
> any pg_init I/O.
>   - queueing is disabled while suspended
>   - the last I/O through cannot complete with an error until the last
>     path has failed, which can't happen until the pg_init for its PG
>     has completed.

Comments from Ed Goggin [based on a different version of the code]:

I think there are two other
use cases besides the __switch_pg() case described above whereby
a pg_init i/o can be left outstanding after its multipath structure's
memory is freed.  

First, the most common case -- it is possible for an uncompleted PG
switch to be pending with no i/os queued to the multipath
when a dev_suspend initiated i/o suspension followed by table swap
occurs.  process_queued_ios() when called by multipath_presuspend(),
will initiate a pg_init even though there are no queued user i/os.
Because there are no i/os queued, the suspend will not block
waiting for the pg_init to complete.  If the dm_table_put() call
on the old table frees the multipath structure memory before the
pg_init i/o completes (likely case), the problem occurs.  This case
can be prevented simply by having process_queued_ios() not initiate
a pg_init i/o if there are no queued i/os pended on the multipath

Second, a somewhat less common case -- a pg_init i/o is outstanding when
a dev_suspend() call is made on a multipath for which the kernel thinks
it currently has no valid paths.  I think the sequence of events for the
use case is as enumerated below.   I think this case can be prevented
by not calling dispatch_queued_ios() if there is a oustanding pg_init.
This state is detected by the conditional logic
        (m->queue_io && !m->pg_init_required)
In this case, any queued i/os will be dispatched only after the
outstanding pg_init i/o completes via the call to process_queued_io()
from dm_pg_init_complete().  dm_pg_init_complete() must also be
changed to reset the queue_io flag if the suspended flag is set
even in the case of an error on the pg_init i/o, otherwise the
i/os would never be dispatched in the "all-paths-down" use case.
(1)     pg_init i/o is sent and causes queuing of one or more user i/os
(2)     all paths are detected as failed in kernel
(3)     multipath reloads new table causing via dev_suspend() ioctl causing
        i/o suspend followed by table swap
        (a)     pre-suspend causes even the last i/o to fail on
                the last path -- even before the pg_init for its
                PG has completed
Comment 1 Alasdair Kergon 2005-07-02 15:55:02 EDT
With the patch from bug 154442 I think this is now resolved:

A pg_init can't be issued unless there's I/O outstanding.

suspend waits for I/O => it waits for pg_init to complete.

destroy first does suspend.

*** This bug has been marked as a duplicate of 154442 ***

Note You need to log in before you can comment on or make changes to this bug.