summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTreehugger Robot2018-07-11 19:08:52 -0500
committerGerrit Code Review2018-07-11 19:08:52 -0500
commitc457df7d34afbc4f96e5351ef5ae3d15381167ec (patch)
treedc75dd8ca702aae028667f8324d909c75e1dc2ae
parent32960e54b44042eb74c845fc9ae50aeb8b74841c (diff)
parent451694e29d4865f41d1097eba0f0c8d7551567d4 (diff)
downloadplatform-system-core-c457df7d34afbc4f96e5351ef5ae3d15381167ec.tar.gz
platform-system-core-c457df7d34afbc4f96e5351ef5ae3d15381167ec.tar.xz
platform-system-core-c457df7d34afbc4f96e5351ef5ae3d15381167ec.zip
Merge "liblp: Make it easier to test UpdatePartitionTable."
-rw-r--r--fs_mgr/liblp/Android.bp3
-rw-r--r--fs_mgr/liblp/include/liblp/writer.h4
-rw-r--r--fs_mgr/liblp/io_test.cpp82
-rw-r--r--fs_mgr/liblp/writer.cpp22
4 files changed, 105 insertions, 6 deletions
diff --git a/fs_mgr/liblp/Android.bp b/fs_mgr/liblp/Android.bp
index f59fa8468..1050cf560 100644
--- a/fs_mgr/liblp/Android.bp
+++ b/fs_mgr/liblp/Android.bp
@@ -46,6 +46,9 @@ cc_library_static {
46cc_test { 46cc_test {
47 name: "liblp_test", 47 name: "liblp_test",
48 defaults: ["fs_mgr_defaults"], 48 defaults: ["fs_mgr_defaults"],
49 cppflags: [
50 "-Wno-unused-parameter",
51 ],
49 static_libs: [ 52 static_libs: [
50 "libbase", 53 "libbase",
51 "liblog", 54 "liblog",
diff --git a/fs_mgr/liblp/include/liblp/writer.h b/fs_mgr/liblp/include/liblp/writer.h
index 6e3c9cb55..f4d1ad7ee 100644
--- a/fs_mgr/liblp/include/liblp/writer.h
+++ b/fs_mgr/liblp/include/liblp/writer.h
@@ -17,6 +17,7 @@
17#ifndef LIBLP_WRITER_H 17#ifndef LIBLP_WRITER_H
18#define LIBLP_WRITER_H 18#define LIBLP_WRITER_H
19 19
20#include <functional>
20#include "metadata_format.h" 21#include "metadata_format.h"
21 22
22namespace android { 23namespace android {
@@ -43,6 +44,9 @@ bool UpdatePartitionTable(const std::string& block_device, const LpMetadata& met
43bool FlashPartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number); 44bool FlashPartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number);
44bool UpdatePartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number); 45bool UpdatePartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number);
45 46
47bool UpdatePartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number,
48 std::function<bool(int, const std::string&)> writer);
49
46// Helper function to serialize geometry and metadata to a normal file, for 50// Helper function to serialize geometry and metadata to a normal file, for
47// flashing or debugging. 51// flashing or debugging.
48bool WriteToImageFile(const char* file, const LpMetadata& metadata); 52bool WriteToImageFile(const char* file, const LpMetadata& metadata);
diff --git a/fs_mgr/liblp/io_test.cpp b/fs_mgr/liblp/io_test.cpp
index 29d8ca5b5..c3f8f369d 100644
--- a/fs_mgr/liblp/io_test.cpp
+++ b/fs_mgr/liblp/io_test.cpp
@@ -393,3 +393,85 @@ TEST(liblp, ImageFiles) {
393 unique_ptr<LpMetadata> imported = ReadFromImageFile(fd); 393 unique_ptr<LpMetadata> imported = ReadFromImageFile(fd);
394 ASSERT_NE(imported, nullptr); 394 ASSERT_NE(imported, nullptr);
395} 395}
396
397class BadWriter {
398 public:
399 // When requested, write garbage instead of the requested bytes, then
400 // return false.
401 bool operator()(int fd, const std::string& blob) {
402 if (++write_count_ == fail_on_write_) {
403 std::unique_ptr<char[]> new_data = std::make_unique<char[]>(blob.size());
404 memset(new_data.get(), 0xe5, blob.size());
405 EXPECT_TRUE(android::base::WriteFully(fd, new_data.get(), blob.size()));
406 return false;
407 } else {
408 return android::base::WriteFully(fd, blob.data(), blob.size());
409 }
410 }
411 void FailOnWrite(int number) {
412 fail_on_write_ = number;
413 write_count_ = 0;
414 }
415
416 private:
417 int fail_on_write_ = 0;
418 int write_count_ = 0;
419};
420
421// Test that an interrupted flash operation on the "primary" copy of metadata
422// is not fatal.
423TEST(liblp, FlashPrimaryMetadataFailure) {
424 // Initial state.
425 unique_fd fd = CreateFlashedDisk();
426 ASSERT_GE(fd, 0);
427
428 BadWriter writer;
429
430 // Read and write it back.
431 writer.FailOnWrite(1);
432 unique_ptr<LpMetadata> imported = ReadMetadata(fd, 0);
433 ASSERT_NE(imported, nullptr);
434 ASSERT_FALSE(UpdatePartitionTable(fd, *imported.get(), 0, writer));
435
436 // We should still be able to read the backup copy.
437 imported = ReadMetadata(fd, 0);
438 ASSERT_NE(imported, nullptr);
439
440 // Flash again, this time fail the backup copy. We should still be able
441 // to read the primary.
442 writer.FailOnWrite(2);
443 ASSERT_FALSE(UpdatePartitionTable(fd, *imported.get(), 0, writer));
444 imported = ReadMetadata(fd, 0);
445 ASSERT_NE(imported, nullptr);
446}
447
448// Test that an interrupted flash operation on the "backup" copy of metadata
449// is not fatal.
450TEST(liblp, FlashBackupMetadataFailure) {
451 // Initial state.
452 unique_fd fd = CreateFlashedDisk();
453 ASSERT_GE(fd, 0);
454
455 BadWriter writer;
456
457 // Read and write it back.
458 writer.FailOnWrite(2);
459 unique_ptr<LpMetadata> imported = ReadMetadata(fd, 0);
460 ASSERT_NE(imported, nullptr);
461 ASSERT_FALSE(UpdatePartitionTable(fd, *imported.get(), 0, writer));
462
463 // We should still be able to read the primary copy.
464 imported = ReadMetadata(fd, 0);
465 ASSERT_NE(imported, nullptr);
466
467 // Flash again, this time fail the primary copy. We should still be able
468 // to read the primary.
469 //
470 // TODO(dvander): This is currently not handled correctly. liblp does not
471 // guarantee both copies are in sync before the update. The ASSERT_EQ
472 // will change to an ASSERT_NE when this is fixed.
473 writer.FailOnWrite(1);
474 ASSERT_FALSE(UpdatePartitionTable(fd, *imported.get(), 0, writer));
475 imported = ReadMetadata(fd, 0);
476 ASSERT_EQ(imported, nullptr);
477}
diff --git a/fs_mgr/liblp/writer.cpp b/fs_mgr/liblp/writer.cpp
index e3dba47da..36c7b5a43 100644
--- a/fs_mgr/liblp/writer.cpp
+++ b/fs_mgr/liblp/writer.cpp
@@ -130,8 +130,13 @@ static bool ValidateAndSerializeMetadata(int fd, const LpMetadata& metadata, std
130 return true; 130 return true;
131} 131}
132 132
133static bool DefaultWriter(int fd, const std::string& blob) {
134 return android::base::WriteFully(fd, blob.data(), blob.size());
135}
136
133static bool WriteMetadata(int fd, const LpMetadataGeometry& geometry, uint32_t slot_number, 137static bool WriteMetadata(int fd, const LpMetadataGeometry& geometry, uint32_t slot_number,
134 const std::string& blob) { 138 const std::string& blob,
139 std::function<bool(int, const std::string&)> writer) {
135 // Make sure we're writing to a valid metadata slot. 140 // Make sure we're writing to a valid metadata slot.
136 if (slot_number >= geometry.metadata_slot_count) { 141 if (slot_number >= geometry.metadata_slot_count) {
137 LERROR << "Invalid logical partition metadata slot number."; 142 LERROR << "Invalid logical partition metadata slot number.";
@@ -144,7 +149,7 @@ static bool WriteMetadata(int fd, const LpMetadataGeometry& geometry, uint32_t s
144 PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset " << primary_offset; 149 PERROR << __PRETTY_FUNCTION__ << "lseek failed: offset " << primary_offset;
145 return false; 150 return false;
146 } 151 }
147 if (!android::base::WriteFully(fd, blob.data(), blob.size())) { 152 if (!writer(fd, blob)) {
148 PERROR << __PRETTY_FUNCTION__ << "write " << blob.size() << " bytes failed"; 153 PERROR << __PRETTY_FUNCTION__ << "write " << blob.size() << " bytes failed";
149 return false; 154 return false;
150 } 155 }
@@ -161,7 +166,7 @@ static bool WriteMetadata(int fd, const LpMetadataGeometry& geometry, uint32_t s
161 << " is within logical partition bounds, sector " << geometry.last_logical_sector; 166 << " is within logical partition bounds, sector " << geometry.last_logical_sector;
162 return false; 167 return false;
163 } 168 }
164 if (!android::base::WriteFully(fd, blob.data(), blob.size())) { 169 if (!writer(fd, blob)) {
165 PERROR << __PRETTY_FUNCTION__ << "backup write " << blob.size() << " bytes failed"; 170 PERROR << __PRETTY_FUNCTION__ << "backup write " << blob.size() << " bytes failed";
166 return false; 171 return false;
167 } 172 }
@@ -197,10 +202,11 @@ bool FlashPartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_numbe
197 } 202 }
198 203
199 // Write metadata to the correct slot, now that geometry is in place. 204 // Write metadata to the correct slot, now that geometry is in place.
200 return WriteMetadata(fd, metadata.geometry, slot_number, metadata_blob); 205 return WriteMetadata(fd, metadata.geometry, slot_number, metadata_blob, DefaultWriter);
201} 206}
202 207
203bool UpdatePartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number) { 208bool UpdatePartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number,
209 std::function<bool(int, const std::string&)> writer) {
204 // Before writing geometry and/or logical partition tables, perform some 210 // Before writing geometry and/or logical partition tables, perform some
205 // basic checks that the geometry and tables are coherent, and will fit 211 // basic checks that the geometry and tables are coherent, and will fit
206 // on the given block device. 212 // on the given block device.
@@ -221,7 +227,7 @@ bool UpdatePartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_numb
221 LERROR << "Incompatible geometry in new logical partition metadata"; 227 LERROR << "Incompatible geometry in new logical partition metadata";
222 return false; 228 return false;
223 } 229 }
224 return WriteMetadata(fd, geometry, slot_number, blob); 230 return WriteMetadata(fd, geometry, slot_number, blob, writer);
225} 231}
226 232
227bool FlashPartitionTable(const std::string& block_device, const LpMetadata& metadata, 233bool FlashPartitionTable(const std::string& block_device, const LpMetadata& metadata,
@@ -244,6 +250,10 @@ bool UpdatePartitionTable(const std::string& block_device, const LpMetadata& met
244 return UpdatePartitionTable(fd, metadata, slot_number); 250 return UpdatePartitionTable(fd, metadata, slot_number);
245} 251}
246 252
253bool UpdatePartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number) {
254 return UpdatePartitionTable(fd, metadata, slot_number, DefaultWriter);
255}
256
247bool WriteToImageFile(int fd, const LpMetadata& input) { 257bool WriteToImageFile(int fd, const LpMetadata& input) {
248 std::string geometry = SerializeGeometry(input.geometry); 258 std::string geometry = SerializeGeometry(input.geometry);
249 std::string padding(LP_METADATA_GEOMETRY_SIZE - geometry.size(), '\0'); 259 std::string padding(LP_METADATA_GEOMETRY_SIZE - geometry.size(), '\0');