[hwstress] Add deletion of flash test partitions.
In the case of an unexpected exit of the flash stress test some
partitions may persist on the device. Add a command to clear out any
existing flash test partitions and flag the partitions to be destroyed
on reboot.
Change-Id: I1c3b6881b8b950cc27b94419c0e01a9de19c99e1
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/405554
Reviewed-by: David Greenaway <dgreenaway@google.com>
Testability-Review: David Greenaway <dgreenaway@google.com>
Commit-Queue: Sarah Pham <smpham@google.com>
diff --git a/garnet/bin/hwstress/args.cc b/garnet/bin/hwstress/args.cc
index fdfcb3cb..1cde501 100644
--- a/garnet/bin/hwstress/args.cc
+++ b/garnet/bin/hwstress/args.cc
@@ -21,6 +21,8 @@
std::unique_ptr<cmdline::ArgsParser<CommandLineArgs>> GetParser() {
auto parser = std::make_unique<cmdline::ArgsParser<CommandLineArgs>>();
+ parser->AddSwitch("cleanup-test-partitions", 'c', "Cleanup all existing flash test partitions.",
+ &CommandLineArgs::destroy_partitions);
parser->AddSwitch("duration", 'd', "Test duration in seconds.",
&CommandLineArgs::test_duration_seconds);
parser->AddSwitch("fvm-path", 'f', "Path to Fuchsia Volume Manager.", &CommandLineArgs::fvm_path);
@@ -70,7 +72,12 @@
than 0, and no more than 100.
Flash test options:
- -f, --fvm-path=<path> Path to Fuchsia Volume Manager
+ -c, --cleanup-test-partitions
+ Cleanup all existing flash test partitions in the
+ system, and then exit without testing. Can be used
+ to clean up persistent test partitions left over from
+ previous flash tests which did not exit cleanly.
+ -f, --fvm-path=<path> Path to Fuchsia Volume Manager.
-m, --memory=<size> Amount of flash memory to test, in megabytes.
Memory test options:
@@ -154,8 +161,12 @@
}
// Ensure mandatory flash test argument is provided
- if (result.subcommand == StressTest::kFlash && result.fvm_path.empty()) {
- return fitx::error(fxl::StringPrintf("Path to Fuchsia Volume Manager must be specified"));
+ if (result.subcommand == StressTest::kFlash) {
+ if (result.destroy_partitions && !result.fvm_path.empty()) {
+ return fitx::error(fxl::StringPrintf("Path to Fuchsia Volume Manager invalid with cleanup"));
+ } else if (!result.destroy_partitions && result.fvm_path.empty()) {
+ return fitx::error(fxl::StringPrintf("Path to Fuchsia Volume Manager must be specified"));
+ }
}
// Ensure no more parameters were given.
diff --git a/garnet/bin/hwstress/args.h b/garnet/bin/hwstress/args.h
index b36b331..2e39d8e 100644
--- a/garnet/bin/hwstress/args.h
+++ b/garnet/bin/hwstress/args.h
@@ -67,6 +67,9 @@
// Path to the Fuchsia Volume Manager
std::string fvm_path;
+ // Destroy any existing flash test partitions.
+ bool destroy_partitions = false;
+
//
// Memory-specific arguments.
//
diff --git a/garnet/bin/hwstress/flash_stress.cc b/garnet/bin/hwstress/flash_stress.cc
index e27927d..9fc8d52 100644
--- a/garnet/bin/hwstress/flash_stress.cc
+++ b/garnet/bin/hwstress/flash_stress.cc
@@ -4,15 +4,12 @@
#include "flash_stress.h"
-#include <fcntl.h>
#include <fuchsia/hardware/block/cpp/fidl.h>
#include <fuchsia/hardware/block/volume/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/zx/fifo.h>
-#include <lib/zx/time.h>
#include <lib/zx/vmar.h>
#include <lib/zx/vmo.h>
-#include <threads.h>
#include <zircon/status.h>
#include <string>
@@ -33,9 +30,6 @@
constexpr uint32_t kMinFvmFreeSpace = 16 * 1024 * 1024;
constexpr uint32_t kMinPartitionFreeSpace = 2 * 1024 * 1024;
-constexpr uuid::Uuid kTestPartGUID = uuid::Uuid({0xC6, 0x24, 0xF5, 0xDD, 0x9D, 0x88, 0x4C, 0x81,
- 0x99, 0x87, 0xCA, 0x92, 0xD1, 0x1B, 0x28, 0x89});
-
struct BlockDevice {
fuchsia::hardware::block::BlockSyncPtr device; // Connection to the block device.
zx::fifo fifo; // FIFO used to read/write to the block device.
@@ -247,10 +241,9 @@
uuid::Uuid unique_guid = uuid::Uuid::Generate();
- alloc_req_t request{
- .slice_count = num_slices,
- .name = "flash-test-fs",
- };
+ alloc_req_t request{.slice_count = num_slices,
+ .name = "flash-test-fs",
+ .flags = fuchsia::hardware::block::volume::ALLOCATE_PARTITION_FLAG_INACTIVE};
memcpy(request.guid, unique_guid.bytes(), sizeof(request.guid));
memcpy(request.type, kTestPartGUID.bytes(), sizeof(request.type));
@@ -341,4 +334,13 @@
return true;
}
+void DestroyFlashTestPartitions(StatusLine* status) {
+ uint32_t count = 0;
+ // Remove any partitions from previous tests
+ while (destroy_partition(nullptr, kTestPartGUID.bytes()) == ZX_OK) {
+ count++;
+ }
+ status->Log("Deleted %u partitions", count);
+}
+
} // namespace hwstress
diff --git a/garnet/bin/hwstress/flash_stress.h b/garnet/bin/hwstress/flash_stress.h
index c556fde..bbe7753 100644
--- a/garnet/bin/hwstress/flash_stress.h
+++ b/garnet/bin/hwstress/flash_stress.h
@@ -13,6 +13,10 @@
namespace hwstress {
+// The GPT partition type used for partitions created by the flash test.
+constexpr uuid::Uuid kTestPartGUID = uuid::Uuid({0xC6, 0x24, 0xF5, 0xDD, 0x9D, 0x88, 0x4C, 0x81,
+ 0x99, 0x87, 0xCA, 0x92, 0xD1, 0x1B, 0x28, 0x89});
+
// Creates and manages the lifetime of a new partition backed by a
// Fuchsia Volume Manager instance.
class TemporaryFvmPartition {
@@ -55,6 +59,9 @@
// Start a stress test.
bool StressFlash(StatusLine* status, const std::string& fvm_path, uint64_t bytes_to_test);
+// Delete any persistent flash test partitions
+void DestroyFlashTestPartitions(StatusLine* status);
+
} // namespace hwstress
#endif // GARNET_BIN_HWSTRESS_FLASH_STRESS_H_
diff --git a/garnet/bin/hwstress/flash_stress_test.cc b/garnet/bin/hwstress/flash_stress_test.cc
index 00ac7e8..20c8607 100644
--- a/garnet/bin/hwstress/flash_stress_test.cc
+++ b/garnet/bin/hwstress/flash_stress_test.cc
@@ -7,6 +7,8 @@
#include <lib/zx/status.h>
#include <lib/zx/vmo.h>
+#include <fbl/unique_fd.h>
+#include <fs-management/fvm.h>
#include <gtest/gtest.h>
#include "src/lib/isolated_devmgr/v2_component/fvm.h"
@@ -36,5 +38,33 @@
ASSERT_TRUE(StressFlash(&status, fvm_path.value(), /*bytes_to_test=*/16 * 1024 * 1024));
}
+TEST(Flash, DeletePartition) {
+ // Create a RAM disk.
+ zx::status<isolated_devmgr::RamDisk> ramdisk = isolated_devmgr::RamDisk::Create(
+ /*block_size=*/kBlockSize, /*block_count=*/kDefaultRamDiskSize / kBlockSize);
+ ASSERT_TRUE(ramdisk.is_ok());
+
+ // Instantiate it as a FVM device.
+ zx::status<std::string> fvm_path =
+ isolated_devmgr::CreateFvmInstance(ramdisk->path(), kDefaultFvmSliceSize);
+ ASSERT_TRUE(fvm_path.is_ok());
+
+ // Access FVM.
+ fbl::unique_fd fvm_fd(open(fvm_path.value().c_str(), O_RDWR));
+ ASSERT_TRUE(fvm_fd);
+
+ alloc_req_t request{.slice_count = 1, .name = "test-fs"};
+ memcpy(request.guid, uuid::Uuid::Generate().bytes(), sizeof(request.guid));
+ memcpy(request.type, kTestPartGUID.bytes(), sizeof(request.type));
+
+ // Create a partition.
+ fbl::unique_fd fd(fvm_allocate_partition(fvm_fd.get(), &request));
+ ASSERT_TRUE(fd);
+
+ StatusLine status;
+ DestroyFlashTestPartitions(&status);
+ ASSERT_TRUE(open_partition(nullptr, kTestPartGUID.bytes(), 0, nullptr) != ZX_OK);
+}
+
} // namespace
} // namespace hwstress
diff --git a/garnet/bin/hwstress/hwstress.cc b/garnet/bin/hwstress/hwstress.cc
index ea5d67e..1ede4d2 100644
--- a/garnet/bin/hwstress/hwstress.cc
+++ b/garnet/bin/hwstress/hwstress.cc
@@ -69,7 +69,12 @@
success = StressCpu(&status, args, duration, sensor.get());
break;
case StressTest::kFlash:
- success = StressFlash(&status, args.fvm_path, flash_to_test);
+ if (args.destroy_partitions) {
+ DestroyFlashTestPartitions(&status);
+ success = true;
+ } else {
+ success = StressFlash(&status, args.fvm_path, flash_to_test);
+ }
break;
case StressTest::kLight:
success = StressLight(&status, args, duration);