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 "asm/types.h"
17 : : #include "fdset.h"
18 : : #include "rst_info.h"
19 : : #include "eventpoll.h"
20 : : #include "proc_parse.h"
21 : : #include "image.h"
22 : : #include "util.h"
23 : : #include "log.h"
24 : :
25 : : #include "protobuf.h"
26 : : #include "protobuf/eventpoll.pb-c.h"
27 : :
28 : : #undef LOG_PREFIX
29 : : #define LOG_PREFIX "epoll: "
30 : :
31 : : struct eventpoll_file_info {
32 : : EventpollFileEntry *efe;
33 : : struct file_desc d;
34 : : };
35 : :
36 : : struct eventpoll_tfd_file_info {
37 : : EventpollTfdEntry *tdefe;
38 : : struct list_head list;
39 : : };
40 : :
41 : : static LIST_HEAD(eventpoll_tfds);
42 : :
43 : : /* Checks if file descriptor @lfd is eventfd */
44 : 16 : int is_eventpoll_link(char *link)
45 : : {
46 : 16 : return is_anon_link_type(link, "[eventpoll]");
47 : : }
48 : :
49 : 8 : static void pr_info_eventpoll_tfd(char *action, EventpollTfdEntry *e)
50 : : {
51 : 8 : pr_info("%seventpoll-tfd: id %#08x tfd %#08x events %#08x data %#016"PRIx64"\n",
52 : : action, e->id, e->tfd, e->events, e->data);
53 : 8 : }
54 : :
55 : : static void pr_info_eventpoll(char *action, EventpollFileEntry *e)
56 : : {
57 : 8 : pr_info("%seventpoll: id %#08x flags %#04x\n", action, e->id, e->flags);
58 : : }
59 : :
60 : 4 : static int dump_eventpoll_entry(union fdinfo_entries *e, void *arg)
61 : : {
62 : 4 : EventpollTfdEntry *efd = &e->epl;
63 : :
64 : 4 : efd->id = *(u32 *)arg;
65 : 4 : pr_info_eventpoll_tfd("Dumping: ", efd);
66 : 4 : return pb_write_one(fdset_fd(glob_fdset, CR_FD_EVENTPOLL_TFD),
67 : : efd, PB_EVENTPOLL_TFD);
68 : : }
69 : :
70 : 4 : static int dump_one_eventpoll(int lfd, u32 id, const struct fd_parms *p)
71 : : {
72 : 4 : EventpollFileEntry e = EVENTPOLL_FILE_ENTRY__INIT;
73 : :
74 : 4 : e.id = id;
75 : 4 : e.flags = p->flags;
76 : 4 : e.fown = (FownEntry *)&p->fown;
77 : :
78 : : pr_info_eventpoll("Dumping ", &e);
79 [ + - ]: 4 : if (pb_write_one(fdset_fd(glob_fdset, CR_FD_EVENTPOLL_FILE),
80 : : &e, PB_EVENTPOLL_FILE))
81 : : return -1;
82 : :
83 : 4 : return parse_fdinfo(lfd, FD_TYPES__EVENTPOLL, dump_eventpoll_entry, &id);
84 : : }
85 : :
86 : : const struct fdtype_ops eventpoll_dump_ops = {
87 : : .type = FD_TYPES__EVENTPOLL,
88 : : .dump = dump_one_eventpoll,
89 : : };
90 : :
91 : 2 : static int eventpoll_open(struct file_desc *d)
92 : : {
93 : : struct eventpoll_file_info *info;
94 : : int tmp;
95 : :
96 : : info = container_of(d, struct eventpoll_file_info, d);
97 : :
98 : 2 : pr_info_eventpoll("Restore ", info->efe);
99 : :
100 : 2 : tmp = epoll_create(1);
101 [ - + ]: 2 : if (tmp < 0) {
102 : 0 : pr_perror("Can't create epoll %#08x",
103 : : info->efe->id);
104 : 0 : return -1;
105 : : }
106 : :
107 [ - + ]: 2 : if (rst_file_params(tmp, info->efe->fown, info->efe->flags)) {
108 : 0 : pr_perror("Can't restore file params on epoll %#08x",
109 : : info->efe->id);
110 : : goto err_close;
111 : : }
112 : :
113 : : return tmp;
114 : : err_close:
115 : 0 : close(tmp);
116 : 0 : return -1;
117 : : }
118 : :
119 : 2 : static int eventpoll_post_open(struct file_desc *d, int fd)
120 : : {
121 : : int ret;
122 : : struct eventpoll_tfd_file_info *td_info;
123 : : struct eventpoll_file_info *info;
124 : :
125 : : info = container_of(d, struct eventpoll_file_info, d);
126 : :
127 [ + + ]: 4 : list_for_each_entry(td_info, &eventpoll_tfds, list) {
128 : : struct epoll_event event;
129 : :
130 [ - + ]: 2 : if (td_info->tdefe->id != info->efe->id)
131 : 0 : continue;
132 : :
133 : 2 : pr_info_eventpoll_tfd("Restore ", td_info->tdefe);
134 : :
135 : 2 : event.events = td_info->tdefe->events;
136 : 2 : event.data.u64 = td_info->tdefe->data;
137 : 2 : ret = epoll_ctl(fd, EPOLL_CTL_ADD, td_info->tdefe->tfd, &event);
138 [ - + ]: 2 : if (ret) {
139 : 0 : pr_perror("Can't add event on %#08x", info->efe->id);
140 : 2 : return -1;
141 : : }
142 : : }
143 : :
144 : : return 0;
145 : : }
146 : :
147 : 2 : static void eventpoll_collect_fd(struct file_desc *d,
148 : : struct fdinfo_list_entry *fle, struct rst_info *ri)
149 : : {
150 : 2 : list_add_tail(&fle->ps_list, &ri->eventpoll);
151 : 2 : }
152 : :
153 : : static struct file_desc_ops desc_ops = {
154 : : .type = FD_TYPES__EVENTPOLL,
155 : : .open = eventpoll_open,
156 : : .post_open = eventpoll_post_open,
157 : : .collect_fd = eventpoll_collect_fd,
158 : : };
159 : :
160 : 2 : static int collect_one_epoll_tfd(void *o, ProtobufCMessage *msg)
161 : : {
162 : : struct eventpoll_tfd_file_info *info = o;
163 : :
164 : 2 : info->tdefe = pb_msg(msg, EventpollTfdEntry);
165 : 2 : list_add(&info->list, &eventpoll_tfds);
166 : 2 : pr_info_eventpoll_tfd("Collected ", info->tdefe);
167 : :
168 : 2 : return 0;
169 : : }
170 : :
171 : : struct collect_image_info epoll_tfd_cinfo = {
172 : : .fd_type = CR_FD_EVENTPOLL_TFD,
173 : : .pb_type = PB_EVENTPOLL_TFD,
174 : : .priv_size = sizeof(struct eventpoll_tfd_file_info),
175 : : .collect = collect_one_epoll_tfd,
176 : : };
177 : :
178 : 2 : static int collect_one_epoll(void *o, ProtobufCMessage *msg)
179 : : {
180 : : struct eventpoll_file_info *info = o;
181 : :
182 : 2 : info->efe = pb_msg(msg, EventpollFileEntry);
183 : 2 : pr_info_eventpoll("Collected ", info->efe);
184 : 2 : return file_desc_add(&info->d, info->efe->id, &desc_ops);
185 : : }
186 : :
187 : : struct collect_image_info epoll_cinfo = {
188 : : .fd_type = CR_FD_EVENTPOLL_FILE,
189 : : .pb_type = PB_EVENTPOLL_FILE,
190 : : .priv_size = sizeof(struct eventpoll_file_info),
191 : : .collect = collect_one_epoll,
192 : : };
|