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:
parent
529f1a099e
commit
cc731cb6da
56
irmap.c
56
irmap.c
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user