summaryrefslogtreecommitdiffstats
path: root/fs/overlayfs
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@redhat.com>2016-12-16 11:02:56 +0100
committerMiklos Szeredi <mszeredi@redhat.com>2016-12-16 11:02:56 +0100
commit8ee6059c58ea525f76b4efb98f8f66845f697efc (patch)
tree548cb4a104a2d00b0e8a01d7019e9c8c4c64f2cb /fs/overlayfs
parentovl: check lower existence of rename target (diff)
downloadlinux-8ee6059c58ea525f76b4efb98f8f66845f697efc.tar.xz
linux-8ee6059c58ea525f76b4efb98f8f66845f697efc.zip
ovl: simplify lookup
If encountering a non-directory, then stop looking at lower layers. In this case the oe->opaque flag is not set anymore, which doesn't matter since existence of lower file is now checked at remove/rename time. Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/overlayfs')
-rw-r--r--fs/overlayfs/super.c54
1 files changed, 25 insertions, 29 deletions
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index c0463fb80f41..a19fbcde16bd 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -473,7 +473,9 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
unsigned int ctr = 0;
struct inode *inode = NULL;
bool upperopaque = false;
- struct dentry *this, *prev = NULL;
+ bool stop = false;
+ bool isdir = false;
+ struct dentry *this;
unsigned int i;
int err;
@@ -494,23 +496,26 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
if (ovl_is_whiteout(this)) {
dput(this);
this = NULL;
- upperopaque = true;
- } else if (poe->numlower && ovl_is_opaquedir(this)) {
- upperopaque = true;
+ stop = upperopaque = true;
+ } else if (!d_is_dir(this)) {
+ stop = true;
+ } else {
+ isdir = true;
+ if (poe->numlower && ovl_is_opaquedir(this))
+ stop = upperopaque = true;
}
}
- upperdentry = prev = this;
+ upperdentry = this;
}
- if (!upperopaque && poe->numlower) {
+ if (!stop && poe->numlower) {
err = -ENOMEM;
stack = kcalloc(poe->numlower, sizeof(struct path), GFP_KERNEL);
if (!stack)
goto out_put_upper;
}
- for (i = 0; !upperopaque && i < poe->numlower; i++) {
- bool opaque = false;
+ for (i = 0; !stop && i < poe->numlower; i++) {
struct path lowerpath = poe->lowerstack[i];
this = ovl_lookup_real(lowerpath.dentry, &dentry->d_name);
@@ -530,35 +535,26 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
break;
}
/*
- * Only makes sense to check opaque dir if this is not the
- * lowermost layer.
+ * If this is a non-directory then stop here.
*/
- if (i < poe->numlower - 1 && ovl_is_opaquedir(this))
- opaque = true;
-
- if (prev && (!S_ISDIR(prev->d_inode->i_mode) ||
- !S_ISDIR(this->d_inode->i_mode))) {
+ if (!d_is_dir(this)) {
+ if (isdir) {
+ dput(this);
+ break;
+ }
+ stop = true;
+ } else {
/*
- * FIXME: check for upper-opaqueness maybe better done
- * in remove code.
+ * Only makes sense to check opaque dir if this is not
+ * the lowermost layer.
*/
- if (prev == upperdentry)
- upperopaque = true;
- dput(this);
- break;
+ if (i < poe->numlower - 1 && ovl_is_opaquedir(this))
+ stop = true;
}
- /*
- * If this is a non-directory then stop here.
- */
- if (!S_ISDIR(this->d_inode->i_mode))
- opaque = true;
stack[ctr].dentry = this;
stack[ctr].mnt = lowerpath.mnt;
ctr++;
- prev = this;
- if (opaque)
- break;
}
oe = ovl_alloc_entry(ctr);