system/core
Révision | aca2bc0992045338dcc5acb21776a387431a270b (tree) |
---|---|
l'heure | 2019-04-17 02:01:19 |
Auteur | Yifan Hong <elsk@goog...> |
Commiter | Android (Google) Code Review |
Merge "init: add umount_all builtin." into qt-dev
@@ -1268,6 +1268,46 @@ int fs_mgr_mount_all(Fstab* fstab, int mount_mode) { | ||
1268 | 1268 | } |
1269 | 1269 | } |
1270 | 1270 | |
1271 | +int fs_mgr_umount_all(android::fs_mgr::Fstab* fstab) { | |
1272 | + AvbUniquePtr avb_handle(nullptr); | |
1273 | + int ret = FsMgrUmountStatus::SUCCESS; | |
1274 | + for (auto& current_entry : *fstab) { | |
1275 | + if (!IsMountPointMounted(current_entry.mount_point)) { | |
1276 | + continue; | |
1277 | + } | |
1278 | + | |
1279 | + if (umount(current_entry.mount_point.c_str()) == -1) { | |
1280 | + PERROR << "Failed to umount " << current_entry.mount_point; | |
1281 | + ret |= FsMgrUmountStatus::ERROR_UMOUNT; | |
1282 | + continue; | |
1283 | + } | |
1284 | + | |
1285 | + if (current_entry.fs_mgr_flags.logical) { | |
1286 | + if (!fs_mgr_update_logical_partition(¤t_entry)) { | |
1287 | + LERROR << "Could not get logical partition blk_device, skipping!"; | |
1288 | + ret |= FsMgrUmountStatus::ERROR_DEVICE_MAPPER; | |
1289 | + continue; | |
1290 | + } | |
1291 | + } | |
1292 | + | |
1293 | + if (current_entry.fs_mgr_flags.avb || !current_entry.avb_keys.empty()) { | |
1294 | + if (!AvbHandle::TearDownAvbHashtree(¤t_entry, true /* wait */)) { | |
1295 | + LERROR << "Failed to tear down AVB on mount point: " << current_entry.mount_point; | |
1296 | + ret |= FsMgrUmountStatus::ERROR_VERITY; | |
1297 | + continue; | |
1298 | + } | |
1299 | + } else if ((current_entry.fs_mgr_flags.verify)) { | |
1300 | + if (!fs_mgr_teardown_verity(¤t_entry, true /* wait */)) { | |
1301 | + LERROR << "Failed to tear down verified partition on mount point: " | |
1302 | + << current_entry.mount_point; | |
1303 | + ret |= FsMgrUmountStatus::ERROR_VERITY; | |
1304 | + continue; | |
1305 | + } | |
1306 | + } | |
1307 | + } | |
1308 | + return ret; | |
1309 | +} | |
1310 | + | |
1271 | 1311 | // wrapper to __mount() and expects a fully prepared fstab_rec, |
1272 | 1312 | // unlike fs_mgr_do_mount which does more things with avb / verity etc. |
1273 | 1313 | int fs_mgr_do_mount_one(const FstabEntry& entry, const std::string& mount_point) { |
@@ -193,7 +193,7 @@ bool CreateLogicalPartition(const std::string& block_device, uint32_t metadata_s | ||
193 | 193 | timeout_ms, path); |
194 | 194 | } |
195 | 195 | |
196 | -bool DestroyLogicalPartition(const std::string& name, const std::chrono::milliseconds& timeout_ms) { | |
196 | +bool UnmapDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms) { | |
197 | 197 | DeviceMapper& dm = DeviceMapper::Instance(); |
198 | 198 | std::string path; |
199 | 199 | if (timeout_ms > std::chrono::milliseconds::zero()) { |
@@ -206,6 +206,13 @@ bool DestroyLogicalPartition(const std::string& name, const std::chrono::millise | ||
206 | 206 | LERROR << "Timed out waiting for device path to unlink: " << path; |
207 | 207 | return false; |
208 | 208 | } |
209 | + return true; | |
210 | +} | |
211 | + | |
212 | +bool DestroyLogicalPartition(const std::string& name, const std::chrono::milliseconds& timeout_ms) { | |
213 | + if (!UnmapDevice(name, timeout_ms)) { | |
214 | + return false; | |
215 | + } | |
209 | 216 | LINFO << "Unmapped logical partition " << name; |
210 | 217 | return true; |
211 | 218 | } |
@@ -103,3 +103,11 @@ int load_verity_state(const android::fs_mgr::FstabEntry& entry, int* mode); | ||
103 | 103 | |
104 | 104 | bool fs_mgr_is_ext4(const std::string& blk_device); |
105 | 105 | bool fs_mgr_is_f2fs(const std::string& blk_device); |
106 | + | |
107 | +bool fs_mgr_teardown_verity(android::fs_mgr::FstabEntry* fstab, bool wait); | |
108 | + | |
109 | +namespace android { | |
110 | +namespace fs_mgr { | |
111 | +bool UnmapDevice(const std::string& name, const std::chrono::milliseconds& timeout_ms); | |
112 | +} // namespace fs_mgr | |
113 | +} // namespace android |
@@ -44,6 +44,7 @@ | ||
44 | 44 | #include "fec/io.h" |
45 | 45 | |
46 | 46 | #include "fs_mgr.h" |
47 | +#include "fs_mgr_dm_linear.h" | |
47 | 48 | #include "fs_mgr_priv.h" |
48 | 49 | |
49 | 50 | // Realistically, this file should be part of the android::fs_mgr namespace; |
@@ -882,3 +883,12 @@ out: | ||
882 | 883 | |
883 | 884 | return retval; |
884 | 885 | } |
886 | + | |
887 | +bool fs_mgr_teardown_verity(FstabEntry* entry, bool wait) { | |
888 | + const std::string mount_point(basename(entry->mount_point.c_str())); | |
889 | + if (!android::fs_mgr::UnmapDevice(mount_point, wait ? 1000ms : 0ms)) { | |
890 | + return false; | |
891 | + } | |
892 | + LINFO << "Unmapped verity device " << mount_point; | |
893 | + return true; | |
894 | +} |
@@ -93,3 +93,14 @@ int fs_mgr_setup_verity(android::fs_mgr::FstabEntry* fstab, bool wait_for_verity | ||
93 | 93 | // specified, the super partition for the corresponding metadata slot will be |
94 | 94 | // returned. Otherwise, it will use the current slot. |
95 | 95 | std::string fs_mgr_get_super_partition_name(int slot = -1); |
96 | + | |
97 | +enum FsMgrUmountStatus : int { | |
98 | + SUCCESS = 0, | |
99 | + ERROR_UNKNOWN = 1 << 0, | |
100 | + ERROR_UMOUNT = 1 << 1, | |
101 | + ERROR_VERITY = 1 << 2, | |
102 | + ERROR_DEVICE_MAPPER = 1 << 3, | |
103 | +}; | |
104 | +// fs_mgr_umount_all() is the reverse of fs_mgr_mount_all. In particular, | |
105 | +// it destroys verity devices from device mapper after the device is unmounted. | |
106 | +int fs_mgr_umount_all(android::fs_mgr::Fstab* fstab); |
@@ -449,6 +449,29 @@ AvbHashtreeResult AvbHandle::SetUpAvbHashtree(FstabEntry* fstab_entry, bool wait | ||
449 | 449 | return AvbHashtreeResult::kSuccess; |
450 | 450 | } |
451 | 451 | |
452 | +bool AvbHandle::TearDownAvbHashtree(FstabEntry* fstab_entry, bool wait) { | |
453 | + if (!fstab_entry) { | |
454 | + return false; | |
455 | + } | |
456 | + | |
457 | + const std::string device_name(GetVerityDeviceName(*fstab_entry)); | |
458 | + | |
459 | + // TODO: remove duplicated code with UnmapDevice() | |
460 | + android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance(); | |
461 | + std::string path; | |
462 | + if (wait) { | |
463 | + dm.GetDmDevicePathByName(device_name, &path); | |
464 | + } | |
465 | + if (!dm.DeleteDevice(device_name)) { | |
466 | + return false; | |
467 | + } | |
468 | + if (!path.empty() && !WaitForFile(path, 1000ms, FileWaitMode::DoesNotExist)) { | |
469 | + return false; | |
470 | + } | |
471 | + | |
472 | + return true; | |
473 | +} | |
474 | + | |
452 | 475 | std::string AvbHandle::GetSecurityPatchLevel(const FstabEntry& fstab_entry) const { |
453 | 476 | if (vbmeta_images_.size() < 1) { |
454 | 477 | return ""; |
@@ -110,6 +110,11 @@ class AvbHandle { | ||
110 | 110 | static AvbHashtreeResult SetUpStandaloneAvbHashtree(FstabEntry* fstab_entry, |
111 | 111 | bool wait_for_verity_dev = true); |
112 | 112 | |
113 | + // Tear down dm devices created by SetUp[Standalone]AvbHashtree | |
114 | + // The 'wait' parameter makes this function wait for the verity device to get destroyed | |
115 | + // before return. | |
116 | + static bool TearDownAvbHashtree(FstabEntry* fstab_entry, bool wait); | |
117 | + | |
113 | 118 | static bool IsDeviceUnlocked(); |
114 | 119 | |
115 | 120 | std::string GetSecurityPatchLevel(const FstabEntry& fstab_entry) const; |
@@ -27,6 +27,7 @@ | ||
27 | 27 | |
28 | 28 | // Target functions to test: |
29 | 29 | using android::fs_mgr::BytesToHex; |
30 | +using android::fs_mgr::FileWaitMode; | |
30 | 31 | using android::fs_mgr::HexToBytes; |
31 | 32 | using android::fs_mgr::NibbleValue; |
32 | 33 | using android::fs_mgr::WaitForFile; |
@@ -175,7 +176,7 @@ TEST(BasicUtilTest, WaitForFileDeferCreation) { | ||
175 | 176 | // Waits this path. |
176 | 177 | base::FilePath wait_path = tmp_dir.Append("libfs_avb-test-exist-dir"); |
177 | 178 | ASSERT_TRUE(base::DeleteFile(wait_path, false /* resursive */)); |
178 | - auto wait_file = std::async(WaitForFile, wait_path.value(), 500ms); | |
179 | + auto wait_file = std::async(WaitForFile, wait_path.value(), 500ms, FileWaitMode::Exists); | |
179 | 180 | |
180 | 181 | // Sleeps 100ms before creating the wait_path. |
181 | 182 | std::this_thread::sleep_for(100ms); |
@@ -196,7 +197,7 @@ TEST(BasicUtilTest, WaitForFileDeferCreationFailure) { | ||
196 | 197 | // Waits this path. |
197 | 198 | base::FilePath wait_path = tmp_dir.Append("libfs_avb-test-exist-dir"); |
198 | 199 | ASSERT_TRUE(base::DeleteFile(wait_path, false /* resursive */)); |
199 | - auto wait_file = std::async(WaitForFile, wait_path.value(), 50ms); | |
200 | + auto wait_file = std::async(WaitForFile, wait_path.value(), 50ms, FileWaitMode::Exists); | |
200 | 201 | |
201 | 202 | // Sleeps 100ms before creating the wait_path. |
202 | 203 | std::this_thread::sleep_for(100ms); |
@@ -82,12 +82,17 @@ std::string BytesToHex(const uint8_t* bytes, size_t bytes_len) { | ||
82 | 82 | return hex; |
83 | 83 | } |
84 | 84 | |
85 | -bool WaitForFile(const std::string& filename, const std::chrono::milliseconds relative_timeout) { | |
85 | +// TODO: remove duplicate code with fs_mgr_wait_for_file | |
86 | +bool WaitForFile(const std::string& filename, const std::chrono::milliseconds relative_timeout, | |
87 | + FileWaitMode file_wait_mode) { | |
86 | 88 | auto start_time = std::chrono::steady_clock::now(); |
87 | 89 | |
88 | 90 | while (true) { |
89 | - if (0 == access(filename.c_str(), F_OK) || errno != ENOENT) { | |
90 | - return true; | |
91 | + int rv = access(filename.c_str(), F_OK); | |
92 | + if (file_wait_mode == FileWaitMode::Exists) { | |
93 | + if (!rv || errno != ENOENT) return true; | |
94 | + } else if (file_wait_mode == FileWaitMode::DoesNotExist) { | |
95 | + if (rv && errno == ENOENT) return true; | |
91 | 96 | } |
92 | 97 | |
93 | 98 | std::this_thread::sleep_for(50ms); |
@@ -52,7 +52,9 @@ bool HexToBytes(uint8_t* bytes, size_t bytes_len, const std::string& hex); | ||
52 | 52 | |
53 | 53 | std::string BytesToHex(const uint8_t* bytes, size_t bytes_len); |
54 | 54 | |
55 | -bool WaitForFile(const std::string& filename, const std::chrono::milliseconds relative_timeout); | |
55 | +enum class FileWaitMode { Exists, DoesNotExist }; | |
56 | +bool WaitForFile(const std::string& filename, const std::chrono::milliseconds relative_timeout, | |
57 | + FileWaitMode wait_mode = FileWaitMode::Exists); | |
56 | 58 | |
57 | 59 | bool IsDeviceUnlocked(); |
58 | 60 |
@@ -451,13 +451,13 @@ static void import_late(const std::vector<std::string>& args, size_t start_index | ||
451 | 451 | if (false) DumpState(); |
452 | 452 | } |
453 | 453 | |
454 | -/* mount_fstab | |
454 | +/* handle_fstab | |
455 | 455 | * |
456 | - * Call fs_mgr_mount_all() to mount the given fstab | |
456 | + * Read the given fstab file and execute func on it. | |
457 | 457 | */ |
458 | -static Result<int> mount_fstab(const char* fstabfile, int mount_mode) { | |
458 | +static Result<int> handle_fstab(const std::string& fstabfile, std::function<int(Fstab*)> func) { | |
459 | 459 | /* |
460 | - * Call fs_mgr_mount_all() to mount all filesystems. We fork(2) and | |
460 | + * Call fs_mgr_[u]mount_all() to [u]mount all filesystems. We fork(2) and | |
461 | 461 | * do the call in the child to provide protection to the main init |
462 | 462 | * process if anything goes wrong (crash or memory leak), and wait for |
463 | 463 | * the child to finish in the parent. |
@@ -478,25 +478,51 @@ static Result<int> mount_fstab(const char* fstabfile, int mount_mode) { | ||
478 | 478 | return Error() << "child aborted"; |
479 | 479 | } |
480 | 480 | } else if (pid == 0) { |
481 | - /* child, call fs_mgr_mount_all() */ | |
481 | + /* child, call fs_mgr_[u]mount_all() */ | |
482 | 482 | |
483 | - // So we can always see what fs_mgr_mount_all() does. | |
483 | + // So we can always see what fs_mgr_[u]mount_all() does. | |
484 | 484 | // Only needed if someone explicitly changes the default log level in their init.rc. |
485 | 485 | android::base::ScopedLogSeverity info(android::base::INFO); |
486 | 486 | |
487 | 487 | Fstab fstab; |
488 | 488 | ReadFstabFromFile(fstabfile, &fstab); |
489 | 489 | |
490 | - int child_ret = fs_mgr_mount_all(&fstab, mount_mode); | |
491 | - if (child_ret == -1) { | |
492 | - PLOG(ERROR) << "fs_mgr_mount_all returned an error"; | |
493 | - } | |
490 | + int child_ret = func(&fstab); | |
491 | + | |
494 | 492 | _exit(child_ret); |
495 | 493 | } else { |
496 | 494 | return Error() << "fork() failed"; |
497 | 495 | } |
498 | 496 | } |
499 | 497 | |
498 | +/* mount_fstab | |
499 | + * | |
500 | + * Call fs_mgr_mount_all() to mount the given fstab | |
501 | + */ | |
502 | +static Result<int> mount_fstab(const std::string& fstabfile, int mount_mode) { | |
503 | + return handle_fstab(fstabfile, [mount_mode](Fstab* fstab) { | |
504 | + int ret = fs_mgr_mount_all(fstab, mount_mode); | |
505 | + if (ret == -1) { | |
506 | + PLOG(ERROR) << "fs_mgr_mount_all returned an error"; | |
507 | + } | |
508 | + return ret; | |
509 | + }); | |
510 | +} | |
511 | + | |
512 | +/* umount_fstab | |
513 | + * | |
514 | + * Call fs_mgr_umount_all() to umount the given fstab | |
515 | + */ | |
516 | +static Result<int> umount_fstab(const std::string& fstabfile) { | |
517 | + return handle_fstab(fstabfile, [](Fstab* fstab) { | |
518 | + int ret = fs_mgr_umount_all(fstab); | |
519 | + if (ret != 0) { | |
520 | + PLOG(ERROR) << "fs_mgr_umount_all returned " << ret; | |
521 | + } | |
522 | + return ret; | |
523 | + }); | |
524 | +} | |
525 | + | |
500 | 526 | /* Queue event based on fs_mgr return code. |
501 | 527 | * |
502 | 528 | * code: return code of fs_mgr_mount_all |
@@ -583,7 +609,7 @@ static Result<Success> do_mount_all(const BuiltinArguments& args) { | ||
583 | 609 | bool import_rc = true; |
584 | 610 | bool queue_event = true; |
585 | 611 | int mount_mode = MOUNT_MODE_DEFAULT; |
586 | - const char* fstabfile = args[1].c_str(); | |
612 | + const auto& fstabfile = args[1]; | |
587 | 613 | std::size_t path_arg_end = args.size(); |
588 | 614 | const char* prop_post_fix = "default"; |
589 | 615 |
@@ -626,6 +652,15 @@ static Result<Success> do_mount_all(const BuiltinArguments& args) { | ||
626 | 652 | return Success(); |
627 | 653 | } |
628 | 654 | |
655 | +/* umount_all <fstab> */ | |
656 | +static Result<Success> do_umount_all(const BuiltinArguments& args) { | |
657 | + auto umount_fstab_return_code = umount_fstab(args[1]); | |
658 | + if (!umount_fstab_return_code) { | |
659 | + return Error() << "umount_fstab() failed " << umount_fstab_return_code.error(); | |
660 | + } | |
661 | + return Success(); | |
662 | +} | |
663 | + | |
629 | 664 | static Result<Success> do_swapon_all(const BuiltinArguments& args) { |
630 | 665 | Fstab fstab; |
631 | 666 | if (!ReadFstabFromFile(args[1], &fstab)) { |
@@ -1165,6 +1200,7 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const { | ||
1165 | 1200 | {"mount", {3, kMax, {false, do_mount}}}, |
1166 | 1201 | {"parse_apex_configs", {0, 0, {false, do_parse_apex_configs}}}, |
1167 | 1202 | {"umount", {1, 1, {false, do_umount}}}, |
1203 | + {"umount_all", {1, 1, {false, do_umount_all}}}, | |
1168 | 1204 | {"readahead", {1, 2, {true, do_readahead}}}, |
1169 | 1205 | {"restart", {1, 1, {false, do_restart}}}, |
1170 | 1206 | {"restorecon", {1, kMax, {true, do_restorecon}}}, |