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) ...@@ -103,6 +103,9 @@ static int root_prepare_shared(void)
if (prepare_shared_tty()) if (prepare_shared_tty())
return -1; return -1;
if (prepare_shared_reg_files())
return -1;
if (collect_reg_files()) if (collect_reg_files())
return -1; return -1;
......
...@@ -43,6 +43,8 @@ struct ghost_file { ...@@ -43,6 +43,8 @@ struct ghost_file {
static u32 ghost_file_ids = 1; static u32 ghost_file_ids = 1;
static LIST_HEAD(ghost_files); static LIST_HEAD(ghost_files);
static mutex_t *ghost_file_mutex;
/* /*
* This constant is selected without any calculations. Just do not * This constant is selected without any calculations. Just do not
* want to pick up too big files with us in the image. * want to pick up too big files with us in the image.
...@@ -351,12 +353,14 @@ static int open_path(struct file_desc *d, ...@@ -351,12 +353,14 @@ static int open_path(struct file_desc *d,
rfi = container_of(d, struct reg_file_info, 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) { if (link(rfi->ghost->path, rfi->path) < 0) {
pr_perror("Can't link %s -> %s\n", pr_perror("Can't link %s -> %s\n",
rfi->ghost->path, rfi->path); rfi->ghost->path, rfi->path);
return -1; return -1;
} }
}
tmp = open_cb(rfi, arg); tmp = open_cb(rfi, arg);
if (tmp < 0) { if (tmp < 0) {
...@@ -370,6 +374,7 @@ static int open_path(struct file_desc *d, ...@@ -370,6 +374,7 @@ static int open_path(struct file_desc *d,
pr_info("Unlink the ghost %s\n", rfi->ghost->path); pr_info("Unlink the ghost %s\n", rfi->ghost->path);
unlink(rfi->ghost->path); unlink(rfi->ghost->path);
} }
mutex_unlock(ghost_file_mutex);
} }
if (restore_fown(tmp, rfi->rfe->fown)) if (restore_fown(tmp, rfi->rfe->fown))
...@@ -438,6 +443,16 @@ static int collect_one_regfile(void *o, ProtobufCMessage *base) ...@@ -438,6 +443,16 @@ static int collect_one_regfile(void *o, ProtobufCMessage *base)
return 0; 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 collect_reg_files(void)
{ {
int ret; int ret;
......
...@@ -24,6 +24,8 @@ extern int open_path_by_id(u32 id, int (*open_cb)(struct reg_file_info *, void * ...@@ -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 void clear_ghost_files(void);
extern int collect_reg_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_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); 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