summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAgata Olender <agata.olender@intel.com>2020-01-13 15:31:49 +0300
committerOlender, Agata <agata.olender@intel.com>2020-01-29 13:36:50 +0300
commitb9a4ef7fd96aeda3e311993810c68bbb6553f3c2 (patch)
tree592a97256535a1e95eed0f3682c5d4b2f948aed6
parent332c885786635d2ab0d797105fee8e90400388c3 (diff)
downloadvirtual-media-b9a4ef7fd96aeda3e311993810c68bbb6553f3c2.tar.xz
Gadget inactivity timeout
MountPoints being inactive for time defined by InactivityTimeout will be unmounted. Inacitivity is measured based on USB gadget R/W statitics. InactivityTimeout must be set in json configuration and is common for all MountPoints. Remaining time to unmount inactive media is exposed per MountPoint on dbus using RemainingInactivityTimeout property. Change-Id: Ieb80e67dae6c3b4cb0482d801b5b4208884b0809 Signed-off-by: Agata Olender <agata.olender@intel.com>
-rw-r--r--src/configuration.hpp9
-rw-r--r--src/main.cpp2
-rw-r--r--src/state_machine.hpp66
-rw-r--r--src/system.hpp17
4 files changed, 94 insertions, 0 deletions
diff --git a/src/configuration.hpp b/src/configuration.hpp
index dd71837..89c9d02 100644
--- a/src/configuration.hpp
+++ b/src/configuration.hpp
@@ -34,6 +34,7 @@ class Configuration
std::string endPointId;
std::optional<int> timeout;
std::optional<int> blocksize;
+ std::chrono::seconds remainingInactivityTimeout;
Mode mode;
static std::vector<std::string> toArgs(const MountPoint& mp)
@@ -59,6 +60,7 @@ class Configuration
bool valid = false;
boost::container::flat_map<std::string, MountPoint> mountPoints;
+ static std::chrono::seconds inactivityTimeout;
Configuration(const std::string& file)
{
@@ -94,6 +96,13 @@ class Configuration
bool setupVariables(const nlohmann::json& config)
{
+ inactivityTimeout =
+ std::chrono::seconds(config.value("InactivityTimeout", 0));
+ if (inactivityTimeout == std::chrono::seconds(0))
+ {
+ LogMsg(Logger::Error, "InactivityTimeout required, not set");
+ }
+
for (const auto& item : config.items())
{
if (item.key() == "MountPoints")
diff --git a/src/main.cpp b/src/main.cpp
index 3636e59..49dab24 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -19,6 +19,8 @@
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
+std::chrono::seconds Configuration::inactivityTimeout;
+
class App
{
public:
diff --git a/src/state_machine.hpp b/src/state_machine.hpp
index 973d7fa..d6ec1b4 100644
--- a/src/state_machine.hpp
+++ b/src/state_machine.hpp
@@ -80,6 +80,8 @@ struct MountPointStateMachine
{
machine.target.reset();
}
+
+ machine.config.remainingInactivityTimeout = std::chrono::seconds(0);
}
};
@@ -115,6 +117,58 @@ struct MountPointStateMachine
BasicState(state, __FUNCTION__), process{state.process} {};
std::weak_ptr<Process> process;
+
+ virtual void onEnter()
+ {
+ timer =
+ std::make_shared<boost::asio::steady_timer>(machine.ioc.get());
+ handler = [this](const boost::system::error_code& ec) {
+ if (ec)
+ {
+ return;
+ }
+
+ auto now = std::chrono::steady_clock::now();
+
+ auto stats = UsbGadget::getStats(machine.name);
+ if (stats && (*stats != lastStats))
+ {
+ lastStats = std::move(*stats);
+ lastAccess = now;
+ }
+
+ auto timeSinceLastAccess =
+ std::chrono::duration_cast<std::chrono::seconds>(
+ now - lastAccess);
+ if (timeSinceLastAccess >= Configuration::inactivityTimeout)
+ {
+ LogMsg(Logger::Info, machine.name,
+ " Inactivity timer expired (",
+ Configuration::inactivityTimeout.count(),
+ "s) - Unmounting");
+ // unmount media & stop retriggering timer
+ machine.emitUnmountEvent();
+ return;
+ }
+ else
+ {
+ machine.config.remainingInactivityTimeout =
+ Configuration::inactivityTimeout - timeSinceLastAccess;
+ }
+
+ timer->expires_from_now(std::chrono::seconds(1));
+ timer->async_wait(handler);
+ };
+ timer->expires_from_now(std::chrono::seconds(1));
+ timer->async_wait(handler);
+ }
+
+ private:
+ // timer wrapped in shared_ptr to allow making state copies
+ std::shared_ptr<boost::asio::steady_timer> timer;
+ std::function<void(const boost::system::error_code&)> handler;
+ std::chrono::time_point<std::chrono::steady_clock> lastAccess;
+ std::string lastStats;
};
struct WaitingForProcessEndState : public BasicState
@@ -278,6 +332,18 @@ struct MountPointStateMachine
iface->register_property("EndpointId",
state.machine.config.endPointId);
iface->register_property("Socket", state.machine.config.unixSocket);
+ iface->register_property(
+ "RemainingInactivityTimeout", 0,
+ [](const int& req, int& property) {
+ throw sdbusplus::exception::SdBusError(
+ EPERM, "Setting RemainingInactivityTimeout property is "
+ "not allowed");
+ return -1;
+ },
+ [& config = state.machine.config](const int& property) -> int {
+ return config.remainingInactivityTimeout.count();
+ });
+
iface->initialize();
}
diff --git a/src/system.hpp b/src/system.hpp
index ca9d17e..ae8a486 100644
--- a/src/system.hpp
+++ b/src/system.hpp
@@ -582,4 +582,21 @@ struct UsbGadget
}
return -1;
}
+
+ static std::optional<std::string> getStats(const std::string& name)
+ {
+ const fs::path statsPath =
+ "/sys/kernel/config/usb_gadget/mass-storage-" + name +
+ "/functions/mass_storage.usb0/lun.0/stats";
+
+ std::ifstream ifs(statsPath);
+ if (!ifs.is_open())
+ {
+ LogMsg(Logger::Error, name, "Failed to open ", statsPath);
+ return {};
+ }
+
+ return std::string{std::istreambuf_iterator<char>(ifs),
+ std::istreambuf_iterator<char>()};
+ }
};