From a68a6665ac08bd5dc677b2fa3f95c80dde39313a Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Fri, 21 Aug 2020 14:14:18 +0200 Subject: [PATCH] sculpt: remove part_block upon failure With this patch, sculpt uses init's heartbeat-monitoring mechanism to detect the failure of part_block instances during storage disovery. If part_block gets stuck, the device is released and can thereby be accessed at the whole-device level. Issue #3861 --- repos/gems/src/app/sculpt_manager/main.cc | 12 ++++++++++++ .../src/app/sculpt_manager/model/child_exit_state.h | 10 +++++++--- .../src/app/sculpt_manager/model/storage_device.h | 9 +++++++-- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/repos/gems/src/app/sculpt_manager/main.cc b/repos/gems/src/app/sculpt_manager/main.cc index 1ee27c3836..709d975fc8 100644 --- a/repos/gems/src/app/sculpt_manager/main.cc +++ b/repos/gems/src/app/sculpt_manager/main.cc @@ -1478,6 +1478,16 @@ void Sculpt::Main::_handle_runtime_state() }); /* for each partition */ + /* respond to failure of part_block */ + if (device.discovery_in_progress()) { + Child_exit_state exit_state(state, device.part_block_start_name()); + if (!exit_state.responsive) { + error(device.part_block_start_name(), " got stuck"); + device.state = Storage_device::RELEASED; + reconfigure_runtime = true; + } + } + /* respond to completion of GPT relabeling */ if (device.relabel_in_progress()) { Child_exit_state exit_state(state, device.relabel_start_name()); @@ -1607,6 +1617,8 @@ void Sculpt::Main::_generate_runtime_config(Xml_generator &xml) const xml.attribute("buffer", "1M"); }); + xml.node("heartbeat", [&] () { xml.attribute("rate_ms", 1000); }); + xml.node("parent-provides", [&] () { gen_parent_service(xml); gen_parent_service(xml); diff --git a/repos/gems/src/app/sculpt_manager/model/child_exit_state.h b/repos/gems/src/app/sculpt_manager/model/child_exit_state.h index a3465250bd..c176bc284f 100644 --- a/repos/gems/src/app/sculpt_manager/model/child_exit_state.h +++ b/repos/gems/src/app/sculpt_manager/model/child_exit_state.h @@ -24,9 +24,10 @@ namespace Sculpt { struct Child_exit_state; } struct Sculpt::Child_exit_state { - bool exists = false; - bool exited = false; - int code = 0; + bool exists = false; + bool exited = false; + bool responsive = true; + int code = 0; typedef String<64> Name; typedef String<16> Version; @@ -39,10 +40,13 @@ struct Sculpt::Child_exit_state if (child.attribute_value("name", Name()) == name) { exists = true; version = child.attribute_value("version", Version()); + if (child.has_attribute("exited")) { exited = true; code = child.attribute_value("exited", 0L); } + + responsive = (child.attribute_value("skipped_heartbeats", 0U) <= 2); } }); } diff --git a/repos/gems/src/app/sculpt_manager/model/storage_device.h b/repos/gems/src/app/sculpt_manager/model/storage_device.h index 721496bcee..dcf5d6af43 100644 --- a/repos/gems/src/app/sculpt_manager/model/storage_device.h +++ b/repos/gems/src/app/sculpt_manager/model/storage_device.h @@ -201,8 +201,11 @@ struct Sculpt::Storage_device return gpt_expand_in_progress() || fs_resize_in_progress(); } - Start_name relabel_start_name() const { return Start_name(label, ".relabel"); } - Start_name expand_start_name() const { return Start_name(label, ".expand"); } + bool discovery_in_progress() const { return state == UNKNOWN; } + + Start_name part_block_start_name() const { return Start_name(label, ".part_block"); } + Start_name relabel_start_name() const { return Start_name(label, ".relabel"); } + Start_name expand_start_name() const { return Start_name(label, ".expand"); } }; @@ -216,6 +219,8 @@ void Sculpt::Storage_device::gen_part_block_start_content(Xml_generator &xml, gen_named_node(xml, "binary", "part_block"); + xml.node("heartbeat", [&] () { }); + xml.node("config", [&] () { xml.node("report", [&] () { xml.attribute("partitions", "yes"); });