Tom Rollet has submitted this change. ( https://gem5-review.googlesource.com/c/public/gem5/+/46619 )

Change subject: sim: Add serialization for file descriptor array
......................................................................

sim: Add serialization for file descriptor array

Add serialization of the fd array when checkpointing in SE mode.
With this patch, host backed files are restored.
Further work needs to be done for restoring other types of
file descriptor.

As the file path saved is relative, on restoration of the checkpoint,
it may fail to open the file if the path is no longer valid.
If it cannot open the file, it will exit the simulation
with a meaningful error message.

Change-Id: I4d0c7cd614a8abaffcae9aba1a28c9fdbc023c5a
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/46619
Reviewed-by: Jason Lowe-Power <[email protected]>
Maintainer: Jason Lowe-Power <[email protected]>
Tested-by: kokoro <[email protected]>
---
M src/sim/fd_array.cc
M src/sim/fd_array.hh
M src/sim/fd_entry.cc
M src/sim/fd_entry.hh
M src/sim/process.cc
M src/sim/syscall_emul.hh
6 files changed, 133 insertions(+), 19 deletions(-)

Approvals:
  Jason Lowe-Power: Looks good to me, approved; Looks good to me, approved
  kokoro: Regressions pass



diff --git a/src/sim/fd_array.cc b/src/sim/fd_array.cc
index 364bd10..0da9978 100644
--- a/src/sim/fd_array.cc
+++ b/src/sim/fd_array.cc
@@ -298,7 +298,7 @@
     int sim_fd = open(filename.c_str(), flags, mode);
     if (sim_fd != -1)
         return sim_fd;
-    fatal("Unable to open %s with mode %O", filename, mode);
+    fatal("Unable to open %s with mode %d", filename, mode);
 }

 int
@@ -348,3 +348,84 @@

     return status;
 }
+
+void
+FDArray::serialize(CheckpointOut &cp) const {
+    ScopedCheckpointSection sec(cp, "fdarray");
+    paramOut(cp, "size", _fdArray.size());
+    for (int tgt_fd = 0; tgt_fd < _fdArray.size(); tgt_fd++) {
+        auto fd = _fdArray[tgt_fd];
+        ScopedCheckpointSection sec(cp, csprintf("Entry%d", tgt_fd));
+        if (!fd) {
+            paramOut(cp, "class", FDEntry::FDClass::fd_null);
+            continue;
+        }
+        paramOut(cp, "class", fd->getClass());
+        fd->serialize(cp);
+    }
+}
+
+void
+FDArray::unserialize(CheckpointIn &cp) {
+    ScopedCheckpointSection sec(cp, "fdarray");
+    uint64_t size;
+    paramIn(cp, "size", size);
+    assert(_fdArray.size() == size &&
+            "FDArray sizes do not match at unserialize!");
+
+    for (int tgt_fd = 0; tgt_fd < _fdArray.size(); tgt_fd++) {
+        if (tgt_fd == STDIN_FILENO || tgt_fd == STDOUT_FILENO ||
+                tgt_fd == STDERR_FILENO)
+            continue;
+        ScopedCheckpointSection sec(cp, csprintf("Entry%d", tgt_fd));
+        FDEntry::FDClass fd_class;
+        paramIn(cp, "class", fd_class);
+        std::shared_ptr<FDEntry> fdep;
+
+        switch (fd_class) {
+            case FDEntry::FDClass::fd_base:
+                panic("Abstract fd entry was serialized");
+                break;
+            case FDEntry::FDClass::fd_hb:
+                fdep = std::make_shared<HBFDEntry>(0, 0);
+                break;
+            case FDEntry::FDClass::fd_file:
+                fdep = std::make_shared<FileFDEntry>(0, 0, "", 0, 00);
+                break;
+            case FDEntry::FDClass::fd_device:
+                fdep = std::make_shared<DeviceFDEntry>(nullptr, "");
+                break;
+            case FDEntry::FDClass::fd_pipe:
+                fdep = std::make_shared<PipeFDEntry>(
+                        0, 0, PipeFDEntry::EndType::read);
+                break;
+            case FDEntry::FDClass::fd_socket:
+                fdep = std::make_shared<SocketFDEntry>(0, 0, 0, 0);
+                break;
+            case FDEntry::FDClass::fd_null:
+                continue;
+            default:
+                panic("Unrecognized fd class");
+                break;
+        }
+
+        fdep->unserialize(cp);
+
+        auto this_ffd = std::dynamic_pointer_cast<FileFDEntry>(fdep);
+        if (!this_ffd)
+            continue;
+        setFDEntry(tgt_fd, fdep);
+
+        mode_t mode = this_ffd->getFileMode();
+        std::string const& path = this_ffd->getFileName();
+        int flags = this_ffd->getFlags();
+
+        // Re-open the file and assign a new sim_fd
+        int sim_fd = openFile(path, flags, mode);
+        this_ffd->setSimFD(sim_fd);
+
+        // Restore the file offset to the proper value
+        uint64_t file_offset = this_ffd->getFileOffset();
+        lseek(sim_fd, file_offset, SEEK_SET);
+    }
+}
diff --git a/src/sim/fd_array.hh b/src/sim/fd_array.hh
index 5295566..e80673f 100644
--- a/src/sim/fd_array.hh
+++ b/src/sim/fd_array.hh
@@ -40,8 +40,9 @@
 #include <string>

 #include "sim/fd_entry.hh"
+#include "sim/serialize.hh"

-class FDArray
+class FDArray : public Serializable
 {
   public:
     /**
@@ -111,6 +112,12 @@
      */
     int closeFDEntry(int tgt_fd);

+    /*
+     * Serialization methods for file descriptors
+     */
+    void serialize(CheckpointOut &cp) const override;
+    void unserialize(CheckpointIn &cp) override;
+
   private:
     /**
      * Help clarify our intention when opening files in the init and
diff --git a/src/sim/fd_entry.cc b/src/sim/fd_entry.cc
index 02677d6..6861a94 100644
--- a/src/sim/fd_entry.cc
+++ b/src/sim/fd_entry.cc
@@ -54,6 +54,7 @@
     SERIALIZE_SCALAR(_flags);
     SERIALIZE_SCALAR(_fileName);
     SERIALIZE_SCALAR(_fileOffset);
+    SERIALIZE_SCALAR(_mode);
 }

 void
@@ -63,6 +64,7 @@
     UNSERIALIZE_SCALAR(_flags);
     UNSERIALIZE_SCALAR(_fileName);
     UNSERIALIZE_SCALAR(_fileOffset);
+    UNSERIALIZE_SCALAR(_mode);
 }

 void
diff --git a/src/sim/fd_entry.hh b/src/sim/fd_entry.hh
index c24710d..50a9e60 100644
--- a/src/sim/fd_entry.hh
+++ b/src/sim/fd_entry.hh
@@ -42,6 +42,7 @@

 class EmulatedDriver;

+
 /**
  * Holds a single file descriptor mapping and that mapping's data for
  * processes running in syscall emulation mode.
@@ -49,14 +50,28 @@
 class FDEntry : public Serializable
 {
   public:
+
+    enum FDClass
+    {
+        fd_base,
+        fd_hb,
+        fd_file,
+        fd_pipe,
+        fd_device,
+        fd_socket,
+        fd_null
+    };
+
     FDEntry(bool close_on_exec = false)
         : _closeOnExec(close_on_exec)
-    { }
+    { _class = FDClass::fd_base; }

     virtual std::shared_ptr<FDEntry> clone() const = 0;

     bool getCOE() const { return _closeOnExec; }

+    FDClass getClass() const { return _class; }
+
     void setCOE(bool close_on_exec) { _closeOnExec = close_on_exec; }

     virtual void serialize(CheckpointOut &cp) const;
@@ -64,6 +79,7 @@

   protected:
     bool _closeOnExec;
+    FDClass _class;
 };

 /**
@@ -76,11 +92,11 @@
   public:
     HBFDEntry(int flags, int sim_fd, bool close_on_exec = false)
         : FDEntry(close_on_exec), _flags(flags), _simFD(sim_fd)
-    { }
+    { _class = FDClass::fd_hb; }

     HBFDEntry(HBFDEntry const& reg, bool close_on_exec = false)
         : FDEntry(close_on_exec), _flags(reg._flags), _simFD(reg._simFD)
-    { }
+    { _class = FDClass::fd_hb; }

     std::shared_ptr<FDEntry>
     clone() const override
@@ -114,12 +130,12 @@
                 uint64_t file_offset, bool close_on_exec = false)
         : HBFDEntry(flags, sim_fd, close_on_exec),
           _fileName(file_name), _fileOffset(file_offset)
-    { }
+    { _class = FDClass::fd_file; }

     FileFDEntry(FileFDEntry const& reg, bool close_on_exec = false)
         : HBFDEntry(reg._flags, reg._simFD, close_on_exec),
           _fileName(reg._fileName), _fileOffset(reg._fileOffset)
-    { }
+    { _class = FDClass::fd_file; }

     std::shared_ptr<FDEntry>
     clone() const override
@@ -129,9 +145,11 @@

     std::string const& getFileName() const { return _fileName; }
     uint64_t getFileOffset() const { return _fileOffset; }
+    mode_t getFileMode() const { return _mode; }

void setFileName(std::string const& file_name) { _fileName = file_name; }
     void setFileOffset(uint64_t f_off) { _fileOffset = f_off; }
+    void setFileMode(mode_t mode) { _mode = mode; }

     void serialize(CheckpointOut &cp) const override;
     void unserialize(CheckpointIn &cp) override;
@@ -139,6 +157,7 @@
   private:
     std::string _fileName;
     uint64_t _fileOffset;
+    mode_t _mode;
 };

 /**
@@ -158,13 +177,13 @@
                 bool close_on_exec = false)
         : HBFDEntry(flags, sim_fd, close_on_exec), _pipeReadSource(-1),
           _pipeEndType(pipe_end_type)
-    { }
+    { _class = FDClass::fd_pipe; }

     PipeFDEntry(PipeFDEntry const& pipe, bool close_on_exec = false)
         : HBFDEntry(pipe._flags, pipe._simFD, close_on_exec),
           _pipeReadSource(pipe._pipeReadSource),
           _pipeEndType(pipe._pipeEndType)
-    { }
+    { _class = FDClass::fd_pipe; }

     std::shared_ptr<FDEntry>
     clone() const override
@@ -196,12 +215,12 @@
     DeviceFDEntry(EmulatedDriver *driver, std::string const& file_name,
                   bool close_on_exec = false)
         : FDEntry(close_on_exec), _driver(driver), _fileName(file_name)
-    { }
+    { _class = FDClass::fd_device; }

     DeviceFDEntry(DeviceFDEntry const& dev, bool close_on_exec = false)
         : FDEntry(close_on_exec), _driver(dev._driver),
           _fileName(dev._fileName)
-    { }
+    { _class = FDClass::fd_device; }

     std::shared_ptr<FDEntry>
     clone() const override
@@ -227,12 +246,12 @@
                   bool close_on_exec = false)
         : HBFDEntry(0, sim_fd, close_on_exec),
           _domain(domain), _type(type), _protocol(protocol)
-    { }
+    { _class = FDClass::fd_socket; }

     SocketFDEntry(SocketFDEntry const& reg, bool close_on_exec = false)
         : HBFDEntry(reg._flags, reg._simFD, close_on_exec),
           _domain(reg._domain), _type(reg._type), _protocol(reg._protocol)
-    { }
+    { _class = FDClass::fd_socket; }

     std::shared_ptr<FDEntry>
     clone() const override
diff --git a/src/sim/process.cc b/src/sim/process.cc
index 4902a13..a77bef3 100644
--- a/src/sim/process.cc
+++ b/src/sim/process.cc
@@ -356,12 +356,14 @@
 {
     memState->serialize(cp);
     pTable->serialize(cp);
+    fds->serialize(cp);
+
     /**
-     * Checkpoints for file descriptors currently do not work. Need to
-     * come back and fix them at a later date.
+     * Checkpoints for pipes, device drivers or sockets currently
+     * do not work. Need to come back and fix them at a later date.
      */

-    warn("Checkpoints for file descriptors currently do not work.");
+    warn("Checkpoints for pipes, device drivers and sockets do not work.");
 }

 void
@@ -369,11 +371,12 @@
 {
     memState->unserialize(cp);
     pTable->unserialize(cp);
+    fds->unserialize(cp);
     /**
-     * Checkpoints for file descriptors currently do not work. Need to
-     * come back and fix them at a later date.
+     * Checkpoints for pipes, device drivers or sockets currently
+     * do not work. Need to come back and fix them at a later date.
      */
-    warn("Checkpoints for file descriptors currently do not work.");
+    warn("Checkpoints for pipes, device drivers and sockets do not work.");
     // The above returns a bool so that you could do something if you don't
// find the param in the checkpoint if you wanted to, like set a default
     // but in this case we'll just stick with the instantiated value if not
diff --git a/src/sim/syscall_emul.hh b/src/sim/syscall_emul.hh
index 54e92b2..cd2d8d1 100644
--- a/src/sim/syscall_emul.hh
+++ b/src/sim/syscall_emul.hh
@@ -887,6 +887,8 @@
      * process to act as a handle for the opened file.
      */
     auto ffdp = std::make_shared<FileFDEntry>(sim_fd, host_flags, path, 0);
+    // Record the file mode for checkpoint restoring
+    ffdp->setFileMode(mode);
     int tgt_fd = p->fds->allocFD(ffdp);
     DPRINTF_SYSCALL(Verbose, "%s: sim_fd[%d], target_fd[%d] -> path:%s\n"
                     "(inferred from:%s)\n", desc->name(),

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/46619
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I4d0c7cd614a8abaffcae9aba1a28c9fdbc023c5a
Gerrit-Change-Number: 46619
Gerrit-PatchSet: 4
Gerrit-Owner: Tom Rollet <[email protected]>
Gerrit-Reviewer: Jason Lowe-Power <[email protected]>
Gerrit-Reviewer: Jason Lowe-Power <[email protected]>
Gerrit-Reviewer: Tom Rollet <[email protected]>
Gerrit-Reviewer: kokoro <[email protected]>
Gerrit-CC: Giacomo Travaglini <[email protected]>
Gerrit-MessageType: merged
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to