Loading fs_mgr/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ cc_library_static { "fs_mgr_verity.cpp", "fs_mgr_avb.cpp", "fs_mgr_avb_ops.cpp", "fs_mgr_dm_linear.cpp", ], static_libs: [ "libfec", Loading fs_mgr/fs_mgr.cpp +37 −0 Original line number Diff line number Diff line Loading @@ -794,6 +794,29 @@ static bool call_vdc(const std::vector<std::string>& args) { return true; } bool fs_mgr_update_logical_partition(struct fstab_rec* rec) { // Logical partitions are specified with a named partition rather than a // block device, so if the block device is a path, then it has already // been updated. if (rec->blk_device[0] == '/') { return true; } android::base::unique_fd dm_fd(open("/dev/device-mapper", O_RDONLY)); if (dm_fd < 0) { PLOG(ERROR) << "open /dev/device-mapper failed"; return false; } struct dm_ioctl io; std::string device_name; if (!fs_mgr_dm_get_device_name(&io, rec->blk_device, dm_fd, &device_name)) { return false; } free(rec->blk_device); rec->blk_device = strdup(device_name.c_str()); return true; } /* When multiple fstab records share the same mount_point, it will * try to mount each one in turn, and ignore any duplicates after a * first successful mount. Loading Loading @@ -845,6 +868,13 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) } } if ((fstab->recs[i].fs_mgr_flags & MF_LOGICAL)) { if (!fs_mgr_update_logical_partition(&fstab->recs[i])) { LERROR << "Could not set up logical partition, skipping!"; continue; } } if (fstab->recs[i].fs_mgr_flags & MF_WAIT && !fs_mgr_wait_for_file(fstab->recs[i].blk_device, 20s)) { LERROR << "Skipping '" << fstab->recs[i].blk_device << "' during mount_all"; Loading Loading @@ -1065,6 +1095,13 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device, return FS_MGR_DOMNT_FAILED; } if ((fstab->recs[i].fs_mgr_flags & MF_LOGICAL)) { if (!fs_mgr_update_logical_partition(&fstab->recs[i])) { LERROR << "Could not set up logical partition, skipping!"; continue; } } /* First check the filesystem if requested */ if (fstab->recs[i].fs_mgr_flags & MF_WAIT && !fs_mgr_wait_for_file(n_blk_device, 20s)) { LERROR << "Skipping mounting '" << n_blk_device << "'"; Loading fs_mgr/fs_mgr_avb.cpp +7 −1 Original line number Diff line number Diff line Loading @@ -585,7 +585,13 @@ SetUpAvbHashtreeResult FsManagerAvbHandle::SetUpAvbHashtree(struct fstab_rec* fs // Derives partition_name from blk_device to query the corresponding AVB HASHTREE descriptor // to setup dm-verity. The partition_names in AVB descriptors are without A/B suffix. std::string partition_name(basename(fstab_entry->blk_device)); std::string partition_name; if (fstab_entry->fs_mgr_flags & MF_LOGICAL) { partition_name = fstab_entry->logical_partition_name; } else { partition_name = basename(fstab_entry->blk_device); } if (fstab_entry->fs_mgr_flags & MF_SLOTSELECT) { auto ab_suffix = partition_name.rfind(fs_mgr_get_slot_suffix()); if (ab_suffix != std::string::npos) { Loading fs_mgr/fs_mgr_dm_linear.cpp 0 → 100644 +141 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "fs_mgr_dm_linear.h" #include <inttypes.h> #include <linux/dm-ioctl.h> #include <string.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <unistd.h> #include <sstream> #include <android-base/logging.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/unique_fd.h> #include "fs_mgr_priv.h" #include "fs_mgr_priv_dm_ioctl.h" namespace android { namespace fs_mgr { std::string LogicalPartitionExtent::Serialize() const { // Note: we need to include an explicit null-terminator. std::string argv = android::base::StringPrintf("%s %" PRIu64, block_device_.c_str(), first_sector_); argv.push_back(0); // The kernel expects each target to be aligned. size_t spec_bytes = sizeof(struct dm_target_spec) + argv.size(); size_t padding = ((spec_bytes + 7) & ~7) - spec_bytes; for (size_t i = 0; i < padding; i++) { argv.push_back(0); } struct dm_target_spec spec; spec.sector_start = logical_sector_; spec.length = num_sectors_; spec.status = 0; strcpy(spec.target_type, "linear"); spec.next = sizeof(struct dm_target_spec) + argv.size(); return std::string((char*)&spec, sizeof(spec)) + argv; } static bool LoadDmTable(int dm_fd, const LogicalPartition& partition) { // Combine all dm_target_spec buffers together. std::string target_string; for (const auto& extent : partition.extents) { target_string += extent.Serialize(); } // Allocate the ioctl buffer. size_t buffer_size = sizeof(struct dm_ioctl) + target_string.size(); std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(buffer_size); // Initialize the ioctl buffer header, then copy our target specs in. struct dm_ioctl* io = reinterpret_cast<struct dm_ioctl*>(buffer.get()); fs_mgr_dm_ioctl_init(io, buffer_size, partition.name); io->target_count = partition.extents.size(); if (partition.attributes & kPartitionReadonly) { io->flags |= DM_READONLY_FLAG; } memcpy(io + 1, target_string.c_str(), target_string.size()); if (ioctl(dm_fd, DM_TABLE_LOAD, io)) { PERROR << "Failed ioctl() on DM_TABLE_LOAD, partition " << partition.name; return false; } return true; } static bool LoadTablesAndActivate(int dm_fd, const LogicalPartition& partition) { if (!LoadDmTable(dm_fd, partition)) { return false; } struct dm_ioctl io; return fs_mgr_dm_resume_table(&io, partition.name, dm_fd); } static bool CreateDmDeviceForPartition(int dm_fd, const LogicalPartition& partition) { struct dm_ioctl io; if (!fs_mgr_dm_create_device(&io, partition.name, dm_fd)) { return false; } if (!LoadTablesAndActivate(dm_fd, partition)) { // Remove the device rather than leave it in an inactive state. fs_mgr_dm_destroy_device(&io, partition.name, dm_fd); return false; } LINFO << "Created device-mapper device: " << partition.name; return true; } bool CreateLogicalPartitions(const LogicalPartitionTable& table) { android::base::unique_fd dm_fd(open("/dev/device-mapper", O_RDWR)); if (dm_fd < 0) { PLOG(ERROR) << "failed to open /dev/device-mapper"; return false; } for (const auto& partition : table.partitions) { if (!CreateDmDeviceForPartition(dm_fd, partition)) { LOG(ERROR) << "could not create dm-linear device for partition: " << partition.name; return false; } } return true; } std::unique_ptr<LogicalPartitionTable> LoadPartitionsFromDeviceTree() { return nullptr; } } // namespace fs_mgr } // namespace android fs_mgr/fs_mgr_fstab.cpp +10 −4 Original line number Diff line number Diff line Loading @@ -109,6 +109,7 @@ static struct flag_list fs_mgr_flags[] = { {"logicalblk=", MF_LOGICALBLKSIZE}, {"sysfs_path=", MF_SYSFS}, {"defaults", 0}, {"logical", MF_LOGICAL}, {0, 0}, }; Loading Loading @@ -445,10 +446,6 @@ static std::string read_fstab_from_dt() { LERROR << "dt_fstab: Failed to find device for partition " << dp->d_name; return {}; } if (!StartsWith(value, "/dev")) { LERROR << "dt_fstab: Invalid device node for partition " << dp->d_name; return {}; } fstab_entry.push_back(value); std::string mount_point; Loading Loading @@ -631,6 +628,10 @@ static struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file) fstab->recs[cnt].erase_blk_size = flag_vals.erase_blk_size; fstab->recs[cnt].logical_blk_size = flag_vals.logical_blk_size; fstab->recs[cnt].sysfs_path = flag_vals.sysfs_path; if (fstab->recs[cnt].fs_mgr_flags & MF_LOGICAL) { fstab->recs[cnt].logical_partition_name = strdup(fstab->recs[cnt].blk_device); } cnt++; } /* If an A/B partition, modify block device to be the real block device */ Loading Loading @@ -797,6 +798,7 @@ void fs_mgr_free_fstab(struct fstab *fstab) for (i = 0; i < fstab->num_entries; i++) { /* Free the pointers return by strdup(3) */ free(fstab->recs[i].blk_device); free(fstab->recs[i].logical_partition_name); free(fstab->recs[i].mount_point); free(fstab->recs[i].fs_type); free(fstab->recs[i].fs_options); Loading Loading @@ -944,3 +946,7 @@ int fs_mgr_has_sysfs_path(const struct fstab_rec *fstab) { return fstab->fs_mgr_flags & MF_SYSFS; } int fs_mgr_is_logical(const struct fstab_rec* fstab) { return fstab->fs_mgr_flags & MF_LOGICAL; } Loading
fs_mgr/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ cc_library_static { "fs_mgr_verity.cpp", "fs_mgr_avb.cpp", "fs_mgr_avb_ops.cpp", "fs_mgr_dm_linear.cpp", ], static_libs: [ "libfec", Loading
fs_mgr/fs_mgr.cpp +37 −0 Original line number Diff line number Diff line Loading @@ -794,6 +794,29 @@ static bool call_vdc(const std::vector<std::string>& args) { return true; } bool fs_mgr_update_logical_partition(struct fstab_rec* rec) { // Logical partitions are specified with a named partition rather than a // block device, so if the block device is a path, then it has already // been updated. if (rec->blk_device[0] == '/') { return true; } android::base::unique_fd dm_fd(open("/dev/device-mapper", O_RDONLY)); if (dm_fd < 0) { PLOG(ERROR) << "open /dev/device-mapper failed"; return false; } struct dm_ioctl io; std::string device_name; if (!fs_mgr_dm_get_device_name(&io, rec->blk_device, dm_fd, &device_name)) { return false; } free(rec->blk_device); rec->blk_device = strdup(device_name.c_str()); return true; } /* When multiple fstab records share the same mount_point, it will * try to mount each one in turn, and ignore any duplicates after a * first successful mount. Loading Loading @@ -845,6 +868,13 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) } } if ((fstab->recs[i].fs_mgr_flags & MF_LOGICAL)) { if (!fs_mgr_update_logical_partition(&fstab->recs[i])) { LERROR << "Could not set up logical partition, skipping!"; continue; } } if (fstab->recs[i].fs_mgr_flags & MF_WAIT && !fs_mgr_wait_for_file(fstab->recs[i].blk_device, 20s)) { LERROR << "Skipping '" << fstab->recs[i].blk_device << "' during mount_all"; Loading Loading @@ -1065,6 +1095,13 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device, return FS_MGR_DOMNT_FAILED; } if ((fstab->recs[i].fs_mgr_flags & MF_LOGICAL)) { if (!fs_mgr_update_logical_partition(&fstab->recs[i])) { LERROR << "Could not set up logical partition, skipping!"; continue; } } /* First check the filesystem if requested */ if (fstab->recs[i].fs_mgr_flags & MF_WAIT && !fs_mgr_wait_for_file(n_blk_device, 20s)) { LERROR << "Skipping mounting '" << n_blk_device << "'"; Loading
fs_mgr/fs_mgr_avb.cpp +7 −1 Original line number Diff line number Diff line Loading @@ -585,7 +585,13 @@ SetUpAvbHashtreeResult FsManagerAvbHandle::SetUpAvbHashtree(struct fstab_rec* fs // Derives partition_name from blk_device to query the corresponding AVB HASHTREE descriptor // to setup dm-verity. The partition_names in AVB descriptors are without A/B suffix. std::string partition_name(basename(fstab_entry->blk_device)); std::string partition_name; if (fstab_entry->fs_mgr_flags & MF_LOGICAL) { partition_name = fstab_entry->logical_partition_name; } else { partition_name = basename(fstab_entry->blk_device); } if (fstab_entry->fs_mgr_flags & MF_SLOTSELECT) { auto ab_suffix = partition_name.rfind(fs_mgr_get_slot_suffix()); if (ab_suffix != std::string::npos) { Loading
fs_mgr/fs_mgr_dm_linear.cpp 0 → 100644 +141 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "fs_mgr_dm_linear.h" #include <inttypes.h> #include <linux/dm-ioctl.h> #include <string.h> #include <sys/ioctl.h> #include <sys/stat.h> #include <unistd.h> #include <sstream> #include <android-base/logging.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <android-base/unique_fd.h> #include "fs_mgr_priv.h" #include "fs_mgr_priv_dm_ioctl.h" namespace android { namespace fs_mgr { std::string LogicalPartitionExtent::Serialize() const { // Note: we need to include an explicit null-terminator. std::string argv = android::base::StringPrintf("%s %" PRIu64, block_device_.c_str(), first_sector_); argv.push_back(0); // The kernel expects each target to be aligned. size_t spec_bytes = sizeof(struct dm_target_spec) + argv.size(); size_t padding = ((spec_bytes + 7) & ~7) - spec_bytes; for (size_t i = 0; i < padding; i++) { argv.push_back(0); } struct dm_target_spec spec; spec.sector_start = logical_sector_; spec.length = num_sectors_; spec.status = 0; strcpy(spec.target_type, "linear"); spec.next = sizeof(struct dm_target_spec) + argv.size(); return std::string((char*)&spec, sizeof(spec)) + argv; } static bool LoadDmTable(int dm_fd, const LogicalPartition& partition) { // Combine all dm_target_spec buffers together. std::string target_string; for (const auto& extent : partition.extents) { target_string += extent.Serialize(); } // Allocate the ioctl buffer. size_t buffer_size = sizeof(struct dm_ioctl) + target_string.size(); std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(buffer_size); // Initialize the ioctl buffer header, then copy our target specs in. struct dm_ioctl* io = reinterpret_cast<struct dm_ioctl*>(buffer.get()); fs_mgr_dm_ioctl_init(io, buffer_size, partition.name); io->target_count = partition.extents.size(); if (partition.attributes & kPartitionReadonly) { io->flags |= DM_READONLY_FLAG; } memcpy(io + 1, target_string.c_str(), target_string.size()); if (ioctl(dm_fd, DM_TABLE_LOAD, io)) { PERROR << "Failed ioctl() on DM_TABLE_LOAD, partition " << partition.name; return false; } return true; } static bool LoadTablesAndActivate(int dm_fd, const LogicalPartition& partition) { if (!LoadDmTable(dm_fd, partition)) { return false; } struct dm_ioctl io; return fs_mgr_dm_resume_table(&io, partition.name, dm_fd); } static bool CreateDmDeviceForPartition(int dm_fd, const LogicalPartition& partition) { struct dm_ioctl io; if (!fs_mgr_dm_create_device(&io, partition.name, dm_fd)) { return false; } if (!LoadTablesAndActivate(dm_fd, partition)) { // Remove the device rather than leave it in an inactive state. fs_mgr_dm_destroy_device(&io, partition.name, dm_fd); return false; } LINFO << "Created device-mapper device: " << partition.name; return true; } bool CreateLogicalPartitions(const LogicalPartitionTable& table) { android::base::unique_fd dm_fd(open("/dev/device-mapper", O_RDWR)); if (dm_fd < 0) { PLOG(ERROR) << "failed to open /dev/device-mapper"; return false; } for (const auto& partition : table.partitions) { if (!CreateDmDeviceForPartition(dm_fd, partition)) { LOG(ERROR) << "could not create dm-linear device for partition: " << partition.name; return false; } } return true; } std::unique_ptr<LogicalPartitionTable> LoadPartitionsFromDeviceTree() { return nullptr; } } // namespace fs_mgr } // namespace android
fs_mgr/fs_mgr_fstab.cpp +10 −4 Original line number Diff line number Diff line Loading @@ -109,6 +109,7 @@ static struct flag_list fs_mgr_flags[] = { {"logicalblk=", MF_LOGICALBLKSIZE}, {"sysfs_path=", MF_SYSFS}, {"defaults", 0}, {"logical", MF_LOGICAL}, {0, 0}, }; Loading Loading @@ -445,10 +446,6 @@ static std::string read_fstab_from_dt() { LERROR << "dt_fstab: Failed to find device for partition " << dp->d_name; return {}; } if (!StartsWith(value, "/dev")) { LERROR << "dt_fstab: Invalid device node for partition " << dp->d_name; return {}; } fstab_entry.push_back(value); std::string mount_point; Loading Loading @@ -631,6 +628,10 @@ static struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file) fstab->recs[cnt].erase_blk_size = flag_vals.erase_blk_size; fstab->recs[cnt].logical_blk_size = flag_vals.logical_blk_size; fstab->recs[cnt].sysfs_path = flag_vals.sysfs_path; if (fstab->recs[cnt].fs_mgr_flags & MF_LOGICAL) { fstab->recs[cnt].logical_partition_name = strdup(fstab->recs[cnt].blk_device); } cnt++; } /* If an A/B partition, modify block device to be the real block device */ Loading Loading @@ -797,6 +798,7 @@ void fs_mgr_free_fstab(struct fstab *fstab) for (i = 0; i < fstab->num_entries; i++) { /* Free the pointers return by strdup(3) */ free(fstab->recs[i].blk_device); free(fstab->recs[i].logical_partition_name); free(fstab->recs[i].mount_point); free(fstab->recs[i].fs_type); free(fstab->recs[i].fs_options); Loading Loading @@ -944,3 +946,7 @@ int fs_mgr_has_sysfs_path(const struct fstab_rec *fstab) { return fstab->fs_mgr_flags & MF_SYSFS; } int fs_mgr_is_logical(const struct fstab_rec* fstab) { return fstab->fs_mgr_flags & MF_LOGICAL; }