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/include/zero.hpp b/include/zero.hpp
index 562b8ce..bfa240d 100644
--- a/include/zero.hpp
+++ b/include/zero.hpp
@@ -6,10 +6,12 @@
 #include <stdplus/fd/create.hpp>
 #include <stdplus/fd/managed.hpp>
 
+#include <chrono>
+
 namespace estoraged
 {
 
-using stdplus::fd::ManagedFd;
+using stdplus::fd::Fd;
 
 class Zero : public Erase
 {
@@ -23,29 +25,35 @@
     /** @brief writes zero to the drive
      * and throws errors accordingly.
      *  @param[in] driveSize - the size of the block device in bytes
+     *  @param[in] fd - the stdplus file descriptor
      */
-    void writeZero(uint64_t driveSize);
+    void writeZero(uint64_t driveSize, Fd& fd);
 
-    /** @brief writes zero to the drive
+    /** @brief writes zero to the drive using default parameters,
      * and throws errors accordingly.
      */
     void writeZero()
     {
-        writeZero(util::findSizeOfBlockDevice(devPath));
+        stdplus::fd::Fd&& fd =
+            stdplus::fd::open(devPath, stdplus::fd::OpenAccess::WriteOnly);
+        writeZero(util::findSizeOfBlockDevice(devPath), fd);
     }
 
-    /** @brief verifies the  uncompressible random pattern is on the drive
+    /** @brief verifies the drive has only zeros on it,
      * and throws errors accordingly.
      *  @param[in] driveSize - the size of the block device in bytes
+     *  @param[in] fd - the stdplus file descriptor
      */
-    void verifyZero(uint64_t driveSize);
+    void verifyZero(uint64_t driveSize, Fd& fd);
 
-    /** @brief verifies the  uncompressible random pattern is on the drive
-     * and throws errors accordingly.
+    /** @brief verifies the drive has only zeros on it,
+     * using the default parameters. It also throws errors accordingly.
      */
     void verifyZero()
     {
-        verifyZero(util::findSizeOfBlockDevice(devPath));
+        stdplus::fd::Fd&& fd =
+            stdplus::fd::open(devPath, stdplus::fd::OpenAccess::ReadOnly);
+        verifyZero(util::findSizeOfBlockDevice(devPath), fd);
     }
 
   private:
@@ -53,6 +61,8 @@
      * 32768 was also tested. It had almost identical performance.
      */
     static constexpr size_t blockSize = 4096;
+    static constexpr size_t maxRetry = 32;
+    static constexpr std::chrono::duration delay = std::chrono::milliseconds(1);
 };
 
 } // namespace estoraged