@@ -204,6 +204,9 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
if (d->fh) {
kfree(d->fh);
d->fh = NULL;
+ /* Follow once by file handle for non-dir */
+ if (!d->is_dir)
+ d->by_fh = false;
}
if (!this->d_inode)
@@ -219,15 +222,21 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
goto put_and_out;
}
if (!d_can_lookup(this)) {
- d->stop = true;
- if (d->is_dir)
+ if (d->is_dir) {
+ d->stop = true;
goto put_and_out;
- goto out;
- }
- d->is_dir = true;
- if (!d->last && ovl_is_opaquedir(this)) {
- d->stop = d->opaque = true;
- goto out;
+ }
+ /* Lookup stable inode of non-dir by file handle */
+ if (!d->by_fh) {
+ d->stop = true;
+ goto out;
+ }
+ } else {
+ d->is_dir = true;
+ if (!d->last && ovl_is_opaquedir(this)) {
+ d->stop = d->opaque = true;
+ goto out;
+ }
}
if (d->last)
goto out;
@@ -236,6 +245,11 @@ static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
if (err)
goto out_err;
}
+ /* No redirect fh for non-dir means pure upper */
+ if (!d->is_dir) {
+ d->stop = !d->fh;
+ goto out;
+ }
if (d->by_path) {
err = ovl_check_redirect(this, d, prelen, post);
if (err)
When non directory upper has overlay.fh xattr, lookup that file handle in lower layers to find the stable inode it refers to. Signed-off-by: Amir Goldstein <amir73il@gmail.com> --- fs/overlayfs/namei.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-)