Merge "Simplified stats_event.c; exposed getter methods"
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index ce1f9ef..d3ee659 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -1351,38 +1351,9 @@
return ret;
}
-static std::string GetUserdataBlockDevice() {
- Fstab fstab;
- if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
- LERROR << "Failed to read /proc/mounts";
- return "";
- }
- auto entry = GetEntryForMountPoint(&fstab, "/data");
- if (entry == nullptr) {
- LERROR << "Didn't find /data mount point in /proc/mounts";
- return "";
- }
- return entry->blk_device;
-}
-
int fs_mgr_remount_userdata_into_checkpointing(Fstab* fstab) {
- const std::string& block_device = GetUserdataBlockDevice();
- LINFO << "Userdata is mounted on " << block_device;
- auto entry = std::find_if(fstab->begin(), fstab->end(), [&block_device](const FstabEntry& e) {
- if (e.mount_point != "/data") {
- return false;
- }
- if (e.blk_device == block_device) {
- return true;
- }
- DeviceMapper& dm = DeviceMapper::Instance();
- std::string path;
- if (!dm.GetDmDevicePathByName("userdata", &path)) {
- return false;
- }
- return path == block_device;
- });
- if (entry == fstab->end()) {
+ auto entry = GetMountedEntryForUserdata(fstab);
+ if (entry == nullptr) {
LERROR << "Can't find /data in fstab";
return -1;
}
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 534eae4..e279af9 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -40,6 +40,7 @@
using android::base::ParseByteCount;
using android::base::ParseInt;
using android::base::ReadFileToString;
+using android::base::Readlink;
using android::base::Split;
using android::base::StartsWith;
@@ -804,6 +805,89 @@
return entries;
}
+static std::string ResolveBlockDevice(const std::string& block_device) {
+ if (!StartsWith(block_device, "/dev/block/")) {
+ LWARNING << block_device << " is not a block device";
+ return block_device;
+ }
+ std::string name = block_device.substr(5);
+ if (!StartsWith(name, "block/dm-")) {
+ // Not a dm-device, but might be a symlink. Optimistically try to readlink.
+ std::string result;
+ if (Readlink(block_device, &result)) {
+ return result;
+ } else if (errno == EINVAL) {
+ // After all, it wasn't a symlink.
+ return block_device;
+ } else {
+ LERROR << "Failed to readlink " << block_device;
+ return "";
+ }
+ }
+ // It's a dm-device, let's find what's inside!
+ std::string sys_dir = "/sys/" + name;
+ while (true) {
+ std::string slaves_dir = sys_dir + "/slaves";
+ std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(slaves_dir.c_str()), closedir);
+ if (!dir) {
+ LERROR << "Failed to open " << slaves_dir;
+ return "";
+ }
+ std::string sub_device_name = "";
+ for (auto entry = readdir(dir.get()); entry; entry = readdir(dir.get())) {
+ if (entry->d_type != DT_LNK) continue;
+ if (!sub_device_name.empty()) {
+ LERROR << "Too many slaves in " << slaves_dir;
+ return "";
+ }
+ sub_device_name = entry->d_name;
+ }
+ if (sub_device_name.empty()) {
+ LERROR << "No slaves in " << slaves_dir;
+ return "";
+ }
+ if (!StartsWith(sub_device_name, "dm-")) {
+ // Not a dm-device! We can stop now.
+ return "/dev/block/" + sub_device_name;
+ }
+ // Still a dm-device, keep digging.
+ sys_dir = "/sys/block/" + sub_device_name;
+ }
+}
+
+FstabEntry* GetMountedEntryForUserdata(Fstab* fstab) {
+ Fstab mounts;
+ if (!ReadFstabFromFile("/proc/mounts", &mounts)) {
+ LERROR << "Failed to read /proc/mounts";
+ return nullptr;
+ }
+ auto mounted_entry = GetEntryForMountPoint(&mounts, "/data");
+ if (mounted_entry == nullptr) {
+ LWARNING << "/data is not mounted";
+ return nullptr;
+ }
+ std::string resolved_block_device = ResolveBlockDevice(mounted_entry->blk_device);
+ if (resolved_block_device.empty()) {
+ return nullptr;
+ }
+ LINFO << "/data is mounted on " << resolved_block_device;
+ for (auto& entry : *fstab) {
+ if (entry.mount_point != "/data") {
+ continue;
+ }
+ std::string block_device;
+ if (!Readlink(entry.blk_device, &block_device)) {
+ LWARNING << "Failed to readlink " << entry.blk_device;
+ block_device = entry.blk_device;
+ }
+ if (block_device == resolved_block_device) {
+ return &entry;
+ }
+ }
+ LERROR << "Didn't find entry that was used to mount /data";
+ return nullptr;
+}
+
std::set<std::string> GetBootDevices() {
// First check the kernel commandline, then try the device tree otherwise
std::string dt_file_name = get_android_dt_dir() + "/boot_devices";
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index 6ce6160..e625170 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -100,6 +100,7 @@
FstabEntry* GetEntryForMountPoint(Fstab* fstab, const std::string& path);
// The Fstab can contain multiple entries for the same mount point with different configurations.
std::vector<FstabEntry*> GetEntriesForMountPoint(Fstab* fstab, const std::string& path);
+FstabEntry* GetMountedEntryForUserdata(Fstab* fstab);
// This method builds DSU fstab entries and transfer the fstab.
//
diff --git a/fs_mgr/liblp/images.cpp b/fs_mgr/liblp/images.cpp
index 6b842b3..e4d92ca 100644
--- a/fs_mgr/liblp/images.cpp
+++ b/fs_mgr/liblp/images.cpp
@@ -110,7 +110,7 @@
return ReadFromImageFile(fd);
}
-bool WriteToImageFile(int fd, const LpMetadata& input) {
+bool WriteToImageFile(borrowed_fd fd, const LpMetadata& input) {
std::string geometry = SerializeGeometry(input.geometry);
std::string metadata = SerializeMetadata(input);
diff --git a/fs_mgr/liblp/images.h b/fs_mgr/liblp/images.h
index a284d2e..88e5882 100644
--- a/fs_mgr/liblp/images.h
+++ b/fs_mgr/liblp/images.h
@@ -29,8 +29,6 @@
// Helper function to serialize geometry and metadata to a normal file, for
// flashing or debugging.
std::unique_ptr<LpMetadata> ReadFromImageFile(int fd);
-bool WriteToImageFile(const char* file, const LpMetadata& metadata);
-bool WriteToImageFile(int fd, const LpMetadata& metadata);
// We use an object to build the image file since it requires that data
// pointers be held alive until the sparse file is destroyed. It's easier
diff --git a/fs_mgr/liblp/include/liblp/liblp.h b/fs_mgr/liblp/include/liblp/liblp.h
index cd860cd..04f8987 100644
--- a/fs_mgr/liblp/include/liblp/liblp.h
+++ b/fs_mgr/liblp/include/liblp/liblp.h
@@ -76,12 +76,15 @@
// supported). It is a format specifically for storing only metadata.
bool IsEmptySuperImage(const std::string& file);
-// Read/Write logical partition metadata to an image file, for diagnostics or
-// flashing. If no partition images are specified, the file will be in the
-// empty format.
+// Read/Write logical partition metadata and contents to an image file, for
+// flashing.
bool WriteToImageFile(const std::string& file, const LpMetadata& metadata, uint32_t block_size,
const std::map<std::string, std::string>& images, bool sparsify);
+
+// Read/Write logical partition metadata to an image file, for producing a
+// super_empty.img (for fastboot wipe-super/update-super) or for diagnostics.
bool WriteToImageFile(const std::string& file, const LpMetadata& metadata);
+bool WriteToImageFile(android::base::borrowed_fd fd, const LpMetadata& metadata);
std::unique_ptr<LpMetadata> ReadFromImageFile(const std::string& image_file);
std::unique_ptr<LpMetadata> ReadFromImageBlob(const void* data, size_t bytes);
diff --git a/fs_mgr/liblp/writer.cpp b/fs_mgr/liblp/writer.cpp
index 8a983ad..bb24069 100644
--- a/fs_mgr/liblp/writer.cpp
+++ b/fs_mgr/liblp/writer.cpp
@@ -83,8 +83,9 @@
// Perform sanity checks so we don't accidentally overwrite valid metadata
// with potentially invalid metadata, or random partition data with metadata.
-static bool ValidateAndSerializeMetadata(const IPartitionOpener& opener, const LpMetadata& metadata,
- const std::string& slot_suffix, std::string* blob) {
+static bool ValidateAndSerializeMetadata([[maybe_unused]] const IPartitionOpener& opener,
+ const LpMetadata& metadata, const std::string& slot_suffix,
+ std::string* blob) {
const LpMetadataGeometry& geometry = metadata.geometry;
*blob = SerializeMetadata(metadata);
@@ -128,6 +129,10 @@
<< block_device.first_logical_sector << " for size " << block_device.size;
return false;
}
+
+ // When flashing on the device, check partition sizes. Don't do this on
+ // the host since there is no way to verify.
+#if defined(__ANDROID__)
BlockDeviceInfo info;
if (!opener.GetInfo(partition_name, &info)) {
PERROR << partition_name << ": ioctl";
@@ -138,6 +143,7 @@
<< block_device.size << ", got " << info.size << ")";
return false;
}
+#endif
}
// Make sure all partition entries reference valid extents.
diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp
index f45c1a4..8dec458 100644
--- a/fs_mgr/tests/fs_mgr_test.cpp
+++ b/fs_mgr/tests/fs_mgr_test.cpp
@@ -955,3 +955,14 @@
ASSERT_NE(nullptr, GetEntryForMountPoint(&fstab, "/data"))
<< "Default fstab doesn't contain /data entry";
}
+
+TEST(fs_mgr, UserdataMountedFromDefaultFstab) {
+ if (getuid() != 0) {
+ GTEST_SKIP() << "Must be run as root.";
+ return;
+ }
+ Fstab fstab;
+ ASSERT_TRUE(ReadDefaultFstab(&fstab)) << "Failed to read default fstab";
+ ASSERT_NE(nullptr, GetMountedEntryForUserdata(&fstab))
+ << "/data wasn't mounted from default fstab";
+}