blob: 7e753c015d630fa577f9ce5b3bb4b3e84f226110 [file] [log] [blame]
Jayanth Othayotha320c7c2017-06-14 07:17:21 -05001#include <unistd.h>
Jayanth Othayothbcb174b2017-07-02 06:29:24 -05002#include <sys/inotify.h>
Jayanth Othayoth481bb3d2017-07-13 03:33:34 -05003#include <regex>
Jayanth Othayotha320c7c2017-06-14 07:17:21 -05004
5#include <phosphor-logging/elog-errors.hpp>
6
7#include "dump_manager.hpp"
8#include "dump_internal.hpp"
9#include "xyz/openbmc_project/Common/error.hpp"
10#include "config.h"
11
12namespace phosphor
13{
14namespace dump
15{
16
17using namespace sdbusplus::xyz::openbmc_project::Common::Error;
18using namespace phosphor::logging;
Jayanth Othayoth481bb3d2017-07-13 03:33:34 -050019using namespace std;
Jayanth Othayotha320c7c2017-06-14 07:17:21 -050020
21namespace internal
22{
23
24void Manager::create(
25 Type type,
26 std::vector<std::string> fullPaths)
27{
Jayanth Othayothd3273ea2017-07-12 22:55:32 -050028 dumpMgr.phosphor::dump::Manager::captureDump(type, fullPaths);
Jayanth Othayotha320c7c2017-06-14 07:17:21 -050029}
30
31} //namepsace internal
32
33uint32_t Manager::createDump()
34{
35 std::vector<std::string> paths;
36
37 return captureDump(Type::UserRequested, paths);
38}
39
40uint32_t Manager::captureDump(
41 Type type,
42 const std::vector<std::string>& fullPaths)
43{
44 pid_t pid = fork();
45
Jayanth Othayotha320c7c2017-06-14 07:17:21 -050046 if (pid == 0)
47 {
Jayanth Othayothf9009a22017-07-12 19:40:34 -050048 fs::path dumpPath(BMC_DUMP_PATH);
49
50 dumpPath /= std::to_string(lastEntryId + 1);
51 execl("/usr/bin/ffdc", "ffdc", "-d", dumpPath.c_str(), nullptr);
Jayanth Othayotha320c7c2017-06-14 07:17:21 -050052
53 //ffdc script execution is failed.
54 auto error = errno;
55 log<level::ERR>("Error occurred during ffdc function execution",
56 entry("ERRNO=%d", error));
57 elog<InternalFailure>();
58 }
59 else if (pid > 0)
60 {
61 auto rc = sd_event_add_child(eventLoop.get(),
62 nullptr,
63 pid,
64 WEXITED | WSTOPPED,
65 callback,
66 nullptr);
67 if (0 > rc)
68 {
69 // Failed to add to event loop
70 log<level::ERR>("Error occurred during the sd_event_add_child call",
71 entry("rc=%d", rc));
72 elog<InternalFailure>();
73 }
74 }
75 else
76 {
77 auto error = errno;
78 log<level::ERR>("Error occurred during fork",
79 entry("ERRNO=%d", error));
80 elog<InternalFailure>();
81 }
82
83 return ++lastEntryId;
84}
85
86void Manager::createEntry(const fs::path& file)
87{
Jayanth Othayoth481bb3d2017-07-13 03:33:34 -050088 //Dump File Name format obmcdump_ID_EPOCHTIME.EXT
89 static constexpr auto ID_POS = 1;
90 static constexpr auto EPOCHTIME_POS = 2;
91 std::regex file_regex("obmcdump_([0-9]+)_([0-9]+).([a-zA-Z0-9]+)");
Jayanth Othayotha320c7c2017-06-14 07:17:21 -050092
Jayanth Othayoth481bb3d2017-07-13 03:33:34 -050093 std::smatch match;
94 std::string name = file.filename();
Jayanth Othayotha320c7c2017-06-14 07:17:21 -050095
Jayanth Othayoth481bb3d2017-07-13 03:33:34 -050096 if (!((std::regex_search(name, match, file_regex)) &&
97 (match.size() > 0)))
98 {
99 log<level::ERR>("Invalid Dump file name",
100 entry("Filename=%s", file.filename()));
101 return;
102 }
Jayanth Othayotha320c7c2017-06-14 07:17:21 -0500103
Jayanth Othayoth481bb3d2017-07-13 03:33:34 -0500104 auto idString = match[ID_POS];
105 auto msString = match[EPOCHTIME_POS];
Jayanth Othayotha320c7c2017-06-14 07:17:21 -0500106
Jayanth Othayoth481bb3d2017-07-13 03:33:34 -0500107 try
108 {
109 auto id = stoul(idString);
110 // Entry Object path.
111 auto objPath = fs::path(OBJ_ENTRY) / std::to_string(id);
112
113 entries.insert(std::make_pair(id,
114 std::make_unique<Entry>(
115 bus,
116 objPath.c_str(),
117 id,
118 stoull(msString),
119 fs::file_size(file),
120 file,
121 *this)));
122 }
123 catch (const std::invalid_argument& e)
124 {
125 log<level::ERR>(e.what());
126 return;
127 }
Jayanth Othayotha320c7c2017-06-14 07:17:21 -0500128}
129
130void Manager::erase(uint32_t entryId)
131{
132 entries.erase(entryId);
133}
134
Jayanth Othayothbcb174b2017-07-02 06:29:24 -0500135void Manager::watchCallback(const UserMap& fileInfo)
136{
137 for (const auto& i : fileInfo)
138 {
Jayanth Othayoth764d1b22017-07-12 19:14:02 -0500139 // For any new dump file create dump entry object
140 // and associated inotify watch.
Jayanth Othayothbcb174b2017-07-02 06:29:24 -0500141 if (IN_CLOSE_WRITE == i.second)
142 {
Jayanth Othayoth764d1b22017-07-12 19:14:02 -0500143 removeWatch(i.first);
144
Jayanth Othayothbcb174b2017-07-02 06:29:24 -0500145 createEntry(i.first);
146 }
Jayanth Othayoth764d1b22017-07-12 19:14:02 -0500147 // Start inotify watch on newly created directory.
148 else if ((IN_CREATE == i.second) && fs::is_directory(i.first))
149 {
150 auto watchObj = std::make_unique<Watch>(
151 eventLoop,
152 IN_NONBLOCK,
153 IN_CLOSE_WRITE,
154 EPOLLIN,
155 i.first,
156 std::bind(
157 std::mem_fn(
158 &phosphor::dump::Manager::watchCallback),
159 this, std::placeholders::_1));
160
161 childWatchMap.emplace(i.first, std::move(watchObj));
162 }
163
Jayanth Othayothbcb174b2017-07-02 06:29:24 -0500164 }
165}
166
Jayanth Othayoth764d1b22017-07-12 19:14:02 -0500167void Manager::removeWatch(const fs::path& path)
168{
169 //Delete Watch entry from map.
170 childWatchMap.erase(path);
171}
172
Jayanth Othayotha320c7c2017-06-14 07:17:21 -0500173} //namespace dump
174} //namespace phosphor