Hi Frieder,

On 2026-10-27T14:16:39+11:00, Frieder Schrempf <[email protected]> wrote:
> blk: Unbind partition devices when removing a block device
>
> blk_post_probe() binds a UCLASS_PARTITION child for each partition
> found on the device. Removing the block device removes these children,
> but does not unbind them. When the block device is probed again, a
> second set of partition devices is bound next to the first one.
>
> This happens for example when the probe of a block device fails in the
> EVT_DM_POST_PROBE event and is retried later. The EFI disk code then
> iterates over all children and tries to install a second EFI handle
> with the same device path for the stale partition device, which fails
> with EFI_ALREADY_STARTED:
>
>   Adding partition for [email protected]:1 failed
>   switch to partitions #0, ERROR
>
> As every further probe adds another set of partition devices, the
> block device can't be used anymore until the next reset. This was seen
> on an i.MX93 board where a single failed read during the first probe
> of the SD card made it unusable for the rest of the boot.
>
> Unbind the partition devices in the pre_remove hook of the block
> uclass, so that they are bound and unbound together with the probe and
> remove of the block device. When only some devices are removed, like
> before booting an OS, the partition devices don't match the remove
> flags and are still active at this point, so remove them first.

I don't think this is true any more. Since commit 3632b5d63c8 ("dm:
Remove children when parent is removed by flags"), when the parent
matches the flags, device_remove() removes the children with
DM_REMOVE_ACTIVE_ALL masked out, before uclass_pre_remove_device() is
called. The partition driver is not vital, so by the time
blk_pre_remove() runs the partition devices are always inactive.
Please can you drop this sentence?

> [...]
>
>  drivers/block/blk-uclass.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)

> diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c
> @@ -841,9 +841,31 @@ static int blk_post_probe(struct udevice *dev)
> +     /*
> +      * The partition devices are bound in blk_post_probe(), so unbind them
> +      * here. Otherwise the next probe adds a second set of them. They are
> +      * still active if the remove flags don't match their driver, so
> +      * remove them first.
> +      */
> +     ret = device_chld_remove(dev, drv, DM_REMOVE_NORMAL);
> +     if (ret)
> +             return ret;
> +
> +     return device_chld_unbind(dev, drv);

For the same reason, the device_chld_remove() call does nothing, since
device_remove() has already removed all the children by this point.
You could just call device_chld_unbind() and trim the last sentence of
the comment. If you want to keep the call as a safety net, please
change the comment so it doesn't say the partitions can still be
active here. If they ever were, device_unbind() would fail with
-EINVAL rather than leave things in a bad state.

Regards,
Simon

Reply via email to