Commit 997b295d authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Pavel Emelyanov

files-reg: Use global mutex to serialize ghost file creation

Otherwise there is a race between files with same names:

link(name -> ghost)                link(name->ghost)
open(name)
unlink(name)
                                   open(name) -> ENOENT
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 08e559b3
......@@ -103,6 +103,9 @@ static int root_prepare_shared(void)
if (prepare_shared_tty())
return -1;
if (prepare_shared_reg_files())
return -1;
if (collect_reg_files())
return -1;
......
......@@ -43,6 +43,8 @@ struct ghost_file {
static u32 ghost_file_ids = 1;
static LIST_HEAD(ghost_files);
static mutex_t *ghost_file_mutex;
/*
* This constant is selected without any calculations. Just do not
* want to pick up too big files with us in the image.
......@@ -351,12 +353,14 @@ static int open_path(struct file_desc *d,
rfi = container_of(d, struct reg_file_info, d);
if (rfi->ghost)
if (rfi->ghost) {
mutex_lock(ghost_file_mutex);
if (link(rfi->ghost->path, rfi->path) < 0) {
pr_perror("Can't link %s -> %s\n",
rfi->ghost->path, rfi->path);
return -1;
}
}
tmp = open_cb(rfi, arg);
if (tmp < 0) {
......@@ -370,6 +374,7 @@ static int open_path(struct file_desc *d,
pr_info("Unlink the ghost %s\n", rfi->ghost->path);
unlink(rfi->ghost->path);
}
mutex_unlock(ghost_file_mutex);
}
if (restore_fown(tmp, rfi->rfe->fown))
......@@ -438,6 +443,16 @@ static int collect_one_regfile(void *o, ProtobufCMessage *base)
return 0;
}
int prepare_shared_reg_files(void)
{
ghost_file_mutex = shmalloc(sizeof(*ghost_file_mutex));
if (!ghost_file_mutex)
return -1;
mutex_init(ghost_file_mutex);
return 0;
}
int collect_reg_files(void)
{
int ret;
......
......@@ -24,6 +24,8 @@ extern int open_path_by_id(u32 id, int (*open_cb)(struct reg_file_info *, void *
extern void clear_ghost_files(void);
extern int collect_reg_files(void);
extern int prepare_shared_reg_files(void);
extern int dump_reg_file(struct fd_parms *p, int lfd, const struct cr_fdset *cr_fdset);
extern int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p);
......
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