= Introduction = Kevin asked for all the ways you can reopen BDSes with different options or flags. This memo only covers all the ways you can reopen, but it doesn't attempt to fully analyze how options or flags change in each case.
This is a systematic review of all the ways you can reopen BDSes in qemu proper, i.e. not in qemu-{img,io,nbd}. I tracked them down by following the call chains leading to bdrv_reopen_multiple(). = QMP commands = * block-commit Two separate code paths, depending on whether we're it's an active layer commit or not. - If active, we reopen the base with the root's flags. If we fail later during start, we try to restore the flags by reopening again. In theory, restoring can fail, and then we mess up the flags. Avoiding that would be nice. The actual commit is done by code shared with drive-mirror, covered below. - Else, we reopen both the base and the overlay read/write. The overlay is the BDS that has the top as backing file. If we fail later during start, we don't attempt to undo a change to read/write, as far as I can tell. Looks like a bug. On completion, we do attempt to undo, by reopening them again with their original flags. * blockdev-snapshot-sync Creating an external snapshot of a node means splicing in a new snapshot BDS with the node as backing file. We then try to reopen the node readonly, because it's now a backing file. Failure is ignored, i.e. the node simply remains as writable as before. * change-backing-file This updates the backing file in the image. If the BDS is read-only, we reopen read/write before, and reopen read-only after. If the first reopen fails, the command fails without doing anything. If the update fails, we try the second reopen before failing the command with the failed update's error. If the second reopen fails (unlikely), the command fails in an ugly way: the BDS is left writable. Avoiding that would be nice. * drive-mirror On successful completion, we do some BDS rewiring I don't fully understand. The mirror target BDS gets swapped into another BDS. If the two have different flags, we reopen the target to make them the same before we swap. An explanation of what happens here is welcome. * transaction This is a wrapper around a list of transaction-capable commands. Thus, nothing new here. = Other user interfaces = * HMP command commit Less capable cousin of QMP command block-commit. Should be implemented on top of QMP, but isn't. Instead, we a separate, specialized duplicate of the general commit code: bdrv_commit(). * Console escape key 's' Like HMP command "commit all". See mux_proc_byte(). Public service announcement: don't name your block backends "all". * HMP command drive_mirror Implemented on top of QMP, so nothing new here. = Generic block layer = bdrv_reopen_queue() collects BDSes for atomic reopen, bdrv_reopen_multiple() actually does it, in two stages, bdrv_reopen_prepare() and bdrv_reopen_commit() / bdrv_reopen_abort(). All three call block driver methods with the same name. bdrv_reopen() is a convenience wrapper for reopening a single BDS. = Block driver methods = Only one of them recurses: * vmdk_reopen_prepare() Queues the extents. Necessary, because the block driver hides them from the generic block layer. Needs work, see also "Review of ways to create BDSes".