Skip to content

Commit

Permalink
ovl: Set d->last properly during lookup
Browse files Browse the repository at this point in the history
d->last signifies that this is the last layer we are looking into and there
is no more. And that means this allows for some optimzation opportunities
during lookup. For example, in ovl_lookup_single() we don't have to check
for opaque xattr of a directory is this is the last layer we are looking
into (d->last = true).

But knowing for sure whether we are looking into last layer can be very
tricky. If redirects are not enabled, then we can look at poe->numlower and
figure out if the lookup we are about to is last layer or not. But if
redircts are enabled then it is possible poe->numlower suggests that we are
looking in last layer, but there is an absolute redirect present in found
element and that redirects us to a layer in root and that means lookup will
continue in lower layers further.

For example, consider following.

/upperdir/pure (opaque=y)
/upperdir/pure/foo (opaque=y,redirect=/bar)
/lowerdir/bar

In this case pure is "pure upper". When we look for "foo", that time
poe->numlower=0. But that alone does not mean that we will not search for a
merge candidate in /lowerdir. Absolute redirect changes that.

IOW, d->last should not be set just based on poe->numlower if redirects are
enabled. That can lead to setting d->last while it should not have and that
means we will not check for opaque xattr while we should have.

So do this.

 - If redirects are not enabled, then continue to rely on poe->numlower
   information to determine if it is last layer or not.

 - If redirects are enabled, then set d->last = true only if this is the
   last layer in root ovl_entry (roe).

Suggested-by: Amir Goldstein <amir73il@gmail.com>
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Fixes: 02b69b2 ("ovl: lookup redirects")
Cc: <stable@vger.kernel.org> #v4.10
  • Loading branch information
rhvgoyal authored and Miklos Szeredi committed Apr 12, 2018
1 parent 695b46e commit 452061f
Showing 1 changed file with 6 additions and 2 deletions.
8 changes: 6 additions & 2 deletions fs/overlayfs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
.is_dir = false,
.opaque = false,
.stop = false,
.last = !poe->numlower,
.last = ofs->config.redirect_follow ? false : !poe->numlower,
.redirect = NULL,
};

Expand Down Expand Up @@ -873,7 +873,11 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
for (i = 0; !d.stop && i < poe->numlower; i++) {
struct ovl_path lower = poe->lowerstack[i];

d.last = i == poe->numlower - 1;
if (!ofs->config.redirect_follow)
d.last = i == poe->numlower - 1;
else
d.last = lower.layer->idx == roe->numlower;

err = ovl_lookup_layer(lower.dentry, &d, &this);
if (err)
goto out_put;
Expand Down

0 comments on commit 452061f

Please sign in to comment.