Merge "Only skip checkpointing for freshly formatted ext4"
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 287285b..30eb7b5 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -104,7 +104,6 @@
// libsparse will support INT_MAX, but this results in large allocations, so
// let's keep it at 1GB to avoid memory pressure on the host.
static constexpr int64_t RESPARSE_LIMIT = 1 * 1024 * 1024 * 1024;
-static uint64_t sparse_limit = 0;
static int64_t target_sparse_limit = -1;
static unsigned g_base_addr = 0x10000000;
@@ -1016,8 +1015,8 @@
return value;
}
-int64_t get_sparse_limit(int64_t size) {
- int64_t limit = sparse_limit;
+int64_t get_sparse_limit(int64_t size, const FlashingPlan* fp) {
+ int64_t limit = int64_t(fp->sparse_limit);
if (limit == 0) {
// Unlimited, so see what the target device's limit is.
// TODO: shouldn't we apply this limit even if you've used -S?
@@ -1038,7 +1037,7 @@
return 0;
}
-static bool load_buf_fd(unique_fd fd, struct fastboot_buffer* buf) {
+static bool load_buf_fd(unique_fd fd, struct fastboot_buffer* buf, const FlashingPlan* fp) {
int64_t sz = get_file_size(fd);
if (sz == -1) {
return false;
@@ -1056,7 +1055,7 @@
}
lseek(fd.get(), 0, SEEK_SET);
- int64_t limit = get_sparse_limit(sz);
+ int64_t limit = get_sparse_limit(sz, fp);
buf->fd = std::move(fd);
if (limit) {
buf->files = load_sparse_files(buf->fd.get(), limit);
@@ -1072,13 +1071,11 @@
return true;
}
-static bool load_buf(const char* fname, struct fastboot_buffer* buf) {
+static bool load_buf(const char* fname, struct fastboot_buffer* buf, const FlashingPlan* fp) {
unique_fd fd(TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_BINARY)));
if (fd == -1) {
- auto path = find_item_given_name(fname);
- fd = unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_BINARY)));
- if (fd == -1) return false;
+ return false;
}
struct stat s;
@@ -1090,7 +1087,7 @@
return false;
}
- return load_buf_fd(std::move(fd), buf);
+ return load_buf_fd(std::move(fd), buf, fp);
}
static void rewrite_vbmeta_buffer(struct fastboot_buffer* buf, bool vbmeta_in_boot) {
@@ -1492,12 +1489,19 @@
verbose("Do flash %s %s", pname, fname);
struct fastboot_buffer buf;
- if (fp->source) {
+ if (fp && fp->source) {
unique_fd fd = fp->source->OpenFile(fname);
- if (fd < 0 || !load_buf_fd(std::move(fd), &buf)) {
+ if (fd < 0 || !load_buf_fd(std::move(fd), &buf, fp)) {
die("could not load '%s': %s", fname, strerror(errno));
}
- } else if (!load_buf(fname, &buf)) {
+ std::vector<char> signature_data;
+ std::string file_string(fname);
+ if (fp->source->ReadFile(file_string.substr(0, file_string.find('.')) + ".sig",
+ &signature_data)) {
+ fb->Download("signature", signature_data);
+ fb->RawCommand("signature", "installing signature");
+ }
+ } else if (!load_buf(fname, &buf, fp)) {
die("cannot load '%s': %s", fname, strerror(errno));
}
@@ -1783,7 +1787,10 @@
CancelSnapshotIfNeeded();
- HardcodedFlash();
+ tasks_ = CollectTasksFromImageList();
+ for (auto& task : tasks_) {
+ task->Run();
+ }
return;
}
@@ -1835,13 +1842,12 @@
}
}
-void FlashAllTool::HardcodedFlash() {
+std::vector<std::unique_ptr<Task>> FlashAllTool::CollectTasksFromImageList() {
CollectImages();
// First flash boot partitions. We allow this to happen either in userspace
// or in bootloader fastboot.
- FlashImages(boot_images_);
-
std::vector<std::unique_ptr<Task>> tasks;
+ AddFlashTasks(boot_images_, tasks);
if (auto flash_super_task = FlashSuperLayoutTask::Initialize(fp_, os_images_)) {
tasks.emplace_back(std::move(flash_super_task));
@@ -1865,53 +1871,26 @@
tasks.emplace_back(std::make_unique<ResizeTask>(fp_, image->part_name, "0", slot));
}
}
- for (auto& i : tasks) {
- i->Run();
- }
- FlashImages(os_images_);
+ AddFlashTasks(os_images_, tasks);
+ return tasks;
}
-void FlashAllTool::FlashImages(const std::vector<std::pair<const Image*, std::string>>& images) {
+void FlashAllTool::AddFlashTasks(const std::vector<std::pair<const Image*, std::string>>& images,
+ std::vector<std::unique_ptr<Task>>& tasks) {
for (const auto& [image, slot] : images) {
fastboot_buffer buf;
unique_fd fd = fp_->source->OpenFile(image->img_name);
- if (fd < 0 || !load_buf_fd(std::move(fd), &buf)) {
+ if (fd < 0 || !load_buf_fd(std::move(fd), &buf, fp_)) {
if (image->optional_if_no_image) {
continue;
}
die("could not load '%s': %s", image->img_name.c_str(), strerror(errno));
}
- FlashImage(*image, slot, &buf);
+ tasks.emplace_back(std::make_unique<FlashTask>(slot, image->part_name, image->img_name,
+ is_vbmeta_partition(image->part_name), fp_));
}
}
-void FlashAllTool::FlashImage(const Image& image, const std::string& slot, fastboot_buffer* buf) {
- auto flash = [&, this](const std::string& partition_name) {
- std::vector<char> signature_data;
- if (fp_->source->ReadFile(image.sig_name, &signature_data)) {
- fb->Download("signature", signature_data);
- fb->RawCommand("signature", "installing signature");
- }
-
- if (is_logical(partition_name)) {
- fb->ResizePartition(partition_name, std::to_string(buf->image_size));
- }
-
- flash_buf(partition_name.c_str(), buf, is_vbmeta_partition(partition_name));
- };
- do_for_partitions(image.part_name, slot, flash, false);
-}
-
-class ZipImageSource final : public ImageSource {
- public:
- explicit ZipImageSource(ZipArchiveHandle zip) : zip_(zip) {}
- bool ReadFile(const std::string& name, std::vector<char>* out) const override;
- unique_fd OpenFile(const std::string& name) const override;
-
- private:
- ZipArchiveHandle zip_;
-};
-
bool ZipImageSource::ReadFile(const std::string& name, std::vector<char>* out) const {
return UnzipToMemory(zip_, name, out);
}
@@ -1935,12 +1914,6 @@
CloseArchive(zip);
}
-class LocalImageSource final : public ImageSource {
- public:
- bool ReadFile(const std::string& name, std::vector<char>* out) const override;
- unique_fd OpenFile(const std::string& name) const override;
-};
-
bool LocalImageSource::ReadFile(const std::string& name, std::vector<char>* out) const {
auto path = find_item_given_name(name);
if (path.empty()) {
@@ -2000,7 +1973,7 @@
void fb_perform_format(const std::string& partition, int skip_if_not_supported,
const std::string& type_override, const std::string& size_override,
- const unsigned fs_options) {
+ const unsigned fs_options, const FlashingPlan* fp) {
std::string partition_type, partition_size;
struct fastboot_buffer buf;
@@ -2013,8 +1986,8 @@
if (target_sparse_limit > 0 && target_sparse_limit < limit) {
limit = target_sparse_limit;
}
- if (sparse_limit > 0 && sparse_limit < limit) {
- limit = sparse_limit;
+ if (fp->sparse_limit > 0 && fp->sparse_limit < limit) {
+ limit = fp->sparse_limit;
}
if (fb->GetVar("partition-type:" + partition, &partition_type) != fastboot::SUCCESS) {
@@ -2069,7 +2042,7 @@
if (fd == -1) {
die("Cannot open generated image: %s", strerror(errno));
}
- if (!load_buf_fd(std::move(fd), &buf)) {
+ if (!load_buf_fd(std::move(fd), &buf, fp)) {
die("Cannot read image: %s", strerror(errno));
}
flash_buf(partition, &buf, is_vbmeta_partition(partition));
@@ -2209,6 +2182,7 @@
{"cmdline", required_argument, 0, 0},
{"disable-verification", no_argument, 0, 0},
{"disable-verity", no_argument, 0, 0},
+ {"disable-super-optimization", no_argument, 0, 0},
{"force", no_argument, 0, 0},
{"fs-options", required_argument, 0, 0},
{"header-version", required_argument, 0, 0},
@@ -2246,6 +2220,8 @@
g_disable_verification = true;
} else if (name == "disable-verity") {
g_disable_verity = true;
+ } else if (name == "disable-super-optimization") {
+ fp->should_optimize_flash_super = false;
} else if (name == "force") {
fp->force_flash = true;
} else if (name == "fs-options") {
@@ -2301,7 +2277,7 @@
serial = optarg;
break;
case 'S':
- if (!android::base::ParseByteCount(optarg, &sparse_limit)) {
+ if (!android::base::ParseByteCount(optarg, &fp->sparse_limit)) {
die("invalid sparse limit %s", optarg);
}
break;
@@ -2419,7 +2395,8 @@
std::string partition = next_arg(&args);
auto format = [&](const std::string& partition) {
- fb_perform_format(partition, 0, type_override, size_override, fp->fs_options);
+ fb_perform_format(partition, 0, type_override, size_override, fp->fs_options,
+ fp.get());
};
do_for_partitions(partition, fp->slot_override, format, true);
} else if (command == "signature") {
@@ -2513,7 +2490,7 @@
std::string filename = next_arg(&args);
struct fastboot_buffer buf;
- if (!load_buf(filename.c_str(), &buf) || buf.type != FB_BUFFER_FD) {
+ if (!load_buf(filename.c_str(), &buf, fp.get()) || buf.type != FB_BUFFER_FD) {
die("cannot load '%s'", filename.c_str());
}
fb->Download(filename, buf.fd.get(), buf.sz);
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index abdf636..196bd67 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -40,6 +40,7 @@
#include "result.h"
#include "socket.h"
#include "util.h"
+#include "ziparchive/zip_archive.h"
class FastBootTool {
public:
@@ -95,6 +96,8 @@
bool wants_set_active = false;
bool skip_secondary = false;
bool force_flash = false;
+ bool should_optimize_flash_super = true;
+ uint64_t sparse_limit = 0;
std::string slot_override;
std::string current_slot;
@@ -113,15 +116,33 @@
void CheckRequirements();
void DetermineSlot();
void CollectImages();
- void FlashImages(const std::vector<std::pair<const Image*, std::string>>& images);
- void FlashImage(const Image& image, const std::string& slot, fastboot_buffer* buf);
- void HardcodedFlash();
+ void AddFlashTasks(const std::vector<std::pair<const Image*, std::string>>& images,
+ std::vector<std::unique_ptr<Task>>& tasks);
+ std::vector<std::unique_ptr<Task>> CollectTasksFromImageList();
std::vector<ImageEntry> boot_images_;
std::vector<ImageEntry> os_images_;
+ std::vector<std::unique_ptr<Task>> tasks_;
+
FlashingPlan* fp_;
};
+class ZipImageSource final : public ImageSource {
+ public:
+ explicit ZipImageSource(ZipArchiveHandle zip) : zip_(zip) {}
+ bool ReadFile(const std::string& name, std::vector<char>* out) const override;
+ unique_fd OpenFile(const std::string& name) const override;
+
+ private:
+ ZipArchiveHandle zip_;
+};
+
+class LocalImageSource final : public ImageSource {
+ public:
+ bool ReadFile(const std::string& name, std::vector<char>* out) const override;
+ unique_fd OpenFile(const std::string& name) const override;
+};
+
bool should_flash_in_userspace(const std::string& partition_name);
bool is_userspace_fastboot();
void do_flash(const char* pname, const char* fname, const bool apply_vbmeta,
@@ -158,11 +179,11 @@
bool supports_AB();
std::string GetPartitionName(const ImageEntry& entry, const std::string& current_slot_);
void flash_partition_files(const std::string& partition, const std::vector<SparsePtr>& files);
-int64_t get_sparse_limit(int64_t size);
+int64_t get_sparse_limit(int64_t size, const FlashingPlan* fp);
std::vector<SparsePtr> resparse_file(sparse_file* s, int64_t max_size);
bool is_retrofit_device();
bool is_logical(const std::string& partition);
void fb_perform_format(const std::string& partition, int skip_if_not_supported,
const std::string& type_override, const std::string& size_override,
- const unsigned fs_options);
+ const unsigned fs_options, const FlashingPlan* fp);
diff --git a/fastboot/task.cpp b/fastboot/task.cpp
index 03f9b89..c1b9a31 100644
--- a/fastboot/task.cpp
+++ b/fastboot/task.cpp
@@ -98,18 +98,20 @@
FlashSuperLayoutTask::FlashSuperLayoutTask(const std::string& super_name,
std::unique_ptr<SuperFlashHelper> helper,
- SparsePtr sparse_layout, uint64_t super_size)
+ SparsePtr sparse_layout, uint64_t super_size,
+ const FlashingPlan* fp)
: super_name_(super_name),
helper_(std::move(helper)),
sparse_layout_(std::move(sparse_layout)),
- super_size_(super_size) {}
+ super_size_(super_size),
+ fp_(fp) {}
void FlashSuperLayoutTask::Run() {
// Use the reported super partition size as the upper limit, rather than
// sparse_file_len, which (1) can fail and (2) is kind of expensive, since
// it will map in all of the embedded fds.
std::vector<SparsePtr> files;
- if (int limit = get_sparse_limit(super_size_)) {
+ if (int limit = get_sparse_limit(super_size_, fp_)) {
files = resparse_file(sparse_layout_.get(), limit);
} else {
files.emplace_back(std::move(sparse_layout_));
@@ -124,6 +126,10 @@
std::unique_ptr<FlashSuperLayoutTask> FlashSuperLayoutTask::Initialize(
const FlashingPlan* fp, std::vector<ImageEntry>& os_images) {
+ if (!fp->should_optimize_flash_super) {
+ LOG(INFO) << "super optimization is disabled";
+ return nullptr;
+ }
if (!supports_AB()) {
LOG(VERBOSE) << "Cannot optimize flashing super on non-AB device";
return nullptr;
@@ -183,11 +189,15 @@
os_images.erase(std::remove_if(os_images.begin(), os_images.end(), remove_if_callback),
os_images.end());
return std::make_unique<FlashSuperLayoutTask>(super_name, std::move(helper), std::move(s),
- partition_size);
+ partition_size, fp);
}
std::unique_ptr<FlashSuperLayoutTask> FlashSuperLayoutTask::InitializeFromTasks(
const FlashingPlan* fp, std::vector<std::unique_ptr<Task>>& tasks) {
+ if (!fp->should_optimize_flash_super) {
+ LOG(INFO) << "super optimization is disabled";
+ return nullptr;
+ }
if (!supports_AB()) {
LOG(VERBOSE) << "Cannot optimize flashing super on non-AB device";
return nullptr;
@@ -252,7 +262,7 @@
tasks.erase(std::remove_if(tasks.begin(), tasks.end(), remove_if_callback), tasks.end());
return std::make_unique<FlashSuperLayoutTask>(super_name, std::move(helper), std::move(s),
- partition_size);
+ partition_size, fp);
}
UpdateSuperTask::UpdateSuperTask(const FlashingPlan* fp) : fp_(fp) {}
@@ -322,7 +332,7 @@
LOG(ERROR) << "wipe task erase failed with partition: " << pname_;
return;
}
- fb_perform_format(pname_, 1, partition_type, "", fp_->fs_options);
+ fb_perform_format(pname_, 1, partition_type, "", fp_->fs_options, fp_);
}
std::string WipeTask::ToString() {
diff --git a/fastboot/task.h b/fastboot/task.h
index 500655d..858f43a 100644
--- a/fastboot/task.h
+++ b/fastboot/task.h
@@ -82,7 +82,7 @@
class FlashSuperLayoutTask : public Task {
public:
FlashSuperLayoutTask(const std::string& super_name, std::unique_ptr<SuperFlashHelper> helper,
- SparsePtr sparse_layout, uint64_t super_size);
+ SparsePtr sparse_layout, uint64_t super_size, const FlashingPlan* fp);
static std::unique_ptr<FlashSuperLayoutTask> Initialize(const FlashingPlan* fp,
std::vector<ImageEntry>& os_images);
static std::unique_ptr<FlashSuperLayoutTask> InitializeFromTasks(
@@ -96,6 +96,7 @@
std::unique_ptr<SuperFlashHelper> helper_;
SparsePtr sparse_layout_;
uint64_t super_size_;
+ const FlashingPlan* fp_;
};
class UpdateSuperTask : public Task {
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index 046d30c..9d1ce7d 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -417,6 +417,7 @@
"libbrotli",
"libcrypto_static",
"liblog",
+ "libgflags",
"libsnapshot_cow",
"libz",
],
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp
index c2c86ee..148ecb0 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/inspect_cow.cpp
@@ -24,11 +24,26 @@
#include <android-base/logging.h>
#include <android-base/unique_fd.h>
+#include <gflags/gflags.h>
#include <libsnapshot/cow_reader.h>
+#include "parser_v2.h"
+
+DEFINE_bool(silent, false, "Run silently");
+DEFINE_bool(decompress, false, "Attempt to decompress data ops");
+DEFINE_bool(show_bad_data, false, "If an op fails to decompress, show its daw data");
+DEFINE_bool(show_ops, false, "Print all opcode information");
+DEFINE_string(order, "", "If show_ops is true, change the order (either merge or reverse-merge)");
+DEFINE_bool(show_merged, false,
+ "If show_ops is true, and order is merge or reverse-merge, include merged ops");
+DEFINE_bool(verify_merge_sequence, false, "Verify merge order sequencing");
+DEFINE_bool(show_merge_sequence, false, "Show merge order sequence");
+DEFINE_bool(show_raw_ops, false, "Show raw ops directly from the underlying parser");
namespace android {
namespace snapshot {
+using android::base::borrowed_fd;
+
void MyLogger(android::base::LogId, android::base::LogSeverity severity, const char*, const char*,
unsigned int, const char* message) {
if (severity == android::base::ERROR) {
@@ -38,32 +53,6 @@
}
}
-static void usage(void) {
- std::cerr << "Usage: inspect_cow [-sd] <COW_FILE>\n";
- std::cerr << "\t -s Run Silent\n";
- std::cerr << "\t -d Attempt to decompress\n";
- std::cerr << "\t -b Show data for failed decompress\n";
- std::cerr << "\t -l Show ops\n";
- std::cerr << "\t -m Show ops in reverse merge order\n";
- std::cerr << "\t -n Show ops in merge order\n";
- std::cerr << "\t -a Include merged ops in any merge order listing\n";
- std::cerr << "\t -o Shows sequence op block order\n";
- std::cerr << "\t -v Verifies merge order has no conflicts\n";
-}
-
-enum OpIter { Normal, RevMerge, Merge };
-
-struct Options {
- bool silent;
- bool decompress;
- bool show_ops;
- bool show_bad;
- bool show_seq;
- bool verify_sequence;
- OpIter iter_type;
- bool include_merged;
-};
-
static void ShowBad(CowReader& reader, const struct CowOperation* op) {
size_t count;
auto buffer = std::make_unique<uint8_t[]>(op->data_length);
@@ -82,7 +71,39 @@
}
}
-static bool Inspect(const std::string& path, Options opt) {
+static bool ShowRawOpStreamV2(borrowed_fd fd, const CowHeader& header) {
+ CowParserV2 parser;
+ if (!parser.Parse(fd, header)) {
+ LOG(ERROR) << "v2 parser failed";
+ return false;
+ }
+ for (const auto& op : *parser.ops()) {
+ std::cout << op << "\n";
+ if (auto iter = parser.data_loc()->find(op.new_block); iter != parser.data_loc()->end()) {
+ std::cout << " data loc: " << iter->second << "\n";
+ }
+ }
+ return true;
+}
+
+static bool ShowRawOpStream(borrowed_fd fd) {
+ CowHeader header;
+ if (!ReadCowHeader(fd, &header)) {
+ LOG(ERROR) << "parse header failed";
+ return false;
+ }
+
+ switch (header.prefix.major_version) {
+ case 1:
+ case 2:
+ return ShowRawOpStreamV2(fd, header);
+ default:
+ LOG(ERROR) << "unknown COW version: " << header.prefix.major_version;
+ return false;
+ }
+}
+
+static bool Inspect(const std::string& path) {
android::base::unique_fd fd(open(path.c_str(), O_RDONLY));
if (fd < 0) {
PLOG(ERROR) << "open failed: " << path;
@@ -103,7 +124,7 @@
bool has_footer = false;
if (reader.GetFooter(&footer)) has_footer = true;
- if (!opt.silent) {
+ if (!FLAGS_silent) {
std::cout << "Version: " << header.prefix.major_version << "."
<< header.prefix.minor_version << "\n";
std::cout << "Header size: " << header.prefix.header_size << "\n";
@@ -119,11 +140,11 @@
}
}
- if (!opt.silent) {
+ if (!FLAGS_silent) {
std::cout << "Parse time: " << (parse_time.count() * 1000) << "ms\n";
}
- if (opt.verify_sequence) {
+ if (FLAGS_verify_merge_sequence) {
std::cout << "\n";
if (reader.VerifyMergeOps()) {
std::cout << "\nMerge sequence is consistent.\n";
@@ -133,32 +154,47 @@
}
std::unique_ptr<ICowOpIter> iter;
- if (opt.iter_type == Normal) {
+ if (FLAGS_order.empty()) {
iter = reader.GetOpIter();
- } else if (opt.iter_type == RevMerge) {
- iter = reader.GetRevMergeOpIter(opt.include_merged);
- } else if (opt.iter_type == Merge) {
- iter = reader.GetMergeOpIter(opt.include_merged);
+ } else if (FLAGS_order == "reverse-merge") {
+ iter = reader.GetRevMergeOpIter(FLAGS_show_merged);
+ } else if (FLAGS_order == "merge") {
+ iter = reader.GetMergeOpIter(FLAGS_show_merged);
}
std::string buffer(header.block_size, '\0');
+ if (!FLAGS_silent && FLAGS_show_raw_ops) {
+ std::cout << "\n";
+ std::cout << "Listing raw op stream:\n";
+ std::cout << "----------------------\n";
+ if (!ShowRawOpStream(fd)) {
+ return false;
+ }
+ }
+
+ if (!FLAGS_silent && FLAGS_show_ops) {
+ std::cout << "\n";
+ std::cout << "Listing op stream:\n";
+ std::cout << "------------------\n";
+ }
+
bool success = true;
uint64_t xor_ops = 0, copy_ops = 0, replace_ops = 0, zero_ops = 0;
while (!iter->AtEnd()) {
const CowOperation* op = iter->Get();
- if (!opt.silent && opt.show_ops) std::cout << *op << "\n";
+ if (!FLAGS_silent && FLAGS_show_ops) std::cout << *op << "\n";
- if (opt.decompress && op->type == kCowReplaceOp && op->compression != kCowCompressNone) {
+ if (FLAGS_decompress && op->type == kCowReplaceOp && op->compression != kCowCompressNone) {
if (reader.ReadData(op, buffer.data(), buffer.size()) < 0) {
std::cerr << "Failed to decompress for :" << *op << "\n";
success = false;
- if (opt.show_bad) ShowBad(reader, op);
+ if (FLAGS_show_bad_data) ShowBad(reader, op);
}
}
- if (op->type == kCowSequenceOp && opt.show_seq) {
+ if (op->type == kCowSequenceOp && FLAGS_show_merge_sequence) {
size_t read;
std::vector<uint32_t> merge_op_blocks;
size_t seq_len = op->data_length / sizeof(uint32_t);
@@ -167,7 +203,7 @@
PLOG(ERROR) << "Failed to read sequence op!";
return false;
}
- if (!opt.silent) {
+ if (!FLAGS_silent) {
std::cout << "Sequence for " << *op << " is :\n";
for (size_t i = 0; i < seq_len; i++) {
std::cout << std::setfill('0') << std::setw(6) << merge_op_blocks[i] << ", ";
@@ -189,7 +225,7 @@
iter->Next();
}
- if (!opt.silent) {
+ if (!FLAGS_silent) {
auto total_ops = replace_ops + zero_ops + copy_ops + xor_ops;
std::cout << "Data ops: " << total_ops << "\n";
std::cout << "Replace ops: " << replace_ops << "\n";
@@ -205,57 +241,20 @@
} // namespace android
int main(int argc, char** argv) {
- int ch;
- struct android::snapshot::Options opt;
- opt.silent = false;
- opt.decompress = false;
- opt.show_bad = false;
- opt.iter_type = android::snapshot::Normal;
- opt.verify_sequence = false;
- opt.include_merged = false;
- while ((ch = getopt(argc, argv, "sdbmnolva")) != -1) {
- switch (ch) {
- case 's':
- opt.silent = true;
- break;
- case 'd':
- opt.decompress = true;
- break;
- case 'b':
- opt.show_bad = true;
- break;
- case 'm':
- opt.iter_type = android::snapshot::RevMerge;
- break;
- case 'n':
- opt.iter_type = android::snapshot::Merge;
- break;
- case 'o':
- opt.show_seq = true;
- break;
- case 'l':
- opt.show_ops = true;
- break;
- case 'v':
- opt.verify_sequence = true;
- break;
- case 'a':
- opt.include_merged = true;
- break;
- default:
- android::snapshot::usage();
- return 1;
- }
- }
+ gflags::ParseCommandLineFlags(&argc, &argv, true);
- if (argc < optind + 1) {
- android::snapshot::usage();
+ if (argc < 2) {
+ gflags::ShowUsageWithFlags(argv[0]);
+ return 1;
+ }
+ if (FLAGS_order != "" && FLAGS_order != "merge" && FLAGS_order != "reverse-merge") {
+ std::cerr << "Order must either be \"merge\" or \"reverse-merge\".\n";
return 1;
}
android::base::InitLogging(argv, android::snapshot::MyLogger);
- if (!android::snapshot::Inspect(argv[optind], opt)) {
+ if (!android::snapshot::Inspect(argv[1])) {
return 1;
}
return 0;
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp
index b6603da..c549969 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp
@@ -14,6 +14,8 @@
// limitations under the License.
//
+#include "writer_v2.h"
+
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
@@ -37,7 +39,7 @@
#include <sys/ioctl.h>
#include <unistd.h>
-#include "writer_v2.h"
+#include "parser_v2.h"
// The info messages here are spammy, but as useful for update_engine. Disable
// them when running on the host.
@@ -252,14 +254,20 @@
}
bool CowWriterV2::OpenForAppend(uint64_t label) {
- auto reader = std::make_unique<CowReader>();
- std::queue<CowOperation> toAdd;
-
- if (!reader->Parse(fd_, {label})) {
+ if (!ReadCowHeader(fd_, &header_)) {
return false;
}
- header_ = reader->GetHeader();
+ CowParserV2 parser;
+ if (!parser.Parse(fd_, header_, {label})) {
+ return false;
+ }
+ if (header_.prefix.major_version > 2) {
+ LOG(ERROR) << "CowWriterV2 tried to open incompatible version "
+ << header_.prefix.major_version;
+ return false;
+ }
+
options_.block_size = header_.block_size;
options_.cluster_ops = header_.cluster_ops;
@@ -267,16 +275,10 @@
footer_.op.num_ops = 0;
InitPos();
- auto iter = reader->GetOpIter();
-
- while (!iter->AtEnd()) {
- AddOperation(*iter->Get());
- iter->Next();
+ for (const auto& op : *parser.ops()) {
+ AddOperation(op);
}
- // Free reader so we own the descriptor position again.
- reader = nullptr;
-
if (lseek(fd_.get(), next_op_pos_, SEEK_SET) < 0) {
PLOG(ERROR) << "lseek failed";
return false;
diff --git a/init/Android.bp b/init/Android.bp
index 41c7a95..f62d7b7 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -265,8 +265,8 @@
],
}
-cc_binary {
- name: "init_second_stage",
+cc_defaults {
+ name: "init_second_stage_defaults",
recovery_available: true,
stem: "init",
defaults: ["init_defaults"],
@@ -304,9 +304,22 @@
],
},
},
+}
+
+cc_binary {
+ name: "init_second_stage",
+ defaults: ["init_second_stage_defaults"],
+}
+
+cc_binary {
+ name: "init_second_stage.microdroid",
+ defaults: ["init_second_stage_defaults"],
+ cflags: ["-DMICRODROID"],
+ installable: false,
visibility: ["//packages/modules/Virtualization/microdroid"],
}
+
soong_config_module_type {
name: "init_first_stage_cc_defaults",
module_type: "cc_defaults",
@@ -324,12 +337,8 @@
installable: false,
},
},
-}
-cc_binary {
- name: "init_first_stage",
stem: "init",
- defaults: ["init_first_stage_defaults"],
srcs: [
"block_dev_initializer.cpp",
@@ -443,6 +452,18 @@
install_in_root: true,
}
+cc_binary {
+ name: "init_first_stage",
+ defaults: ["init_first_stage_defaults"],
+}
+
+cc_binary {
+ name: "init_first_stage.microdroid",
+ defaults: ["init_first_stage_defaults"],
+ cflags: ["-DMICRODROID"],
+ installable: false,
+}
+
phony {
name: "init_system",
required: ["init_second_stage"],