• R/O
  • HTTP
  • SSH
  • HTTPS

提交

标签
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

system/core


Commit MetaInfo

修订版5f4e8eac8a0db87a43ed7a930103f4241c22d479 (tree)
时间2017-06-21 06:29:51
作者Tom Cherry <tomcherry@goog...>
CommiterTom Cherry

Log Message

init: poll in first stage mount if required devices are not found

First stage mount in init currently attempts to regenerate uevents for
specific devices to create the corresponding dev nodes. However, this
is racy as first stage mount happens early in the boot process and
it's possible that some of these devices have not yet been created by
the kernel.

To fix this issue, init will poll on the uevent socket for up to 10
seconds waiting for the kernel to create the required device. It will
return false and panic if this 10 second timeout passes.

Note that the same uevent socket is used in the uevent regeneration
and the polling code, so there is no race if the device is created
after the uevent regeneration and before polling starts; the first
poll will pick up the device.

Bug: 62681642
Bug: 62682821
Test: Boot bullhead
Test: Boot sailfish
Test: Boot hikey + hotplug/unplug sdcard
Merged-In: I4a6ff043eb7115b729ca4954ebc6c9e000132993
Change-Id: I4a6ff043eb7115b729ca4954ebc6c9e000132993

更改概述

差异

--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -19,6 +19,7 @@
1919 #include <fcntl.h>
2020 #include <fnmatch.h>
2121 #include <libgen.h>
22+#include <poll.h>
2223 #include <stddef.h>
2324 #include <stdio.h>
2425 #include <stdlib.h>
@@ -1028,6 +1029,37 @@ void device_close() {
10281029 selinux_status_close();
10291030 }
10301031
1031-int get_device_fd() {
1032- return device_fd;
1032+void device_poll(const coldboot_callback& callback,
1033+ const std::optional<std::chrono::milliseconds> relative_timeout) {
1034+ using namespace std::chrono;
1035+
1036+ pollfd ufd;
1037+ ufd.events = POLLIN;
1038+ ufd.fd = device_fd;
1039+
1040+ auto start_time = steady_clock::now();
1041+
1042+ while (true) {
1043+ ufd.revents = 0;
1044+
1045+ int timeout_ms = -1;
1046+ if (relative_timeout) {
1047+ auto now = steady_clock::now();
1048+ auto time_elapsed = duration_cast<milliseconds>(now - start_time);
1049+ if (time_elapsed > *relative_timeout) return;
1050+
1051+ auto remaining_timeout = *relative_timeout - time_elapsed;
1052+ timeout_ms = remaining_timeout.count();
1053+ }
1054+
1055+ int nr = poll(&ufd, 1, timeout_ms);
1056+ if (nr == 0) return;
1057+ if (nr < 0) {
1058+ continue;
1059+ }
1060+ if (ufd.revents & POLLIN) {
1061+ auto ret = handle_device_fd(callback);
1062+ if (should_stop_coldboot(ret)) return;
1063+ }
1064+ }
10331065 }
--- a/init/devices.h
+++ b/init/devices.h
@@ -17,9 +17,12 @@
1717 #ifndef _INIT_DEVICES_H
1818 #define _INIT_DEVICES_H
1919
20-#include <functional>
2120 #include <sys/stat.h>
2221
22+#include <chrono>
23+#include <functional>
24+#include <optional>
25+
2326 enum coldboot_action_t {
2427 // coldboot continues without creating the device for the uevent
2528 COLDBOOT_CONTINUE = 0,
@@ -53,8 +56,10 @@ extern int add_dev_perms(const char *name, const char *attr,
5356 mode_t perm, unsigned int uid,
5457 unsigned int gid, unsigned short prefix,
5558 unsigned short wildcard);
56-int get_device_fd();
5759
5860 char** get_block_device_symlinks(struct uevent* uevent);
5961
62+void device_poll(const coldboot_callback& callback = nullptr,
63+ const std::optional<std::chrono::milliseconds> relative_timeout = {});
64+
6065 #endif /* _INIT_DEVICES_H */
--- a/init/init_first_stage.cpp
+++ b/init/init_first_stage.cpp
@@ -19,6 +19,7 @@
1919 #include <stdlib.h>
2020 #include <unistd.h>
2121
22+#include <chrono>
2223 #include <memory>
2324 #include <set>
2425 #include <string>
@@ -33,6 +34,8 @@
3334 #include "fs_mgr_avb.h"
3435 #include "util.h"
3536
37+using namespace std::chrono_literals;
38+
3639 // Class Declarations
3740 // ------------------
3841 class FirstStageMount {
@@ -47,8 +50,8 @@ class FirstStageMount {
4750 bool InitDevices();
4851
4952 protected:
50- void InitRequiredDevices();
51- void InitVerityDevice(const std::string& verity_device);
53+ bool InitRequiredDevices();
54+ bool InitVerityDevice(const std::string& verity_device);
5255 bool MountPartitions();
5356
5457 virtual coldboot_action_t ColdbootCallback(uevent* uevent);
@@ -139,42 +142,53 @@ bool FirstStageMount::DoFirstStageMount() {
139142 return true;
140143 }
141144
142-bool FirstStageMount::InitDevices() {
143- if (!GetRequiredDevices()) return false;
144-
145- InitRequiredDevices();
146-
147- // InitRequiredDevices() will remove found partitions from required_devices_partition_names_.
148- // So if it isn't empty here, it means some partitions are not found.
149- if (!required_devices_partition_names_.empty()) {
150- LOG(ERROR) << __FUNCTION__ << "(): partition(s) not found: "
151- << android::base::Join(required_devices_partition_names_, ", ");
152- return false;
153- } else {
154- return true;
155- }
156-}
145+bool FirstStageMount::InitDevices() { return GetRequiredDevices() && InitRequiredDevices(); }
157146
158147 // Creates devices with uevent->partition_name matching one in the member variable
159148 // required_devices_partition_names_. Found partitions will then be removed from it
160149 // for the subsequent member function to check which devices are NOT created.
161-void FirstStageMount::InitRequiredDevices() {
150+bool FirstStageMount::InitRequiredDevices() {
162151 if (required_devices_partition_names_.empty()) {
163- return;
152+ return true;
164153 }
165154
166155 if (need_dm_verity_) {
167156 const std::string dm_path = "/devices/virtual/misc/device-mapper";
168- device_init(("/sys" + dm_path).c_str(), [&dm_path](uevent* uevent) -> coldboot_action_t {
169- if (uevent->path && uevent->path == dm_path) return COLDBOOT_STOP;
157+ bool found = false;
158+ auto dm_callback = [&dm_path, &found](uevent* uevent) -> coldboot_action_t {
159+ if (uevent->path && uevent->path == dm_path) {
160+ found = true;
161+ return COLDBOOT_STOP;
162+ }
170163 return COLDBOOT_CONTINUE; // dm_path not found, continue to find it.
171- });
164+ };
165+ device_init(("/sys" + dm_path).c_str(), dm_callback);
166+ if (!found) {
167+ device_poll(dm_callback, 10s);
168+ }
169+ if (!found) {
170+ LOG(ERROR) << "device-mapper device not found";
171+ return false;
172+ }
172173 }
173174
174- device_init(nullptr,
175- [this](uevent* uevent) -> coldboot_action_t { return ColdbootCallback(uevent); });
175+ auto uevent_callback = [this](uevent* uevent) -> coldboot_action_t {
176+ return ColdbootCallback(uevent);
177+ };
178+
179+ device_init(nullptr, uevent_callback);
180+ if (!required_devices_partition_names_.empty()) {
181+ device_poll(uevent_callback, 10s);
182+ }
183+
184+ if (!required_devices_partition_names_.empty()) {
185+ LOG(ERROR) << __PRETTY_FUNCTION__ << ": partition(s) not found: "
186+ << android::base::Join(required_devices_partition_names_, ", ");
187+ return false;
188+ }
176189
177190 device_close();
191+ return true;
178192 }
179193
180194 coldboot_action_t FirstStageMount::ColdbootCallback(uevent* uevent) {
@@ -203,18 +217,30 @@ coldboot_action_t FirstStageMount::ColdbootCallback(uevent* uevent) {
203217 }
204218
205219 // Creates "/dev/block/dm-XX" for dm-verity by running coldboot on /sys/block/dm-XX.
206-void FirstStageMount::InitVerityDevice(const std::string& verity_device) {
220+bool FirstStageMount::InitVerityDevice(const std::string& verity_device) {
207221 const std::string device_name(basename(verity_device.c_str()));
208222 const std::string syspath = "/sys/block/" + device_name;
223+ bool found = false;
209224
210- device_init(syspath.c_str(), [&](uevent* uevent) -> coldboot_action_t {
225+ auto verity_callback = [&](uevent* uevent) -> coldboot_action_t {
211226 if (uevent->device_name && uevent->device_name == device_name) {
212227 LOG(VERBOSE) << "Creating dm-verity device : " << verity_device;
228+ found = true;
213229 return COLDBOOT_STOP;
214230 }
215231 return COLDBOOT_CONTINUE;
216- });
232+ };
233+
234+ device_init(syspath.c_str(), verity_callback);
235+ if (!found) {
236+ device_poll(verity_callback, 10s);
237+ }
238+ if (!found) {
239+ LOG(ERROR) << "dm-verity device not found";
240+ return false;
241+ }
217242 device_close();
243+ return true;
218244 }
219245
220246 bool FirstStageMount::MountPartitions() {
@@ -280,7 +306,7 @@ bool FirstStageMountVBootV1::SetUpDmVerity(fstab_rec* fstab_rec) {
280306 } else if (ret == FS_MGR_SETUP_VERITY_SUCCESS) {
281307 // The exact block device name (fstab_rec->blk_device) is changed to "/dev/block/dm-XX".
282308 // Needs to create it because ueventd isn't started in init first stage.
283- InitVerityDevice(fstab_rec->blk_device);
309+ return InitVerityDevice(fstab_rec->blk_device);
284310 } else {
285311 return false;
286312 }
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -17,7 +17,6 @@
1717 #include <ctype.h>
1818 #include <fcntl.h>
1919 #include <grp.h>
20-#include <poll.h>
2120 #include <pwd.h>
2221 #include <signal.h>
2322 #include <stdio.h>
@@ -76,20 +75,7 @@ int ueventd_main(int argc, char **argv)
7675
7776 device_init();
7877
79- pollfd ufd;
80- ufd.events = POLLIN;
81- ufd.fd = get_device_fd();
82-
83- while (true) {
84- ufd.revents = 0;
85- int nr = poll(&ufd, 1, -1);
86- if (nr <= 0) {
87- continue;
88- }
89- if (ufd.revents & POLLIN) {
90- handle_device_fd();
91- }
92- }
78+ device_poll();
9379
9480 return 0;
9581 }