Skip to content

Commit

Permalink
ovl: relax same fs constrain for ovl_check_origin()
Browse files Browse the repository at this point in the history
For the case of all layers not on the same fs, try to decode the copy up
origin file handle on any of the lower layers.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
  • Loading branch information
Amir Goldstein authored and Miklos Szeredi committed Jul 4, 2017
1 parent 2cac0c0 commit f7d3dac
Showing 1 changed file with 24 additions and 18 deletions.
42 changes: 24 additions & 18 deletions fs/overlayfs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,28 +272,24 @@ static int ovl_lookup_layer(struct dentry *base, struct ovl_lookup_data *d,
static int ovl_check_origin(struct dentry *dentry, struct dentry *upperdentry,
struct path **stackp, unsigned int *ctrp)
{
struct super_block *same_sb = ovl_same_sb(dentry->d_sb);
struct ovl_entry *roe = dentry->d_sb->s_root->d_fsdata;
struct vfsmount *mnt;
struct dentry *origin;
struct dentry *origin = NULL;
int i;

if (!same_sb || !roe->numlower)
return 0;

/*
* Since all layers are on the same fs, we use the first layer for
* decoding the file handle. We may get a disconnected dentry,
* which is fine, because we only need to hold the origin inode in
* cache and use its inode number. We may even get a connected dentry,
* that is not under the first layer's root. That is also fine for
* using it's inode number - it's the same as if we held a reference
* to a dentry in first layer that was moved under us.
*/
mnt = roe->lowerstack[0].mnt;

origin = ovl_get_origin(upperdentry, mnt);
if (IS_ERR_OR_NULL(origin))
return PTR_ERR(origin);
for (i = 0; i < roe->numlower; i++) {
mnt = roe->lowerstack[i].mnt;
origin = ovl_get_origin(upperdentry, mnt);
if (IS_ERR(origin))
return PTR_ERR(origin);

if (origin)
break;
}

if (!origin)
return 0;

BUG_ON(*stackp || *ctrp);
*stackp = kmalloc(sizeof(struct path), GFP_TEMPORARY);
Expand Down Expand Up @@ -371,6 +367,16 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
}
if (upperdentry && !d.is_dir) {
BUG_ON(!d.stop || d.redirect);
/*
* Lookup copy up origin by decoding origin file handle.
* We may get a disconnected dentry, which is fine,
* because we only need to hold the origin inode in
* cache and use its inode number. We may even get a
* connected dentry, that is not under any of the lower
* layers root. That is also fine for using it's inode
* number - it's the same as if we held a reference
* to a dentry in lower layer that was moved under us.
*/
err = ovl_check_origin(dentry, upperdentry,
&stack, &ctr);
if (err)
Expand Down

0 comments on commit f7d3dac

Please sign in to comment.