Fix Short read/write issue
It was possible for "short" reads and writes to cause the pattern and
zero steps to not work correctly. This change adds logic to deal with
the short reads.
Tested: unit test and machine test
root@bmc# time busctl call xyz.openbmc_project.eStoraged.mmcblk0 \
> /xyz/openbmc_project/inventory/storage/mmcblk0 \
> xyz.openbmc_project.Inventory.Item.Volume Erase s \
> xyz.openbmc_project.Inventory.Item.Volume.EraseMethod.ZeroOverWrite \
> --timeout=1200
real 6m0.815s
user 0m0.010s
sys 0m0.010s
Change-Id: If8df9bdba159a3bcfa77104a4c17b8d352794db2
Signed-off-by: John Edward Broadbent <jebr@google.com>
diff --git a/src/erase/zero.cpp b/src/erase/zero.cpp
index 2c5a6f5..d26e1b9 100644
--- a/src/erase/zero.cpp
+++ b/src/erase/zero.cpp
@@ -2,26 +2,26 @@
#include "erase.hpp"
+#include <unistd.h>
+
#include <phosphor-logging/lg2.hpp>
#include <stdplus/fd/create.hpp>
#include <stdplus/fd/managed.hpp>
#include <xyz/openbmc_project/Common/error.hpp>
#include <array>
+#include <chrono>
#include <span>
+#include <thread>
namespace estoraged
{
using sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
-using stdplus::fd::ManagedFd;
+using stdplus::fd::Fd;
-void Zero::writeZero(const uint64_t driveSize)
+void Zero::writeZero(const uint64_t driveSize, Fd& fd)
{
-
- ManagedFd fd =
- stdplus::fd::open(devPath, stdplus::fd::OpenAccess::WriteOnly);
-
uint64_t currentIndex = 0;
const std::array<const std::byte, blockSize> blockOfZeros{};
@@ -32,7 +32,31 @@
: driveSize - currentIndex;
try
{
- fd.write({blockOfZeros.data(), writeSize});
+ size_t written = 0;
+ size_t retry = 0;
+ while (written < writeSize)
+ {
+ written += fd.write({blockOfZeros.data() + written,
+ writeSize - written})
+ .size();
+ if (written == writeSize)
+ {
+ break;
+ }
+ if (written > writeSize)
+ {
+ throw InternalFailure();
+ }
+ retry++;
+ if (retry > maxRetry)
+ {
+ lg2::error("Unable to make full write",
+ "REDFISH_MESSAGE_ID",
+ std::string("eStorageD.1.0.EraseFailure"));
+ throw InternalFailure();
+ }
+ std::this_thread::sleep_for(delay);
+ }
}
catch (...)
{
@@ -45,11 +69,8 @@
}
}
-void Zero::verifyZero(uint64_t driveSize)
+void Zero::verifyZero(uint64_t driveSize, Fd& fd)
{
- ManagedFd fd =
- stdplus::fd::open(devPath, stdplus::fd::OpenAccess::ReadOnly);
-
uint64_t currentIndex = 0;
std::array<std::byte, blockSize> readArr{};
const std::array<const std::byte, blockSize> blockOfZeros{};
@@ -61,7 +82,29 @@
: driveSize - currentIndex;
try
{
- fd.read({readArr.data(), readSize});
+ size_t read = 0;
+ size_t retry = 0;
+ while (read < readSize)
+ {
+ read +=
+ fd.read({readArr.data() + read, readSize - read}).size();
+ if (read == readSize)
+ {
+ break;
+ }
+ if (read > readSize)
+ {
+ throw InternalFailure();
+ }
+ retry++;
+ if (retry > maxRetry)
+ {
+ lg2::error("Unable to make full read", "REDFISH_MESSAGE_ID",
+ std::string("eStorageD.1.0.EraseFailure"));
+ throw InternalFailure();
+ }
+ std::this_thread::sleep_for(delay);
+ }
}
catch (...)
{