Merge "Make ext4 userdata checkpoints work with metadata encryption"

This commit is contained in:
Treehugger Robot 2019-06-27 17:29:03 +00:00 committed by Gerrit Code Review
commit 99ae1d943b
2 changed files with 88 additions and 34 deletions

View File

@ -908,7 +908,7 @@ class CheckpointManager {
public:
CheckpointManager(int needs_checkpoint = -1) : needs_checkpoint_(needs_checkpoint) {}
bool Update(FstabEntry* entry) {
bool Update(FstabEntry* entry, const std::string& block_device = std::string()) {
if (!entry->fs_mgr_flags.checkpoint_blk && !entry->fs_mgr_flags.checkpoint_fs) {
return true;
}
@ -927,7 +927,7 @@ class CheckpointManager {
return true;
}
if (!UpdateCheckpointPartition(entry)) {
if (!UpdateCheckpointPartition(entry, block_device)) {
LERROR << "Could not set up checkpoint partition, skipping!";
return false;
}
@ -957,7 +957,7 @@ class CheckpointManager {
}
private:
bool UpdateCheckpointPartition(FstabEntry* entry) {
bool UpdateCheckpointPartition(FstabEntry* entry, const std::string& block_device) {
if (entry->fs_mgr_flags.checkpoint_fs) {
if (is_f2fs(entry->fs_type)) {
entry->fs_options += ",checkpoint=disable";
@ -965,39 +965,43 @@ class CheckpointManager {
LERROR << entry->fs_type << " does not implement checkpoints.";
}
} else if (entry->fs_mgr_flags.checkpoint_blk) {
unique_fd fd(TEMP_FAILURE_RETRY(open(entry->blk_device.c_str(), O_RDONLY | O_CLOEXEC)));
if (fd < 0) {
PERROR << "Cannot open device " << entry->blk_device;
return false;
}
auto actual_block_device = block_device.empty() ? entry->blk_device : block_device;
if (fs_mgr_find_bow_device(actual_block_device).empty()) {
unique_fd fd(
TEMP_FAILURE_RETRY(open(entry->blk_device.c_str(), O_RDONLY | O_CLOEXEC)));
if (fd < 0) {
PERROR << "Cannot open device " << entry->blk_device;
return false;
}
uint64_t size = get_block_device_size(fd) / 512;
if (!size) {
PERROR << "Cannot get device size";
return false;
}
uint64_t size = get_block_device_size(fd) / 512;
if (!size) {
PERROR << "Cannot get device size";
return false;
}
android::dm::DmTable table;
if (!table.AddTarget(
std::make_unique<android::dm::DmTargetBow>(0, size, entry->blk_device))) {
LERROR << "Failed to add bow target";
return false;
}
android::dm::DmTable table;
if (!table.AddTarget(std::make_unique<android::dm::DmTargetBow>(
0, size, entry->blk_device))) {
LERROR << "Failed to add bow target";
return false;
}
DeviceMapper& dm = DeviceMapper::Instance();
if (!dm.CreateDevice("bow", table)) {
PERROR << "Failed to create bow device";
return false;
}
DeviceMapper& dm = DeviceMapper::Instance();
if (!dm.CreateDevice("bow", table)) {
PERROR << "Failed to create bow device";
return false;
}
std::string name;
if (!dm.GetDmDevicePathByName("bow", &name)) {
PERROR << "Failed to get bow device name";
return false;
}
std::string name;
if (!dm.GetDmDevicePathByName("bow", &name)) {
PERROR << "Failed to get bow device name";
return false;
}
device_map_[name] = entry->blk_device;
entry->blk_device = name;
device_map_[name] = entry->blk_device;
entry->blk_device = name;
}
}
return true;
}
@ -1007,6 +1011,50 @@ class CheckpointManager {
std::map<std::string, std::string> device_map_;
};
std::string fs_mgr_find_bow_device(const std::string& block_device) {
if (block_device.substr(0, 5) != "/dev/") {
LOG(ERROR) << "Expected block device, got " << block_device;
return std::string();
}
std::string sys_dir = std::string("/sys/") + block_device.substr(5);
for (;;) {
std::string name;
if (!android::base::ReadFileToString(sys_dir + "/dm/name", &name)) {
PLOG(ERROR) << block_device << " is not dm device";
return std::string();
}
if (name == "bow\n") return sys_dir;
std::string slaves = sys_dir + "/slaves";
std::unique_ptr<DIR, decltype(&closedir)> directory(opendir(slaves.c_str()), closedir);
if (!directory) {
PLOG(ERROR) << "Can't open slave directory " << slaves;
return std::string();
}
int count = 0;
for (dirent* entry = readdir(directory.get()); entry; entry = readdir(directory.get())) {
if (entry->d_type != DT_LNK) continue;
if (count == 1) {
LOG(ERROR) << "Too many slaves in " << slaves;
return std::string();
}
++count;
sys_dir = std::string("/sys/block/") + entry->d_name;
}
if (count != 1) {
LOG(ERROR) << "No slave in " << slaves;
return std::string();
}
}
}
static bool IsMountPointMounted(const std::string& mount_point) {
// Check if this is already mounted.
Fstab fstab;
@ -1144,7 +1192,8 @@ int fs_mgr_mount_all(Fstab* fstab, int mount_mode) {
}
encryptable = status;
if (status == FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION) {
if (!call_vdc({"cryptfs", "encryptFstab", attempted_entry.mount_point})) {
if (!call_vdc({"cryptfs", "encryptFstab", attempted_entry.blk_device,
attempted_entry.mount_point})) {
LERROR << "Encryption failed";
return FS_MGR_MNTALL_FAIL;
}
@ -1215,7 +1264,8 @@ int fs_mgr_mount_all(Fstab* fstab, int mount_mode) {
encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED;
} else if (mount_errno != EBUSY && mount_errno != EACCES &&
should_use_metadata_encryption(attempted_entry)) {
if (!call_vdc({"cryptfs", "mountFstab", attempted_entry.mount_point})) {
if (!call_vdc({"cryptfs", "mountFstab", attempted_entry.blk_device,
attempted_entry.mount_point})) {
++error_count;
}
encryptable = FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED;
@ -1345,7 +1395,7 @@ static int fs_mgr_do_mount_helper(Fstab* fstab, const std::string& n_name,
}
}
if (!checkpoint_manager.Update(&fstab_entry)) {
if (!checkpoint_manager.Update(&fstab_entry, n_blk_device)) {
LERROR << "Could not set up checkpoint partition, skipping!";
continue;
}

View File

@ -104,3 +104,7 @@ enum FsMgrUmountStatus : int {
// fs_mgr_umount_all() is the reverse of fs_mgr_mount_all. In particular,
// it destroys verity devices from device mapper after the device is unmounted.
int fs_mgr_umount_all(android::fs_mgr::Fstab* fstab);
// Finds the dm_bow device on which this block device is stacked, or returns
// empty string
std::string fs_mgr_find_bow_device(const std::string& block_device);