system/core
Revision | cac9a2b10bf269437490c40a5717fb2fb8cdb08c (tree) |
---|---|
Time | 2019-06-28 08:25:33 |
Author | Paul Lawrence <paullawrence@goog...> |
Commiter | android-build-merger |
Merge "Make ext4 userdata checkpoints work with metadata encryption" into qt-dev
am: be4e6131d8
Change-Id: Ic522f20a8f1998ed63c90e0e2e6d469ef530b5f2
@@ -923,7 +923,7 @@ class CheckpointManager { | ||
923 | 923 | public: |
924 | 924 | CheckpointManager(int needs_checkpoint = -1) : needs_checkpoint_(needs_checkpoint) {} |
925 | 925 | |
926 | - bool Update(FstabEntry* entry) { | |
926 | + bool Update(FstabEntry* entry, const std::string& block_device = std::string()) { | |
927 | 927 | if (!entry->fs_mgr_flags.checkpoint_blk && !entry->fs_mgr_flags.checkpoint_fs) { |
928 | 928 | return true; |
929 | 929 | } |
@@ -942,7 +942,7 @@ class CheckpointManager { | ||
942 | 942 | return true; |
943 | 943 | } |
944 | 944 | |
945 | - if (!UpdateCheckpointPartition(entry)) { | |
945 | + if (!UpdateCheckpointPartition(entry, block_device)) { | |
946 | 946 | LERROR << "Could not set up checkpoint partition, skipping!"; |
947 | 947 | return false; |
948 | 948 | } |
@@ -972,7 +972,7 @@ class CheckpointManager { | ||
972 | 972 | } |
973 | 973 | |
974 | 974 | private: |
975 | - bool UpdateCheckpointPartition(FstabEntry* entry) { | |
975 | + bool UpdateCheckpointPartition(FstabEntry* entry, const std::string& block_device) { | |
976 | 976 | if (entry->fs_mgr_flags.checkpoint_fs) { |
977 | 977 | if (is_f2fs(entry->fs_type)) { |
978 | 978 | entry->fs_options += ",checkpoint=disable"; |
@@ -980,39 +980,43 @@ class CheckpointManager { | ||
980 | 980 | LERROR << entry->fs_type << " does not implement checkpoints."; |
981 | 981 | } |
982 | 982 | } else if (entry->fs_mgr_flags.checkpoint_blk) { |
983 | - unique_fd fd(TEMP_FAILURE_RETRY(open(entry->blk_device.c_str(), O_RDONLY | O_CLOEXEC))); | |
984 | - if (fd < 0) { | |
985 | - PERROR << "Cannot open device " << entry->blk_device; | |
986 | - return false; | |
987 | - } | |
983 | + auto actual_block_device = block_device.empty() ? entry->blk_device : block_device; | |
984 | + if (fs_mgr_find_bow_device(actual_block_device).empty()) { | |
985 | + unique_fd fd( | |
986 | + TEMP_FAILURE_RETRY(open(entry->blk_device.c_str(), O_RDONLY | O_CLOEXEC))); | |
987 | + if (fd < 0) { | |
988 | + PERROR << "Cannot open device " << entry->blk_device; | |
989 | + return false; | |
990 | + } | |
988 | 991 | |
989 | - uint64_t size = get_block_device_size(fd) / 512; | |
990 | - if (!size) { | |
991 | - PERROR << "Cannot get device size"; | |
992 | - return false; | |
993 | - } | |
992 | + uint64_t size = get_block_device_size(fd) / 512; | |
993 | + if (!size) { | |
994 | + PERROR << "Cannot get device size"; | |
995 | + return false; | |
996 | + } | |
994 | 997 | |
995 | - android::dm::DmTable table; | |
996 | - if (!table.AddTarget( | |
997 | - std::make_unique<android::dm::DmTargetBow>(0, size, entry->blk_device))) { | |
998 | - LERROR << "Failed to add bow target"; | |
999 | - return false; | |
1000 | - } | |
998 | + android::dm::DmTable table; | |
999 | + if (!table.AddTarget(std::make_unique<android::dm::DmTargetBow>( | |
1000 | + 0, size, entry->blk_device))) { | |
1001 | + LERROR << "Failed to add bow target"; | |
1002 | + return false; | |
1003 | + } | |
1001 | 1004 | |
1002 | - DeviceMapper& dm = DeviceMapper::Instance(); | |
1003 | - if (!dm.CreateDevice("bow", table)) { | |
1004 | - PERROR << "Failed to create bow device"; | |
1005 | - return false; | |
1006 | - } | |
1005 | + DeviceMapper& dm = DeviceMapper::Instance(); | |
1006 | + if (!dm.CreateDevice("bow", table)) { | |
1007 | + PERROR << "Failed to create bow device"; | |
1008 | + return false; | |
1009 | + } | |
1007 | 1010 | |
1008 | - std::string name; | |
1009 | - if (!dm.GetDmDevicePathByName("bow", &name)) { | |
1010 | - PERROR << "Failed to get bow device name"; | |
1011 | - return false; | |
1012 | - } | |
1011 | + std::string name; | |
1012 | + if (!dm.GetDmDevicePathByName("bow", &name)) { | |
1013 | + PERROR << "Failed to get bow device name"; | |
1014 | + return false; | |
1015 | + } | |
1013 | 1016 | |
1014 | - device_map_[name] = entry->blk_device; | |
1015 | - entry->blk_device = name; | |
1017 | + device_map_[name] = entry->blk_device; | |
1018 | + entry->blk_device = name; | |
1019 | + } | |
1016 | 1020 | } |
1017 | 1021 | return true; |
1018 | 1022 | } |
@@ -1022,6 +1026,50 @@ class CheckpointManager { | ||
1022 | 1026 | std::map<std::string, std::string> device_map_; |
1023 | 1027 | }; |
1024 | 1028 | |
1029 | +std::string fs_mgr_find_bow_device(const std::string& block_device) { | |
1030 | + if (block_device.substr(0, 5) != "/dev/") { | |
1031 | + LOG(ERROR) << "Expected block device, got " << block_device; | |
1032 | + return std::string(); | |
1033 | + } | |
1034 | + | |
1035 | + std::string sys_dir = std::string("/sys/") + block_device.substr(5); | |
1036 | + | |
1037 | + for (;;) { | |
1038 | + std::string name; | |
1039 | + if (!android::base::ReadFileToString(sys_dir + "/dm/name", &name)) { | |
1040 | + PLOG(ERROR) << block_device << " is not dm device"; | |
1041 | + return std::string(); | |
1042 | + } | |
1043 | + | |
1044 | + if (name == "bow\n") return sys_dir; | |
1045 | + | |
1046 | + std::string slaves = sys_dir + "/slaves"; | |
1047 | + std::unique_ptr<DIR, decltype(&closedir)> directory(opendir(slaves.c_str()), closedir); | |
1048 | + if (!directory) { | |
1049 | + PLOG(ERROR) << "Can't open slave directory " << slaves; | |
1050 | + return std::string(); | |
1051 | + } | |
1052 | + | |
1053 | + int count = 0; | |
1054 | + for (dirent* entry = readdir(directory.get()); entry; entry = readdir(directory.get())) { | |
1055 | + if (entry->d_type != DT_LNK) continue; | |
1056 | + | |
1057 | + if (count == 1) { | |
1058 | + LOG(ERROR) << "Too many slaves in " << slaves; | |
1059 | + return std::string(); | |
1060 | + } | |
1061 | + | |
1062 | + ++count; | |
1063 | + sys_dir = std::string("/sys/block/") + entry->d_name; | |
1064 | + } | |
1065 | + | |
1066 | + if (count != 1) { | |
1067 | + LOG(ERROR) << "No slave in " << slaves; | |
1068 | + return std::string(); | |
1069 | + } | |
1070 | + } | |
1071 | +} | |
1072 | + | |
1025 | 1073 | static bool IsMountPointMounted(const std::string& mount_point) { |
1026 | 1074 | // Check if this is already mounted. |
1027 | 1075 | Fstab fstab; |
@@ -1160,7 +1208,8 @@ int fs_mgr_mount_all(Fstab* fstab, int mount_mode) { | ||
1160 | 1208 | } |
1161 | 1209 | encryptable = status; |
1162 | 1210 | if (status == FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION) { |
1163 | - if (!call_vdc({"cryptfs", "encryptFstab", attempted_entry.mount_point})) { | |
1211 | + if (!call_vdc({"cryptfs", "encryptFstab", attempted_entry.blk_device, | |
1212 | + attempted_entry.mount_point})) { | |
1164 | 1213 | LERROR << "Encryption failed"; |
1165 | 1214 | return FS_MGR_MNTALL_FAIL; |
1166 | 1215 | } |
@@ -1231,7 +1280,8 @@ int fs_mgr_mount_all(Fstab* fstab, int mount_mode) { | ||
1231 | 1280 | encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED; |
1232 | 1281 | } else if (mount_errno != EBUSY && mount_errno != EACCES && |
1233 | 1282 | should_use_metadata_encryption(attempted_entry)) { |
1234 | - if (!call_vdc({"cryptfs", "mountFstab", attempted_entry.mount_point})) { | |
1283 | + if (!call_vdc({"cryptfs", "mountFstab", attempted_entry.blk_device, | |
1284 | + attempted_entry.mount_point})) { | |
1235 | 1285 | ++error_count; |
1236 | 1286 | } |
1237 | 1287 | encryptable = FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED; |
@@ -1361,7 +1411,7 @@ static int fs_mgr_do_mount_helper(Fstab* fstab, const std::string& n_name, | ||
1361 | 1411 | } |
1362 | 1412 | } |
1363 | 1413 | |
1364 | - if (!checkpoint_manager.Update(&fstab_entry)) { | |
1414 | + if (!checkpoint_manager.Update(&fstab_entry, n_blk_device)) { | |
1365 | 1415 | LERROR << "Could not set up checkpoint partition, skipping!"; |
1366 | 1416 | continue; |
1367 | 1417 | } |
@@ -104,3 +104,7 @@ enum FsMgrUmountStatus : int { | ||
104 | 104 | // fs_mgr_umount_all() is the reverse of fs_mgr_mount_all. In particular, |
105 | 105 | // it destroys verity devices from device mapper after the device is unmounted. |
106 | 106 | int fs_mgr_umount_all(android::fs_mgr::Fstab* fstab); |
107 | + | |
108 | +// Finds the dm_bow device on which this block device is stacked, or returns | |
109 | +// empty string | |
110 | +std::string fs_mgr_find_bow_device(const std::string& block_device); |