Commit cc731cb6 authored by Pavel Emelyanov's avatar Pavel Emelyanov

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: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 529f1a09
......@@ -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;
}
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