summaryrefslogtreecommitdiff
path: root/fs/overlayfs/inode.c
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2020-01-14 22:17:25 +0200
committerMiklos Szeredi <mszeredi@redhat.com>2020-01-24 09:46:45 +0100
commitb7bf9908e17c4dc4b80876f299ac03ddf188efd9 (patch)
tree5b37db7eb28823b29b26e40e1b93092ecdf6b300 /fs/overlayfs/inode.c
parent1b81dddd354cf304574d79004400a6385613ae4e (diff)
ovl: fix corner case of non-constant st_dev;st_ino
On non-samefs overlay without xino, non pure upper inodes should use a pseudo_dev assigned to each unique lower fs, but if lower layer is on the same fs and upper layer, it has no pseudo_dev assigned. In this overlay layers setup: - two filesystems, A and B - upper layer is on A - lower layer 1 is also on A - lower layer 2 is on B Non pure upper overlay inode, whose origin is in layer 1 will have the st_dev;st_ino values of the real lower inode before copy up and the st_dev;st_ino values of the real upper inode after copy up. Fix this inconsitency by assigning a unique pseudo_dev also for upper fs, that will be used as st_dev value along with the lower inode st_dev for overlay inodes in the case above. Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/overlayfs/inode.c')
-rw-r--r--fs/overlayfs/inode.c16
1 files changed, 4 insertions, 12 deletions
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 60f7b8f092f2..79e8994e3bc1 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -121,13 +121,12 @@ static int ovl_map_dev_ino(struct dentry *dentry, struct kstat *stat, int fsid)
*/
stat->dev = dentry->d_sb->s_dev;
stat->ino = dentry->d_inode->i_ino;
- } else if (fsid) {
+ } else {
/*
* For non-samefs setup, if we cannot map all layers st_ino
* to a unified address space, we need to make sure that st_dev
- * is unique per lower fs. Upper layer uses real st_dev and
- * lower layers use the unique anonymous bdev assigned to the
- * lower fs.
+ * is unique per underlying fs, so we use the unique anonymous
+ * bdev assigned to the underlying fs.
*/
stat->dev = OVL_FS(dentry->d_sb)->fs[fsid].pseudo_dev;
}
@@ -143,7 +142,6 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
struct path realpath;
const struct cred *old_cred;
bool is_dir = S_ISDIR(dentry->d_inode->i_mode);
- bool samefs = ovl_same_fs(dentry->d_sb);
int fsid = 0;
int err;
bool metacopy_blocks = false;
@@ -198,13 +196,7 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
(!ovl_verify_lower(dentry->d_sb) &&
(is_dir || lowerstat.nlink == 1))) {
fsid = ovl_layer_lower(dentry)->fsid;
- /*
- * Cannot use origin st_dev;st_ino because
- * origin inode content may differ from overlay
- * inode content.
- */
- if (samefs || fsid)
- stat->ino = lowerstat.ino;
+ stat->ino = lowerstat.ino;
}
/*