summaryrefslogtreecommitdiffstats
path: root/fs/overlayfs
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2017-04-24 02:37:28 -0400
committerMiklos Szeredi <mszeredi@redhat.com>2017-05-05 05:38:58 -0400
commitb7a807dc2010334e62e0afd89d6f7a8913eb14ff (patch)
treec2cb34dce0e3a52ac37fededcc63c835a3138a1c /fs/overlayfs
parent595485033db2c24178257698254fd4182fdb4123 (diff)
ovl: persistent inode number for directories
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>
Diffstat (limited to 'fs/overlayfs')
-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 */