|
@@ -285,16 +285,15 @@ static int ovl_lookup_layer(struct dentry *base, struct ovl_lookup_data *d,
|
|
|
|
|
|
|
|
|
static int ovl_check_origin(struct dentry *upperdentry,
|
|
|
- struct path *lowerstack, unsigned int numlower,
|
|
|
- struct path **stackp, unsigned int *ctrp)
|
|
|
+ struct ovl_path *lower, unsigned int numlower,
|
|
|
+ struct ovl_path **stackp, unsigned int *ctrp)
|
|
|
{
|
|
|
struct vfsmount *mnt;
|
|
|
struct dentry *origin = NULL;
|
|
|
int i;
|
|
|
|
|
|
-
|
|
|
for (i = 0; i < numlower; i++) {
|
|
|
- mnt = lowerstack[i].mnt;
|
|
|
+ mnt = lower[i].layer->mnt;
|
|
|
origin = ovl_get_origin(upperdentry, mnt);
|
|
|
if (IS_ERR(origin))
|
|
|
return PTR_ERR(origin);
|
|
@@ -308,12 +307,12 @@ static int ovl_check_origin(struct dentry *upperdentry,
|
|
|
|
|
|
BUG_ON(*ctrp);
|
|
|
if (!*stackp)
|
|
|
- *stackp = kmalloc(sizeof(struct path), GFP_KERNEL);
|
|
|
+ *stackp = kmalloc(sizeof(struct ovl_path), GFP_KERNEL);
|
|
|
if (!*stackp) {
|
|
|
dput(origin);
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
- **stackp = (struct path) { .dentry = origin, .mnt = mnt };
|
|
|
+ **stackp = (struct ovl_path){.dentry = origin, .layer = lower[i].layer};
|
|
|
*ctrp = 1;
|
|
|
|
|
|
return 0;
|
|
@@ -383,13 +382,13 @@ fail:
|
|
|
* OVL_XATTR_ORIGIN and that origin file handle can be decoded to lower path.
|
|
|
* Return 0 on match, -ESTALE on mismatch or stale origin, < 0 on error.
|
|
|
*/
|
|
|
-int ovl_verify_index(struct dentry *index, struct path *lowerstack,
|
|
|
+int ovl_verify_index(struct dentry *index, struct ovl_path *lower,
|
|
|
unsigned int numlower)
|
|
|
{
|
|
|
struct ovl_fh *fh = NULL;
|
|
|
size_t len;
|
|
|
- struct path origin = { };
|
|
|
- struct path *stack = &origin;
|
|
|
+ struct ovl_path origin = { };
|
|
|
+ struct ovl_path *stack = &origin;
|
|
|
unsigned int ctr = 0;
|
|
|
int err;
|
|
|
|
|
@@ -428,7 +427,7 @@ int ovl_verify_index(struct dentry *index, struct path *lowerstack,
|
|
|
if (err)
|
|
|
goto fail;
|
|
|
|
|
|
- err = ovl_check_origin(index, lowerstack, numlower, &stack, &ctr);
|
|
|
+ err = ovl_check_origin(index, lower, numlower, &stack, &ctr);
|
|
|
if (!err && !ctr)
|
|
|
err = -ESTALE;
|
|
|
if (err)
|
|
@@ -567,11 +566,24 @@ int ovl_path_next(int idx, struct dentry *dentry, struct path *path)
|
|
|
idx++;
|
|
|
}
|
|
|
BUG_ON(idx > oe->numlower);
|
|
|
- *path = oe->lowerstack[idx - 1];
|
|
|
+ path->dentry = oe->lowerstack[idx - 1].dentry;
|
|
|
+ path->mnt = oe->lowerstack[idx - 1].layer->mnt;
|
|
|
|
|
|
return (idx < oe->numlower) ? idx + 1 : -1;
|
|
|
}
|
|
|
|
|
|
+static int ovl_find_layer(struct ovl_fs *ofs, struct ovl_path *path)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < ofs->numlower; i++) {
|
|
|
+ if (ofs->lower_layers[i].mnt == path->layer->mnt)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return i;
|
|
|
+}
|
|
|
+
|
|
|
struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
|
|
|
unsigned int flags)
|
|
|
{
|
|
@@ -580,7 +592,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
|
|
|
struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
|
|
|
struct ovl_entry *poe = dentry->d_parent->d_fsdata;
|
|
|
struct ovl_entry *roe = dentry->d_sb->s_root->d_fsdata;
|
|
|
- struct path *stack = NULL;
|
|
|
+ struct ovl_path *stack = NULL;
|
|
|
struct dentry *upperdir, *upperdentry = NULL;
|
|
|
struct dentry *index = NULL;
|
|
|
unsigned int ctr = 0;
|
|
@@ -645,17 +657,17 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
|
|
|
|
|
|
if (!d.stop && poe->numlower) {
|
|
|
err = -ENOMEM;
|
|
|
- stack = kcalloc(ofs->numlower, sizeof(struct path),
|
|
|
+ stack = kcalloc(ofs->numlower, sizeof(struct ovl_path),
|
|
|
GFP_KERNEL);
|
|
|
if (!stack)
|
|
|
goto out_put_upper;
|
|
|
}
|
|
|
|
|
|
for (i = 0; !d.stop && i < poe->numlower; i++) {
|
|
|
- struct path lowerpath = poe->lowerstack[i];
|
|
|
+ struct ovl_path lower = poe->lowerstack[i];
|
|
|
|
|
|
d.last = i == poe->numlower - 1;
|
|
|
- err = ovl_lookup_layer(lowerpath.dentry, &d, &this);
|
|
|
+ err = ovl_lookup_layer(lower.dentry, &d, &this);
|
|
|
if (err)
|
|
|
goto out_put;
|
|
|
|
|
@@ -663,7 +675,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
|
|
|
continue;
|
|
|
|
|
|
stack[ctr].dentry = this;
|
|
|
- stack[ctr].mnt = lowerpath.mnt;
|
|
|
+ stack[ctr].layer = lower.layer;
|
|
|
ctr++;
|
|
|
|
|
|
if (d.stop)
|
|
@@ -673,10 +685,8 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
|
|
|
poe = roe;
|
|
|
|
|
|
/* Find the current layer on the root dentry */
|
|
|
- for (i = 0; i < poe->numlower; i++)
|
|
|
- if (poe->lowerstack[i].mnt == lowerpath.mnt)
|
|
|
- break;
|
|
|
- if (WARN_ON(i == poe->numlower))
|
|
|
+ i = ovl_find_layer(ofs, &lower);
|
|
|
+ if (WARN_ON(i == ofs->numlower))
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
@@ -699,7 +709,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
|
|
|
goto out_put;
|
|
|
|
|
|
oe->opaque = upperopaque;
|
|
|
- memcpy(oe->lowerstack, stack, sizeof(struct path) * ctr);
|
|
|
+ memcpy(oe->lowerstack, stack, sizeof(struct ovl_path) * ctr);
|
|
|
dentry->d_fsdata = oe;
|
|
|
|
|
|
if (upperdentry)
|