Commit 3c174a88 authored by Pavel Emelyanov's avatar Pavel Emelyanov

files: Generalize fd restore, make file_desc common hash

No need in per-type hash tables and search routines. We can
handle it via generic file_desc structure. Some more thoughts
on unixsk and pipe lists are still required :(
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 527b67b9
...@@ -26,19 +26,50 @@ static int nr_fdinfo_list; ...@@ -26,19 +26,50 @@ static int nr_fdinfo_list;
static struct fmap_fd *fmap_fds; static struct fmap_fd *fmap_fds;
#define FDESC_HASH_SIZE 64
static struct list_head file_descs[FDESC_HASH_SIZE];
int prepare_shared_fdinfo(void) int prepare_shared_fdinfo(void)
{ {
int i;
fdinfo_list = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, 0, 0); fdinfo_list = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, 0, 0);
if (fdinfo_list == MAP_FAILED) { if (fdinfo_list == MAP_FAILED) {
pr_perror("Can't map fdinfo_list"); pr_perror("Can't map fdinfo_list");
return -1; return -1;
} }
for (i = 0; i < FDESC_HASH_SIZE; i++)
INIT_LIST_HEAD(&file_descs[i]);
return 0; return 0;
} }
void file_desc_add(struct file_desc *d) void file_desc_add(struct file_desc *d, int type, u32 id)
{ {
d->type = type;
d->id = id;
INIT_LIST_HEAD(&d->fd_info_head); INIT_LIST_HEAD(&d->fd_info_head);
list_add_tail(&d->hash, &file_descs[id % FDESC_HASH_SIZE]);
}
struct file_desc *find_file_desc_raw(int type, u32 id)
{
struct file_desc *d;
struct list_head *chain;
chain = &file_descs[id % FDESC_HASH_SIZE];
list_for_each_entry(d, chain, hash)
if (d->type == type && d->id == id)
return d;
return NULL;
}
static inline struct file_desc *find_file_desc(struct fdinfo_entry *fe)
{
return find_file_desc_raw(fe->type, fe->id);
} }
struct fdinfo_list_entry *file_master(struct file_desc *d) struct fdinfo_list_entry *file_master(struct file_desc *d)
...@@ -51,71 +82,37 @@ struct fdinfo_list_entry *file_master(struct file_desc *d) ...@@ -51,71 +82,37 @@ struct fdinfo_list_entry *file_master(struct file_desc *d)
struct reg_file_info { struct reg_file_info {
struct reg_file_entry rfe; struct reg_file_entry rfe;
char *path; char *path;
struct list_head list;
struct file_desc d; struct file_desc d;
}; };
#define REG_FILES_HSIZE 32
static struct list_head reg_files[REG_FILES_HSIZE];
void show_saved_files(void) void show_saved_files(void)
{ {
int i; int i;
struct reg_file_info *rfi; struct file_desc *fd;
pr_info("Reg files:\n"); pr_info("File descs:\n");
for (i = 0; i < REG_FILES_HSIZE; i++) for (i = 0; i < FDESC_HASH_SIZE; i++)
list_for_each_entry(rfi, &reg_files[i], list) { list_for_each_entry(fd, &file_descs[i], hash) {
struct fdinfo_list_entry *le; struct fdinfo_list_entry *le;
pr_info(" `- ID %x\n", rfi->rfe.id); pr_info(" `- type %d ID %x\n", fd->type, fd->id);
list_for_each_entry(le, &rfi->d.fd_info_head, list) list_for_each_entry(le, &fd->fd_info_head, list)
pr_info(" `- FD %d pid %d\n", le->fd, le->pid); pr_info(" `- FD %d pid %d\n", le->fd, le->pid);
} }
} }
static struct reg_file_info *find_reg_file(int id) static struct reg_file_info *find_reg_file(int id)
{ {
int chain; struct file_desc *fd;
struct reg_file_info *rfi;
chain = id % REG_FILES_HSIZE;
list_for_each_entry(rfi, &reg_files[chain], list)
if (rfi->rfe.id == id)
return rfi;
return NULL;
}
static struct file_desc *find_reg_desc(int id)
{
struct reg_file_info *rfi;
rfi = find_reg_file(id);
return &rfi->d;
}
static struct file_desc *find_file_desc(struct fdinfo_entry *fe)
{
if (fe->type == FDINFO_REG)
return find_reg_desc(fe->id);
if (fe->type == FDINFO_INETSK)
return find_inetsk_desc(fe->id);
if (fe->type == FDINFO_PIPE)
return find_pipe_desc(fe->id);
if (fe->type == FDINFO_UNIXSK)
return find_unixsk_desc(fe->id);
BUG_ON(1); fd = find_file_desc_raw(FDINFO_REG, id);
return NULL; return container_of(fd, struct reg_file_info, d);
} }
int collect_reg_files(void) int collect_reg_files(void)
{ {
struct reg_file_info *rfi = NULL; struct reg_file_info *rfi = NULL;
int fd, ret = -1, chain; int fd, ret = -1;
for (chain = 0; chain < REG_FILES_HSIZE; chain++)
INIT_LIST_HEAD(&reg_files[chain]);
fd = open_image_ro(CR_FD_REG_FILES); fd = open_image_ro(CR_FD_REG_FILES);
if (fd < 0) if (fd < 0)
...@@ -147,9 +144,7 @@ int collect_reg_files(void) ...@@ -147,9 +144,7 @@ int collect_reg_files(void)
rfi->path[len] = '\0'; rfi->path[len] = '\0';
pr_info("Collected [%s] ID %x\n", rfi->path, rfi->rfe.id); pr_info("Collected [%s] ID %x\n", rfi->path, rfi->rfe.id);
file_desc_add(&rfi->d); file_desc_add(&rfi->d, FDINFO_REG, rfi->rfe.id);
chain = rfi->rfe.id % REG_FILES_HSIZE;
list_add_tail(&rfi->list, &reg_files[chain]);
} }
if (rfi) { if (rfi) {
......
...@@ -40,11 +40,15 @@ struct fdinfo_list_entry { ...@@ -40,11 +40,15 @@ struct fdinfo_list_entry {
}; };
struct file_desc { struct file_desc {
int type;
u32 id;
struct list_head hash;
struct list_head fd_info_head; struct list_head fd_info_head;
}; };
extern void file_desc_add(struct file_desc *d); extern void file_desc_add(struct file_desc *d, int type, u32 id);
extern struct fdinfo_list_entry *file_master(struct file_desc *d); extern struct fdinfo_list_entry *file_master(struct file_desc *d);
extern struct file_desc *find_file_desc_raw(int type, u32 id);
extern void transport_name_gen(struct sockaddr_un *addr, extern void transport_name_gen(struct sockaddr_un *addr,
int *len, int pid, long fd); int *len, int pid, long fd);
...@@ -62,7 +66,6 @@ struct file_desc; ...@@ -62,7 +66,6 @@ struct file_desc;
extern int collect_pipes(void); extern int collect_pipes(void);
extern void mark_pipe_master(void); extern void mark_pipe_master(void);
extern int open_pipe(struct file_desc *); extern int open_pipe(struct file_desc *);
struct file_desc *find_pipe_desc(int id);
extern int pipe_should_open_transport(struct fdinfo_entry *fe, extern int pipe_should_open_transport(struct fdinfo_entry *fe,
struct file_desc *d); struct file_desc *d);
......
...@@ -12,8 +12,6 @@ extern int dump_socket(struct fd_parms *p, int lfd, ...@@ -12,8 +12,6 @@ extern int dump_socket(struct fd_parms *p, int lfd,
struct fdinfo_list_entry; struct fdinfo_list_entry;
struct file_desc; struct file_desc;
struct file_desc *find_inetsk_desc(int id);
struct file_desc *find_unixsk_desc(int id);
struct fdinfo_entry; struct fdinfo_entry;
extern int unixsk_should_open_transport(struct fdinfo_entry *, extern int unixsk_should_open_transport(struct fdinfo_entry *,
struct file_desc *); struct file_desc *);
......
...@@ -29,20 +29,10 @@ static LIST_HEAD(pipes); ...@@ -29,20 +29,10 @@ static LIST_HEAD(pipes);
static struct pipe_info *find_pipe(int id) static struct pipe_info *find_pipe(int id)
{ {
struct pipe_info *pi; struct file_desc *fd;
list_for_each_entry(pi, &pipes, list) fd = find_file_desc_raw(FDINFO_PIPE, id);
if (pi->pe.id == id) return container_of(fd, struct pipe_info, d);
return pi;
return NULL;
}
struct file_desc *find_pipe_desc(int id)
{
struct pipe_info *pi;
pi = find_pipe(id);
return &pi->d;
} }
int collect_pipes(void) int collect_pipes(void)
...@@ -68,7 +58,8 @@ int collect_pipes(void) ...@@ -68,7 +58,8 @@ int collect_pipes(void)
pr_info("Collected pipe entry ID %x PIPE ID %x\n", pr_info("Collected pipe entry ID %x PIPE ID %x\n",
pi->pe.id, pi->pe.pipe_id); pi->pe.id, pi->pe.pipe_id);
file_desc_add(&pi->d);
file_desc_add(&pi->d, FDINFO_PIPE, pi->pe.id);
list_for_each_entry(tmp, &pipes, list) list_for_each_entry(tmp, &pipes, list)
if (pi->pe.pipe_id == tmp->pe.pipe_id) if (pi->pe.pipe_id == tmp->pe.pipe_id)
......
...@@ -800,20 +800,10 @@ static LIST_HEAD(unix_sockets); ...@@ -800,20 +800,10 @@ static LIST_HEAD(unix_sockets);
static struct unix_sk_info *find_unix_sk(int id) static struct unix_sk_info *find_unix_sk(int id)
{ {
struct unix_sk_info *ui; struct file_desc *d;
list_for_each_entry(ui, &unix_sockets, list)
if (ui->ue.id == id)
return ui;
return NULL;
}
struct file_desc *find_unixsk_desc(int id)
{
struct unix_sk_info *ui;
ui = find_unix_sk(id); d = find_file_desc_raw(FDINFO_UNIXSK, id);
return &ui->d; return container_of(d, struct unix_sk_info, d);
} }
struct sk_packet { struct sk_packet {
...@@ -901,40 +891,13 @@ static int restore_socket_queue(int fd, unsigned int peer_id) ...@@ -901,40 +891,13 @@ static int restore_socket_queue(int fd, unsigned int peer_id)
struct inet_sk_info { struct inet_sk_info {
struct inet_sk_entry ie; struct inet_sk_entry ie;
struct list_head list;
struct file_desc d; struct file_desc d;
}; };
#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 chain;
struct inet_sk_info *ii;
chain = id % INET_SK_HSIZE;
list_for_each_entry(ii, &inet_sockets[chain], list)
if (ii->ie.id == id)
return ii;
return NULL;
}
struct file_desc *find_inetsk_desc(int id)
{
struct inet_sk_info *ii;
ii = find_inet_sk(id);
return &ii->d;
}
int collect_inet_sockets(void) int collect_inet_sockets(void)
{ {
struct inet_sk_info *ii = NULL; struct inet_sk_info *ii = NULL;
int fd, ret = -1, chain; int fd, ret = -1;
for (chain = 0; chain < INET_SK_HSIZE; chain++)
INIT_LIST_HEAD(&inet_sockets[chain]);
fd = open_image_ro(CR_FD_INETSK); fd = open_image_ro(CR_FD_INETSK);
if (fd < 0) if (fd < 0)
...@@ -950,9 +913,7 @@ int collect_inet_sockets(void) ...@@ -950,9 +913,7 @@ int collect_inet_sockets(void)
if (ret <= 0) if (ret <= 0)
break; break;
file_desc_add(&ii->d); file_desc_add(&ii->d, FDINFO_INETSK, ii->ie.id);
chain = ii->ie.id % INET_SK_HSIZE;
list_add_tail(&ii->list, &inet_sockets[chain]);
} }
if (ii) if (ii)
...@@ -1454,8 +1415,8 @@ int collect_unix_sockets(void) ...@@ -1454,8 +1415,8 @@ int collect_unix_sockets(void)
ui->peer = NULL; ui->peer = NULL;
ui->flags = 0; ui->flags = 0;
file_desc_add(&ui->d);
pr_info(" `- Got %u peer %u\n", ui->ue.id, ui->ue.peer); pr_info(" `- Got %u peer %u\n", ui->ue.id, ui->ue.peer);
file_desc_add(&ui->d, FDINFO_UNIXSK, ui->ue.id);
list_add_tail(&ui->list, &unix_sockets); list_add_tail(&ui->list, &unix_sockets);
} }
......
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