[CRIU] [PATCH 5/7] irmap: Revalidate irmap entries if required

Pavel Emelyanov xemul at parallels.com
Thu Jan 30 02:24:23 PST 2014


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 at parallels.com>
---
 irmap.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 47 insertions(+), 9 deletions(-)

diff --git a/irmap.c b/irmap.c
index aca773d..7d326c4 100644
--- a/irmap.c
+++ b/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;
 }
-- 
1.8.4.2


More information about the CRIU mailing list