summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdriana Kobylak <anoo@us.ibm.com>2018-05-08 11:52:44 -0500
committerAdriana Kobylak <anoo@us.ibm.com>2018-05-08 12:00:16 -0500
commita90743427789417fb36fa63b3a4ce72ecc8fca1c (patch)
tree75c47f80674d3ca98dff29d1bbaa7bbeeba4b5ae
parentb072d1bec4f8c5ee2de13722a4af63ba4350d7c7 (diff)
downloadphosphor-bmc-code-mgmt-a90743427789417fb36fa63b3a4ce72ecc8fca1c.tar.gz
phosphor-bmc-code-mgmt-a90743427789417fb36fa63b3a4ce72ecc8fca1c.zip
sync_manager: Add callback to do rsync
Call rsync when the subscribed file or directory is modified or deleted. Don't create error logs as syncing is used for backup and does not affect the system's operation. Any errors will be logged into the journal. Closes openbmc/openbmc#2918 Change-Id: I2671f0afd2924c15ea883d4d037c641c6e9680b4 Signed-off-by: Adriana Kobylak <anoo@us.ibm.com>
-rwxr-xr-xconfigure.ac2
-rw-r--r--sync_manager.cpp66
-rw-r--r--sync_manager.hpp8
-rw-r--r--sync_manager_main.cpp3
-rw-r--r--sync_watch.cpp39
-rw-r--r--sync_watch.hpp4
6 files changed, 115 insertions, 7 deletions
diff --git a/configure.ac b/configure.ac
index 1155cfe..0165e08 100755
--- a/configure.ac
+++ b/configure.ac
@@ -96,6 +96,8 @@ AC_DEFINE(MEDIA_DIR, "/media/",
[The base dir where all RO partitions are mounted])
AC_DEFINE(BMC_ROFS_PREFIX, "/media/rofs-",
[The prefix path for the versioned read-only bmc partitions])
+AC_DEFINE(ALT_RWFS, "/media/alt/var/persist",
+ [The path of the alt rwfs overlay])
AC_DEFINE(PERSIST_DIR, "/var/lib/obmc/phosphor-bmc-code-mgmt/",
[The dir where activation data is stored in files])
AC_DEFINE(SYSTEMD_BUSNAME, "org.freedesktop.systemd1",
diff --git a/sync_manager.cpp b/sync_manager.cpp
index 6a50711..f83aebd 100644
--- a/sync_manager.cpp
+++ b/sync_manager.cpp
@@ -1,3 +1,9 @@
+#include <experimental/filesystem>
+#include <phosphor-logging/log.hpp>
+#include <sys/inotify.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include "config.h"
#include "sync_manager.hpp"
namespace phosphor
@@ -7,8 +13,66 @@ namespace software
namespace manager
{
-int Sync::processEntry()
+using namespace phosphor::logging;
+namespace fs = std::experimental::filesystem;
+
+int Sync::processEntry(int mask, const fs::path& entryPath)
{
+ int status{};
+ pid_t pid = fork();
+
+ if (pid == 0)
+ {
+ fs::path dst(ALT_RWFS / entryPath);
+
+ // rsync needs an additional --delete argument to handle file deletions
+ // so need to differentiate between the different file events.
+ if (mask & IN_CLOSE_WRITE)
+ {
+ if (!(fs::exists(dst)))
+ {
+ if (fs::is_directory(entryPath))
+ {
+ // Source is a directory, create it at the destination.
+ fs::create_directories(dst);
+ }
+ else
+ {
+ // Source is a file, create the directory where this file
+ // resides at the destination.
+ fs::create_directories(dst.parent_path());
+ }
+ }
+
+ execl("/usr/bin/rsync", "rsync", "-a", entryPath.c_str(),
+ dst.c_str(), nullptr);
+ // execl only returns on fail
+ log<level::ERR>("Error occurred during the rsync call",
+ entry("ERRNO=%d", errno),
+ entry("PATH=%s", entryPath.c_str()));
+ return -1;
+ }
+ else if (mask & IN_DELETE)
+ {
+ execl("/usr/bin/rsync", "rsync", "-a", "--delete",
+ entryPath.c_str(), dst.c_str(), nullptr);
+ // execl only returns on fail
+ log<level::ERR>("Error occurred during the rsync delete call",
+ entry("ERRNO=%d", errno),
+ entry("PATH=%s", entryPath.c_str()));
+ return -1;
+ }
+ }
+ else if (pid > 0)
+ {
+ waitpid(pid, &status, 0);
+ }
+ else
+ {
+ log<level::ERR>("Error occurred during fork", entry("ERRNO=%d", errno));
+ return -1;
+ }
+
return 0;
}
diff --git a/sync_manager.hpp b/sync_manager.hpp
index a940461..45bfca4 100644
--- a/sync_manager.hpp
+++ b/sync_manager.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include <experimental/filesystem>
+
namespace phosphor
{
namespace software
@@ -7,6 +9,8 @@ namespace software
namespace manager
{
+namespace fs = std::experimental::filesystem;
+
/** @class Sync
* @brief Contains filesystem sync functions.
* @details The software manager class that contains functions to perform
@@ -24,9 +28,11 @@ class Sync
/**
* @brief Process requested file or directory.
+ * @param[in] mask - The inotify mask.
+ * @param[in] entryPath - The file or directory to process.
* @param[out] result - 0 if successful.
*/
- int processEntry();
+ int processEntry(int mask, const fs::path& entryPath);
};
} // namespace manager
diff --git a/sync_manager_main.cpp b/sync_manager_main.cpp
index 46a2d95..e1834b5 100644
--- a/sync_manager_main.cpp
+++ b/sync_manager_main.cpp
@@ -23,7 +23,8 @@ int main(int argc, char* argv[])
using namespace phosphor::software::manager;
phosphor::software::manager::SyncWatch watch(
- *loop, std::bind(std::mem_fn(&Sync::processEntry), &syncManager));
+ *loop, std::bind(std::mem_fn(&Sync::processEntry), &syncManager,
+ std::placeholders::_1, std::placeholders::_2));
bus.attach_event(loop, SD_EVENT_PRIORITY_NORMAL);
sd_event_loop(loop);
}
diff --git a/sync_watch.cpp b/sync_watch.cpp
index 0fc61d8..a8b4eeb 100644
--- a/sync_watch.cpp
+++ b/sync_watch.cpp
@@ -17,7 +17,7 @@ using namespace phosphor::logging;
namespace fs = std::experimental::filesystem;
SyncWatch::SyncWatch(sd_event& loop,
- std::function<int(fs::path&)> syncCallback) :
+ std::function<int(int, fs::path&)> syncCallback) :
syncCallback(syncCallback)
{
auto syncfile = fs::path(SYNC_LIST_DIR_PATH) / SYNC_LIST_FILE_NAME;
@@ -37,7 +37,8 @@ SyncWatch::SyncWatch(sd_event& loop,
continue;
}
- auto wd = inotify_add_watch(fd, line.c_str(), IN_CLOSE_WRITE);
+ auto wd =
+ inotify_add_watch(fd, line.c_str(), IN_CLOSE_WRITE | IN_DELETE);
if (-1 == wd)
{
log<level::ERR>("inotify_add_watch failed",
@@ -81,6 +82,40 @@ SyncWatch::~SyncWatch()
int SyncWatch::callback(sd_event_source* s, int fd, uint32_t revents,
void* userdata)
{
+ if (!(revents & EPOLLIN))
+ {
+ return 0;
+ }
+
+ constexpr auto maxBytes = 1024;
+ uint8_t buffer[maxBytes];
+ auto bytes = read(fd, buffer, maxBytes);
+ if (0 > bytes)
+ {
+ return 0;
+ }
+
+ auto syncWatch = static_cast<SyncWatch*>(userdata);
+ auto offset = 0;
+ while (offset < bytes)
+ {
+ auto event = reinterpret_cast<inotify_event*>(&buffer[offset]);
+
+ // fileMap<fd, std::map<wd, path>>
+ auto it1 = syncWatch->fileMap.find(fd);
+ if (it1 != syncWatch->fileMap.end())
+ {
+ auto it2 = it1->second.begin();
+ auto rc = syncWatch->syncCallback(event->mask, it2->second);
+ if (rc)
+ {
+ return rc;
+ }
+ }
+
+ offset += offsetof(inotify_event, name) + event->len;
+ }
+
return 0;
}
diff --git a/sync_watch.hpp b/sync_watch.hpp
index a7f8557..4303671 100644
--- a/sync_watch.hpp
+++ b/sync_watch.hpp
@@ -29,7 +29,7 @@ class SyncWatch
* @param[in] syncCallback - The callback function for processing
* files
*/
- SyncWatch(sd_event& loop, std::function<int(fs::path&)> syncCallback);
+ SyncWatch(sd_event& loop, std::function<int(int, fs::path&)> syncCallback);
SyncWatch(const SyncWatch&) = delete;
SyncWatch& operator=(const SyncWatch&) = delete;
@@ -58,7 +58,7 @@ class SyncWatch
std::map<fd, std::map<wd, fs::path>> fileMap;
/** @brief The callback function for processing the inotify event */
- std::function<int(fs::path&)> syncCallback;
+ std::function<int(int, fs::path&)> syncCallback;
};
} // namespace manager
OpenPOWER on IntegriCloud