Commit 94a11df0 authored by Pavel Emelyanov's avatar Pavel Emelyanov

inet: Collect inet sockets early on restore

Same as previous patch -- pull inet sockets in and store in the hash for the same reasons.
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 84678526
...@@ -414,6 +414,9 @@ static int prepare_shared(int ps_fd) ...@@ -414,6 +414,9 @@ static int prepare_shared(int ps_fd)
if (collect_reg_files()) if (collect_reg_files())
return -1; return -1;
if (collect_inet_sockets())
return -1;
while (1) { while (1) {
struct pstree_entry e; struct pstree_entry e;
......
...@@ -11,6 +11,7 @@ extern int dump_socket(struct fd_parms *p, int lfd, ...@@ -11,6 +11,7 @@ extern int dump_socket(struct fd_parms *p, int lfd,
const struct cr_fdset *cr_fdset); const struct cr_fdset *cr_fdset);
extern int collect_sockets(void); extern int collect_sockets(void);
extern int collect_inet_sockets(void);
extern int prepare_sockets(int pid); extern int prepare_sockets(int pid);
struct fdinfo_entry; struct fdinfo_entry;
extern int open_inet_sk(struct fdinfo_entry *fe); extern int open_inet_sk(struct fdinfo_entry *fe);
......
...@@ -1240,31 +1240,56 @@ err: ...@@ -1240,31 +1240,56 @@ err:
return ret; return ret;
} }
static int read_inetsk_image(u32 id, struct inet_sk_entry *ie) struct inet_sk_info {
struct inet_sk_entry ie;
struct list_head list;
};
#define INET_SK_HSIZE 32
static struct list_head inet_sockets[INET_SK_HSIZE];
static struct inet_sk_info *find_inet_sk(int id)
{ {
int ifd; int chain;
struct inet_sk_info *ii;
ifd = open_image_ro(CR_FD_INETSK); chain = id % INET_SK_HSIZE;
if (ifd < 0) list_for_each_entry(ii, &inet_sockets[chain], list)
return -1; if (ii->ie.id == id)
return ii;
return NULL;
}
while (1) { int collect_inet_sockets(void)
int ret; {
struct inet_sk_info *ii = NULL;
int fd, ret = -1, chain;
ret = read_img_eof(ifd, ie); for (chain = 0; chain < INET_SK_HSIZE; chain++)
if (ret < 0) INIT_LIST_HEAD(&inet_sockets[chain]);
return ret;
if (ret == 0) { fd = open_image_ro(CR_FD_INETSK);
pr_err("Can't find inet sk %u\n", id); if (fd < 0)
return -1; return -1;
}
if (ie->id == id) while (1) {
ii = xmalloc(sizeof(*ii));
ret = -1;
if (!ii)
break; break;
ret = read_img_eof(fd, &ii->ie);
if (ret <= 0)
break;
chain = ii->ie.id % INET_SK_HSIZE;
list_add_tail(&ii->list, &inet_sockets[chain]);
} }
close(ifd); if (ii)
xfree(ii);
close(fd);
return 0; return 0;
} }
...@@ -1272,24 +1297,27 @@ int open_inet_sk(struct fdinfo_entry *fe) ...@@ -1272,24 +1297,27 @@ int open_inet_sk(struct fdinfo_entry *fe)
{ {
int sk; int sk;
struct sockaddr_in addr; struct sockaddr_in addr;
struct inet_sk_entry ie; struct inet_sk_info *ii;
if (read_inetsk_image(fe->id, &ie)) ii = find_inet_sk(fe->id);
if (ii == NULL) {
pr_err("Can't find inet sk %u\n", fe->id);
return -1; return -1;
}
show_one_inet_img("Restore", &ie); show_one_inet_img("Restore", &ii->ie);
if (ie.family != AF_INET) { if (ii->ie.family != AF_INET) {
pr_err("Unsupported socket family: %d\n", ie.family); pr_err("Unsupported socket family: %d\n", ii->ie.family);
return -1; return -1;
} }
if ((ie.type != SOCK_STREAM) && (ie.type != SOCK_DGRAM)) { if ((ii->ie.type != SOCK_STREAM) && (ii->ie.type != SOCK_DGRAM)) {
pr_err("Unsupported socket type: %d\n", ie.type); pr_err("Unsupported socket type: %d\n", ii->ie.type);
return -1; return -1;
} }
sk = socket(ie.family, ie.type, ie.proto); sk = socket(ii->ie.family, ii->ie.type, ii->ie.proto);
if (sk < 0) { if (sk < 0) {
pr_perror("Can't create unix socket"); pr_perror("Can't create unix socket");
return -1; return -1;
...@@ -1300,37 +1328,37 @@ int open_inet_sk(struct fdinfo_entry *fe) ...@@ -1300,37 +1328,37 @@ int open_inet_sk(struct fdinfo_entry *fe)
* bind() and listen(), and that's all. * bind() and listen(), and that's all.
*/ */
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.sin_family = ie.family; addr.sin_family = ii->ie.family;
addr.sin_port = htons(ie.src_port); addr.sin_port = htons(ii->ie.src_port);
memcpy(&addr.sin_addr.s_addr, ie.src_addr, sizeof(unsigned int) * 4); memcpy(&addr.sin_addr.s_addr, ii->ie.src_addr, sizeof(unsigned int) * 4);
if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) == -1) { if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
pr_perror("Can't bind to a socket"); pr_perror("Can't bind to a socket");
goto err; goto err;
} }
if (ie.state == TCP_LISTEN) { if (ii->ie.state == TCP_LISTEN) {
if (ie.proto != IPPROTO_TCP) { if (ii->ie.proto != IPPROTO_TCP) {
pr_err("Wrong socket in listen state %d\n", ie.proto); pr_err("Wrong socket in listen state %d\n", ii->ie.proto);
goto err; goto err;
} }
if (listen(sk, ie.backlog) == -1) { if (listen(sk, ii->ie.backlog) == -1) {
pr_perror("Can't listen on a socket"); pr_perror("Can't listen on a socket");
goto err; goto err;
} }
} }
if (ie.state == TCP_ESTABLISHED) { if (ii->ie.state == TCP_ESTABLISHED) {
if (ie.proto != IPPROTO_UDP) { if (ii->ie.proto != IPPROTO_UDP) {
pr_err("Connected TCP socket in image\n"); pr_err("Connected TCP socket in image\n");
goto err; goto err;
} }
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.sin_family = ie.family; addr.sin_family = ii->ie.family;
addr.sin_port = htons(ie.dst_port); addr.sin_port = htons(ii->ie.dst_port);
memcpy(&addr.sin_addr.s_addr, ie.dst_addr, sizeof(ie.dst_addr)); memcpy(&addr.sin_addr.s_addr, ii->ie.dst_addr, sizeof(ii->ie.dst_addr));
if (connect(sk, (struct sockaddr *)&addr, sizeof(addr)) == -1) { if (connect(sk, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
pr_perror("Can't connect UDP socket back"); pr_perror("Can't connect UDP socket back");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment