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