return ERR_PTR(-ENOMEM);
}
+/* Get the upper or lower dentry in stach whose on layer @idx */
+static struct dentry *ovl_dentry_real_at(struct dentry *dentry, int idx)
+{
+ struct ovl_entry *oe = dentry->d_fsdata;
+ int i;
+
+ if (!idx)
+ return ovl_dentry_upper(dentry);
+
+ for (i = 0; i < oe->numlower; i++) {
+ if (oe->lowerstack[i].layer->idx == idx)
+ return oe->lowerstack[i].dentry;
+ }
+
+ return NULL;
+}
+
/*
* Lookup a child overlay dentry to get a connected overlay dentry whose real
* dentry is @real. If @real is on upper layer, we lookup a child overlay
struct name_snapshot name;
int err;
- /* TODO: lookup by lower real dentry */
- if (layer->idx)
- return ERR_PTR(-EACCES);
-
/*
* Lookup child overlay dentry by real name. The dir mutex protects us
* from racing with overlay rename. If the overlay dentry that is above
inode_lock_nested(dir, I_MUTEX_PARENT);
err = -ECHILD;
parent = dget_parent(real);
- if (ovl_dentry_upper(connected) != parent)
+ if (ovl_dentry_real_at(connected, layer->idx) != parent)
goto fail;
/*
dput(this);
err = -ENOENT;
goto fail;
- } else if (ovl_dentry_upper(this) != real) {
+ } else if (ovl_dentry_real_at(this, layer->idx) != real) {
dput(this);
err = -ESTALE;
goto fail;
int err = 0;
/* TODO: use index when looking up by lower real dentry */
- if (layer->idx)
- return ERR_PTR(-EACCES);
connected = dget(sb->s_root);
while (!err) {
struct dentry *next, *this;
struct dentry *parent = NULL;
- struct dentry *real_connected = ovl_dentry_upper(connected);
+ struct dentry *real_connected = ovl_dentry_real_at(connected,
+ layer->idx);
if (real_connected == real)
break;
{
struct ovl_fs *ofs = sb->s_fs_info;
struct ovl_layer upper_layer = { .mnt = ofs->upper_mnt };
+ struct ovl_layer *layer = upper ? &upper_layer : lowerpath->layer;
struct dentry *real = upper ?: (index ?: lowerpath->dentry);
/*
if (!d_is_dir(real))
return ovl_obtain_alias(sb, upper, lowerpath, index);
- /* TODO: lookup connected dir from real lower dir */
- if (!upper)
- return ERR_PTR(-EACCES);
-
/* Removed empty directory? */
- if ((upper->d_flags & DCACHE_DISCONNECTED) || d_unhashed(upper))
+ if ((real->d_flags & DCACHE_DISCONNECTED) || d_unhashed(real))
return ERR_PTR(-ENOENT);
/*
- * If real upper dentry is connected and hashed, get a connected
- * overlay dentry with the same path as the real upper dentry.
+ * If real dentry is connected and hashed, get a connected overlay
+ * dentry whose real dentry is @real.
*/
- return ovl_lookup_real(sb, upper, &upper_layer);
+ return ovl_lookup_real(sb, real, layer);
}
static struct dentry *ovl_upper_fh_to_d(struct super_block *sb,