sculpt: handle failures of usb_block_drv

This patch handles the situation where the usb_block_drv exits for any
reason, in particular when the driver fails to initialize the device. In
such cases, the usb_block_drv used to stay stale in the system,
effectively preventing the device from being passed to a VM. With the
patch, the USB storage device gets flagged as failed, the usb_block_drv
is removed from the runtime, and the condition is reflected at the user
interface.

This situation occurred on the attempt to access an iomega zip drive
with a version of the usb_block_drv without support for the START-STOP
command, but it may potentially also occur in other circumstances.

Fixes #3468
This commit is contained in:
Norman Feske 2019-08-09 10:57:39 +02:00 committed by Christian Helmuth
parent 2d03e622f1
commit 67a3c2ea4b
4 changed files with 38 additions and 8 deletions

View File

@ -1099,6 +1099,7 @@ void Sculpt::Main::_handle_runtime_state()
_runtime_state.update_from_state_report(state);
bool reconfigure_runtime = false;
bool regenerate_dialog = false;
/* check for completed storage operations */
_storage._storage_devices.for_each([&] (Storage_device &device) {
@ -1185,6 +1186,17 @@ void Sculpt::Main::_handle_runtime_state()
}); /* for each device */
/* handle failed initialization of USB-storage devices */
_storage._storage_devices.usb_storage_devices.for_each([&] (Usb_storage_device &dev) {
String<64> name(dev.usb_block_drv_name());
Child_exit_state exit_state(state, name);
if (exit_state.exited) {
dev.discard_usb_block_drv();
reconfigure_runtime = true;
regenerate_dialog = true;
}
});
/* remove prepare subsystem when finished */
{
Child_exit_state exit_state(state, "prepare");
@ -1233,7 +1245,7 @@ void Sculpt::Main::_handle_runtime_state()
| _runtime_view_state.apply_child_state_report(child)) {
reconfigure_runtime = true;
generate_dialog();
regenerate_dialog = true;
}
});
@ -1245,9 +1257,12 @@ void Sculpt::Main::_handle_runtime_state()
if (_deploy.update_child_conditions()) {
reconfigure_runtime = true;
generate_dialog();
regenerate_dialog = true;
}
if (regenerate_dialog)
generate_dialog();
if (reconfigure_runtime)
generate_runtime_config();
}

View File

@ -25,9 +25,10 @@ namespace Sculpt { struct Storage_device; };
struct Sculpt::Storage_device
{
enum State {
UNKNOWN, /* partition information not yet known */
USED, /* part_block is running and has reported partition info */
RELEASED /* partition info is known but part_block is not running */
UNKNOWN, /* partition information not yet known */
USED, /* part_block is running and has reported partition info */
RELEASED, /* partition info is known but part_block is not running */
FAILED /* driver failed to access the device */
};
Allocator &_alloc;

View File

@ -81,6 +81,16 @@ struct Sculpt::Usb_storage_device : List_model<Usb_storage_device>::Element,
return drv_needed || Storage_device::state == UNKNOWN;
}
/**
* Release USB device
*
* This method is called as response to a failed USB-block-driver
* initialization.
*/
void discard_usb_block_drv() { Storage_device::state = FAILED; }
bool discarded() const { return Storage_device::state == FAILED; }
Label usb_block_drv_name() const { return Label(label, ".drv"); }
Usb_storage_device(Env &env, Allocator &alloc, Signal_context_capability sigh,

View File

@ -275,12 +275,13 @@ void Sculpt::Storage_dialog::_gen_block_device(Xml_generator &xml,
void Sculpt::Storage_dialog::_gen_usb_storage_device(Xml_generator &xml,
Usb_storage_device const &dev) const
{
bool const selected = _device_item.selected(dev.label);
bool const discarded = dev.discarded();
bool const selected = !discarded && _device_item.selected(dev.label);
xml.node("button", [&] () {
xml.attribute("name", dev.label);
if (_device_item.hovered(dev.label))
if (_device_item.hovered(dev.label) && !discarded)
xml.attribute("hovered", "yes");
if (selected)
@ -307,10 +308,13 @@ void Sculpt::Storage_dialog::_gen_usb_storage_device(Xml_generator &x
});
});
typedef String<64> Info;
Info const info = dev.discarded() ? Info("unsupported") : Info(dev.capacity);
gen_named_node(xml, "float", "capacity", [&] () {
xml.attribute("east", "yes");
xml.node("label", [&] () {
xml.attribute("text", String<64>(dev.capacity)); }); });
xml.attribute("text", info); }); });
});
});