summaryrefslogtreecommitdiffstats
path: root/fs/overlayfs/super.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/super.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/super.c')
-rw-r--r--fs/overlayfs/super.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 7cf543608b9f..dcdcb4e3003a 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -229,8 +229,7 @@ static void ovl_free_fs(struct ovl_fs *ofs)
mntput(ofs->layers[i].mnt);
}
kfree(ofs->layers);
- /* fs[0].pseudo_dev is either null or real upper st_dev */
- for (i = 1; i < ofs->numfs; i++)
+ for (i = 0; i < ofs->numfs; i++)
free_anon_bdev(ofs->fs[i].pseudo_dev);
kfree(ofs->fs);
@@ -1341,13 +1340,19 @@ static int ovl_get_layers(struct super_block *sb, struct ovl_fs *ofs,
ofs->numlayer = 1;
/*
- * All lower layers that share the same fs as upper layer, use the real
- * upper st_dev.
+ * All lower layers that share the same fs as upper layer, use the same
+ * pseudo_dev as upper layer. Allocate fs[0].pseudo_dev even for lower
+ * only overlay to simplify ovl_fs_free().
* is_lower will be set if upper fs is shared with a lower layer.
*/
+ err = get_anon_bdev(&ofs->fs[0].pseudo_dev);
+ if (err) {
+ pr_err("failed to get anonymous bdev for upper fs\n");
+ goto out;
+ }
+
if (ofs->upper_mnt) {
ofs->fs[0].sb = ofs->upper_mnt->mnt_sb;
- ofs->fs[0].pseudo_dev = ofs->upper_mnt->mnt_sb->s_dev;
ofs->fs[0].is_lower = false;
}