diff options
author | Miklos Szeredi <mszeredi@redhat.com> | 2016-12-16 11:02:56 +0100 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2016-12-16 11:02:56 +0100 |
commit | 8ee6059c58ea525f76b4efb98f8f66845f697efc (patch) | |
tree | 548cb4a104a2d00b0e8a01d7019e9c8c4c64f2cb /fs/overlayfs | |
parent | ovl: check lower existence of rename target (diff) | |
download | linux-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.c | 54 |
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); |