summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/overlayfs/dir.c37
1 files changed, 33 insertions, 4 deletions
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index bfabc65fdc74..0c5e79966957 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -150,12 +150,39 @@ static int ovl_dir_getattr(const struct path *path, struct kstat *stat,
150 type = ovl_path_real(dentry, &realpath); 150 type = ovl_path_real(dentry, &realpath);
151 old_cred = ovl_override_creds(dentry->d_sb); 151 old_cred = ovl_override_creds(dentry->d_sb);
152 err = vfs_getattr(&realpath, stat, request_mask, flags); 152 err = vfs_getattr(&realpath, stat, request_mask, flags);
153 revert_creds(old_cred);
154 if (err) 153 if (err)
155 return err; 154 goto out;
155
156 /*
157 * When all layers are on the same fs, use the copy-up-origin st_ino,
158 * which is persistent, unique and constant across copy up.
159 *
160 * Otherwise the pair {real st_ino; overlay st_dev} is not unique, so
161 * use the non persistent overlay st_ino.
162 */
163 if (ovl_same_sb(dentry->d_sb)) {
164 if (OVL_TYPE_ORIGIN(type)) {
165 struct kstat lowerstat;
166
167 ovl_path_lower(dentry, &realpath);
168 err = vfs_getattr(&realpath, &lowerstat,
169 STATX_INO, flags);
170 if (err)
171 goto out;
172
173 WARN_ON_ONCE(stat->dev != lowerstat.dev);
174 stat->ino = lowerstat.ino;
175 }
176 } else {
177 stat->ino = dentry->d_inode->i_ino;
178 }
156 179
180 /*
181 * Always use the overlay st_dev for directories, so 'find -xdev' will
182 * scan the entire overlay mount and won't cross the overlay mount
183 * boundaries.
184 */
157 stat->dev = dentry->d_sb->s_dev; 185 stat->dev = dentry->d_sb->s_dev;
158 stat->ino = dentry->d_inode->i_ino;
159 186
160 /* 187 /*
161 * It's probably not worth it to count subdirs to get the 188 * It's probably not worth it to count subdirs to get the
@@ -164,8 +191,10 @@ static int ovl_dir_getattr(const struct path *path, struct kstat *stat,
164 */ 191 */
165 if (OVL_TYPE_MERGE(type)) 192 if (OVL_TYPE_MERGE(type))
166 stat->nlink = 1; 193 stat->nlink = 1;
194out:
195 revert_creds(old_cred);
167 196
168 return 0; 197 return err;
169} 198}
170 199
171/* Common operations required to be done after creation of file on upper */ 200/* Common operations required to be done after creation of file on upper */