@@ -409,10 +409,12 @@ bool SnapshotManager::MapDmUserCow(LockedFile* lock, const std::string& name,
409
409
if (!dm.CreateDevice (name, table, path, timeout_ms)) {
410
410
return false ;
411
411
}
412
+ if (!WaitForDevice (*path, timeout_ms)) {
413
+ return false ;
414
+ }
412
415
413
416
auto control_device = " /dev/dm-user/" + misc_name;
414
- if (!android::fs_mgr::WaitForFile (control_device, timeout_ms)) {
415
- LOG (ERROR) << " Timed out waiting for dm-user misc device: " << control_device;
417
+ if (!WaitForDevice (control_device, timeout_ms)) {
416
418
return false ;
417
419
}
418
420
@@ -1340,10 +1342,12 @@ bool SnapshotManager::PerformSecondStageTransition() {
1340
1342
continue ;
1341
1343
}
1342
1344
1345
+ auto misc_name = user_cow_name;
1346
+
1343
1347
DmTable table;
1344
- table.Emplace <DmTargetUser>(0 , target.spec .length , user_cow_name );
1348
+ table.Emplace <DmTargetUser>(0 , target.spec .length , misc_name );
1345
1349
if (!dm.LoadTableAndActivate (user_cow_name, table)) {
1346
- LOG (ERROR) << " Unable to swap tables for " << user_cow_name ;
1350
+ LOG (ERROR) << " Unable to swap tables for " << misc_name ;
1347
1351
continue ;
1348
1352
}
1349
1353
@@ -1369,14 +1373,13 @@ bool SnapshotManager::PerformSecondStageTransition() {
1369
1373
}
1370
1374
1371
1375
// Wait for ueventd to acknowledge and create the control device node.
1372
- std::string control_device = " /dev/dm-user/" + user_cow_name;
1373
- if (!android::fs_mgr::WaitForFile (control_device, 10s)) {
1374
- LOG (ERROR) << " Could not find control device: " << control_device;
1376
+ std::string control_device = " /dev/dm-user/" + misc_name;
1377
+ if (!WaitForDevice (control_device, 10s)) {
1375
1378
continue ;
1376
1379
}
1377
1380
1378
1381
uint64_t base_sectors =
1379
- snapuserd_client_->InitDmUserCow (user_cow_name , cow_image_device, backing_device);
1382
+ snapuserd_client_->InitDmUserCow (misc_name , cow_image_device, backing_device);
1380
1383
if (base_sectors == 0 ) {
1381
1384
// Unrecoverable as metadata reads from cow device failed
1382
1385
LOG (FATAL) << " Failed to retrieve base_sectors from Snapuserd" ;
@@ -1385,7 +1388,7 @@ bool SnapshotManager::PerformSecondStageTransition() {
1385
1388
1386
1389
CHECK (base_sectors == target.spec .length );
1387
1390
1388
- if (!snapuserd_client_->AttachDmUser (user_cow_name )) {
1391
+ if (!snapuserd_client_->AttachDmUser (misc_name )) {
1389
1392
// This error is unrecoverable. We cannot proceed because reads to
1390
1393
// the underlying device will fail.
1391
1394
LOG (FATAL) << " Could not initialize snapuserd for " << user_cow_name;
@@ -1924,13 +1927,20 @@ bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock,
1924
1927
if (live_snapshot_status->compression_enabled ()) {
1925
1928
auto name = GetDmUserCowName (params.GetPartitionName ());
1926
1929
1927
- // :TODO: need to force init to process uevents for these in first-stage.
1928
1930
std::string cow_path;
1929
1931
if (!GetMappedImageDevicePath (cow_name, &cow_path)) {
1930
1932
LOG (ERROR) << " Could not determine path for: " << cow_name;
1931
1933
return false ;
1932
1934
}
1933
1935
1936
+ // Ensure both |base_path| and |cow_path| are created, for snapuserd.
1937
+ if (!WaitForDevice (base_path, remaining_time)) {
1938
+ return false ;
1939
+ }
1940
+ if (!WaitForDevice (cow_path, remaining_time)) {
1941
+ return false ;
1942
+ }
1943
+
1934
1944
std::string new_cow_device;
1935
1945
if (!MapDmUserCow (lock, name, cow_path, base_path, remaining_time, &new_cow_device)) {
1936
1946
LOG (ERROR) << " Could not map dm-user device for partition "
@@ -2070,7 +2080,7 @@ bool SnapshotManager::UnmapCowDevices(LockedFile* lock, const std::string& name)
2070
2080
if (!EnsureSnapuserdConnected ()) {
2071
2081
return false ;
2072
2082
}
2073
- if (!dm.DeleteDevice (dm_user_name)) {
2083
+ if (!dm.DeleteDeviceIfExists (dm_user_name)) {
2074
2084
LOG (ERROR) << " Cannot unmap " << dm_user_name;
2075
2085
return false ;
2076
2086
}
@@ -3302,5 +3312,39 @@ bool SnapshotManager::GetMappedImageDeviceStringOrPath(const std::string& device
3302
3312
return true ;
3303
3313
}
3304
3314
3315
+ bool SnapshotManager::WaitForDevice (const std::string& device,
3316
+ std::chrono::milliseconds timeout_ms) {
3317
+ if (!android::base::StartsWith (device, " /" )) {
3318
+ return true ;
3319
+ }
3320
+
3321
+ // In first-stage init, we rely on init setting a callback which can
3322
+ // regenerate uevents and populate /dev for us.
3323
+ if (uevent_regen_callback_) {
3324
+ if (!uevent_regen_callback_ (device)) {
3325
+ LOG (ERROR) << " Failed to find device after regenerating uevents: " << device;
3326
+ return false ;
3327
+ }
3328
+ return true ;
3329
+ }
3330
+
3331
+ // Otherwise, the only kind of device we need to wait for is a dm-user
3332
+ // misc device. Normal calls to DeviceMapper::CreateDevice() guarantee
3333
+ // the path has been created.
3334
+ if (!android::base::StartsWith (device, " /dev/dm-user/" )) {
3335
+ return true ;
3336
+ }
3337
+
3338
+ if (timeout_ms.count () == 0 ) {
3339
+ LOG (ERROR) << " No timeout was specified to wait for device: " << device;
3340
+ return false ;
3341
+ }
3342
+ if (!android::fs_mgr::WaitForFile (device, timeout_ms)) {
3343
+ LOG (ERROR) << " Timed out waiting for device to appear: " << device;
3344
+ return false ;
3345
+ }
3346
+ return true ;
3347
+ }
3348
+
3305
3349
} // namespace snapshot
3306
3350
} // namespace android
0 commit comments