libsnapshot: Ensure we can remove bad snapshots when beginning an update.
If somehow we wind up with snapshots with a source suffix, we could wind up trying to unmap an in-use partition. Detect this case and allow the snapshot to be deleted without the unmap. Bug: 183567503 Test: vts_libsnapshot_test Change-Id: I87dd5bb3a7b9be59dede624924374ccc47b563c2
This commit is contained in:
parent
4f898d4e33
commit
bcd19ed73e
2 changed files with 40 additions and 0 deletions
|
@ -1619,6 +1619,18 @@ bool SnapshotManager::RemoveAllSnapshots(LockedFile* lock) {
|
|||
// as dm-snapshot (for example, after merge completes).
|
||||
bool should_unmap = current_slot != Slot::Target;
|
||||
bool should_delete = ShouldDeleteSnapshot(flashing_status, current_slot, name);
|
||||
if (should_unmap && android::base::EndsWith(name, device_->GetSlotSuffix())) {
|
||||
// Something very unexpected has happened - we want to unmap this
|
||||
// snapshot, but it's on the wrong slot. We can't unmap an active
|
||||
// partition. If this is not really a snapshot, skip the unmap
|
||||
// step.
|
||||
auto& dm = DeviceMapper::Instance();
|
||||
if (dm.GetState(name) == DmDeviceState::INVALID || !IsSnapshotDevice(name)) {
|
||||
LOG(ERROR) << "Detected snapshot " << name << " on " << current_slot << " slot"
|
||||
<< " for source partition; removing without unmap.";
|
||||
should_unmap = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool partition_ok = true;
|
||||
if (should_unmap && !UnmapPartitionWithSnapshot(lock, name)) {
|
||||
|
|
|
@ -2021,6 +2021,34 @@ TEST_F(SnapshotUpdateTest, MapAllSnapshots) {
|
|||
ASSERT_TRUE(IsPartitionUnchanged("sys_b"));
|
||||
}
|
||||
|
||||
TEST_F(SnapshotUpdateTest, CancelOnTargetSlot) {
|
||||
AddOperationForPartitions();
|
||||
|
||||
// Execute the update from B->A.
|
||||
test_device->set_slot_suffix("_b");
|
||||
ASSERT_TRUE(sm->BeginUpdate());
|
||||
ASSERT_TRUE(sm->CreateUpdateSnapshots(manifest_));
|
||||
|
||||
std::string path;
|
||||
ASSERT_TRUE(CreateLogicalPartition(
|
||||
CreateLogicalPartitionParams{
|
||||
.block_device = fake_super,
|
||||
.metadata_slot = 0,
|
||||
.partition_name = "sys_a",
|
||||
.timeout_ms = 1s,
|
||||
.partition_opener = opener_.get(),
|
||||
},
|
||||
&path));
|
||||
|
||||
// Hold sys_a open so it can't be unmapped.
|
||||
unique_fd fd(open(path.c_str(), O_RDONLY));
|
||||
|
||||
// Switch back to "A", make sure we can cancel. Instead of unmapping sys_a
|
||||
// we should simply delete the old snapshots.
|
||||
test_device->set_slot_suffix("_a");
|
||||
ASSERT_TRUE(sm->BeginUpdate());
|
||||
}
|
||||
|
||||
class FlashAfterUpdateTest : public SnapshotUpdateTest,
|
||||
public WithParamInterface<std::tuple<uint32_t, bool>> {
|
||||
public:
|
||||
|
|
Loading…
Reference in a new issue