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;
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 i;
fdinfo_list = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, 0, 0);
if (fdinfo_list == MAP_FAILED) {
pr_perror("Can't map fdinfo_list");
return -1;
}
for (i = 0; i < FDESC_HASH_SIZE; i++)
INIT_LIST_HEAD(&file_descs[i]);
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);
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)
......@@ -51,71 +82,37 @@ struct fdinfo_list_entry *file_master(struct file_desc *d)
struct reg_file_info {
struct reg_file_entry rfe;
char *path;
struct list_head list;
struct file_desc d;
};
#define REG_FILES_HSIZE 32
static struct list_head reg_files[REG_FILES_HSIZE];
void show_saved_files(void)
{
int i;
struct reg_file_info *rfi;
struct file_desc *fd;
pr_info("Reg files:\n");
for (i = 0; i < REG_FILES_HSIZE; i++)
list_for_each_entry(rfi, &reg_files[i], list) {
pr_info("File descs:\n");
for (i = 0; i < FDESC_HASH_SIZE; i++)
list_for_each_entry(fd, &file_descs[i], hash) {
struct fdinfo_list_entry *le;
pr_info(" `- ID %x\n", rfi->rfe.id);
list_for_each_entry(le, &rfi->d.fd_info_head, list)
pr_info(" `- type %d ID %x\n", fd->type, fd->id);
list_for_each_entry(le, &fd->fd_info_head, list)
pr_info(" `- FD %d pid %d\n", le->fd, le->pid);
}
}
static struct reg_file_info *find_reg_file(int id)
{
int chain;
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);
struct file_desc *fd;
BUG_ON(1);
return NULL;
fd = find_file_desc_raw(FDINFO_REG, id);
return container_of(fd, struct reg_file_info, d);
}
int collect_reg_files(void)
{
struct reg_file_info *rfi = NULL;
int fd, ret = -1, chain;
for (chain = 0; chain < REG_FILES_HSIZE; chain++)
INIT_LIST_HEAD(&reg_files[chain]);
int fd, ret = -1;
fd = open_image_ro(CR_FD_REG_FILES);
if (fd < 0)
......@@ -147,9 +144,7 @@ int collect_reg_files(void)
rfi->path[len] = '\0';
pr_info("Collected [%s] ID %x\n", rfi->path, rfi->rfe.id);
file_desc_add(&rfi->d);
chain = rfi->rfe.id % REG_FILES_HSIZE;
list_add_tail(&rfi->list, &reg_files[chain]);
file_desc_add(&rfi->d, FDINFO_REG, rfi->rfe.id);
}
if (rfi) {
......
......@@ -40,11 +40,15 @@ struct fdinfo_list_entry {
};
struct file_desc {
int type;
u32 id;
struct list_head hash;
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 file_desc *find_file_desc_raw(int type, u32 id);
extern void transport_name_gen(struct sockaddr_un *addr,
int *len, int pid, long fd);
......@@ -62,7 +66,6 @@ struct file_desc;
extern int collect_pipes(void);
extern void mark_pipe_master(void);
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,
struct file_desc *d);
......
......@@ -12,8 +12,6 @@ extern int dump_socket(struct fd_parms *p, int lfd,
struct fdinfo_list_entry;
struct file_desc;
struct file_desc *find_inetsk_desc(int id);
struct file_desc *find_unixsk_desc(int id);
struct fdinfo_entry;
extern int unixsk_should_open_transport(struct fdinfo_entry *,
struct file_desc *);
......
......@@ -29,20 +29,10 @@ static LIST_HEAD(pipes);
static struct pipe_info *find_pipe(int id)
{
struct pipe_info *pi;
struct file_desc *fd;
list_for_each_entry(pi, &pipes, list)
if (pi->pe.id == id)
return pi;
return NULL;
}
struct file_desc *find_pipe_desc(int id)
{
struct pipe_info *pi;
pi = find_pipe(id);
return &pi->d;
fd = find_file_desc_raw(FDINFO_PIPE, id);
return container_of(fd, struct pipe_info, d);
}
int collect_pipes(void)
......@@ -68,7 +58,8 @@ int collect_pipes(void)
pr_info("Collected pipe entry ID %x PIPE ID %x\n",
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)
if (pi->pe.pipe_id == tmp->pe.pipe_id)
......
......@@ -800,20 +800,10 @@ static LIST_HEAD(unix_sockets);
static struct unix_sk_info *find_unix_sk(int id)
{
struct unix_sk_info *ui;
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;
struct file_desc *d;
ui = find_unix_sk(id);
return &ui->d;
d = find_file_desc_raw(FDINFO_UNIXSK, id);
return container_of(d, struct unix_sk_info, d);
}
struct sk_packet {
......@@ -901,40 +891,13 @@ static int restore_socket_queue(int fd, unsigned int peer_id)
struct inet_sk_info {
struct inet_sk_entry ie;
struct list_head list;
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)
{
struct inet_sk_info *ii = NULL;
int fd, ret = -1, chain;
for (chain = 0; chain < INET_SK_HSIZE; chain++)
INIT_LIST_HEAD(&inet_sockets[chain]);
int fd, ret = -1;
fd = open_image_ro(CR_FD_INETSK);
if (fd < 0)
......@@ -950,9 +913,7 @@ int collect_inet_sockets(void)
if (ret <= 0)
break;
file_desc_add(&ii->d);
chain = ii->ie.id % INET_SK_HSIZE;
list_add_tail(&ii->list, &inet_sockets[chain]);
file_desc_add(&ii->d, FDINFO_INETSK, ii->ie.id);
}
if (ii)
......@@ -1454,8 +1415,8 @@ int collect_unix_sockets(void)
ui->peer = NULL;
ui->flags = 0;
file_desc_add(&ui->d);
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);
}
......
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