Merge "Make RemoveCgroup idempotent" into main
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 87c4cd2..a6d8226 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -2825,7 +2825,8 @@
}
prev_file = match[1];
- unwindstack::Elf elf(unwindstack::Memory::CreateFileMemory(prev_file, 0).release());
+ auto elf_memory = unwindstack::Memory::CreateFileMemory(prev_file, 0);
+ unwindstack::Elf elf(elf_memory);
if (!elf.Init() || !elf.valid()) {
// Skipping invalid elf files.
continue;
diff --git a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
index eed81fc..e44dc10 100644
--- a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
@@ -28,7 +28,6 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
-#include <async_safe/log.h>
#include <bionic/macros.h>
#include "tombstone.pb.h"
@@ -138,7 +137,8 @@
break;
default:
- async_safe_fatal("unknown architecture");
+ CBL("Unknown architecture %d printing thread registers", tombstone.arch());
+ return;
}
for (const auto& reg : thread.registers()) {
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index d55f8d3..faea5eb 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -828,7 +828,14 @@
<< ",type=" << entry.fs_type << ", gc_allowance=" << gc_allowance << "%)=" << ret
<< "(" << save_errno << ")";
}
- ret = mount(source.c_str(), target.c_str(), entry.fs_type.c_str(), mountflags,
+
+ // Let's get the raw dm target, if it's a symlink, since some existing applications
+ // rely on /proc/mounts to find the userdata's dm target path. Don't break that assumption.
+ std::string real_source;
+ if (!android::base::Realpath(source, &real_source)) {
+ real_source = source;
+ }
+ ret = mount(real_source.c_str(), target.c_str(), entry.fs_type.c_str(), mountflags,
opts.c_str());
save_errno = errno;
if (try_f2fs_gc_allowance) gc_allowance += 10;
diff --git a/fs_mgr/fs_mgr_overlayfs_mount.cpp b/fs_mgr/fs_mgr_overlayfs_mount.cpp
index ae7ed4c..cdbac00 100644
--- a/fs_mgr/fs_mgr_overlayfs_mount.cpp
+++ b/fs_mgr/fs_mgr_overlayfs_mount.cpp
@@ -34,6 +34,7 @@
#include <android-base/file.h>
#include <android-base/macros.h>
#include <android-base/properties.h>
+#include <android-base/scopeguard.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <ext4_utils/ext4_utils.h>
@@ -58,6 +59,9 @@
constexpr char kCacheMountPoint[] = "/cache";
constexpr char kPhysicalDevice[] = "/dev/block/by-name/";
+// Mount tree to temporarily hold references to submounts.
+constexpr char kMoveMountTempDir[] = "/dev/remount";
+
constexpr char kLowerdirOption[] = "lowerdir=";
constexpr char kUpperdirOption[] = "upperdir=";
constexpr char kWorkdirOption[] = "workdir=";
@@ -284,10 +288,6 @@
if (ret) {
PERROR << "__mount(target=" << mount_point
<< ",flag=" << (shared_flag ? "MS_SHARED" : "MS_PRIVATE") << ")=" << ret;
- // If "/system" doesn't look like a mountpoint, retry with "/".
- if (errno == EINVAL && mount_point == "/system") {
- return fs_mgr_overlayfs_set_shared_mount("/", shared_flag);
- }
return false;
}
return true;
@@ -374,24 +374,23 @@
return info;
}
-static bool fs_mgr_overlayfs_mount(const FstabEntry& entry) {
- const auto mount_point = fs_mgr_mount_point(entry.mount_point);
- const auto options = fs_mgr_get_overlayfs_options(entry);
+static bool fs_mgr_overlayfs_mount_one(const FstabEntry& fstab_entry) {
+ const auto mount_point = fs_mgr_mount_point(fstab_entry.mount_point);
+ const auto options = fs_mgr_get_overlayfs_options(fstab_entry);
if (options.empty()) return false;
- auto retval = true;
-
struct MoveEntry {
std::string mount_point;
std::string dir;
bool shared_flag;
};
-
std::vector<MoveEntry> moved_mounts;
- auto parent_private = false;
- auto parent_made_private = false;
- auto dev_private = false;
- auto dev_made_private = false;
+
+ bool retval = true;
+ bool move_dir_shared = true;
+ bool parent_shared = true;
+ bool root_shared = true;
+ bool root_made_private = false;
// There could be multiple mount entries with the same mountpoint.
// Group these entries together with stable_sort, and keep only the last entry of a group.
@@ -411,18 +410,32 @@
// mountinfo is reversed twice, so still is in lexical sorted order.
for (const auto& entry : mountinfo) {
- if ((entry.mount_point == mount_point) && !entry.shared_flag) {
- parent_private = true;
+ if (entry.mount_point == kMoveMountTempDir) {
+ move_dir_shared = entry.shared_flag;
}
- if ((entry.mount_point == "/dev") && !entry.shared_flag) {
- dev_private = true;
+ if (entry.mount_point == mount_point ||
+ (mount_point == "/system" && entry.mount_point == "/")) {
+ parent_shared = entry.shared_flag;
}
+ if (entry.mount_point == "/") {
+ root_shared = entry.shared_flag;
+ }
+ }
+
+ // Precondition is that kMoveMountTempDir is MS_PRIVATE, otherwise don't try to move any
+ // submount in to or out of it.
+ if (move_dir_shared) {
+ mountinfo.clear();
}
// Need to make the original mountpoint MS_PRIVATE, so that the overlayfs can be MS_MOVE.
// This could happen if its parent mount is remounted later.
- if (!parent_private) {
- parent_made_private = fs_mgr_overlayfs_set_shared_mount(mount_point, false);
+ if (!fs_mgr_overlayfs_set_shared_mount(mount_point, false)) {
+ // If failed to set "/system" mount type, it might be due to "/system" not being a valid
+ // mountpoint after switch root. Retry with "/" in this case.
+ if (errno == EINVAL && mount_point == "/system") {
+ root_made_private = fs_mgr_overlayfs_set_shared_mount("/", false);
+ }
}
for (const auto& entry : mountinfo) {
@@ -440,8 +453,8 @@
// mountinfo is in lexical order, so no need to worry about |entry| being a parent mount of
// entries of |moved_mounts|.
- // use as the bound directory in /dev.
- MoveEntry new_entry{entry.mount_point, "/dev/TemporaryDir-XXXXXX", entry.shared_flag};
+ MoveEntry new_entry{entry.mount_point, kMoveMountTempDir + "/TemporaryDir-XXXXXX"s,
+ entry.shared_flag};
{
AutoSetFsCreateCon createcon;
auto new_context = fs_mgr_get_context(entry.mount_point);
@@ -497,10 +510,6 @@
// Move submounts back.
for (const auto& entry : moved_mounts) {
- if (!dev_private && !dev_made_private) {
- dev_made_private = fs_mgr_overlayfs_set_shared_mount("/dev", false);
- }
-
if (!fs_mgr_overlayfs_move_mount(entry.dir, entry.mount_point)) {
retval = false;
} else if (entry.shared_flag &&
@@ -509,12 +518,13 @@
}
rmdir(entry.dir.c_str());
}
- if (dev_made_private) {
- fs_mgr_overlayfs_set_shared_mount("/dev", true);
- }
- if (parent_made_private) {
+ // If the original (overridden) mount was MS_SHARED, then set the overlayfs mount to MS_SHARED.
+ if (parent_shared) {
fs_mgr_overlayfs_set_shared_mount(mount_point, true);
}
+ if (root_shared && root_made_private) {
+ fs_mgr_overlayfs_set_shared_mount("/", true);
+ }
return retval;
}
@@ -730,6 +740,25 @@
if (!OverlayfsSetupAllowed()) {
return false;
}
+
+ // Ensure kMoveMountTempDir is standalone mount tree with 'private' propagation by bind mounting
+ // to itself and set to MS_PRIVATE.
+ // Otherwise mounts moved in to it would have their propagation type changed unintentionally.
+ // Section 5d, https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt
+ if (!fs_mgr_overlayfs_already_mounted(kMoveMountTempDir, false)) {
+ if (mkdir(kMoveMountTempDir, 0755) && errno != EEXIST) {
+ PERROR << "mkdir " << kMoveMountTempDir;
+ }
+ if (mount(kMoveMountTempDir, kMoveMountTempDir, nullptr, MS_BIND, nullptr)) {
+ PERROR << "bind mount " << kMoveMountTempDir;
+ }
+ }
+ fs_mgr_overlayfs_set_shared_mount(kMoveMountTempDir, false);
+ android::base::ScopeGuard umountDir([]() {
+ umount(kMoveMountTempDir);
+ rmdir(kMoveMountTempDir);
+ });
+
auto ret = true;
auto scratch_can_be_mounted = !fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false);
for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) {
@@ -742,7 +771,7 @@
scratch_can_be_mounted = false;
TryMountScratch();
}
- ret &= fs_mgr_overlayfs_mount(entry);
+ ret &= fs_mgr_overlayfs_mount_one(entry);
}
return ret;
}
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index 3a9ed9b..e261aa3 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -612,8 +612,12 @@
std::optional<std::string> ExtractBlockDeviceName(const std::string& path) {
static constexpr std::string_view kDevBlockPrefix("/dev/block/");
- if (android::base::StartsWith(path, kDevBlockPrefix)) {
- return path.substr(kDevBlockPrefix.length());
+ std::string real_path;
+ if (!android::base::Realpath(path, &real_path)) {
+ real_path = path;
+ }
+ if (android::base::StartsWith(real_path, kDevBlockPrefix)) {
+ return real_path.substr(kDevBlockPrefix.length());
}
return {};
}
diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h
index 3e7ecc6..22c475f 100644
--- a/fs_mgr/libdm/include/libdm/dm.h
+++ b/fs_mgr/libdm/include/libdm/dm.h
@@ -52,8 +52,8 @@
static constexpr uint64_t kSectorSize = 512;
-// Returns `path` without /dev/block prefix if and only if `path` starts with
-// that prefix.
+// Returns `path` without /dev/block prefix if `path` starts with that prefix.
+// Or, if `path` is a symlink, do the same with its real path.
std::optional<std::string> ExtractBlockDeviceName(const std::string& path);
// This interface is for testing purposes. See DeviceMapper proper for what these methods do.
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
index 8917116..9e6cfea 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
@@ -105,10 +105,12 @@
static constexpr uint8_t kNumResumePoints = 4;
struct CowHeaderV3 : public CowHeader {
- // Location of sequence buffer in COW.
- uint64_t sequence_buffer_offset;
+ // Number of sequence data stored (each of which is a 32 byte integer)
+ uint64_t sequence_data_count;
+ // number of currently written resume points
+ uint32_t resume_point_count;
// Size, in bytes, of the CowResumePoint buffer.
- uint32_t resume_buffer_size;
+ uint32_t resume_point_max;
// Number of CowOperationV3 structs in the operation buffer, currently and total
// region size.
uint32_t op_count;
@@ -230,6 +232,19 @@
return op.source_info & kCowOpSourceInfoDataMask;
}
+static constexpr off_t GetOpOffset(uint32_t op_index, const CowHeaderV3 header) {
+ return header.prefix.header_size + header.buffer_size +
+ (header.resume_point_max * sizeof(ResumePoint)) + (op_index * sizeof(CowOperationV3));
+}
+static constexpr off_t GetDataOffset(const CowHeaderV3 header) {
+ return header.prefix.header_size + header.buffer_size +
+ (header.resume_point_max * sizeof(ResumePoint)) +
+ header.op_count_max * sizeof(CowOperation);
+}
+static constexpr off_t GetResumeOffset(const CowHeaderV3 header) {
+ return header.prefix.header_size + header.buffer_size;
+}
+
struct CowFooter {
CowFooterOperation op;
uint8_t unused[64];
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.cpp
index d411ab9..8e0f190 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.cpp
@@ -75,14 +75,14 @@
}
bool CowParserV3::ReadResumeBuffer(borrowed_fd fd) {
- resume_points_ = std::make_shared<std::vector<ResumePoint>>(header_.resume_buffer_size);
+ resume_points_ = std::make_shared<std::vector<ResumePoint>>(header_.resume_point_count);
return android::base::ReadFullyAtOffset(fd, resume_points_->data(),
- header_.resume_buffer_size * sizeof(ResumePoint),
- header_.prefix.header_size + header_.buffer_size);
+ header_.resume_point_count * sizeof(ResumePoint),
+ GetResumeOffset(header_));
}
-std::optional<uint32_t> CowParserV3::FindResumeOp(const uint32_t label) {
+std::optional<uint32_t> CowParserV3::FindResumeOp(const uint64_t label) {
for (auto& resume_point : *resume_points_) {
if (resume_point.label == label) {
return resume_point.op_index;
@@ -94,18 +94,12 @@
return std::nullopt;
}
-off_t CowParserV3::GetDataOffset() const {
- return sizeof(CowHeaderV3) + header_.buffer_size +
- header_.resume_buffer_size * sizeof(ResumePoint) +
- header_.op_count_max * sizeof(CowOperation);
-}
-
bool CowParserV3::ParseOps(borrowed_fd fd, const uint32_t op_index) {
ops_ = std::make_shared<std::vector<CowOperationV3>>();
ops_->resize(op_index);
- const off_t offset = header_.prefix.header_size + header_.buffer_size +
- header_.resume_buffer_size * sizeof(ResumePoint);
+ // read beginning of operation buffer -> so op_index = 0
+ const off_t offset = GetOpOffset(0, header_);
if (!android::base::ReadFullyAtOffset(fd, ops_->data(), ops_->size() * sizeof(CowOperationV3),
offset)) {
PLOG(ERROR) << "read ops failed";
@@ -113,7 +107,7 @@
}
// fill out mapping of XOR op data location
- uint64_t data_pos = GetDataOffset();
+ uint64_t data_pos = GetDataOffset(header_);
xor_data_loc_ = std::make_shared<std::unordered_map<uint64_t, uint64_t>>();
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.h b/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.h
index dceb815..afc01af 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.h
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/parser_v3.h
@@ -49,8 +49,7 @@
private:
bool ParseOps(android::base::borrowed_fd fd, const uint32_t op_index);
- std::optional<uint32_t> FindResumeOp(const uint32_t label);
- off_t GetDataOffset() const;
+ std::optional<uint32_t> FindResumeOp(const uint64_t label);
CowHeaderV3 header_ = {};
std::shared_ptr<std::vector<CowOperationV3>> ops_;
bool ReadResumeBuffer(android::base::borrowed_fd fd);
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp
index c41e07c..9f857ee 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/test_v3.cpp
@@ -482,5 +482,43 @@
header = reader.header_v3();
ASSERT_EQ(header.op_count, 15);
}
+
+TEST_F(CowTestV3, BufferMetadataSyncTest) {
+ CowOptions options;
+ options.op_count_max = 100;
+ auto writer = CreateCowWriter(3, options, GetCowFd());
+ /*
+ Header metadafields
+ sequence_data_count = 0;
+ resume_point_count = 0;
+ resume_point_max = 4;
+ */
+ ASSERT_TRUE(writer->Finalize());
+
+ CowReader reader;
+ ASSERT_TRUE(reader.Parse(cow_->fd));
+
+ auto header = reader.header_v3();
+ ASSERT_EQ(header.sequence_data_count, 0);
+ ASSERT_EQ(header.resume_point_count, 0);
+ ASSERT_EQ(header.resume_point_max, 4);
+
+ writer->AddLabel(0);
+ ASSERT_TRUE(reader.Parse(cow_->fd));
+ header = reader.header_v3();
+ ASSERT_EQ(header.sequence_data_count, 0);
+ ASSERT_EQ(header.resume_point_count, 1);
+ ASSERT_EQ(header.resume_point_max, 4);
+
+ ASSERT_TRUE(reader.Parse(cow_->fd));
+ header = reader.header_v3();
+
+ /*
+ Header metadafields
+ sequence_data_count = 1;
+ resume_point_count = 0;
+ resume_point_max = 4;
+ */
+}
} // namespace snapshot
} // namespace android
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
index 89fd903..81ccea9 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
@@ -77,8 +77,9 @@
// v3 specific fields
// WIP: not quite sure how some of these are calculated yet, assuming buffer_size is determined
// during COW size estimation
- header_.sequence_buffer_offset = 0;
- header_.resume_buffer_size = kNumResumePoints;
+ header_.sequence_data_count = 0;
+ header_.resume_point_count = 0;
+ header_.resume_point_max = kNumResumePoints;
header_.op_count = 0;
header_.op_count_max = 0;
header_.compression_algorithm = kCowCompressNone;
@@ -99,6 +100,7 @@
return false;
}
header_.compression_algorithm = *algorithm;
+ header_.op_count_max = options_.op_count_max;
if (parts.size() > 1) {
if (!android::base::ParseUint(parts[1], &compression_.compression_level)) {
@@ -162,14 +164,14 @@
return false;
}
}
- header_.op_count_max = options_.op_count_max;
+
resume_points_ = std::make_shared<std::vector<ResumePoint>>();
if (!Sync()) {
LOG(ERROR) << "Header sync failed";
return false;
}
- next_data_pos_ = GetDataOffset();
+ next_data_pos_ = GetDataOffset(header_);
return true;
}
@@ -191,7 +193,7 @@
resume_points_ = parser.resume_points();
options_.block_size = header_.block_size;
- next_data_pos_ = GetDataOffset();
+ next_data_pos_ = GetDataOffset(header_);
TranslatedCowOps ops;
parser.Translate(&ops);
@@ -296,20 +298,21 @@
resume_points_->end());
resume_points_->push_back({label, header_.op_count});
+ header_.resume_point_count++;
// remove the oldest resume point if resume_buffer is full
- while (resume_points_->size() > header_.resume_buffer_size) {
+ while (resume_points_->size() > header_.resume_point_max) {
resume_points_->erase(resume_points_->begin());
}
- CHECK_LE(resume_points_->size(), header_.resume_buffer_size);
+ CHECK_LE(resume_points_->size(), header_.resume_point_max);
if (!android::base::WriteFullyAtOffset(fd_, resume_points_->data(),
resume_points_->size() * sizeof(ResumePoint),
- GetResumeOffset())) {
+ GetResumeOffset(header_))) {
PLOG(ERROR) << "writing resume buffer failed";
return false;
}
- return Sync();
+ return Finalize();
}
bool CowWriterV3::EmitSequenceData(size_t num_ops, const uint32_t* data) {
@@ -331,7 +334,7 @@
return false;
}
- const off_t offset = GetOpOffset(header_.op_count);
+ const off_t offset = GetOpOffset(header_.op_count, header_);
if (!android::base::WriteFullyAtOffset(fd_, &op, sizeof(op), offset)) {
PLOG(ERROR) << "write failed for " << op << " at " << offset;
return false;
@@ -360,9 +363,7 @@
}
uint64_t CowWriterV3::GetCowSize() {
- LOG(ERROR) << __LINE__ << " " << __FILE__
- << " <- Get Cow Size function here should never be called";
- return 0;
+ return next_data_pos_;
}
} // namespace snapshot
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
index 8a2bd2c..3dfc33c 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
@@ -49,19 +49,6 @@
uint16_t offset, uint8_t type);
bool CompressBlocks(size_t num_blocks, const void* data);
- off_t GetOpOffset(uint32_t op_index) const {
- CHECK_LT(op_index, header_.op_count_max);
- return header_.prefix.header_size + header_.buffer_size +
- (header_.resume_buffer_size * sizeof(ResumePoint)) +
- (op_index * sizeof(CowOperationV3));
- }
- off_t GetDataOffset() const {
- return sizeof(CowHeaderV3) + header_.buffer_size +
- (header_.resume_buffer_size * sizeof(ResumePoint)) +
- header_.op_count_max * sizeof(CowOperation);
- }
- off_t GetResumeOffset() const { return sizeof(CowHeaderV3) + header_.buffer_size; }
-
private:
CowHeaderV3 header_{};
CowCompression compression_;
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index c639e43..e91e3b7 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -4339,32 +4339,30 @@
}
bool SnapshotManager::IsUserspaceSnapshotUpdateInProgress() {
- auto slot = GetCurrentSlot();
- if (slot == Slot::Target) {
- // Merge in-progress
- if (IsSnapuserdRequired()) {
+ // We cannot grab /metadata/ota lock here as this
+ // is in reboot path. See b/308900853
+ //
+ // Check if any of the partitions are mounted
+ // off dm-user block device. If so, then we are certain
+ // that OTA update in progress.
+ auto current_suffix = device_->GetSlotSuffix();
+ auto& dm = DeviceMapper::Instance();
+ auto dm_block_devices = dm.FindDmPartitions();
+ if (dm_block_devices.empty()) {
+ LOG(ERROR) << "No dm-enabled block device is found.";
+ return false;
+ }
+ for (auto& partition : dm_block_devices) {
+ std::string partition_name = partition.first + current_suffix;
+ DeviceMapper::TargetInfo snap_target;
+ if (!GetSingleTarget(partition_name, TableQuery::Status, &snap_target)) {
+ return false;
+ }
+ auto type = DeviceMapper::GetTargetType(snap_target.spec);
+ if (type == "user") {
return true;
}
}
-
- // Let's check more deeper to see if snapshots are mounted
- auto lock = LockExclusive();
- if (!lock) {
- return false;
- }
-
- std::vector<std::string> snapshots;
- if (!ListSnapshots(lock.get(), &snapshots)) {
- return false;
- }
-
- for (const auto& snapshot : snapshots) {
- // Active snapshot and daemon is alive
- if (IsSnapshotDevice(snapshot) && EnsureSnapuserdConnected(2s)) {
- return true;
- }
- }
-
return false;
}
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp
index d979e20..ffd7a4b 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp
@@ -51,11 +51,10 @@
std::shared_ptr<HandlerThread> SnapshotHandlerManager::AddHandler(
const std::string& misc_name, const std::string& cow_device_path,
const std::string& backing_device, const std::string& base_path_merge,
- std::shared_ptr<IBlockServerOpener> opener, int num_worker_threads, bool use_iouring,
- bool perform_verification) {
+ std::shared_ptr<IBlockServerOpener> opener, int num_worker_threads, bool use_iouring) {
auto snapuserd = std::make_shared<SnapshotHandler>(misc_name, cow_device_path, backing_device,
base_path_merge, opener, num_worker_threads,
- use_iouring, perform_verification);
+ use_iouring, perform_verification_);
if (!snapuserd->InitCowDevice()) {
LOG(ERROR) << "Failed to initialize Snapuserd";
return nullptr;
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h
index b1605f0..ff6ee8f 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.h
@@ -57,8 +57,7 @@
const std::string& backing_device,
const std::string& base_path_merge,
std::shared_ptr<IBlockServerOpener> opener,
- int num_worker_threads, bool use_iouring,
- bool perform_verification) = 0;
+ int num_worker_threads, bool use_iouring) = 0;
// Start serving requests on a snapshot handler.
virtual bool StartHandler(const std::string& misc_name) = 0;
@@ -84,6 +83,9 @@
// Returns whether all snapshots have verified.
virtual bool GetVerificationStatus() = 0;
+
+ // Disable partition verification
+ virtual void DisableVerification() = 0;
};
class SnapshotHandlerManager final : public ISnapshotHandlerManager {
@@ -94,8 +96,7 @@
const std::string& backing_device,
const std::string& base_path_merge,
std::shared_ptr<IBlockServerOpener> opener,
- int num_worker_threads, bool use_iouring,
- bool perform_verification) override;
+ int num_worker_threads, bool use_iouring) override;
bool StartHandler(const std::string& misc_name) override;
bool DeleteHandler(const std::string& misc_name) override;
bool InitiateMerge(const std::string& misc_name) override;
@@ -104,6 +105,7 @@
void TerminateMergeThreads() override;
double GetMergePercentage() override;
bool GetVerificationStatus() override;
+ void DisableVerification() override { perform_verification_ = false; }
private:
bool StartHandler(const std::shared_ptr<HandlerThread>& handler);
@@ -128,6 +130,7 @@
int num_partitions_merge_complete_ = 0;
std::queue<std::shared_ptr<HandlerThread>> merge_handlers_;
android::base::unique_fd monitor_merge_event_fd_;
+ bool perform_verification_ = true;
};
} // namespace snapshot
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
index 13b9a00..6eee357 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
@@ -360,16 +360,15 @@
num_worker_threads = 1;
}
- bool perform_verification = true;
- if (android::base::EndsWith(misc_name, "-init") || is_socket_present_) {
- perform_verification = false;
+ if (android::base::EndsWith(misc_name, "-init") || is_socket_present_ ||
+ (access(kBootSnapshotsWithoutSlotSwitch, F_OK) == 0)) {
+ handlers_->DisableVerification();
}
auto opener = block_server_factory_->CreateOpener(misc_name);
return handlers_->AddHandler(misc_name, cow_device_path, backing_device, base_path_merge,
- opener, num_worker_threads, io_uring_enabled_,
- perform_verification);
+ opener, num_worker_threads, io_uring_enabled_);
}
bool UserSnapshotServer::WaitForSocket() {
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h
index be28541..9926071 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.h
@@ -40,6 +40,8 @@
static constexpr uint32_t kMaxPacketSize = 512;
static constexpr uint8_t kMaxMergeThreads = 2;
+static constexpr char kBootSnapshotsWithoutSlotSwitch[] =
+ "/metadata/ota/snapshot-boot-without-slot-switch";
class UserSnapshotServer {
private:
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
index bed71cf..73c3cbf 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
@@ -627,9 +627,10 @@
void SnapuserdTest::InitCowDevice() {
auto factory = harness_->GetBlockServerFactory();
auto opener = factory->CreateOpener(system_device_ctrl_name_);
+ handlers_->DisableVerification();
auto handler =
handlers_->AddHandler(system_device_ctrl_name_, cow_system_->path, base_dev_->GetPath(),
- base_dev_->GetPath(), opener, 1, GetParam(), false);
+ base_dev_->GetPath(), opener, 1, GetParam());
ASSERT_NE(handler, nullptr);
ASSERT_NE(handler->snapuserd(), nullptr);
#ifdef __ANDROID__
diff --git a/init/init.cpp b/init/init.cpp
index 83cb78b..aeccd66 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -117,7 +117,6 @@
static int property_triggers_enabled = 0;
-int sigchld_fd = -1;
static int sigterm_fd = -1;
static int property_fd = -1;
@@ -717,7 +716,7 @@
static void HandleSignalFd(int signal) {
signalfd_siginfo siginfo;
- const int signal_fd = signal == SIGCHLD ? sigchld_fd : sigterm_fd;
+ const int signal_fd = signal == SIGCHLD ? Service::GetSigchldFd() : sigterm_fd;
ssize_t bytes_read = TEMP_FAILURE_RETRY(read(signal_fd, &siginfo, sizeof(siginfo)));
if (bytes_read != sizeof(siginfo)) {
PLOG(ERROR) << "Failed to read siginfo from signal_fd";
@@ -751,20 +750,24 @@
}
}
+static Result<void> RegisterSignalFd(Epoll* epoll, int signal, int fd) {
+ return epoll->RegisterHandler(
+ fd, [signal]() { HandleSignalFd(signal); }, EPOLLIN | EPOLLPRI);
+}
+
static Result<int> CreateAndRegisterSignalFd(Epoll* epoll, int signal) {
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, signal);
- unique_fd signal_fd(signalfd(-1, &mask, SFD_CLOEXEC));
- if (signal_fd == -1) {
- return ErrnoError() << "failed to create signalfd for signal " << signal;
+ if (sigprocmask(SIG_BLOCK, &mask, nullptr) == -1) {
+ return ErrnoError() << "failed to block signal " << signal;
}
- auto result = epoll->RegisterHandler(
- signal_fd.get(), [signal]() { HandleSignalFd(signal); }, EPOLLIN | EPOLLPRI);
- if (!result.ok()) {
- return result.error();
+ unique_fd signal_fd(signalfd(-1, &mask, SFD_CLOEXEC));
+ if (signal_fd.get() < 0) {
+ return ErrnoError() << "failed to create signalfd for signal " << signal;
}
+ OR_RETURN(RegisterSignalFd(epoll, signal, signal_fd.get()));
return signal_fd.release();
}
@@ -775,34 +778,18 @@
const struct sigaction act { .sa_flags = SA_NOCLDSTOP, .sa_handler = SIG_DFL };
sigaction(SIGCHLD, &act, nullptr);
- sigset_t mask;
- sigemptyset(&mask);
- sigaddset(&mask, SIGCHLD);
-
- if (!IsRebootCapable()) {
- // If init does not have the CAP_SYS_BOOT capability, it is running in a container.
- // In that case, receiving SIGTERM will cause the system to shut down.
- sigaddset(&mask, SIGTERM);
- }
-
- if (sigprocmask(SIG_BLOCK, &mask, nullptr) == -1) {
- PLOG(FATAL) << "failed to block signals";
- }
-
// Register a handler to unblock signals in the child processes.
const int result = pthread_atfork(nullptr, nullptr, &UnblockSignals);
if (result != 0) {
LOG(FATAL) << "Failed to register a fork handler: " << strerror(result);
}
- Result<int> cs_result = CreateAndRegisterSignalFd(epoll, SIGCHLD);
+ Result<void> cs_result = RegisterSignalFd(epoll, SIGCHLD, Service::GetSigchldFd());
if (!cs_result.ok()) {
PLOG(FATAL) << cs_result.error();
}
- sigchld_fd = cs_result.value();
- Service::SetSigchldFd(sigchld_fd);
- if (sigismember(&mask, SIGTERM)) {
+ if (!IsRebootCapable()) {
Result<int> cs_result = CreateAndRegisterSignalFd(epoll, SIGTERM);
if (!cs_result.ok()) {
PLOG(FATAL) << cs_result.error();
diff --git a/init/init.h b/init/init.h
index b781167..9c7e918 100644
--- a/init/init.h
+++ b/init/init.h
@@ -28,8 +28,6 @@
namespace android {
namespace init {
-extern int sigchld_fd;
-
Parser CreateParser(ActionManager& action_manager, ServiceList& service_list);
Parser CreateApexConfigParser(ActionManager& action_manager, ServiceList& service_list);
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 5757922..1a26c4d 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -563,7 +563,7 @@
}
}
if (timeout > 0ms) {
- WaitToBeReaped(sigchld_fd, pids, timeout);
+ WaitToBeReaped(Service::GetSigchldFd(), pids, timeout);
} else {
// Even if we don't to wait for services to stop, we still optimistically reap zombies.
ReapAnyOutstandingChildren();
diff --git a/init/security.cpp b/init/security.cpp
index 0c73fae..3e15447 100644
--- a/init/security.cpp
+++ b/init/security.cpp
@@ -20,6 +20,7 @@
#include <errno.h>
#include <fcntl.h>
#include <linux/perf_event.h>
+#include <math.h>
#include <selinux/selinux.h>
#include <sys/ioctl.h>
#include <sys/syscall.h>
@@ -121,8 +122,12 @@
}
#elif defined(__x86_64__)
// x86_64 supports 28 - 32 rnd bits, but Android wants to ensure that the
- // theoretical maximum of 32 bits is always supported and used.
- if (SetMmapRndBitsMin(32, 32, false) && (!Has32BitAbi() || SetMmapRndBitsMin(16, 16, true))) {
+ // theoretical maximum of 32 bits is always supported and used; except in
+ // the case of the x86 page size emulator which supports a maximum
+ // of 30 bits for 16k page size, or 28 bits for 64k page size.
+ int max_bits = 32 - (static_cast<int>(log2(getpagesize())) - 12);
+ if (SetMmapRndBitsMin(max_bits, max_bits, false) &&
+ (!Has32BitAbi() || SetMmapRndBitsMin(16, 16, true))) {
return {};
}
#elif defined(__arm__) || defined(__i386__)
diff --git a/init/service.cpp b/init/service.cpp
index d351a8f..eb24dd5 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -37,6 +37,7 @@
#include <cutils/sockets.h>
#include <processgroup/processgroup.h>
#include <selinux/selinux.h>
+#include <sys/signalfd.h>
#include <string>
@@ -68,6 +69,7 @@
using android::base::SetProperty;
using android::base::StartsWith;
using android::base::StringPrintf;
+using android::base::unique_fd;
using android::base::WriteStringToFile;
namespace android {
@@ -136,7 +138,6 @@
unsigned long Service::next_start_order_ = 1;
bool Service::is_exec_service_running_ = false;
-int Service::sigchld_fd_ = -1;
Service::Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
const std::string& filename, const std::vector<std::string>& args)
@@ -792,6 +793,35 @@
mount_namespace_ = IsDefaultMountNamespaceReady() ? NS_DEFAULT : NS_BOOTSTRAP;
}
+static int ThreadCount() {
+ std::unique_ptr<DIR, decltype(&closedir)> dir(opendir("/proc/self/task"), closedir);
+ if (!dir) {
+ return -1;
+ }
+
+ int count = 0;
+ dirent* entry;
+ while ((entry = readdir(dir.get())) != nullptr) {
+ if (entry->d_name[0] != '.') {
+ count++;
+ }
+ }
+ return count;
+}
+
+// Must be called BEFORE any threads are created. See also the sigprocmask() man page.
+unique_fd Service::CreateSigchldFd() {
+ CHECK_EQ(ThreadCount(), 1);
+ sigset_t mask;
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGCHLD);
+ if (sigprocmask(SIG_BLOCK, &mask, nullptr) < 0) {
+ PLOG(FATAL) << "Failed to block SIGCHLD";
+ }
+
+ return unique_fd(signalfd(-1, &mask, SFD_CLOEXEC));
+}
+
void Service::SetStartedInFirstStage(pid_t pid) {
LOG(INFO) << "adding first-stage service '" << name_ << "'...";
diff --git a/init/service.h b/init/service.h
index 13c8b5f..5e9af25 100644
--- a/init/service.h
+++ b/init/service.h
@@ -156,7 +156,10 @@
const Subcontext* subcontext() const { return subcontext_; }
const std::string& filename() const { return filename_; }
void set_filename(const std::string& name) { filename_ = name; }
- static void SetSigchldFd(int sigchld_fd) { sigchld_fd_ = sigchld_fd; }
+ static int GetSigchldFd() {
+ static int sigchld_fd = CreateSigchldFd().release();
+ return sigchld_fd;
+ }
private:
void NotifyStateChange(const std::string& new_state) const;
@@ -169,10 +172,10 @@
void RunService(const std::vector<Descriptor>& descriptors, InterprocessFifo cgroups_activated,
InterprocessFifo setsid_finished);
void SetMountNamespace();
+ static ::android::base::unique_fd CreateSigchldFd();
static unsigned long next_start_order_;
static bool is_exec_service_running_;
- static int sigchld_fd_;
const std::string name_;
std::set<std::string> classnames_;
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index 586e2cf..3f0d0e9 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -297,6 +297,10 @@
}
static UeventdConfiguration GetConfiguration() {
+ if (IsMicrodroid()) {
+ return ParseConfig({"/system/etc/ueventd.rc", "/vendor/etc/ueventd.rc"});
+ }
+
auto hardware = android::base::GetProperty("ro.hardware", "");
struct LegacyPathInfo {
diff --git a/libprocessgroup/include/processgroup/processgroup.h b/libprocessgroup/include/processgroup/processgroup.h
index a319c63..9107838 100644
--- a/libprocessgroup/include/processgroup/processgroup.h
+++ b/libprocessgroup/include/processgroup/processgroup.h
@@ -87,7 +87,6 @@
bool setProcessGroupSoftLimit(uid_t uid, int initialPid, int64_t softLimitInBytes);
bool setProcessGroupLimit(uid_t uid, int initialPid, int64_t limitInBytes);
-void removeAllProcessGroups(void);
void removeAllEmptyProcessGroups(void);
// Provides the path for an attribute in a specific process group
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 6d07538..76868bb 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -242,7 +242,7 @@
return ret;
}
-static bool RemoveUidCgroups(const std::string& uid_path, bool empty_only) {
+static bool RemoveEmptyUidCgroups(const std::string& uid_path) {
std::unique_ptr<DIR, decltype(&closedir)> uid(opendir(uid_path.c_str()), closedir);
bool empty = true;
if (uid != NULL) {
@@ -257,21 +257,6 @@
}
auto path = StringPrintf("%s/%s", uid_path.c_str(), dir->d_name);
- if (empty_only) {
- struct stat st;
- auto procs_file = StringPrintf("%s/%s", path.c_str(),
- PROCESSGROUP_CGROUP_PROCS_FILE);
- if (stat(procs_file.c_str(), &st) == -1) {
- PLOG(ERROR) << "Failed to get stats for " << procs_file;
- continue;
- }
- if (st.st_size > 0) {
- // skip non-empty groups
- LOG(VERBOSE) << "Skipping non-empty group " << path;
- empty = false;
- continue;
- }
- }
LOG(VERBOSE) << "Removing " << path;
if (rmdir(path.c_str()) == -1) {
if (errno != EBUSY) {
@@ -284,7 +269,9 @@
return empty;
}
-static void removeAllProcessGroupsInternal(bool empty_only) {
+void removeAllEmptyProcessGroups() {
+ LOG(VERBOSE) << "removeAllEmptyProcessGroups()";
+
std::vector<std::string> cgroups;
std::string path, memcg_apps_path;
@@ -311,7 +298,7 @@
}
auto path = StringPrintf("%s/%s", cgroup_root_path.c_str(), dir->d_name);
- if (!RemoveUidCgroups(path, empty_only)) {
+ if (!RemoveEmptyUidCgroups(path)) {
LOG(VERBOSE) << "Skip removing " << path;
continue;
}
@@ -324,16 +311,6 @@
}
}
-void removeAllProcessGroups() {
- LOG(VERBOSE) << "removeAllProcessGroups()";
- removeAllProcessGroupsInternal(false);
-}
-
-void removeAllEmptyProcessGroups() {
- LOG(VERBOSE) << "removeAllEmptyProcessGroups()";
- removeAllProcessGroupsInternal(true);
-}
-
/**
* Process groups are primarily created by the Zygote, meaning that uid/pid groups are created by
* the user root. Ownership for the newly created cgroup and all of its files must thus be
diff --git a/libprocessgroup/profiles/cgroups.json b/libprocessgroup/profiles/cgroups.json
index 3e4393d..d013ec8 100644
--- a/libprocessgroup/profiles/cgroups.json
+++ b/libprocessgroup/profiles/cgroups.json
@@ -1,13 +1,6 @@
{
"Cgroups": [
{
- "Controller": "blkio",
- "Path": "/dev/blkio",
- "Mode": "0775",
- "UID": "system",
- "GID": "system"
- },
- {
"Controller": "cpu",
"Path": "/dev/cpuctl",
"Mode": "0755",
@@ -39,6 +32,12 @@
{
"Controller": "freezer",
"Path": "."
+ },
+ {
+ "Controller": "io",
+ "Path": ".",
+ "NeedsActivation": true,
+ "Optional": true
}
]
}
diff --git a/libprocessgroup/profiles/task_profiles.json b/libprocessgroup/profiles/task_profiles.json
index 1fc66ba..2c08b0b 100644
--- a/libprocessgroup/profiles/task_profiles.json
+++ b/libprocessgroup/profiles/task_profiles.json
@@ -76,6 +76,21 @@
"Name": "FreezerState",
"Controller": "freezer",
"File": "cgroup.freeze"
+ },
+ {
+ "Name": "BfqWeight",
+ "Controller": "io",
+ "File": "io.bfq.weight"
+ },
+ {
+ "Name": "CfqGroupIdle",
+ "Controller": "io",
+ "File": "io.group_idle"
+ },
+ {
+ "Name": "CfqWeight",
+ "Controller": "io",
+ "File": "io.weight"
}
],
@@ -439,11 +454,30 @@
"Name": "LowIoPriority",
"Actions": [
{
- "Name": "JoinCgroup",
+ "Name": "SetAttribute",
"Params":
{
- "Controller": "blkio",
- "Path": "background"
+ "Name": "BfqWeight",
+ "Value": "10",
+ "Optional": "true"
+ }
+ },
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "CfqGroupIdle",
+ "Value": "0",
+ "Optional": "true"
+ }
+ },
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "CfqWeight",
+ "Value": "200",
+ "Optional": "true"
}
}
]
@@ -452,11 +486,30 @@
"Name": "NormalIoPriority",
"Actions": [
{
- "Name": "JoinCgroup",
+ "Name": "SetAttribute",
"Params":
{
- "Controller": "blkio",
- "Path": ""
+ "Name": "BfqWeight",
+ "Value": "100",
+ "Optional": "true"
+ }
+ },
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "CfqGroupIdle",
+ "Value": "0",
+ "Optional": "true"
+ }
+ },
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "CfqWeight",
+ "Value": "1000",
+ "Optional": "true"
}
}
]
@@ -465,11 +518,30 @@
"Name": "HighIoPriority",
"Actions": [
{
- "Name": "JoinCgroup",
+ "Name": "SetAttribute",
"Params":
{
- "Controller": "blkio",
- "Path": ""
+ "Name": "BfqWeight",
+ "Value": "100",
+ "Optional": "true"
+ }
+ },
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "CfqGroupIdle",
+ "Value": "0",
+ "Optional": "true"
+ }
+ },
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "CfqWeight",
+ "Value": "1000",
+ "Optional": "true"
}
}
]
@@ -478,11 +550,30 @@
"Name": "MaxIoPriority",
"Actions": [
{
- "Name": "JoinCgroup",
+ "Name": "SetAttribute",
"Params":
{
- "Controller": "blkio",
- "Path": ""
+ "Name": "BfqWeight",
+ "Value": "100",
+ "Optional": "true"
+ }
+ },
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "CfqGroupIdle",
+ "Value": "0",
+ "Optional": "true"
+ }
+ },
+ {
+ "Name": "SetAttribute",
+ "Params":
+ {
+ "Name": "CfqWeight",
+ "Value": "1000",
+ "Optional": "true"
}
}
]
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index f51b076..d5bd47c 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -316,7 +316,7 @@
FdCacheHelper::Init(controller_.GetProcsFilePath(path_, 0, 0), fd_[ProfileAction::RCT_PROCESS]);
}
-bool SetCgroupAction::AddTidToCgroup(int tid, int fd, const char* controller_name) {
+bool SetCgroupAction::AddTidToCgroup(int tid, int fd, ResourceCacheType cache_type) const {
if (tid <= 0) {
return true;
}
@@ -332,6 +332,7 @@
return true;
}
+ const char* controller_name = controller()->name();
// ENOSPC is returned when cpuset cgroup that we are joining has no online cpus
if (errno == ENOSPC && !strcmp(controller_name, "cpuset")) {
// This is an abnormal case happening only in testing, so report it only once
@@ -345,7 +346,8 @@
<< "' into cpuset because all cpus in that cpuset are offline";
empty_cpuset_reported = true;
} else {
- PLOG(ERROR) << "AddTidToCgroup failed to write '" << value << "'; fd=" << fd;
+ PLOG(ERROR) << "AddTidToCgroup failed to write '" << value << "'; path=" << path_ << "; "
+ << (cache_type == RCT_TASK ? "task" : "process");
}
return false;
@@ -356,7 +358,7 @@
std::lock_guard<std::mutex> lock(fd_mutex_);
if (FdCacheHelper::IsCached(fd_[cache_type])) {
// fd is cached, reuse it
- if (!AddTidToCgroup(id, fd_[cache_type], controller()->name())) {
+ if (!AddTidToCgroup(id, fd_[cache_type], cache_type)) {
LOG(ERROR) << "Failed to add task into cgroup";
return ProfileAction::FAIL;
}
@@ -391,7 +393,7 @@
PLOG(WARNING) << Name() << "::" << __func__ << ": failed to open " << procs_path;
return false;
}
- if (!AddTidToCgroup(pid, tmp_fd, controller()->name())) {
+ if (!AddTidToCgroup(pid, tmp_fd, RCT_PROCESS)) {
LOG(ERROR) << "Failed to add task into cgroup";
return false;
}
@@ -412,7 +414,7 @@
PLOG(WARNING) << Name() << "::" << __func__ << ": failed to open " << tasks_path;
return false;
}
- if (!AddTidToCgroup(tid, tmp_fd, controller()->name())) {
+ if (!AddTidToCgroup(tid, tmp_fd, RCT_TASK)) {
LOG(ERROR) << "Failed to add task into cgroup";
return false;
}
@@ -866,7 +868,13 @@
auto controller = cg_map.FindController(controller_name);
if (controller.HasValue()) {
- profile->Add(std::make_unique<SetCgroupAction>(controller, path));
+ if (controller.version() == 1) {
+ profile->Add(std::make_unique<SetCgroupAction>(controller, path));
+ } else {
+ LOG(WARNING) << "A JoinCgroup action in the " << profile_name
+ << " profile is used for controller " << controller_name
+ << " in the cgroup v2 hierarchy and will be ignored";
+ }
} else {
LOG(WARNING) << "JoinCgroup: controller " << controller_name << " is not found";
}
diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h
index 4663f64..16ffe63 100644
--- a/libprocessgroup/task_profiles.h
+++ b/libprocessgroup/task_profiles.h
@@ -160,7 +160,7 @@
android::base::unique_fd fd_[ProfileAction::RCT_COUNT];
mutable std::mutex fd_mutex_;
- static bool AddTidToCgroup(int tid, int fd, const char* controller_name);
+ bool AddTidToCgroup(int tid, int fd, ResourceCacheType cache_type) const;
CacheUseResult UseCachedFd(ResourceCacheType cache_type, int id) const;
};
diff --git a/libutils/binder/StrongPointer_test.cpp b/libutils/binder/StrongPointer_test.cpp
index f27c1f1..aa993c3 100644
--- a/libutils/binder/StrongPointer_test.cpp
+++ b/libutils/binder/StrongPointer_test.cpp
@@ -106,3 +106,17 @@
EXPECT_DEATH(sp<TypeParam>::fromExisting(foo), "");
delete foo;
}
+
+TYPED_TEST(StrongPointer, release) {
+ bool isDeleted = false;
+ TypeParam* foo = nullptr;
+ {
+ sp<TypeParam> sp1 = sp<TypeParam>::make(&isDeleted);
+ ASSERT_EQ(1, sp1->getStrongCount());
+ foo = sp1.release();
+ }
+ ASSERT_FALSE(isDeleted) << "release failed, deleted anyway when sp left scope";
+ ASSERT_EQ(1, foo->getStrongCount()) << "release mismanaged refcount";
+ foo->decStrong(nullptr);
+ ASSERT_TRUE(isDeleted) << "foo was leaked!";
+}
diff --git a/libutils/binder/include/utils/StrongPointer.h b/libutils/binder/include/utils/StrongPointer.h
index 54aa691..43c00c9 100644
--- a/libutils/binder/include/utils/StrongPointer.h
+++ b/libutils/binder/include/utils/StrongPointer.h
@@ -98,6 +98,15 @@
void clear();
+ // Releases the ownership of the object managed by this instance of sp, if any.
+ // The caller is now responsible for managing it. That is, the caller must ensure
+ // decStrong() is called when the pointer is no longer used.
+ [[nodiscard]] inline T* release() noexcept {
+ auto ret = m_ptr;
+ m_ptr = nullptr;
+ return ret;
+ }
+
// Accessors
inline T& operator* () const { return *m_ptr; }
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 317f809..fb64736 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -219,26 +219,6 @@
write /dev/stune/nnapi-hal/schedtune.boost 1
write /dev/stune/nnapi-hal/schedtune.prefer_idle 1
- # Create blkio group and apply initial settings.
- # This feature needs kernel to support it, and the
- # device's init.rc must actually set the correct values.
- mkdir /dev/blkio/background
- chown system system /dev/blkio
- chown system system /dev/blkio/background
- chown system system /dev/blkio/tasks
- chown system system /dev/blkio/background/tasks
- chown system system /dev/blkio/cgroup.procs
- chown system system /dev/blkio/background/cgroup.procs
- chmod 0664 /dev/blkio/tasks
- chmod 0664 /dev/blkio/background/tasks
- chmod 0664 /dev/blkio/cgroup.procs
- chmod 0664 /dev/blkio/background/cgroup.procs
- write /dev/blkio/blkio.weight 1000
- write /dev/blkio/background/blkio.weight 200
- write /dev/blkio/background/blkio.bfq.weight 10
- write /dev/blkio/blkio.group_idle 0
- write /dev/blkio/background/blkio.group_idle 0
-
restorecon_recursive /mnt
mount configfs none /config nodev noexec nosuid
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
index 60dcc2a..3927501 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -71,6 +71,7 @@
/dev/mtp_usb 0660 root mtp
/dev/usb_accessory 0660 root usb
/dev/tun 0660 system vpn
+/dev/hidraw* 0660 system system
# CDMA radio interface MUX
/dev/ppp 0660 radio vpn