Branch data Line data Source code
1 : : #include <unistd.h>
2 : : #include <stdio.h>
3 : : #include <stdlib.h>
4 : : #include <errno.h>
5 : : #include <fcntl.h>
6 : : #include <stdlib.h>
7 : : #include <string.h>
8 : : #include <limits.h>
9 : : #include <sys/stat.h>
10 : : #include <sys/statfs.h>
11 : : #include <sys/types.h>
12 : : #include <sys/ioctl.h>
13 : : #include <sys/epoll.h>
14 : :
15 : : #include "compiler.h"
16 : : #include "types.h"
17 : : #include "eventpoll.h"
18 : : #include "proc_parse.h"
19 : : #include "crtools.h"
20 : : #include "image.h"
21 : : #include "util.h"
22 : : #include "log.h"
23 : :
24 : : #include "protobuf.h"
25 : : #include "protobuf/eventpoll.pb-c.h"
26 : :
27 : : #undef LOG_PREFIX
28 : : #define LOG_PREFIX "epoll: "
29 : :
30 : : struct eventpoll_file_info {
31 : : EventpollFileEntry *efe;
32 : : struct file_desc d;
33 : : };
34 : :
35 : : struct eventpoll_tfd_file_info {
36 : : EventpollTfdEntry *tdefe;
37 : : struct list_head list;
38 : : };
39 : :
40 : : static LIST_HEAD(eventpoll_tfds);
41 : :
42 : : /* Checks if file desciptor @lfd is eventfd */
43 : 6 : int is_eventpoll_link(int lfd)
44 : : {
45 : 6 : return is_anon_link_type(lfd, "[eventpoll]");
46 : : }
47 : :
48 : 7 : static void pr_info_eventpoll_tfd(char *action, EventpollTfdEntry *e)
49 : : {
50 : 7 : pr_info("%seventpoll-tfd: id %#08x tfd %#08x events %#08x data %#016lx\n",
51 : : action, e->id, e->tfd, e->events, e->data);
52 : 7 : }
53 : :
54 : 7 : static void pr_info_eventpoll(char *action, EventpollFileEntry *e)
55 : : {
56 : 7 : pr_info("%seventpoll: id %#08x flags %#04x\n", action, e->id, e->flags);
57 : 7 : }
58 : :
59 : 0 : void show_eventpoll_tfd(int fd, struct cr_options *o)
60 : : {
61 : 0 : pb_show_plain(fd, PB_EVENTPOLL_TFD);
62 : 0 : }
63 : :
64 : 0 : void show_eventpoll(int fd, struct cr_options *o)
65 : : {
66 : 0 : pb_show_plain(fd, PB_EVENTPOLL);
67 : 0 : }
68 : :
69 : 2 : static int dump_eventpoll_entry(union fdinfo_entries *e, void *arg)
70 : : {
71 : 2 : EventpollTfdEntry *efd = &e->epl;
72 : :
73 : 2 : efd->id = *(u32 *)arg;
74 : 2 : pr_info_eventpoll_tfd("Dumping: ", efd);
75 : 2 : return pb_write_one(fdset_fd(glob_fdset, CR_FD_EVENTPOLL_TFD),
76 : : efd, PB_EVENTPOLL_TFD);
77 : : }
78 : :
79 : 2 : static int dump_one_eventpoll(int lfd, u32 id, const struct fd_parms *p)
80 : : {
81 : 2 : EventpollFileEntry e = EVENTPOLL_FILE_ENTRY__INIT;
82 : :
83 : 2 : e.id = id;
84 : 2 : e.flags = p->flags;
85 : 2 : e.fown = (FownEntry *)&p->fown;
86 : :
87 : 2 : pr_info_eventpoll("Dumping ", &e);
88 [ + - ]: 2 : if (pb_write_one(fdset_fd(glob_fdset, CR_FD_EVENTPOLL),
89 : : &e, PB_EVENTPOLL))
90 : : return -1;
91 : :
92 : 2 : return parse_fdinfo(lfd, FD_TYPES__EVENTPOLL, dump_eventpoll_entry, &id);
93 : : }
94 : :
95 : : static const struct fdtype_ops eventpoll_ops = {
96 : : .type = FD_TYPES__EVENTPOLL,
97 : : .dump = dump_one_eventpoll,
98 : : };
99 : :
100 : 2 : int dump_eventpoll(struct fd_parms *p, int lfd, const struct cr_fdset *set)
101 : : {
102 : 2 : return do_dump_gen_file(p, lfd, &eventpoll_ops, set);
103 : : }
104 : :
105 : 2 : static int eventpoll_open(struct file_desc *d)
106 : : {
107 : : struct eventpoll_file_info *info;
108 : : int tmp;
109 : :
110 : 2 : info = container_of(d, struct eventpoll_file_info, d);
111 : :
112 : 2 : pr_info_eventpoll("Restore ", info->efe);
113 : :
114 : 2 : tmp = epoll_create(1);
115 [ - + ]: 2 : if (tmp < 0) {
116 : 0 : pr_perror("Can't create epoll %#08x",
117 : : info->efe->id);
118 : 0 : return -1;
119 : : }
120 : :
121 [ - + ]: 2 : if (rst_file_params(tmp, info->efe->fown, info->efe->flags)) {
122 : 0 : pr_perror("Can't restore file params on epoll %#08x",
123 : : info->efe->id);
124 : : goto err_close;
125 : : }
126 : :
127 : : return tmp;
128 : : err_close:
129 : 0 : close(tmp);
130 : 2 : return -1;
131 : : }
132 : :
133 : 2 : static int eventpoll_post_open(struct file_desc *d, int fd)
134 : : {
135 : : int ret;
136 : : struct eventpoll_tfd_file_info *td_info;
137 : : struct eventpoll_file_info *info;
138 : :
139 : 2 : info = container_of(d, struct eventpoll_file_info, d);
140 : :
141 [ + + ]: 4 : list_for_each_entry(td_info, &eventpoll_tfds, list) {
142 : : struct epoll_event event;
143 : :
144 [ - + ]: 2 : if (td_info->tdefe->id != info->efe->id)
145 : 0 : continue;
146 : :
147 : 2 : pr_info_eventpoll_tfd("Restore ", td_info->tdefe);
148 : :
149 : 2 : event.events = td_info->tdefe->events;
150 : 2 : event.data.u64 = td_info->tdefe->data;
151 : 2 : ret = epoll_ctl(fd, EPOLL_CTL_ADD, td_info->tdefe->tfd, &event);
152 [ - + ]: 2 : if (ret) {
153 : 2 : pr_perror("Can't add event on %#08x", info->efe->id);
154 : : return -1;
155 : : }
156 : : }
157 : :
158 : : return 0;
159 : : }
160 : :
161 : 3 : static struct list_head *eventpoll_select_list(struct file_desc *d, struct rst_info *ri)
162 : : {
163 : 3 : return &ri->eventpoll;
164 : : }
165 : :
166 : : static struct file_desc_ops desc_ops = {
167 : : .type = FD_TYPES__EVENTPOLL,
168 : : .open = eventpoll_open,
169 : : .post_open = eventpoll_post_open,
170 : : .select_ps_list = eventpoll_select_list,
171 : : };
172 : :
173 : 3 : static int collect_one_epoll_tfd(void *o, ProtobufCMessage *msg)
174 : : {
175 : 3 : struct eventpoll_tfd_file_info *info = o;
176 : :
177 : 3 : info->tdefe = pb_msg(msg, EventpollTfdEntry);
178 : 3 : list_add(&info->list, &eventpoll_tfds);
179 : 3 : pr_info_eventpoll_tfd("Collected ", info->tdefe);
180 : :
181 : 3 : return 0;
182 : : }
183 : :
184 : 3 : static int collect_one_epoll(void *o, ProtobufCMessage *msg)
185 : : {
186 : 3 : struct eventpoll_file_info *info = o;
187 : :
188 : 3 : info->efe = pb_msg(msg, EventpollFileEntry);
189 : 3 : file_desc_add(&info->d, info->efe->id, &desc_ops);
190 : 3 : pr_info_eventpoll("Collected ", info->efe);
191 : :
192 : 3 : return 0;
193 : : }
194 : :
195 : 355 : int collect_eventpoll(void)
196 : : {
197 : : int ret;
198 : :
199 : 355 : ret = collect_image(CR_FD_EVENTPOLL_TFD, PB_EVENTPOLL_TFD,
200 : : sizeof(struct eventpoll_tfd_file_info),
201 : : collect_one_epoll_tfd);
202 [ + - ]: 355 : if (!ret)
203 : 355 : ret = collect_image(CR_FD_EVENTPOLL, PB_EVENTPOLL,
204 : : sizeof(struct eventpoll_file_info),
205 : : collect_one_epoll);
206 : :
207 : 355 : return ret;
208 : 10 : }
|