Cody Schuffelen | 147b88e | 2019-09-09 16:00:11 -0700 | [diff] [blame] | 1 | #include "host/commands/assemble_cvd/data_image.h" |
Cody Schuffelen | 3528908 | 2019-01-28 22:25:30 -0800 | [diff] [blame] | 2 | |
| 3 | #include <glog/logging.h> |
| 4 | |
| 5 | #include "common/libs/utils/files.h" |
| 6 | #include "common/libs/utils/subprocess.h" |
| 7 | |
| 8 | namespace { |
| 9 | const std::string kDataPolicyUseExisting = "use_existing"; |
| 10 | const std::string kDataPolicyCreateIfMissing = "create_if_missing"; |
| 11 | const std::string kDataPolicyAlwaysCreate = "always_create"; |
| 12 | const std::string kDataPolicyResizeUpTo= "resize_up_to"; |
| 13 | |
Cody Schuffelen | 3528908 | 2019-01-28 22:25:30 -0800 | [diff] [blame] | 14 | const int FSCK_ERROR_CORRECTED = 1; |
| 15 | const int FSCK_ERROR_CORRECTED_REQUIRES_REBOOT = 2; |
| 16 | |
| 17 | bool ForceFsckImage(const char* data_image) { |
A. Cody Schuffelen | 64cb145 | 2020-03-04 15:34:57 -0800 | [diff] [blame] | 18 | auto fsck_path = vsoc::DefaultHostArtifactsPath("bin/fsck.f2fs"); |
| 19 | int fsck_status = cvd::execute({fsck_path, "-y", "-f", data_image}); |
Cody Schuffelen | 3528908 | 2019-01-28 22:25:30 -0800 | [diff] [blame] | 20 | if (fsck_status & ~(FSCK_ERROR_CORRECTED|FSCK_ERROR_CORRECTED_REQUIRES_REBOOT)) { |
Alistair Delva | 4c70e26 | 2019-10-15 14:33:59 -0700 | [diff] [blame] | 21 | LOG(ERROR) << "`fsck.f2fs -y -f " << data_image << "` failed with code " |
Cody Schuffelen | 3528908 | 2019-01-28 22:25:30 -0800 | [diff] [blame] | 22 | << fsck_status; |
| 23 | return false; |
| 24 | } |
| 25 | return true; |
| 26 | } |
| 27 | |
| 28 | bool ResizeImage(const char* data_image, int data_image_mb) { |
| 29 | auto file_mb = cvd::FileSize(data_image) >> 20; |
| 30 | if (file_mb > data_image_mb) { |
| 31 | LOG(ERROR) << data_image << " is already " << file_mb << " MB, will not " |
| 32 | << "resize down."; |
| 33 | return false; |
| 34 | } else if (file_mb == data_image_mb) { |
| 35 | LOG(INFO) << data_image << " is already the right size"; |
| 36 | return true; |
| 37 | } else { |
| 38 | off_t raw_target = static_cast<off_t>(data_image_mb) << 20; |
| 39 | int truncate_status = |
| 40 | cvd::SharedFD::Open(data_image, O_RDWR)->Truncate(raw_target); |
| 41 | if (truncate_status != 0) { |
| 42 | LOG(ERROR) << "`truncate --size=" << data_image_mb << "M " |
| 43 | << data_image << "` failed with code " << truncate_status; |
| 44 | return false; |
| 45 | } |
| 46 | bool fsck_success = ForceFsckImage(data_image); |
| 47 | if (!fsck_success) { |
| 48 | return false; |
| 49 | } |
A. Cody Schuffelen | 64cb145 | 2020-03-04 15:34:57 -0800 | [diff] [blame] | 50 | auto resize_path = vsoc::DefaultHostArtifactsPath("bin/resize.f2fs"); |
| 51 | int resize_status = cvd::execute({resize_path, data_image}); |
Cody Schuffelen | 3528908 | 2019-01-28 22:25:30 -0800 | [diff] [blame] | 52 | if (resize_status != 0) { |
Alistair Delva | 4c70e26 | 2019-10-15 14:33:59 -0700 | [diff] [blame] | 53 | LOG(ERROR) << "`resize.f2fs " << data_image << "` failed with code " |
Cody Schuffelen | 3528908 | 2019-01-28 22:25:30 -0800 | [diff] [blame] | 54 | << resize_status; |
| 55 | return false; |
| 56 | } |
| 57 | fsck_success = ForceFsckImage(data_image); |
| 58 | if (!fsck_success) { |
| 59 | return false; |
| 60 | } |
| 61 | } |
| 62 | return true; |
| 63 | } |
| 64 | } // namespace |
| 65 | |
Paul Trautrim | ba8f8e9 | 2019-03-12 17:55:48 +0900 | [diff] [blame] | 66 | void CreateBlankImage( |
Kenny Root | 1f50ee6 | 2020-01-24 12:06:19 -0800 | [diff] [blame] | 67 | const std::string& image, int block_count, const std::string& image_fmt, |
| 68 | const std::string& block_size) { |
Paul Trautrim | ba8f8e9 | 2019-03-12 17:55:48 +0900 | [diff] [blame] | 69 | LOG(INFO) << "Creating " << image; |
| 70 | std::string of = "of="; |
| 71 | of += image; |
| 72 | std::string count = "count="; |
Kenny Root | 1f50ee6 | 2020-01-24 12:06:19 -0800 | [diff] [blame] | 73 | count += std::to_string(block_count); |
| 74 | std::string bs = "bs=" + block_size; |
| 75 | cvd::execute({"/bin/dd", "if=/dev/zero", of, bs, count}); |
A. Cody Schuffelen | d77ae13 | 2020-03-04 18:47:31 -0800 | [diff] [blame] | 76 | if (image_fmt == "ext4") { |
| 77 | cvd::execute({"/sbin/mkfs.ext4", image}); |
| 78 | } else if (image_fmt != "none") { |
A. Cody Schuffelen | 64cb145 | 2020-03-04 15:34:57 -0800 | [diff] [blame] | 79 | auto make_f2fs_path = vsoc::DefaultHostArtifactsPath("bin/make_f2fs"); |
| 80 | cvd::execute({make_f2fs_path, "-t", image_fmt, image, "-g", "android"}); |
Paul Trautrim | ba8f8e9 | 2019-03-12 17:55:48 +0900 | [diff] [blame] | 81 | } |
| 82 | } |
| 83 | |
Cody Schuffelen | 3c99f5b | 2019-06-14 17:26:01 -0700 | [diff] [blame] | 84 | bool ApplyDataImagePolicy(const vsoc::CuttlefishConfig& config, |
| 85 | const std::string& data_image) { |
Cody Schuffelen | 2b51bab | 2019-01-29 18:14:48 -0800 | [diff] [blame] | 86 | bool data_exists = cvd::FileHasContent(data_image.c_str()); |
Cody Schuffelen | 3528908 | 2019-01-28 22:25:30 -0800 | [diff] [blame] | 87 | bool remove{}; |
| 88 | bool create{}; |
| 89 | bool resize{}; |
| 90 | |
Cody Schuffelen | 2b51bab | 2019-01-29 18:14:48 -0800 | [diff] [blame] | 91 | if (config.data_policy() == kDataPolicyUseExisting) { |
Cody Schuffelen | 3528908 | 2019-01-28 22:25:30 -0800 | [diff] [blame] | 92 | if (!data_exists) { |
| 93 | LOG(ERROR) << "Specified data image file does not exists: " << data_image; |
| 94 | return false; |
| 95 | } |
Cody Schuffelen | 2b51bab | 2019-01-29 18:14:48 -0800 | [diff] [blame] | 96 | if (config.blank_data_image_mb() > 0) { |
Cody Schuffelen | 3528908 | 2019-01-28 22:25:30 -0800 | [diff] [blame] | 97 | LOG(ERROR) << "You should NOT use -blank_data_image_mb with -data_policy=" |
| 98 | << kDataPolicyUseExisting; |
| 99 | return false; |
| 100 | } |
| 101 | create = false; |
| 102 | remove = false; |
| 103 | resize = false; |
Cody Schuffelen | 2b51bab | 2019-01-29 18:14:48 -0800 | [diff] [blame] | 104 | } else if (config.data_policy() == kDataPolicyAlwaysCreate) { |
Cody Schuffelen | 3528908 | 2019-01-28 22:25:30 -0800 | [diff] [blame] | 105 | remove = data_exists; |
| 106 | create = true; |
| 107 | resize = false; |
Cody Schuffelen | 2b51bab | 2019-01-29 18:14:48 -0800 | [diff] [blame] | 108 | } else if (config.data_policy() == kDataPolicyCreateIfMissing) { |
Cody Schuffelen | 3528908 | 2019-01-28 22:25:30 -0800 | [diff] [blame] | 109 | create = !data_exists; |
| 110 | remove = false; |
| 111 | resize = false; |
Cody Schuffelen | 2b51bab | 2019-01-29 18:14:48 -0800 | [diff] [blame] | 112 | } else if (config.data_policy() == kDataPolicyResizeUpTo) { |
Cody Schuffelen | 3528908 | 2019-01-28 22:25:30 -0800 | [diff] [blame] | 113 | create = false; |
| 114 | remove = false; |
| 115 | resize = true; |
| 116 | } else { |
Cody Schuffelen | 2b51bab | 2019-01-29 18:14:48 -0800 | [diff] [blame] | 117 | LOG(ERROR) << "Invalid data_policy: " << config.data_policy(); |
Cody Schuffelen | 3528908 | 2019-01-28 22:25:30 -0800 | [diff] [blame] | 118 | return false; |
| 119 | } |
| 120 | |
| 121 | if (remove) { |
Jorge E. Moreira | 7b0059a | 2019-03-22 17:38:14 -0700 | [diff] [blame] | 122 | cvd::RemoveFile(data_image.c_str()); |
Cody Schuffelen | 3528908 | 2019-01-28 22:25:30 -0800 | [diff] [blame] | 123 | } |
| 124 | |
| 125 | if (create) { |
Cody Schuffelen | 2b51bab | 2019-01-29 18:14:48 -0800 | [diff] [blame] | 126 | if (config.blank_data_image_mb() <= 0) { |
Cody Schuffelen | 3528908 | 2019-01-28 22:25:30 -0800 | [diff] [blame] | 127 | LOG(ERROR) << "-blank_data_image_mb is required to create data image"; |
| 128 | return false; |
| 129 | } |
Cody Schuffelen | 2b51bab | 2019-01-29 18:14:48 -0800 | [diff] [blame] | 130 | CreateBlankImage(data_image.c_str(), config.blank_data_image_mb(), |
| 131 | config.blank_data_image_fmt()); |
Cody Schuffelen | 3528908 | 2019-01-28 22:25:30 -0800 | [diff] [blame] | 132 | } else if (resize) { |
| 133 | if (!data_exists) { |
| 134 | LOG(ERROR) << data_image << " does not exist, but resizing was requested"; |
| 135 | return false; |
| 136 | } |
Cody Schuffelen | 2b51bab | 2019-01-29 18:14:48 -0800 | [diff] [blame] | 137 | return ResizeImage(data_image.c_str(), config.blank_data_image_mb()); |
Cody Schuffelen | 3528908 | 2019-01-28 22:25:30 -0800 | [diff] [blame] | 138 | } else { |
| 139 | LOG(INFO) << data_image << " exists. Not creating it."; |
| 140 | } |
| 141 | |
| 142 | return true; |
| 143 | } |
Yifan Hong | 19d713e | 2019-05-01 14:12:07 -0700 | [diff] [blame] | 144 | |
| 145 | bool InitializeMiscImage(const std::string& misc_image) { |
| 146 | bool misc_exists = cvd::FileHasContent(misc_image.c_str()); |
| 147 | |
| 148 | if (misc_exists) { |
| 149 | LOG(INFO) << "misc partition image: use existing"; |
| 150 | return true; |
| 151 | } |
| 152 | |
| 153 | LOG(INFO) << "misc partition image: creating empty"; |
| 154 | CreateBlankImage(misc_image, 1 /* mb */, "none"); |
| 155 | return true; |
| 156 | } |