Commit b146fe4a authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Pavel Emelyanov

inotify: Use ghost files if the watchee is a deleted file, v2

The watch target might be a deleted file. In this case we can't
re-create it on restore procedure.

A typical scenario
------------------

 fd = inotify_init1()
 wd = open(path)
 inotify_add_watch(path)
 unlink(path)
 ... checkpoint ...

here we have a @path which is unlinked but still present in inotify
watch list because inode is not yet freed. And if the program is killed
after checkpoint the last reference to a path get eliminated and inode
get freed from the kernel memory.

Thus any furher attempts to open the path via file handle (note that file
handle can't be used to create new file, the kernel doesn't permit that)
will simply fail.

So if plain opening via file handle failed we assume that at least
the file might be in our ghost files list (we're optimists, right?)
and if we successed we simply use a path generated by ghost file
engine for us.

v2 [by xemul@]:
 - gather reference to ghost file remap early
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 7eb33a76
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "image.h" #include "image.h"
#include "util.h" #include "util.h"
#include "files.h" #include "files.h"
#include "files-reg.h"
#include "file-ids.h" #include "file-ids.h"
#include "log.h" #include "log.h"
#include "list.h" #include "list.h"
...@@ -43,6 +44,7 @@ ...@@ -43,6 +44,7 @@
struct inotify_wd_info { struct inotify_wd_info {
struct list_head list; struct list_head list;
InotifyWdEntry *iwe; InotifyWdEntry *iwe;
struct file_remap *remap;
}; };
struct inotify_file_info { struct inotify_file_info {
...@@ -108,9 +110,10 @@ int dump_inotify(struct fd_parms *p, int lfd, const struct cr_fdset *set) ...@@ -108,9 +110,10 @@ int dump_inotify(struct fd_parms *p, int lfd, const struct cr_fdset *set)
return do_dump_gen_file(p, lfd, &inotify_ops, set); return do_dump_gen_file(p, lfd, &inotify_ops, set);
} }
static int restore_one_inotify(int inotify_fd, InotifyWdEntry *iwe) static int restore_one_inotify(int inotify_fd, struct inotify_wd_info *info)
{ {
char path[32]; InotifyWdEntry *iwe = info->iwe;
char buf[32], *path = buf;
int mntfd = -1, ret = -1; int mntfd = -1, ret = -1;
int wd, target = -1; int wd, target = -1;
fh_t handle = { }; fh_t handle = { };
...@@ -129,14 +132,17 @@ static int restore_one_inotify(int inotify_fd, InotifyWdEntry *iwe) ...@@ -129,14 +132,17 @@ static int restore_one_inotify(int inotify_fd, InotifyWdEntry *iwe)
return -1; return -1;
} }
target = sys_open_by_handle_at(mntfd, (void *)&handle, 0); if (!info->remap) {
if (target < 0) { target = sys_open_by_handle_at(mntfd, (void *)&handle, 0);
pr_perror("Can't open file handle for 0x%08x:0x%016lx", if (target < 0) {
iwe->s_dev, iwe->i_ino); pr_perror("Can't open file handle for 0x%08x:0x%016lx",
goto err; iwe->s_dev, iwe->i_ino);
} goto err;
}
snprintf(buf, sizeof(buf), "/proc/self/fd/%d", target);
} else
path = info->remap->path;
snprintf(path, sizeof(path), "/proc/self/fd/%d", target);
pr_debug("\t\tRestore watch for 0x%08x:0x%016lx\n", iwe->s_dev, iwe->i_ino); pr_debug("\t\tRestore watch for 0x%08x:0x%016lx\n", iwe->s_dev, iwe->i_ino);
/* /*
...@@ -162,6 +168,9 @@ static int restore_one_inotify(int inotify_fd, InotifyWdEntry *iwe) ...@@ -162,6 +168,9 @@ static int restore_one_inotify(int inotify_fd, InotifyWdEntry *iwe)
inotify_rm_watch(inotify_fd, wd); inotify_rm_watch(inotify_fd, wd);
} }
if (info->remap)
remap_put(info->remap);
err: err:
close_safe(&mntfd); close_safe(&mntfd);
close_safe(&target); close_safe(&target);
...@@ -184,7 +193,7 @@ static int open_inotify_fd(struct file_desc *d) ...@@ -184,7 +193,7 @@ static int open_inotify_fd(struct file_desc *d)
list_for_each_entry(wd_info, &info->marks, list) { list_for_each_entry(wd_info, &info->marks, list) {
pr_info("\tRestore inotify for 0x%08x\n", wd_info->iwe->id); pr_info("\tRestore inotify for 0x%08x\n", wd_info->iwe->id);
if (restore_one_inotify(tmp, wd_info->iwe)) { if (restore_one_inotify(tmp, wd_info)) {
close_safe(&tmp); close_safe(&tmp);
break; break;
} }
...@@ -208,6 +217,7 @@ static int collect_mark(struct inotify_wd_info *mark) ...@@ -208,6 +217,7 @@ static int collect_mark(struct inotify_wd_info *mark)
list_for_each_entry(p, &info_head, list) { list_for_each_entry(p, &info_head, list) {
if (p->ife->id == mark->iwe->id) { if (p->ife->id == mark->iwe->id) {
list_add(&mark->list, &p->marks); list_add(&mark->list, &p->marks);
mark->remap = lookup_ghost_remap(mark->iwe->s_dev, mark->iwe->i_ino);
return 0; return 0;
} }
} }
......
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