Skip to content

Commit a0c5ad3

Browse files
amir73ilMiklos Szeredi
authored andcommitted
ovl: relax same fs constraint for constant st_ino
For the case of all layers not on the same fs, return the copy up origin inode st_dev/st_ino for non-dir from stat(2). This guaranties constant st_dev/st_ino for non-dir across copy up. Like the same fs case, st_ino of non-dir is also persistent. If the st_dev/st_ino for copied up object would have been the same as that of the real underlying lower file, running diff on underlying lower file and overlay copied up file would result in diff reporting that the two files are equal when in fact, they may have different content. Therefore, unlike the same fs case, st_dev is not persistent because it uses the unique anonymous bdev allocated for the lower layer. Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
1 parent ba1e563 commit a0c5ad3

File tree

1 file changed

+29
-20
lines changed

1 file changed

+29
-20
lines changed

fs/overlayfs/inode.c

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
7474
struct path realpath;
7575
const struct cred *old_cred;
7676
bool is_dir = S_ISDIR(dentry->d_inode->i_mode);
77+
bool samefs = ovl_same_sb(dentry->d_sb);
7778
int err;
7879

7980
type = ovl_path_real(dentry, &realpath);
@@ -83,16 +84,13 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
8384
goto out;
8485

8586
/*
86-
* When all layers are on the same fs, all real inode number are
87-
* unique, so we use the overlay st_dev, which is friendly to du -x.
88-
*
89-
* We also use st_ino of the copy up origin, if we know it.
90-
* This guaranties constant st_dev/st_ino across copy up.
87+
* For non-dir or same fs, we use st_ino of the copy up origin, if we
88+
* know it. This guaranties constant st_dev/st_ino across copy up.
9189
*
9290
* If filesystem supports NFS export ops, this also guaranties
9391
* persistent st_ino across mount cycle.
9492
*/
95-
if (ovl_same_sb(dentry->d_sb)) {
93+
if (!is_dir || samefs) {
9694
if (OVL_TYPE_ORIGIN(type)) {
9795
struct kstat lowerstat;
9896
u32 lowermask = STATX_INO | (!is_dir ? STATX_NLINK : 0);
@@ -103,7 +101,6 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
103101
if (err)
104102
goto out;
105103

106-
WARN_ON_ONCE(stat->dev != lowerstat.dev);
107104
/*
108105
* Lower hardlinks may be broken on copy up to different
109106
* upper files, so we cannot use the lower origin st_ino
@@ -115,27 +112,39 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
115112
if (is_dir || lowerstat.nlink == 1 ||
116113
ovl_test_flag(OVL_INDEX, d_inode(dentry)))
117114
stat->ino = lowerstat.ino;
115+
116+
if (samefs)
117+
WARN_ON_ONCE(stat->dev != lowerstat.dev);
118+
else
119+
stat->dev = ovl_get_pseudo_dev(dentry);
118120
}
119-
stat->dev = dentry->d_sb->s_dev;
120-
} else if (is_dir) {
121+
if (samefs) {
122+
/*
123+
* When all layers are on the same fs, all real inode
124+
* number are unique, so we use the overlay st_dev,
125+
* which is friendly to du -x.
126+
*/
127+
stat->dev = dentry->d_sb->s_dev;
128+
} else if (!OVL_TYPE_UPPER(type)) {
129+
/*
130+
* For non-samefs setup, to make sure that st_dev/st_ino
131+
* pair is unique across the system, we use a unique
132+
* anonymous st_dev for lower layer inode.
133+
*/
134+
stat->dev = ovl_get_pseudo_dev(dentry);
135+
}
136+
} else {
121137
/*
122-
* If not all layers are on the same fs the pair {real st_ino;
123-
* overlay st_dev} is not unique, so use the non persistent
124-
* overlay st_ino.
125-
*
126138
* Always use the overlay st_dev for directories, so 'find
127139
* -xdev' will scan the entire overlay mount and won't cross the
128140
* overlay mount boundaries.
141+
*
142+
* If not all layers are on the same fs the pair {real st_ino;
143+
* overlay st_dev} is not unique, so use the non persistent
144+
* overlay st_ino for directories.
129145
*/
130146
stat->dev = dentry->d_sb->s_dev;
131147
stat->ino = dentry->d_inode->i_ino;
132-
} else if (!OVL_TYPE_UPPER(type)) {
133-
/*
134-
* For non-samefs setup, to make sure that st_dev/st_ino pair
135-
* is unique across the system, we use a unique anonymous
136-
* st_dev for lower layer inode.
137-
*/
138-
stat->dev = ovl_get_pseudo_dev(dentry);
139148
}
140149

141150
/*

0 commit comments

Comments
 (0)