adb: better error messages on deduplicated filesystems.
If BOARD_EXT4_SHARE_DUP_BLOCKS is true, "adb remount" will error saying the filesystem is read-only. Instead, it will now list affected partitions and explain why they can't be remounted. Bug: 64109868 Test: adb remount with deduplicated system image Change-Id: Ida737a6be8e9fe9ea26300897d82b1a149e72f6d
This commit is contained in:
parent
53248e47f4
commit
a962ec0c73
1 changed files with 50 additions and 8 deletions
|
@ -25,14 +25,18 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/vfs.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <android-base/properties.h>
|
||||
#include <ext4_utils/ext4_utils.h>
|
||||
|
||||
#include "adb.h"
|
||||
#include "adb_io.h"
|
||||
#include "adb_unique_fd.h"
|
||||
#include "adb_utils.h"
|
||||
#include "fs_mgr.h"
|
||||
|
||||
|
@ -82,7 +86,27 @@ bool make_block_device_writable(const std::string& dev) {
|
|||
return result;
|
||||
}
|
||||
|
||||
static bool remount_partition(int fd, const char* dir) {
|
||||
static bool fs_has_shared_blocks(const char* dev) {
|
||||
struct statfs fs;
|
||||
if (statfs(dev, &fs) == -1 || fs.f_type == EXT4_SUPER_MAGIC) {
|
||||
return false;
|
||||
}
|
||||
unique_fd fd(unix_open(dev, O_RDONLY));
|
||||
if (fd < 0) {
|
||||
return false;
|
||||
}
|
||||
struct ext4_super_block sb;
|
||||
if (lseek64(fd, 1024, SEEK_SET) < 0 || unix_read(fd, &sb, sizeof(sb)) < 0) {
|
||||
return false;
|
||||
}
|
||||
struct fs_info info;
|
||||
if (ext4_parse_sb(&sb, &info) < 0) {
|
||||
return false;
|
||||
}
|
||||
return (info.feat_ro_compat & EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS) != 0;
|
||||
}
|
||||
|
||||
static bool remount_partition(int fd, const char* dir, std::vector<std::string>& dedup) {
|
||||
if (!directory_exists(dir)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -108,6 +132,12 @@ static bool remount_partition(int fd, const char* dir) {
|
|||
return false;
|
||||
}
|
||||
if (mount(dev.c_str(), dir, "none", MS_REMOUNT, nullptr) == -1) {
|
||||
if (errno == EROFS && fs_has_shared_blocks(dev.c_str())) {
|
||||
// We return true so remount_service() can detect that the only
|
||||
// failure was deduplicated filesystems.
|
||||
dedup.push_back(dev);
|
||||
return true;
|
||||
}
|
||||
WriteFdFmt(fd, "remount of the %s superblock failed: %s\n", dir, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
@ -140,17 +170,29 @@ void remount_service(int fd, void* cookie) {
|
|||
}
|
||||
|
||||
bool success = true;
|
||||
std::vector<std::string> dedup;
|
||||
if (android::base::GetBoolProperty("ro.build.system_root_image", false)) {
|
||||
success &= remount_partition(fd, "/");
|
||||
success &= remount_partition(fd, "/", dedup);
|
||||
} else {
|
||||
success &= remount_partition(fd, "/system");
|
||||
success &= remount_partition(fd, "/system", dedup);
|
||||
}
|
||||
success &= remount_partition(fd, "/odm");
|
||||
success &= remount_partition(fd, "/oem");
|
||||
success &= remount_partition(fd, "/product");
|
||||
success &= remount_partition(fd, "/vendor");
|
||||
success &= remount_partition(fd, "/odm", dedup);
|
||||
success &= remount_partition(fd, "/oem", dedup);
|
||||
success &= remount_partition(fd, "/product", dedup);
|
||||
success &= remount_partition(fd, "/vendor", dedup);
|
||||
|
||||
WriteFdExactly(fd, success ? "remount succeeded\n" : "remount failed\n");
|
||||
if (!success) {
|
||||
WriteFdExactly(fd, "remount failed\n");
|
||||
} else if (dedup.empty()) {
|
||||
WriteFdExactly(fd, "remount succeeded\n");
|
||||
} else {
|
||||
WriteFdExactly(fd,
|
||||
"The following partitions are deduplicated and could "
|
||||
"not be remounted:\n");
|
||||
for (const std::string& name : dedup) {
|
||||
WriteFdFmt(fd, " %s\n", name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
adb_close(fd);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue