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