update_engine: Added more logging and debugging for rollback checking
To help troubleshoot issues similar to http://crbug.com/356975 I added
more logging in DBus methods of update_engine to trace various stages
of determining available boot partitions, etc.
Also added two more DBus methods - to get the suggested rollback
partition name (and switched CanRollback to use this method) and
the list of availavle kernel partitions along with the 'bootable'
flag for each.
Changed update_engine_client to show the name of avaiable rollback
partition with --can_rollback and also added --show_kernels to
output list of available kernel partitions and whether each partition
is bootable or not.
BUG=None
TEST=Unit tests pass
Change-Id: Ib7f92a6460c578953ea1ba9b23bd0669acb0e22f
Reviewed-on: https://chromium-review.googlesource.com/191949
Reviewed-by: Alex Vakulenko <avakulenko@chromium.org>
Tested-by: Alex Vakulenko <avakulenko@chromium.org>
Commit-Queue: Alex Vakulenko <avakulenko@chromium.org>
diff --git a/UpdateEngine.conf b/UpdateEngine.conf
index bdfd3c8..e9fe2d5 100644
--- a/UpdateEngine.conf
+++ b/UpdateEngine.conf
@@ -20,6 +20,12 @@
send_member="CanRollback"/>
<allow send_destination="org.chromium.UpdateEngine"
send_interface="org.chromium.UpdateEngineInterface"
+ send_member="GetRollbackPartition"/>
+ <allow send_destination="org.chromium.UpdateEngine"
+ send_interface="org.chromium.UpdateEngineInterface"
+ send_member="GetKernelDevices"/>
+ <allow send_destination="org.chromium.UpdateEngine"
+ send_interface="org.chromium.UpdateEngineInterface"
send_member="ResetStatus"/>
<allow send_destination="org.chromium.UpdateEngine"
send_interface="org.chromium.UpdateEngineInterface"
@@ -50,7 +56,7 @@
send_member="GetDurationSinceUpdate"/>
<allow send_destination="org.chromium.UpdateEngine"
send_interface="org.chromium.UpdateEngineInterface"
- send_member="GetOldVersion"/>
+ send_member="GetPrevVersion"/>
<allow send_interface="org.chromium.UpdateEngineLibcrosProxyResolvedInterface" />
</policy>
<policy user="power">
diff --git a/dbus_service.cc b/dbus_service.cc
index 7235be1..03bc602 100644
--- a/dbus_service.cc
+++ b/dbus_service.cc
@@ -8,6 +8,7 @@
#include <string>
#include <base/logging.h>
+#include <base/strings/stringprintf.h>
#include <policy/device_policy.h>
#include "update_engine/clock_interface.h"
@@ -196,8 +197,33 @@
gboolean* out_can_rollback,
GError **error)
{
- LOG(INFO) << "Checking for a rollback partition.";
- *out_can_rollback = self->system_state_->update_attempter()->CanRollback();
+ bool can_rollback = self->system_state_->update_attempter()->CanRollback();
+ LOG(INFO) << "Checking for a rollback partition. Result: " << can_rollback;
+ *out_can_rollback = can_rollback;
+ return TRUE;
+}
+
+gboolean update_engine_service_get_rollback_partition(
+ UpdateEngineService* self,
+ gchar** out_rollback_partition_name,
+ GError **error) {
+ auto name = self->system_state_->update_attempter()->GetRollbackPartition();
+ LOG(INFO) << "Getting rollback partition name. Result: " << name;
+ *out_rollback_partition_name = g_strdup(name.c_str());
+ return TRUE;
+}
+
+gboolean update_engine_service_get_kernel_devices(UpdateEngineService* self,
+ gchar** out_kernel_devices,
+ GError **error) {
+ auto devices = self->system_state_->update_attempter()->GetKernelDevices();
+ std::string info;
+ for (auto&& device : devices) {
+ base::StringAppendF(&info, "%d:%s\n",
+ device.second ? 1 : 0, device.first.c_str());
+ }
+ LOG(INFO) << "Available kernel devices: " << info;
+ *out_kernel_devices = g_strdup(info.c_str());
return TRUE;
}
diff --git a/dbus_service.h b/dbus_service.h
index 3449f1f..3507918 100644
--- a/dbus_service.h
+++ b/dbus_service.h
@@ -69,6 +69,18 @@
gboolean* out_can_rollback,
GError **error);
+// Returns the name of kernel partition that can be rolled back into.
+gboolean update_engine_service_get_rollback_partition(
+ UpdateEngineService* self,
+ gchar** out_rollback_partition_name,
+ GError **error);
+
+// Returns a list of available kernel partitions and whether each of them
+// can be booted from or not.
+gboolean update_engine_service_get_kernel_devices(UpdateEngineService* self,
+ gchar** out_kernel_devices,
+ GError **error);
+
gboolean update_engine_service_reset_status(UpdateEngineService* self,
GError **error);
diff --git a/hardware.cc b/hardware.cc
index 44bc9de..f094d97 100644
--- a/hardware.cc
+++ b/hardware.cc
@@ -86,10 +86,7 @@
}
std::vector<std::string> devices;
- const int slot_count = 2; // Use only partition slots A and B
- devices.reserve(slot_count);
- for(int slot = 0; slot < slot_count; slot++) {
- int partition_num = (slot + 1) * 2; // for now, only #2, #4
+ for (int partition_num : {2, 4}) { // for now, only #2, #4 for slot A & B
std::string device = utils::MakePartitionName(disk_name, partition_num);
if(!device.empty()) {
devices.push_back(std::move(device));
diff --git a/update_attempter.cc b/update_attempter.cc
index d5c2d98..e71d104 100644
--- a/update_attempter.cc
+++ b/update_attempter.cc
@@ -785,19 +785,28 @@
}
bool UpdateAttempter::CanRollback() const {
+ return !GetRollbackPartition().empty();
+}
+
+std::string UpdateAttempter::GetRollbackPartition() const {
std::vector<std::string> kernel_devices =
system_state_->hardware()->GetKernelDevices();
std::string boot_kernel_device =
system_state_->hardware()->BootKernelDevice();
+ LOG(INFO) << "UpdateAttempter::GetRollbackPartition";
+ for (auto&& name : kernel_devices)
+ LOG(INFO) << " Available kernel device = " << name;
+ LOG(INFO) << " Boot kernel device = " << boot_kernel_device;
+
auto current = std::find(kernel_devices.begin(), kernel_devices.end(),
boot_kernel_device);
if(current == kernel_devices.end()) {
LOG(ERROR) << "Unable to find the boot kernel device in the list of "
<< "available devices";
- return false;
+ return std::string();
}
for (std::string const& device_name : kernel_devices) {
@@ -805,12 +814,35 @@
bool bootable = false;
if (system_state_->hardware()->IsKernelBootable(device_name, &bootable) &&
bootable) {
- return true;
+ return device_name;
}
}
}
- return false;
+ return std::string();
+}
+
+std::vector<std::pair<std::string, bool>>
+ UpdateAttempter::GetKernelDevices() const {
+ std::vector<std::string> kernel_devices =
+ system_state_->hardware()->GetKernelDevices();
+
+ std::string boot_kernel_device =
+ system_state_->hardware()->BootKernelDevice();
+
+ std::vector<std::pair<std::string, bool>> info_list;
+ info_list.reserve(kernel_devices.size());
+
+ for (std::string device_name : kernel_devices) {
+ bool bootable = false;
+ system_state_->hardware()->IsKernelBootable(device_name, &bootable);
+ // Add '*' to the name of the partition we booted from.
+ if (device_name == boot_kernel_device)
+ device_name += '*';
+ info_list.emplace_back(device_name, bootable);
+ }
+
+ return info_list;
}
void UpdateAttempter::CheckForUpdate(const string& app_version,
diff --git a/update_attempter.h b/update_attempter.h
index d76d168..d64771b 100644
--- a/update_attempter.h
+++ b/update_attempter.h
@@ -153,6 +153,15 @@
// partition exists.
bool CanRollback() const;
+ // This is the internal entry point for getting a rollback partition name,
+ // if one exists. It returns the bootable rollback kernel device partition
+ // name or empty string if none is available.
+ std::string GetRollbackPartition() const;
+
+ // Returns a list of available kernel partitions along with information
+ // whether it is possible to boot from it.
+ std::vector<std::pair<std::string, bool>> GetKernelDevices() const;
+
// Initiates a reboot if the current state is
// UPDATED_NEED_REBOOT. Returns true on sucess, false otherwise.
bool RebootIfNeeded();
diff --git a/update_engine.xml b/update_engine.xml
index 3891374..b99f345 100644
--- a/update_engine.xml
+++ b/update_engine.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8" ?>
+<?xml version="1.0" encoding="utf-8" ?>
<!-- COPYRIGHT HERE
dbus-binding-tool -mode=glib-server -prefix=update_engine update_engine.xml
> glib_server.h
@@ -81,5 +81,11 @@
<method name="GetPrevVersion">
<arg type="s" name="prev_version" direction="out" />
</method>
+ <method name="GetKernelDevices">
+ <arg type="s" name="kernel_devices" direction="out" />
+ </method>
+ <method name="GetRollbackPartition">
+ <arg type="s" name="rollback_partition_name" direction="out" />
+ </method>
</interface>
</node>
diff --git a/update_engine_client.cc b/update_engine_client.cc
index d27f027..3ee2a2a 100644
--- a/update_engine_client.cc
+++ b/update_engine_client.cc
@@ -59,6 +59,8 @@
"Listen for status updates and print them to the screen.");
DEFINE_bool(prev_version, false,
"Show the previous OS version used before the update reboot.");
+DEFINE_bool(show_kernels, false, "Show the list of kernel patritions and "
+ "whether each of them is bootable or not");
namespace {
@@ -211,20 +213,40 @@
return true;
}
-bool CanRollback() {
+std::string GetRollbackPartition() {
DBusGProxy* proxy;
GError* error = NULL;
CHECK(GetProxy(&proxy));
- gboolean can_rollback = FALSE;
- gboolean rc = update_engine_client_can_rollback(proxy,
- &can_rollback,
- &error);
+ char* rollback_partition = nullptr;
+ gboolean rc = update_engine_client_get_rollback_partition(proxy,
+ &rollback_partition,
+ &error);
CHECK_EQ(rc, TRUE) << "Error while querying rollback partition availabilty: "
<< GetAndFreeGError(&error);
- return can_rollback;
+ std::string partition = rollback_partition;
+ g_free(rollback_partition);
+ return partition;
}
+
+std::string GetKernelDevices() {
+ DBusGProxy* proxy;
+ GError* error = nullptr;
+
+ CHECK(GetProxy(&proxy));
+
+ char* kernel_devices = nullptr;
+ gboolean rc = update_engine_client_get_kernel_devices(proxy,
+ &kernel_devices,
+ &error);
+ CHECK_EQ(rc, TRUE) << "Error while getting a list of kernel devices: "
+ << GetAndFreeGError(&error);
+ std::string devices = kernel_devices;
+ g_free(kernel_devices);
+ return devices;
+}
+
bool CheckForUpdates(const string& app_version, const string& omaha_url) {
DBusGProxy* proxy;
GError* error = NULL;
@@ -452,9 +474,13 @@
// Show the rollback availability.
if (FLAGS_can_rollback) {
- bool can_rollback = CanRollback();
- LOG(INFO) << "Rollback partition: "
- << (can_rollback ? "AVAILABLE" : "UNAVAILABLE");
+ std::string rollback_partition = GetRollbackPartition();
+ if (rollback_partition.empty())
+ rollback_partition = "UNAVAILABLE";
+ else
+ rollback_partition = "AVAILABLE: " + rollback_partition;
+
+ LOG(INFO) << "Rollback partition: " << rollback_partition;
}
// Show the current P2P enabled setting.
@@ -547,6 +573,11 @@
ShowPrevVersion();
}
+ if (FLAGS_show_kernels) {
+ LOG(INFO) << "Kernel partitions:\n"
+ << GetKernelDevices();
+ }
+
LOG(INFO) << "Done.";
return 0;
}