summary refs log tree commit diff
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
parent3ee23ff1025a18796607cf4110a8ffa8e2d163fd (diff)
downloadlinux-8ee6059c58ea525f76b4efb98f8f66845f697efc.tar.gz
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);