blob: 62084665053724e7924124bff5338ae4264c9a2e [file] [log] [blame]
Jayanth Othayoth1756c062017-05-23 22:48:11 -05001#include <stdexcept>
2#include <cstddef>
3#include <cstring>
4#include <string>
5#include <vector>
6#include <sys/inotify.h>
7#include <unistd.h>
8#include "config.h"
9#include "dump_watch.hpp"
10#include <experimental/filesystem>
11#include <phosphor-logging/log.hpp>
12#include <phosphor-logging/elog.hpp>
13#include <phosphor-logging/elog-errors.hpp>
14#include "elog-errors.hpp"
15#include <xyz/openbmc_project/Dump/Monitor/error.hpp>
16#include "xyz/openbmc_project/Common/error.hpp"
17
18namespace phosphor
19{
20namespace dump
21{
22
23CustomFd::~CustomFd()
24{
25 if (fd >= 0)
26 {
27 close(fd);
28 }
29}
30
31namespace inotify
32{
33
34using namespace std::string_literals;
35using namespace phosphor::logging;
36using namespace sdbusplus::xyz::openbmc_project::Dump::Monitor::Error;
37using namespace sdbusplus::xyz::openbmc_project::Common::Error;
38namespace fs = std::experimental::filesystem;
39
40Watch::~Watch()
41{
42 if ((fd() >= 0) && (wd >= 0))
43 {
44 inotify_rm_watch(fd(), wd);
45 }
46}
47
48Watch::Watch(sd_event* loop):
49 fd(inotifyInit())
50{
51 // Check if CORE DIR exists.
52 fs::path coreDirPath(CORE_FILE_DIR);
53 if (!fs::is_directory(coreDirPath))
54 {
55 namespace metadata = xyz::openbmc_project::Dump::Monitor;
56 elog<InvalidCorePath>(metadata::InvalidCorePath::PATH(CORE_FILE_DIR));
57 }
58
59 //Check for existing coredumps, Dump manager should handle this before
60 //starting the core monitoring.
61 //This is to handle coredumps created prior to Dump applications start,
62 //or missing coredump reporting due to Dump application crashs.
63 if (!fs::is_empty(coreDirPath))
64 {
65 //TODO openbmc/openbmc#1510 Enable Dump collection function here.
66 }
67
68 wd = inotify_add_watch(fd(), CORE_FILE_DIR, IN_CLOSE_WRITE);
69 if (-1 == wd)
70 {
71 auto error = errno;
72 log<level::ERR>("Error occurred during the inotify_add_watch call",
73 entry("ERRNO=%s", strerror(error)));
74 elog<InternalFailure>();
75 }
76
77 auto rc = sd_event_add_io(loop,
78 nullptr,
79 fd(),
80 EPOLLIN,
81 callback,
82 this);
83 if (0 > rc)
84 {
85 // Failed to add to event loop
86 auto error = errno;
87 log<level::ERR>("Error occurred during the sd_event_add_io call",
88 entry("ERRNO=%s", strerror(error)));
89 elog<InternalFailure>();
90 }
91}
92
93int Watch::inotifyInit()
94{
95 auto fd = inotify_init1(IN_NONBLOCK);
96
97 if (-1 == fd)
98 {
99 auto error = errno;
100 log<level::ERR>("Error occurred during the inotify_init1",
101 entry("ERRNO=%s", strerror(error)));
102 elog<InternalFailure>();
103 }
104
105 return fd;
106}
107
108int Watch::callback(sd_event_source* s,
109 int fd,
110 uint32_t revents,
111 void* userdata)
112{
113 if (!(revents & EPOLLIN))
114 {
115 return 0;
116 }
117
118 //Maximum inotify events supported in the buffer
119 constexpr auto maxBytes = sizeof(struct inotify_event) + NAME_MAX + 1;
120 uint8_t buffer[maxBytes];
121
122 auto bytes = read(fd, buffer, maxBytes);
123 if (0 > bytes)
124 {
125 //Failed to read inotify event
126 //Report error and return
127 auto error = errno;
128 log<level::ERR>("Error occurred during the read",
129 entry("ERRNO=%s", strerror(error)));
130 report<InternalFailure>();
131 return 0;
132 }
133
134 auto offset = 0;
135
136 std::vector<fs::path> corePaths;
137
138 while (offset < bytes)
139 {
140 auto event = reinterpret_cast<inotify_event*>(&buffer[offset]);
141 if ((event->mask & IN_CLOSE_WRITE) && !(event->mask & IN_ISDIR))
142 {
143 corePaths.emplace_back(fs::path(CORE_FILE_DIR) / event->name);
144 }
145
146 offset += offsetof(inotify_event, name) + event->len;
147 }
148
149 // Generate new BMC Dump( Core dump Type) incase valid cores
150 if (!corePaths.empty())
151 {
152 //TODO openbmc/openbmc#1510 Enable Dump collection function here
153 }
154 return 0;
155}
156
157} // namespace inotify
158} // namespace dump
159} // namespace phosphor