Merge "Support multiple fstab configs for one mount point"
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index d7e8f32..f713ff2 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -13,6 +13,7 @@
"-Wno-unused-function",
"-Wno-nullability-completeness",
"-Os",
+ "-fno-finite-loops",
],
local_include_dirs: ["include"],
diff --git a/debuggerd/OWNERS b/debuggerd/OWNERS
index bfeedca..6f7e4a3 100644
--- a/debuggerd/OWNERS
+++ b/debuggerd/OWNERS
@@ -1,2 +1 @@
cferris@google.com
-jmgao@google.com
diff --git a/diagnose_usb/OWNERS b/diagnose_usb/OWNERS
index 643b448..fcd7757 100644
--- a/diagnose_usb/OWNERS
+++ b/diagnose_usb/OWNERS
@@ -1,2 +1 @@
-jmgao@google.com
yabinc@google.com
diff --git a/fastboot/OWNERS b/fastboot/OWNERS
index a72ee07..58b2a81 100644
--- a/fastboot/OWNERS
+++ b/fastboot/OWNERS
@@ -1,4 +1,3 @@
dvander@google.com
hridya@google.com
enh@google.com
-jmgao@google.com
diff --git a/fastboot/device/flashing.cpp b/fastboot/device/flashing.cpp
index ee0aa58..9b5d2cd 100644
--- a/fastboot/device/flashing.cpp
+++ b/fastboot/device/flashing.cpp
@@ -187,11 +187,17 @@
", build may be missing broken or missing boot_devices");
}
+ std::string slot_suffix = device->GetCurrentSlot();
+ uint32_t slot_number = SlotNumberForSlotSuffix(slot_suffix);
+
+ std::string other_slot_suffix;
+ if (!slot_suffix.empty()) {
+ other_slot_suffix = (slot_suffix == "_a") ? "_b" : "_a";
+ }
+
// If we are unable to read the existing metadata, then the super partition
// is corrupt. In this case we reflash the whole thing using the provided
// image.
- std::string slot_suffix = device->GetCurrentSlot();
- uint32_t slot_number = SlotNumberForSlotSuffix(slot_suffix);
std::unique_ptr<LpMetadata> old_metadata = ReadMetadata(super_name, slot_number);
if (wipe || !old_metadata) {
if (!FlashPartitionTable(super_name, *new_metadata.get())) {
@@ -203,11 +209,15 @@
}
std::set<std::string> partitions_to_keep;
+ bool virtual_ab = android::base::GetBoolProperty("ro.virtual_ab.enabled", false);
for (const auto& partition : old_metadata->partitions) {
// Preserve partitions in the other slot, but not the current slot.
std::string partition_name = GetPartitionName(partition);
- if (!slot_suffix.empty() && GetPartitionSlotSuffix(partition_name) == slot_suffix) {
- continue;
+ if (!slot_suffix.empty()) {
+ auto part_suffix = GetPartitionSlotSuffix(partition_name);
+ if (part_suffix == slot_suffix || (part_suffix == other_slot_suffix && virtual_ab)) {
+ continue;
+ }
}
std::string group_name = GetPartitionGroupName(old_metadata->groups[partition.group_index]);
// Skip partitions in the COW group
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index c87ce60..532b524 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -941,7 +941,8 @@
// Tries to locate top-level vbmeta from boot.img footer.
uint64_t footer_offset = buf->sz - AVB_FOOTER_SIZE;
if (0 != data.compare(footer_offset, AVB_FOOTER_MAGIC_LEN, AVB_FOOTER_MAGIC)) {
- die("Failed to find AVB_FOOTER at offset: %" PRId64, footer_offset);
+ die("Failed to find AVB_FOOTER at offset: %" PRId64 ", is BOARD_AVB_ENABLE true?",
+ footer_offset);
}
const AvbFooter* footer = reinterpret_cast<const AvbFooter*>(data.c_str() + footer_offset);
vbmeta_offset = be64toh(footer->vbmeta_offset);
@@ -1021,6 +1022,24 @@
return;
}
+ // If overflows and negative, it should be < buf->sz.
+ int64_t partition_size = static_cast<int64_t>(get_partition_size(partition));
+
+ if (partition_size == buf->sz) {
+ return;
+ }
+ // Some device bootloaders might not implement `fastboot getvar partition-size:boot[_a|_b]`.
+ // In this case, partition_size will be zero.
+ if (partition_size < buf->sz) {
+ fprintf(stderr,
+ "Warning: skip copying boot image avb footer"
+ " (boot partition size: %" PRId64 ", boot image size: %" PRId64 ").\n",
+ partition_size, buf->sz);
+ return;
+ }
+
+ // IMPORTANT: after the following read, we need to reset buf->fd before return (if not die).
+ // Because buf->fd will still be used afterwards.
std::string data;
if (!android::base::ReadFdToString(buf->fd, &data)) {
die("Failed reading from boot");
@@ -1028,17 +1047,9 @@
uint64_t footer_offset = buf->sz - AVB_FOOTER_SIZE;
if (0 != data.compare(footer_offset, AVB_FOOTER_MAGIC_LEN, AVB_FOOTER_MAGIC)) {
+ lseek(buf->fd.get(), 0, SEEK_SET); // IMPORTANT: resets buf->fd before return.
return;
}
- // If overflows and negative, it should be < buf->sz.
- int64_t partition_size = static_cast<int64_t>(get_partition_size(partition));
-
- if (partition_size == buf->sz) {
- return;
- }
- if (partition_size < buf->sz) {
- die("boot partition is smaller than boot image");
- }
unique_fd fd(make_temporary_fd("boot rewriting"));
if (!android::base::WriteStringToFd(data, fd)) {
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index d4fc2b9..6170aee 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -65,6 +65,7 @@
"-D_FILE_OFFSET_BITS=64",
],
srcs: [
+ "blockdev.cpp",
"file_wait.cpp",
"fs_mgr.cpp",
"fs_mgr_format.cpp",
diff --git a/fs_mgr/blockdev.cpp b/fs_mgr/blockdev.cpp
new file mode 100644
index 0000000..14b217c
--- /dev/null
+++ b/fs_mgr/blockdev.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+
+#include <dirent.h>
+#include <libdm/dm.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <sys/types.h>
+#include "blockdev.h"
+
+using android::base::Basename;
+using android::base::ErrnoError;
+using android::base::Error;
+using android::base::Result;
+using android::base::ResultError;
+using android::base::StartsWith;
+using android::base::StringPrintf;
+using android::base::unique_fd;
+using android::dm::DeviceMapper;
+
+// Return the parent device of a partition. Converts e.g. "sda26" into "sda".
+static std::string PartitionParent(const std::string& blockdev) {
+ if (blockdev.find('/') != std::string::npos) {
+ LOG(ERROR) << __func__ << ": invalid argument " << blockdev;
+ return blockdev;
+ }
+ auto dir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/sys/class/block"), closedir};
+ if (!dir) {
+ return blockdev;
+ }
+ for (struct dirent* ent = readdir(dir.get()); ent; ent = readdir(dir.get())) {
+ if (ent->d_name[0] == '.') {
+ continue;
+ }
+ std::string path = StringPrintf("/sys/class/block/%s/%s", ent->d_name, blockdev.c_str());
+ struct stat statbuf;
+ if (stat(path.c_str(), &statbuf) >= 0) {
+ return ent->d_name;
+ }
+ }
+ return blockdev;
+}
+
+// Convert a major:minor pair into a block device name.
+static std::string BlockdevName(dev_t dev) {
+ auto dir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/dev/block"), closedir};
+ if (!dir) {
+ return {};
+ }
+ for (struct dirent* ent = readdir(dir.get()); ent; ent = readdir(dir.get())) {
+ if (ent->d_name[0] == '.') {
+ continue;
+ }
+ const std::string path = std::string("/dev/block/") + ent->d_name;
+ struct stat statbuf;
+ if (stat(path.c_str(), &statbuf) >= 0 && dev == statbuf.st_rdev) {
+ return ent->d_name;
+ }
+ }
+ return {};
+}
+
+// Trim whitespace from the end of a string.
+static void rtrim(std::string& s) {
+ s.erase(s.find_last_not_of('\n') + 1, s.length());
+}
+
+// For file `file_path`, retrieve the block device backing the filesystem on
+// which the file exists and return the queue depth of the block device.
+static Result<uint32_t> BlockDeviceQueueDepth(const std::string& file_path) {
+ struct stat statbuf;
+ int res = stat(file_path.c_str(), &statbuf);
+ if (res < 0) {
+ return ErrnoError() << "stat(" << file_path << ")";
+ }
+ std::string blockdev = "/dev/block/" + BlockdevName(statbuf.st_dev);
+ LOG(DEBUG) << __func__ << ": " << file_path << " -> " << blockdev;
+ if (blockdev.empty()) {
+ const std::string err_msg =
+ StringPrintf("Failed to convert %u:%u (path %s)", major(statbuf.st_dev),
+ minor(statbuf.st_dev), file_path.c_str());
+ return ResultError(err_msg, 0);
+ }
+ auto& dm = DeviceMapper::Instance();
+ for (;;) {
+ std::optional<std::string> child = dm.GetParentBlockDeviceByPath(blockdev);
+ if (!child) {
+ break;
+ }
+ LOG(DEBUG) << __func__ << ": " << blockdev << " -> " << *child;
+ blockdev = *child;
+ }
+ std::optional<std::string> maybe_blockdev = android::dm::ExtractBlockDeviceName(blockdev);
+ if (!maybe_blockdev) {
+ return ResultError("Failed to remove /dev/block/ prefix from " + blockdev, 0);
+ }
+ blockdev = PartitionParent(*maybe_blockdev);
+ LOG(DEBUG) << __func__ << ": "
+ << "Partition parent: " << blockdev;
+ const std::string nr_tags_path =
+ StringPrintf("/sys/class/block/%s/mq/0/nr_tags", blockdev.c_str());
+ std::string nr_tags;
+ if (!android::base::ReadFileToString(nr_tags_path, &nr_tags)) {
+ return ResultError("Failed to read " + nr_tags_path, 0);
+ }
+ rtrim(nr_tags);
+ LOG(DEBUG) << __func__ << ": " << file_path << " is backed by /dev/" << blockdev
+ << " and that block device supports queue depth " << nr_tags;
+ return strtol(nr_tags.c_str(), NULL, 0);
+}
+
+// Set 'nr_requests' of `loop_device_path` to the queue depth of the block
+// device backing `file_path`.
+Result<void> ConfigureQueueDepth(const std::string& loop_device_path,
+ const std::string& file_path) {
+ if (!StartsWith(loop_device_path, "/dev/")) {
+ return Error() << "Invalid argument " << loop_device_path;
+ }
+
+ const std::string loop_device_name = Basename(loop_device_path);
+
+ const Result<uint32_t> qd = BlockDeviceQueueDepth(file_path);
+ if (!qd.ok()) {
+ LOG(DEBUG) << __func__ << ": "
+ << "BlockDeviceQueueDepth() returned " << qd.error();
+ return ResultError(qd.error());
+ }
+ const std::string nr_requests = StringPrintf("%u", *qd);
+ const std::string sysfs_path =
+ StringPrintf("/sys/class/block/%s/queue/nr_requests", loop_device_name.c_str());
+ unique_fd sysfs_fd(open(sysfs_path.c_str(), O_RDWR | O_CLOEXEC));
+ if (sysfs_fd == -1) {
+ return ErrnoError() << "Failed to open " << sysfs_path;
+ }
+
+ const int res = write(sysfs_fd.get(), nr_requests.data(), nr_requests.length());
+ if (res < 0) {
+ return ErrnoError() << "Failed to write to " << sysfs_path;
+ }
+ return {};
+}
diff --git a/fs_mgr/blockdev.h b/fs_mgr/blockdev.h
new file mode 100644
index 0000000..2c0d68a
--- /dev/null
+++ b/fs_mgr/blockdev.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/result.h>
+#include <string>
+
+android::base::Result<void> ConfigureQueueDepth(const std::string& loop_device_path,
+ const std::string& file_path);
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index ec66144..5f15aad 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -72,6 +72,7 @@
#include <log/log_properties.h>
#include <logwrap/logwrap.h>
+#include "blockdev.h"
#include "fs_mgr_priv.h"
#define KEY_LOC_PROP "ro.crypto.keyfile.userdata"
@@ -2110,6 +2111,8 @@
ConfigureIoScheduler(loop_device);
+ ConfigureQueueDepth(loop_device, "/");
+
// set block size & direct IO
unique_fd loop_fd(TEMP_FAILURE_RETRY(open(loop_device.c_str(), O_RDWR | O_CLOEXEC)));
if (loop_fd.get() == -1) {
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 4d32bda..0522ac5 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -1133,7 +1133,7 @@
return false;
}
if (!images->BackingImageExists(partition_name)) {
- static constexpr uint64_t kMinimumSize = 16_MiB;
+ static constexpr uint64_t kMinimumSize = 64_MiB;
static constexpr uint64_t kMaximumSize = 2_GiB;
uint64_t size = std::clamp(info.size / 2, kMinimumSize, kMaximumSize);
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index 8e3d5a5..4034e30 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -578,34 +578,30 @@
return std::string{spec.target_type, sizeof(spec.target_type)};
}
-static bool ExtractBlockDeviceName(const std::string& path, std::string* name) {
+std::optional<std::string> ExtractBlockDeviceName(const std::string& path) {
static constexpr std::string_view kDevBlockPrefix("/dev/block/");
if (android::base::StartsWith(path, kDevBlockPrefix)) {
- *name = path.substr(kDevBlockPrefix.length());
- return true;
+ return path.substr(kDevBlockPrefix.length());
}
- return false;
+ return {};
}
bool DeviceMapper::IsDmBlockDevice(const std::string& path) {
- std::string name;
- if (!ExtractBlockDeviceName(path, &name)) {
- return false;
- }
- return android::base::StartsWith(name, "dm-");
+ std::optional<std::string> name = ExtractBlockDeviceName(path);
+ return name && android::base::StartsWith(*name, "dm-");
}
std::optional<std::string> DeviceMapper::GetDmDeviceNameByPath(const std::string& path) {
- std::string name;
- if (!ExtractBlockDeviceName(path, &name)) {
+ std::optional<std::string> name = ExtractBlockDeviceName(path);
+ if (!name) {
LOG(WARNING) << path << " is not a block device";
return std::nullopt;
}
- if (!android::base::StartsWith(name, "dm-")) {
+ if (!android::base::StartsWith(*name, "dm-")) {
LOG(WARNING) << path << " is not a dm device";
return std::nullopt;
}
- std::string dm_name_file = "/sys/block/" + name + "/dm/name";
+ std::string dm_name_file = "/sys/block/" + *name + "/dm/name";
std::string dm_name;
if (!android::base::ReadFileToString(dm_name_file, &dm_name)) {
PLOG(ERROR) << "Failed to read file " << dm_name_file;
@@ -616,16 +612,16 @@
}
std::optional<std::string> DeviceMapper::GetParentBlockDeviceByPath(const std::string& path) {
- std::string name;
- if (!ExtractBlockDeviceName(path, &name)) {
+ std::optional<std::string> name = ExtractBlockDeviceName(path);
+ if (!name) {
LOG(WARNING) << path << " is not a block device";
return std::nullopt;
}
- if (!android::base::StartsWith(name, "dm-")) {
+ if (!android::base::StartsWith(*name, "dm-")) {
// Reached bottom of the device mapper stack.
return std::nullopt;
}
- auto slaves_dir = "/sys/block/" + name + "/slaves";
+ auto slaves_dir = "/sys/block/" + *name + "/slaves";
auto dir = std::unique_ptr<DIR, decltype(&closedir)>(opendir(slaves_dir.c_str()), closedir);
if (dir == nullptr) {
PLOG(ERROR) << "Failed to open: " << slaves_dir;
diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h
index 31c3003..7e01b85 100644
--- a/fs_mgr/libdm/include/libdm/dm.h
+++ b/fs_mgr/libdm/include/libdm/dm.h
@@ -51,6 +51,10 @@
static constexpr uint64_t kSectorSize = 512;
+// Returns `path` without /dev/block prefix if and only if `path` starts with
+// that prefix.
+std::optional<std::string> ExtractBlockDeviceName(const std::string& path);
+
class DeviceMapper final {
public:
class DmBlockDevice final {
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h
index 0457986..3655c01 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_writer.h
@@ -36,6 +36,8 @@
MOCK_METHOD(bool, EmitCopy, (uint64_t, uint64_t), (override));
MOCK_METHOD(bool, EmitRawBlocks, (uint64_t, const void*, size_t), (override));
+ MOCK_METHOD(bool, EmitXorBlocks, (uint32_t, const void*, size_t, uint32_t, uint16_t),
+ (override));
MOCK_METHOD(bool, EmitZeroBlocks, (uint64_t, uint64_t), (override));
MOCK_METHOD(bool, EmitLabel, (uint64_t), (override));
MOCK_METHOD(bool, EmitSequenceData, (size_t, const uint32_t*), (override));
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 035038f..7633d9c 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -1305,20 +1305,8 @@
return {};
}
-
-static bool IsApexUpdatable() {
- static bool updatable = android::sysprop::ApexProperties::updatable().value_or(false);
- return updatable;
-}
-
static Result<void> do_update_linker_config(const BuiltinArguments&) {
- // If APEX is not updatable, then all APEX information are already included in the first
- // linker config generation, so there is no need to update linker configuration again.
- if (IsApexUpdatable()) {
- return GenerateLinkerConfiguration();
- }
-
- return {};
+ return GenerateLinkerConfiguration();
}
static Result<void> parse_apex_configs() {
diff --git a/init/mount_namespace.cpp b/init/mount_namespace.cpp
index 575cae9..593e5ae 100644
--- a/init/mount_namespace.cpp
+++ b/init/mount_namespace.cpp
@@ -97,110 +97,6 @@
return true;
}
-#ifdef ACTIVATE_FLATTENED_APEX
-
-static Result<void> MountDir(const std::string& path, const std::string& mount_path) {
- if (int ret = mkdir(mount_path.c_str(), 0755); ret != 0 && errno != EEXIST) {
- return ErrnoError() << "Could not create mount point " << mount_path;
- }
- if (mount(path.c_str(), mount_path.c_str(), nullptr, MS_BIND, nullptr) != 0) {
- return ErrnoError() << "Could not bind mount " << path << " to " << mount_path;
- }
- return {};
-}
-
-static Result<apex::proto::ApexManifest> GetApexManifest(const std::string& apex_dir) {
- const std::string manifest_path = apex_dir + "/apex_manifest.pb";
- std::string content;
- if (!android::base::ReadFileToString(manifest_path, &content)) {
- return Error() << "Failed to read manifest file: " << manifest_path;
- }
- apex::proto::ApexManifest manifest;
- if (!manifest.ParseFromString(content)) {
- return Error() << "Can't parse manifest file: " << manifest_path;
- }
- return manifest;
-}
-
-template <typename Fn>
-static Result<void> ActivateFlattenedApexesFrom(const std::string& from_dir,
- const std::string& to_dir, Fn on_activate) {
- std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(from_dir.c_str()), closedir);
- if (!dir) {
- return {};
- }
- dirent* entry;
- std::vector<std::string> entries;
-
- while ((entry = readdir(dir.get())) != nullptr) {
- if (entry->d_name[0] == '.') continue;
- if (entry->d_type == DT_DIR) {
- entries.push_back(entry->d_name);
- }
- }
-
- std::sort(entries.begin(), entries.end());
- for (const auto& name : entries) {
- const std::string apex_path = from_dir + "/" + name;
- const auto apex_manifest = GetApexManifest(apex_path);
- if (!apex_manifest.ok()) {
- LOG(ERROR) << apex_path << " is not an APEX directory: " << apex_manifest.error();
- continue;
- }
- const std::string mount_path = to_dir + "/" + apex_manifest->name();
- if (auto result = MountDir(apex_path, mount_path); !result.ok()) {
- return result;
- }
- on_activate(apex_path, *apex_manifest);
- }
- return {};
-}
-
-static bool ActivateFlattenedApexesIfPossible() {
- if (IsRecoveryMode() || IsApexUpdatable()) {
- return true;
- }
-
- const std::string kApexTop = "/apex";
- const std::vector<std::string> kBuiltinDirsForApexes = {
- "/system/apex",
- "/system_ext/apex",
- "/product/apex",
- "/vendor/apex",
- };
-
- std::vector<com::android::apex::ApexInfo> apex_infos;
- auto on_activate = [&](const std::string& apex_path,
- const apex::proto::ApexManifest& apex_manifest) {
- apex_infos.emplace_back(apex_manifest.name(), apex_path, apex_path, apex_manifest.version(),
- apex_manifest.versionname(), /*isFactory=*/true, /*isActive=*/true,
- /* lastUpdateMillis= */ 0);
- };
-
- for (const auto& dir : kBuiltinDirsForApexes) {
- if (auto result = ActivateFlattenedApexesFrom(dir, kApexTop, on_activate); !result.ok()) {
- LOG(ERROR) << result.error();
- return false;
- }
- }
-
- std::ostringstream oss;
- com::android::apex::ApexInfoList apex_info_list(apex_infos);
- com::android::apex::write(oss, apex_info_list);
- const std::string kApexInfoList = kApexTop + "/apex-info-list.xml";
- if (!android::base::WriteStringToFile(oss.str(), kApexInfoList)) {
- PLOG(ERROR) << "Failed to write " << kApexInfoList;
- return false;
- }
- if (selinux_android_restorecon(kApexInfoList.c_str(), 0) != 0) {
- PLOG(ERROR) << "selinux_android_restorecon(" << kApexInfoList << ") failed";
- }
-
- return true;
-}
-
-#endif // ACTIVATE_FLATTENED_APEX
-
static android::base::unique_fd bootstrap_ns_fd;
static android::base::unique_fd default_ns_fd;
@@ -294,9 +190,7 @@
default_ns_fd.reset(OpenMountNamespace());
default_ns_id = GetMountNamespaceId();
}
-#ifdef ACTIVATE_FLATTENED_APEX
- success &= ActivateFlattenedApexesIfPossible();
-#endif
+
LOG(INFO) << "SetupMountNamespaces done";
return success;
}
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 0e788e4..c5f1ee4 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -1035,6 +1035,20 @@
return;
}
}
+ } else if (reboot_target == "quiescent") {
+ bootloader_message boot = {};
+ if (std::string err; !read_bootloader_message(&boot, &err)) {
+ LOG(ERROR) << "Failed to read bootloader message: " << err;
+ }
+ // Update the boot command field if it's empty, and preserve
+ // the other arguments in the bootloader message.
+ if (!CommandIsPresent(&boot)) {
+ strlcpy(boot.command, "boot-quiescent", sizeof(boot.command));
+ if (std::string err; !write_bootloader_message(boot, &err)) {
+ LOG(ERROR) << "Failed to set bootloader message: " << err;
+ return;
+ }
+ }
} else if (reboot_target == "sideload" || reboot_target == "sideload-auto-reboot" ||
reboot_target == "fastboot") {
std::string arg = reboot_target == "sideload-auto-reboot" ? "sideload_auto_reboot"
diff --git a/rootdir/init.rc b/rootdir/init.rc
index a7322fa..ab0aff5 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -591,9 +591,10 @@
# Load trusted keys from dm-verity protected partitions
exec -- /system/bin/fsverity_init --load-verified-keys
+on late-fs && property:ro.product.cpu.abilist64=*
# Set up a tracing instance for system_server to monitor error_report_end events.
# These are sent by kernel tools like KASAN and KFENCE when a memory corruption
- # is detected.
+ # is detected. This is only needed for 64-bit systems.
mkdir /sys/kernel/tracing/instances/bootreceiver 0700 system system
restorecon_recursive /sys/kernel/tracing/instances/bootreceiver
write /sys/kernel/tracing/instances/bootreceiver/buffer_size_kb 1