[SRU][Zesty][PATCH 08/10] ovl: merge getattr for dir and nondir
Daniel Axtens
daniel.axtens at canonical.com
Mon Oct 30 06:53:29 UTC 2017
From: Miklos Szeredi <mszeredi at redhat.com>
BugLink: https://bugs.launchpad.net/bugs/1728489
Signed-off-by: Miklos Szeredi <mszeredi at redhat.com>
(backported from commit 5b712091a3a3904b0ae8311e18e6b540a070d464)
Signed-off-by: Daniel Axtens <daniel.axtens at canonical.com>
---
This patch also has no description in upstream.
---
fs/overlayfs/dir.c | 59 +-----------------------------------------------
fs/overlayfs/inode.c | 28 ++++++++++++++++++++---
fs/overlayfs/overlayfs.h | 2 ++
3 files changed, 28 insertions(+), 61 deletions(-)
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index 94d9ee8aa837..0f57a42426ef 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -138,63 +138,6 @@ static int ovl_set_opaque(struct dentry *dentry, struct dentry *upperdentry)
return err;
}
-static int ovl_dir_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
-{
- int err;
- enum ovl_path_type type;
- struct path realpath;
- const struct cred *old_cred;
-
- type = ovl_path_real(dentry, &realpath);
- old_cred = ovl_override_creds(dentry->d_sb);
- err = vfs_getattr(&realpath, stat);
- if (err)
- goto out;
-
- /*
- * When all layers are on the same fs, use the copy-up-origin st_ino,
- * which is persistent, unique and constant across copy up.
- *
- * Otherwise the pair {real st_ino; overlay st_dev} is not unique, so
- * use the non persistent overlay st_ino.
- */
- if (ovl_same_sb(dentry->d_sb)) {
- if (OVL_TYPE_ORIGIN(type)) {
- struct kstat lowerstat;
-
- ovl_path_lower(dentry, &realpath);
- err = vfs_getattr(&realpath, &lowerstat);
- if (err)
- goto out;
-
- WARN_ON_ONCE(stat->dev != lowerstat.dev);
- stat->ino = lowerstat.ino;
- }
- } else {
- stat->ino = dentry->d_inode->i_ino;
- }
-
- /*
- * Always use the overlay st_dev for directories, so 'find -xdev' will
- * scan the entire overlay mount and won't cross the overlay mount
- * boundaries.
- */
- stat->dev = dentry->d_sb->s_dev;
-
- /*
- * It's probably not worth it to count subdirs to get the
- * correct link count. nlink=1 seems to pacify 'find' and
- * other utilities.
- */
- if (OVL_TYPE_MERGE(type))
- stat->nlink = 1;
-out:
- revert_creds(old_cred);
-
- return err;
-}
-
/* Common operations required to be done after creation of file on upper */
static void ovl_instantiate(struct dentry *dentry, struct inode *inode,
struct dentry *newdentry, bool hardlink)
@@ -1096,7 +1039,7 @@ const struct inode_operations ovl_dir_inode_operations = {
.create = ovl_create,
.mknod = ovl_mknod,
.permission = ovl_permission,
- .getattr = ovl_dir_getattr,
+ .getattr = ovl_getattr,
.listxattr = ovl_listxattr,
.get_acl = ovl_get_acl,
.update_time = ovl_update_time,
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index c9eb9193f4ef..c80109b340a4 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -56,12 +56,13 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr)
return err;
}
-static int ovl_getattr(struct vfsmount *mnt, struct dentry *dentry,
- struct kstat *stat)
+int ovl_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat)
{
enum ovl_path_type type;
struct path realpath;
const struct cred *old_cred;
+ bool is_dir = S_ISDIR(dentry->d_inode->i_mode);
int err;
type = ovl_path_real(dentry, &realpath);
@@ -95,11 +96,32 @@ static int ovl_getattr(struct vfsmount *mnt, struct dentry *dentry,
* upper files, so we cannot use the lower origin st_ino
* for those different files, even for the same fs case.
*/
- if (lowerstat.nlink == 1)
+ if (is_dir || lowerstat.nlink == 1)
stat->ino = lowerstat.ino;
}
stat->dev = dentry->d_sb->s_dev;
+ } else if (is_dir) {
+ /*
+ * If not all layers are on the same fs the pair {real st_ino;
+ * overlay st_dev} is not unique, so use the non persistent
+ * overlay st_ino.
+ *
+ * Always use the overlay st_dev for directories, so 'find
+ * -xdev' will scan the entire overlay mount and won't cross the
+ * overlay mount boundaries.
+ */
+ stat->dev = dentry->d_sb->s_dev;
+ stat->ino = dentry->d_inode->i_ino;
}
+
+ /*
+ * It's probably not worth it to count subdirs to get the
+ * correct link count. nlink=1 seems to pacify 'find' and
+ * other utilities.
+ */
+ if (is_dir && OVL_TYPE_MERGE(type))
+ stat->nlink = 1;
+
out:
revert_creds(old_cred);
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 883a77b0636c..929165460f28 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -237,6 +237,8 @@ void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt,
/* inode.c */
int ovl_setattr(struct dentry *dentry, struct iattr *attr);
+int ovl_getattr(struct vfsmount *mnt, struct dentry *dentry,
+ struct kstat *stat);
int ovl_permission(struct inode *inode, int mask);
int ovl_xattr_set(struct dentry *dentry, const char *name, const void *value,
size_t size, int flags);
--
2.11.0
More information about the kernel-team
mailing list