2
0
mirror of https://github.com/checkpoint-restore/criu synced 2025-08-29 05:18:00 +00:00

irmap: Revalidate irmap entries if required

We will load some irmap entries in cache from image file,
thus producing potentially stale data in irmap cache. To
handle this, make it possible to mark the entries with
need-revalidation mark and do fstat + numbers comparison
when meeting the entry in cache.

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
Pavel Emelyanov 2014-01-30 13:57:45 +04:00
parent 529f1a099e
commit cc731cb6da

56
irmap.c
View File

@ -39,7 +39,7 @@ struct irmap {
unsigned long ino;
char *path;
struct irmap *next;
bool revalidate;
int nr_kids;
struct irmap *kids;
};
@ -69,6 +69,7 @@ static int irmap_update_stat(struct irmap *i)
return -1;
}
i->revalidate = false;
i->dev = st.st_dev;
i->ino = st.st_ino;
if (!S_ISDIR(st.st_mode))
@ -172,28 +173,65 @@ static struct irmap *irmap_scan(struct irmap *t, unsigned int dev, unsigned long
return NULL;
}
static int irmap_revalidate(struct irmap *c, struct irmap **p)
{
struct stat st;
pr_debug("Revalidate stat for %s\n", c->path);
if (fstatat(mntns_root, c->path + 1, &st, AT_SYMLINK_NOFOLLOW)) {
/* File can be (re)moved, so just treat it as invalid */
pr_perror("Can't stat %s", c->path);
goto invalid;
}
if (c->dev != st.st_dev)
goto invalid;
if (c->ino != st.st_ino)
goto invalid;
c->revalidate = false;
return 0;
invalid:
pr_debug("\t%x:%lx is invalid\n", c->dev, c->ino);
*p = c->next;
xfree(c->path);
xfree(c);
return 1;
}
char *irmap_lookup(unsigned int s_dev, unsigned long i_ino)
{
struct irmap *c, *h;
struct irmap *c, *h, **p;
char *path = NULL;
int hv;
pr_debug("Resolving %x:%lx path\n", s_dev, i_ino);
hv = irmap_hashfn(s_dev, i_ino);
for (c = cache[hv]; c; c = c->next)
if (c->dev == s_dev && c->ino == i_ino) {
pr_debug("\tFound %s in cache\n", c->path);
return c->path;
}
for (p = &cache[hv]; *p; p = &(*p)->next) {
c = *p;
if (!(c->dev == s_dev && c->ino == i_ino))
continue;
if (c->revalidate && irmap_revalidate(c, p))
continue;
pr_debug("\tFound %s in cache\n", c->path);
path = c->path;
goto out;
}
for (h = hints; h->path; h++) {
pr_debug("Scanning %s hint\n", h->path);
c = irmap_scan(h, s_dev, i_ino);
if (c) {
pr_debug("\tScanned %s\n", c->path);
return c->path;
path = c->path;
goto out;
}
}
return NULL;
out:
return path;
}