summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2016-11-21 18:57:34 +0200
committerMiklos Szeredi <mszeredi@redhat.com>2016-12-16 11:02:57 +0100
commit97c684cc911060ba7f97c0925eaf842f159a39e8 (patch)
treeebb8de7d74b26fedbc84636f4e5c6810f7fe3dc6 /fs
parent5cf5b477f0ca33f56a30c7ec00e61a6204da2efb (diff)
downloadlinux-97c684cc911060ba7f97c0925eaf842f159a39e8.tar.bz2
ovl: create directories inside merged parent opaque
The benefit of making directories opaque on creation is that lookups can stop short when they reach the original created directory, instead of continue lookup the entire depth of parent directory stack. The best case is overlay with N layers, performing lookup for first level directory, which exists only in upper. In that case, there will be only one lookup instead of N. Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/overlayfs/dir.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index 76e39aaaa038..3cc65e60df02 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -184,6 +184,11 @@ static void ovl_instantiate(struct dentry *dentry, struct inode *inode,
d_instantiate(dentry, inode);
}
+static bool ovl_type_merge(struct dentry *dentry)
+{
+ return OVL_TYPE_MERGE(ovl_path_type(dentry));
+}
+
static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
struct kstat *stat, const char *link,
struct dentry *hardlink)
@@ -206,6 +211,11 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
if (err)
goto out_dput;
+ if (ovl_type_merge(dentry->d_parent)) {
+ /* Setting opaque here is just an optimization, allow to fail */
+ ovl_set_opaque(dentry, newdentry);
+ }
+
ovl_instantiate(dentry, inode, newdentry, !!hardlink);
newdentry = NULL;
out_dput:
@@ -1006,7 +1016,7 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
if (is_dir) {
if (ovl_type_merge_or_lower(old))
err = ovl_set_redirect(old, samedir);
- else if (!old_opaque && ovl_lower_positive(new))
+ else if (!old_opaque && ovl_type_merge(new->d_parent))
err = ovl_set_opaque(old, olddentry);
if (err)
goto out_dput;
@@ -1014,7 +1024,7 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
if (!overwrite && new_is_dir) {
if (ovl_type_merge_or_lower(new))
err = ovl_set_redirect(new, samedir);
- else if (!new_opaque && ovl_lower_positive(old))
+ else if (!new_opaque && ovl_type_merge(old->d_parent))
err = ovl_set_opaque(new, newdentry);
if (err)
goto out_dput;