[SRU,Xenial,2/2] ovl: persistent inode number for directories

Message ID 20171030065614.10145-3-daniel.axtens@canonical.com
State New
Headers show
Series
  • LP#1728489: tar -x sometimes fails on overlayfs
Related show

Commit Message

Daniel Axtens Oct. 30, 2017, 6:56 a.m.
From: Amir Goldstein <amir73il@gmail.com>

BugLink: https://bugs.launchpad.net/bugs/1728489

stat(2) on overlay directories reports the overlay temp inode
number, which is constant across copy up, but is not persistent.

When all layers are on the same fs, report the copy up origin inode
number for directories.

This inode number is persistent, unique across the overlay mount and
constant across copy up.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
(backported from commit b7a807dc2010334e62e0afd89d6f7a8913eb14ff)
Signed-off-by: Daniel Axtens <daniel.axtens@canonical.com>
---
 fs/overlayfs/dir.c | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

Patch

diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index 6e0c7274b0f2..7b8bbd05e9a0 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -176,8 +176,35 @@  static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry,
 	if (err)
 		return err;
 
+	/*
+	 * When all layers are on the same fs, use the copy-up-origin st_ino,
+	 * which is persistent, unique and constant across copy up.
+	 *
+	 * Otherwise the pair {real st_ino; overlay st_dev} is not unique, so
+	 * use the non persistent overlay st_ino.
+	 */
+	if (ovl_same_sb(dentry->d_sb)) {
+		if (OVL_TYPE_MERGE(type) && OVL_TYPE_UPPER(type)) {
+			struct kstat lowerstat;
+
+			ovl_path_lower(dentry, &realpath);
+			err = vfs_getattr(&realpath, &lowerstat);
+			if (err)
+				return err;
+
+			WARN_ON_ONCE(stat->dev != lowerstat.dev);
+			stat->ino = lowerstat.ino;
+		}
+	} else {
+		stat->ino = dentry->d_inode->i_ino;
+	}
+
+	/*
+	 * Always use the overlay st_dev for directories, so 'find -xdev' will
+	 * scan the entire overlay mount and won't cross the overlay mount
+	 * boundaries.
+	 */
 	stat->dev = dentry->d_sb->s_dev;
-	stat->ino = dentry->d_inode->i_ino;
 
 	/*
 	 * It's probably not worth it to count subdirs to get the