/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- drain
- refill
- postRestart
- serializeSubClass
- asEpoll
- onCTL
- drain
- refill
- postRestart
- serializeSubClass
- drain
- refill
- postRestart
- serializeSubClass
- drain
- refill
- postRestart
- serializeSubClass
- asInotify
- add_watch_descriptors
- remove_watch_descriptors
1 /****************************************************************************
2 * Copyright (C) 2006-2010 by Jason Ansel, Kapil Arya, and Gene Cooperman *
3 * jansel@csail.mit.edu, kapil@ccs.neu.edu, gene@ccs.neu.edu *
4 * *
5 * This file is part of the dmtcp/src module of DMTCP (DMTCP:dmtcp/src). *
6 * *
7 * DMTCP:dmtcp/src is free software: you can redistribute it and/or *
8 * modify it under the terms of the GNU Lesser General Public License as *
9 * published by the Free Software Foundation, either version 3 of the *
10 * License, or (at your option) any later version. *
11 * *
12 * DMTCP:dmtcp/src is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU Lesser General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU Lesser General Public *
18 * License along with DMTCP:dmtcp/src. If not, see *
19 * <http://www.gnu.org/licenses/>. *
20 ****************************************************************************/
21
22 #include <sys/ioctl.h>
23 #include <sys/select.h>
24 #include <sys/un.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <sys/file.h>
28 #include <termios.h>
29 #include <iostream>
30 #include <ios>
31 #include <fstream>
32 #include <linux/limits.h>
33 #include <arpa/inet.h>
34
35 #include "dmtcp.h"
36 #include "shareddata.h"
37 #include "util.h"
38 #include "jassert.h"
39 #include "jfilesystem.h"
40 #include "jconvert.h"
41
42 #include "eventconnection.h"
43 #include "eventwrappers.h"
44 #include "util_descriptor.h"
45 using namespace dmtcp;
46 /*****************************************************************************
47 * Epoll Connection
48 *****************************************************************************/
49
50 #ifdef HAVE_SYS_EPOLL_H
51 void EpollConnection::drain()
52 {
53 JASSERT(_fds.size() > 0);
54 }
55
56 void EpollConnection::refill(bool isRestart)
57 {
58 JASSERT(_fds.size() > 0);
59 if (isRestart) {
60 typedef map< int, struct epoll_event >::iterator fdEventIterator;
61 fdEventIterator fevt = _fdToEvent.begin();
62 for (; fevt != _fdToEvent.end(); fevt++) {
63 JTRACE("restore sfd options") (fevt->first);
64 int ret = _real_epoll_ctl(_fds[0], EPOLL_CTL_ADD, fevt->first,
65 &(fevt->second));
66 JWARNING(ret == 0) (_fds[0]) (ret) (strerror(errno))
67 .Text("Error in restoring options");
68 }
69 }
70 }
71
72 void EpollConnection::postRestart()
73 {
74 JASSERT(_fds.size()>0);
75 JTRACE("Recreating epoll connection") (_fds[0]) (id());
76 int tempFd = _real_epoll_create(_size) ;
77 JASSERT(tempFd >= 0);
78 Util::dupFds(tempFd, _fds);
79 }
80
81 void EpollConnection::serializeSubClass(jalib::JBinarySerializer& o)
82 {
83 JSERIALIZE_ASSERT_POINT("EpollConnection");
84 o & _type & _stat;
85 o.serializeMap(_fdToEvent);
86 }
87
88 EpollConnection& EpollConnection::asEpoll()
89 {
90 return *this;
91 }
92
93 void EpollConnection::onCTL(int op, int fd, struct epoll_event *event)
94 {
95 JASSERT(((op==EPOLL_CTL_MOD || op==EPOLL_CTL_ADD) && event != NULL) ||
96 op==EPOLL_CTL_DEL) (epollType())
97 (id())
98 .Text("Passing a NULL event! HUH!");
99
100 struct epoll_event myEvent;
101 _type = EPOLL_CTL;
102 if (op == EPOLL_CTL_DEL) {
103 _fdToEvent.erase(fd);
104 return;
105 }
106 memcpy(&myEvent, event, sizeof myEvent);
107 _fdToEvent[fd] = myEvent;
108 }
109 #endif
110
111 /*****************************************************************************
112 * Eventfd Connection
113 *****************************************************************************/
114 #ifdef HAVE_SYS_EVENTFD_H
115 void EventFdConnection::drain()
116 {
117 JASSERT(_fds.size() > 0);
118 JTRACE("Checkpoint eventfd.") (_fds[0]);
119
120 int new_flags =(_fcntlFlags &(~(O_RDONLY|O_WRONLY))) | O_RDWR | O_NONBLOCK;
121 int evtfd = _fds[0];
122 JASSERT(evtfd >= 0) (evtfd) (JASSERT_ERRNO);
123 // set the new flags
124 JASSERT(fcntl(evtfd, F_SETFL, new_flags) == 0)
125 (evtfd) (new_flags) (JASSERT_ERRNO);
126 ssize_t size;
127 uint64_t u;
128 unsigned int counter = 1;
129
130 // Read whatever is there on top of evtfd
131 size = read(evtfd, &u, sizeof(uint64_t));
132 if (-1 != size) {
133 JTRACE("Read value u: ") (evtfd) (u);
134 // EFD_SEMAPHORE flag not specified,
135 // the counter value would have been reset to 0 upon read
136 // Save the value, so that it can be restored in post-checkpoint
137 if (!(_flags & EFD_SEMAPHORE)) {
138 _initval = u;
139 } else {
140 // EFD_SEMAPHORE specified, so can't read the current counter value
141 // Keep reading till "semaphore" becomes 0.
142 while (-1 != read(evtfd, &u, sizeof(uint64_t)))
143 counter++;
144 _initval = counter;
145 }
146 } else {
147 JTRACE("Nothing to be read from eventfd.")
148 (evtfd) (errno) (strerror(errno));
149 _initval = 0;
150 }
151 JTRACE("Checkpointing eventfd: end.") (_fds[0]) (_initval);
152 }
153
154 void EventFdConnection::refill(bool isRestart)
155 {
156 JTRACE("Begin refill eventfd.") (_fds[0]);
157 JASSERT(_fds.size() > 0);
158 evtfd = _fds[0];
159 if (!isRestart) {
160 uint64_t u =(unsigned long long) _initval;
161 JTRACE("Writing") (u);
162 JWARNING(write(evtfd, &u, sizeof(uint64_t)) == sizeof(uint64_t))
163 (evtfd) (errno) (strerror(errno))
164 .Text("Write to eventfd failed during refill");
165 }
166 JTRACE("End refill eventfd.") (_fds[0]);
167 }
168
169 void EventFdConnection::postRestart()
170 {
171 JASSERT(_fds.size() > 0);
172
173 JTRACE("Restoring EventFd Connection") (id());
174 errno = 0;
175 int tempfd = _real_eventfd(_initval, _flags);
176 JASSERT(tempfd > 0) (tempfd) (JASSERT_ERRNO);
177 Util::dupFds(tempfd, _fds);
178 }
179
180 void EventFdConnection::serializeSubClass(jalib::JBinarySerializer& o)
181 {
182 JSERIALIZE_ASSERT_POINT("EventFdConnection");
183 o & _initval & _flags;
184 JTRACE("Serializing EvenFdConn.") ;
185 }
186 #endif
187
188 /*****************************************************************************
189 * Signalfd Connection
190 *****************************************************************************/
191 #ifdef HAVE_SYS_SIGNALFD_H
192 void SignalFdConnection::drain()
193 {
194 JASSERT(_fds.size() > 0);
195
196 JTRACE("Checkpoint signalfd.") (_fds[0]);
197
198 int new_flags =(_fcntlFlags &(~(O_RDONLY|O_WRONLY))) | O_RDWR | O_NONBLOCK;
199 signlfd = _fds[0];
200 JASSERT(signlfd >= 0) (signlfd) (JASSERT_ERRNO);
201 // set the new flags
202 JASSERT(fcntl(signlfd, F_SETFL, new_flags) == 0)
203 (signlfd) (new_flags) (JASSERT_ERRNO);
204 ssize_t size;
205 struct signalfd_siginfo _fdsi;
206
207 // Read whatever is there on top of signalfd
208 size = read(signlfd, &_fdsi, sizeof(struct signalfd_siginfo));
209 if (-1 != size) {
210 // Save the value, so that it can be restored in post-checkpoint
211 memcpy(&_fdsi, &_fdsi, sizeof(struct signalfd_siginfo));
212
213 } else {
214 JTRACE("Nothing to be read from signalfd.")
215 (signlfd) (errno) (strerror(errno));
216 }
217 JTRACE("Checkpointing signlfd: end.") (_fds[0]) ;
218 }
219
220 void SignalFdConnection::refill(bool isRestart)
221 {
222 JTRACE("Begin refill signalfd.") (_fds[0]);
223 JASSERT(_fds.size() > 0);
224 //raise the signals
225 JTRACE("Raising the signal...") (_fdsi.ssi_signo);
226 raise(_fdsi.ssi_signo);
227 JTRACE("End refill signalfd.") (_fds[0]);
228 }
229
230 void SignalFdConnection::postRestart()
231 {
232 JASSERT(_fds.size() > 0);
233
234 JTRACE("Restoring SignalFd Connection") (id());
235 errno = 0;
236 int tempfd = _real_signalfd(-1, &_mask, _flags);
237 JASSERT(tempfd > 0) (tempfd) (JASSERT_ERRNO);
238 Util::dupFds(tempfd, _fds);
239 }
240
241 void SignalFdConnection::serializeSubClass(jalib::JBinarySerializer& o)
242 {
243 JSERIALIZE_ASSERT_POINT("SignalFdConnection");
244 o & _flags & _mask & _fdsi;
245 JTRACE("Serializing SignalFdConn.") ;
246 }
247 #endif
248
249 #ifdef DMTCP_USE_INOTIFY
250 /*****************************************************************************
251 * Inotify Connection
252 *****************************************************************************/
253 void InotifyConnection::drain()
254 {
255 JASSERT(_fds.size() > 0);
256 }
257
258 void InotifyConnection::refill(bool isRestart)
259 {
260 JASSERT(_fds.size() > 0);
261 if (isRestart) {
262 int num_of_descriptors;
263 Util::Descriptor descriptor;
264 descriptor_types_u watch_descriptor;
265
266 //get the number of watch descriptors stored in dmtcp
267 num_of_descriptors = descriptor.count_descriptors();
268
269 JTRACE("inotify restoreOptions") (_fds[0]) (id()) (num_of_descriptors);
270
271 for (int i = 0; i < num_of_descriptors; i++) {
272 if (true == descriptor.get_descriptor(i, INOTIFY_ADD_WATCH_DESCRIPTOR,
273 &watch_descriptor)) {
274 int old_wd = watch_descriptor.add_watch.watch_descriptor;
275
276 int new_wd =
277 _real_inotify_add_watch(watch_descriptor.add_watch.file_descriptor,
278 watch_descriptor.add_watch.pathname,
279 watch_descriptor.add_watch.mask);
280
281 JWARNING(_real_dup2(new_wd, old_wd) == old_wd)
282 (new_wd) (old_wd) (JASSERT_ERRNO);
283 JTRACE("restore watch descriptors")
284 (old_wd) (new_wd) (watch_descriptor.add_watch.file_descriptor)
285 (watch_descriptor.add_watch.pathname)
286 (watch_descriptor.add_watch.mask);
287 }
288 }
289 }
290 }
291
292 void InotifyConnection::postRestart()
293 {
294 //create a new inotify instance and clone it as the old one
295 int tempfd = _real_inotify_init1(_flags);
296 JASSERT(tempfd >= 0);
297 Util::dupFds(tempfd, _fds);
298 }
299
300 void InotifyConnection::serializeSubClass(jalib::JBinarySerializer& o)
301 {
302 JSERIALIZE_ASSERT_POINT("InotifyConnection");
303 o & _type & _stat;
304 //o.serializeMap(_inotify_fd_to_wd);
305 //o.serializeMap(_wd_to_pathname);
306 //o.serializeMap(_pathname_to_mask);
307 }
308
309 InotifyConnection& InotifyConnection::asInotify()
310 {
311 JTRACE("Return the connection as Inotify connection");
312 return *this;
313 }
314
315 void InotifyConnection::add_watch_descriptors(int wd, int fd,
316 const char *pathname,
317 uint32_t mask)
318 {
319 int string_len;
320
321 JTRACE("save inotify watch descriptor within dmtcp")
322 (wd) (fd) (pathname) (mask);
323 JASSERT(pathname != NULL) .Text("pathname is NULL");
324 if (NULL != pathname) {
325 Util::Descriptor descriptor;
326 descriptor_types_u watch_descriptor;
327
328 //set watch_descriptor to zeros
329 memset(&watch_descriptor, 0, sizeof(watch_descriptor));
330
331 // get the string length
332 string_len = strlen(pathname);
333
334 // fill up the structure
335 watch_descriptor.add_watch.file_descriptor = fd;
336 watch_descriptor.add_watch.mask = mask;
337 watch_descriptor.add_watch.watch_descriptor = wd;
338 watch_descriptor.add_watch.type = INOTIFY_ADD_WATCH_DESCRIPTOR;
339 strncpy(watch_descriptor.add_watch.pathname, pathname, string_len);
340
341 // save the watch descriptor structure
342 descriptor.add_descriptor(&watch_descriptor);
343 }
344 }
345
346 void InotifyConnection::remove_watch_descriptors(int wd)
347 {
348 Util::Descriptor descriptor;
349 descriptor.remove_descriptor(INOTIFY_ADD_WATCH_DESCRIPTOR, (void *)&wd);
350 }
351 #endif