* [PATCH 1/3] ovl: Allocate anonymous devs for lowerdirs
@ 2017-10-06 9:25 Chandan Rajendra
2017-10-06 9:25 ` [PATCH 2/3] ovl: relax same fs constrain for constant st_ino Chandan Rajendra
2017-10-06 9:25 ` [PATCH 3/3] ovl: Relax same fs constraint for constant d_ino Chandan Rajendra
0 siblings, 2 replies; 3+ messages in thread
From: Chandan Rajendra @ 2017-10-06 9:25 UTC (permalink / raw)
To: linux-unionfs, amir73il; +Cc: Chandan Rajendra, miklos
For stat(2) on lowerdir non-dir entries in non-samefs case, this commit
provides unique values for st_dev. The unique values are obtained by
allocating anonymous bdevs for each of the lowerdirs in the overlayfs
instance.
Signed-off-by: Chandan Rajendra <chandan@linux.vnet.ibm.com>
---
fs/overlayfs/copy_up.c | 1 -
fs/overlayfs/inode.c | 18 +++++++++++++
fs/overlayfs/namei.c | 37 +++++++++++++-------------
fs/overlayfs/overlayfs.h | 5 ++--
fs/overlayfs/ovl_entry.h | 14 ++++++++--
fs/overlayfs/readdir.c | 4 +--
fs/overlayfs/super.c | 67 ++++++++++++++++++++++++++++++------------------
fs/overlayfs/util.c | 8 ++++--
8 files changed, 101 insertions(+), 53 deletions(-)
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index aad97b3..80d0d9c 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -22,7 +22,6 @@
#include <linux/ratelimit.h>
#include <linux/exportfs.h>
#include "overlayfs.h"
-#include "ovl_entry.h"
#define OVL_COPY_UP_CHUNK_SIZE (1 << 20)
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index a619add..3091cd6 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -8,6 +8,7 @@
*/
#include <linux/fs.h>
+#include <linux/mount.h>
#include <linux/slab.h>
#include <linux/cred.h>
#include <linux/xattr.h>
@@ -15,6 +16,21 @@
#include <linux/ratelimit.h>
#include "overlayfs.h"
+
+static dev_t ovl_get_pseudo_dev(struct dentry *dentry, dev_t dev)
+{
+ struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
+ struct ovl_entry *oe = dentry->d_fsdata;
+
+ if (ofs->upper_mnt && ofs->upper_mnt->mnt_sb->s_dev == dev)
+ return dev;
+
+ if (oe->numlower)
+ return oe->lowerstack[0].layer->pseudo_dev;
+
+ return dev;
+}
+
int ovl_setattr(struct dentry *dentry, struct iattr *attr)
{
int err;
@@ -121,6 +137,8 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
*/
stat->dev = dentry->d_sb->s_dev;
stat->ino = dentry->d_inode->i_ino;
+ } else {
+ stat->dev = ovl_get_pseudo_dev(dentry, stat->dev);
}
/*
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index c3addd1..1c578d4 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -15,7 +15,6 @@
#include <linux/mount.h>
#include <linux/exportfs.h>
#include "overlayfs.h"
-#include "ovl_entry.h"
struct ovl_lookup_data {
struct qstr name;
@@ -286,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_lower *lower, unsigned int numlower,
+ struct ovl_lower **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);
@@ -309,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_lower), GFP_KERNEL);
if (!*stackp) {
dput(origin);
return -ENOMEM;
}
- **stackp = (struct path) { .dentry = origin, .mnt = mnt };
+ **stackp = (struct ovl_lower) { .dentry = origin, .layer = lower[i].layer };
*ctrp = 1;
return 0;
@@ -384,13 +382,13 @@ int ovl_verify_origin(struct dentry *dentry, struct vfsmount *mnt,
* 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_lower *lower,
unsigned int numlower)
{
struct ovl_fh *fh = NULL;
size_t len;
- struct path origin = { };
- struct path *stack = &origin;
+ struct ovl_lower origin = { };
+ struct ovl_lower *stack = &origin;
unsigned int ctr = 0;
int err;
@@ -430,7 +428,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)
@@ -568,7 +566,8 @@ 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;
}
@@ -581,7 +580,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_lower *stack = NULL;
struct dentry *upperdir, *upperdentry = NULL;
struct dentry *index = NULL;
unsigned int ctr = 0;
@@ -645,17 +644,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_lower),
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_lower 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 +662,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)
@@ -674,7 +673,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
/* Find the current layer on the root dentry */
for (i = 0; i < poe->numlower; i++)
- if (poe->lowerstack[i].mnt == lowerpath.mnt)
+ if (poe->lowerstack[i].layer->mnt == lower.layer->mnt)
break;
if (WARN_ON(i == poe->numlower))
break;
@@ -699,7 +698,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_lower) * ctr);
dentry->d_fsdata = oe;
if (upperdentry)
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index d4e8c1a..7c747a5 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/uuid.h>
+#include "ovl_entry.h"
enum ovl_path_type {
__OVL_PATH_UPPER = (1 << 0),
@@ -245,7 +246,7 @@ static inline bool ovl_is_impuredir(struct dentry *dentry)
/* namei.c */
int ovl_verify_origin(struct dentry *dentry, struct vfsmount *mnt,
struct dentry *origin, bool is_upper, bool set);
-int ovl_verify_index(struct dentry *index, struct path *lowerstack,
+int ovl_verify_index(struct dentry *index, struct ovl_lower *lower,
unsigned int numlower);
int ovl_get_index_name(struct dentry *origin, struct qstr *name);
int ovl_path_next(int idx, struct dentry *dentry, struct path *path);
@@ -262,7 +263,7 @@ int ovl_check_d_type_supported(struct path *realpath);
void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt,
struct dentry *dentry, int level);
int ovl_indexdir_cleanup(struct dentry *dentry, struct vfsmount *mnt,
- struct path *lowerstack, unsigned int numlower);
+ struct ovl_lower *lower, unsigned int numlower);
/* inode.c */
int ovl_set_nlink_upper(struct dentry *dentry);
diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
index 878a750..c2d9322 100644
--- a/fs/overlayfs/ovl_entry.h
+++ b/fs/overlayfs/ovl_entry.h
@@ -17,11 +17,21 @@ struct ovl_config {
bool index;
};
+struct ovl_lower_mnt {
+ struct vfsmount *mnt;
+ dev_t pseudo_dev;
+};
+
+struct ovl_lower {
+ struct ovl_lower_mnt *layer;
+ struct dentry *dentry;
+};
+
/* private information held for overlayfs's superblock */
struct ovl_fs {
struct vfsmount *upper_mnt;
unsigned numlower;
- struct vfsmount **lower_mnt;
+ struct ovl_lower_mnt *lower_mnt;
/* workbasedir is the path at workdir= mount option */
struct dentry *workbasedir;
/* workdir is the 'work' directory under workbasedir */
@@ -49,7 +59,7 @@ struct ovl_entry {
struct rcu_head rcu;
};
unsigned numlower;
- struct path lowerstack[];
+ struct ovl_lower lowerstack[];
};
struct ovl_entry *ovl_alloc_entry(unsigned int numlower);
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
index 62e9b22..02f48cb 100644
--- a/fs/overlayfs/readdir.c
+++ b/fs/overlayfs/readdir.c
@@ -985,7 +985,7 @@ void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt,
}
int ovl_indexdir_cleanup(struct dentry *dentry, struct vfsmount *mnt,
- struct path *lowerstack, unsigned int numlower)
+ struct ovl_lower *lower, unsigned int numlower)
{
int err;
struct inode *dir = dentry->d_inode;
@@ -1020,7 +1020,7 @@ int ovl_indexdir_cleanup(struct dentry *dentry, struct vfsmount *mnt,
err = PTR_ERR(index);
break;
}
- err = ovl_verify_index(index, lowerstack, numlower);
+ err = ovl_verify_index(index, lower, numlower);
if (err) {
if (err == -EROFS)
break;
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index fd5ea4f..8f0a28f 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -18,7 +18,6 @@
#include <linux/seq_file.h>
#include <linux/posix_acl_xattr.h>
#include "overlayfs.h"
-#include "ovl_entry.h"
MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
MODULE_DESCRIPTION("Overlay filesystem");
@@ -216,8 +215,10 @@ static void ovl_put_super(struct super_block *sb)
if (ufs->upper_mnt)
ovl_inuse_unlock(ufs->upper_mnt->mnt_root);
mntput(ufs->upper_mnt);
- for (i = 0; i < ufs->numlower; i++)
- mntput(ufs->lower_mnt[i]);
+ for (i = 0; i < ufs->numlower; i++) {
+ mntput(ufs->lower_mnt[i].mnt);
+ free_anon_bdev(ufs->lower_mnt[i].pseudo_dev);
+ }
kfree(ufs->lower_mnt);
kfree(ufs->config.lowerdir);
@@ -1015,15 +1016,25 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
}
err = -ENOMEM;
- ufs->lower_mnt = kcalloc(numlower, sizeof(struct vfsmount *), GFP_KERNEL);
+ ufs->lower_mnt = kcalloc(numlower, sizeof(struct ovl_lower_mnt),
+ GFP_KERNEL);
if (ufs->lower_mnt == NULL)
goto out_put_workdir;
for (i = 0; i < numlower; i++) {
- struct vfsmount *mnt = clone_private_mount(&stack[i]);
+ struct vfsmount *mnt;
+ dev_t dev;
+
+ err = get_anon_bdev(&dev);
+ if (err) {
+ pr_err("overlayfs: failed to get anonymous bdev for lowerpath\n");
+ goto out_put_lower_mnt;
+ }
+ mnt = clone_private_mount(&stack[i]);
err = PTR_ERR(mnt);
if (IS_ERR(mnt)) {
pr_err("overlayfs: failed to clone lowerpath\n");
+ free_anon_bdev(dev);
goto out_put_lower_mnt;
}
/*
@@ -1032,7 +1043,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
*/
mnt->mnt_flags |= MNT_READONLY | MNT_NOATIME;
- ufs->lower_mnt[ufs->numlower] = mnt;
+ ufs->lower_mnt[ufs->numlower].mnt = mnt;
+ ufs->lower_mnt[ufs->numlower].pseudo_dev = dev;
ufs->numlower++;
/* Check if all lower layers are on same sb */
@@ -1048,13 +1060,23 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
else if (ufs->upper_mnt->mnt_sb != ufs->same_sb)
ufs->same_sb = NULL;
+ err = -ENOMEM;
+ oe = ovl_alloc_entry(numlower);
+ if (!oe)
+ goto out_put_lower_mnt;
+
+ for (i = 0; i < numlower; i++) {
+ oe->lowerstack[i].dentry = stack[i].dentry;
+ oe->lowerstack[i].layer = &(ufs->lower_mnt[i]);
+ }
+
if (!(ovl_force_readonly(ufs)) && ufs->config.index) {
/* Verify lower root is upper root origin */
- err = ovl_verify_origin(upperpath.dentry, ufs->lower_mnt[0],
- stack[0].dentry, false, true);
+ err = ovl_verify_origin(upperpath.dentry, oe->lowerstack[0].layer->mnt,
+ oe->lowerstack[0].dentry, false, true);
if (err) {
pr_err("overlayfs: failed to verify upper root origin\n");
- goto out_put_lower_mnt;
+ goto out_free_oe;
}
ufs->indexdir = ovl_workdir_create(sb, ufs, workpath.dentry,
@@ -1070,7 +1092,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
if (!err)
err = ovl_indexdir_cleanup(ufs->indexdir,
ufs->upper_mnt,
- stack, numlower);
+ oe->lowerstack,
+ numlower);
}
if (err || !ufs->indexdir)
pr_warn("overlayfs: try deleting index dir or mounting with '-o index=off' to disable inodes index.\n");
@@ -1095,11 +1118,6 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
/* Never override disk quota limits or use reserved space */
cap_lower(cred->cap_effective, CAP_SYS_RESOURCE);
- err = -ENOMEM;
- oe = ovl_alloc_entry(numlower);
- if (!oe)
- goto out_put_cred;
-
sb->s_magic = OVERLAYFS_SUPER_MAGIC;
sb->s_op = &ovl_super_operations;
sb->s_xattr = ovl_xattr_handlers;
@@ -1108,11 +1126,12 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
root_dentry = d_make_root(ovl_new_inode(sb, S_IFDIR, 0));
if (!root_dentry)
- goto out_free_oe;
+ goto out_put_cred;
mntput(upperpath.mnt);
for (i = 0; i < numlower; i++)
mntput(stack[i].mnt);
+ kfree(stack);
mntput(workpath.mnt);
kfree(lowertmp);
@@ -1121,11 +1140,6 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
if (ovl_is_impuredir(upperpath.dentry))
ovl_set_flag(OVL_IMPURE, d_inode(root_dentry));
}
- for (i = 0; i < numlower; i++) {
- oe->lowerstack[i].dentry = stack[i].dentry;
- oe->lowerstack[i].mnt = ufs->lower_mnt[i];
- }
- kfree(stack);
root_dentry->d_fsdata = oe;
@@ -1136,15 +1150,18 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
return 0;
-out_free_oe:
- kfree(oe);
out_put_cred:
put_cred(ufs->creator_cred);
out_put_indexdir:
dput(ufs->indexdir);
+out_free_oe:
+ kfree(oe);
out_put_lower_mnt:
- for (i = 0; i < ufs->numlower; i++)
- mntput(ufs->lower_mnt[i]);
+ for (i = 0; i < ufs->numlower; i++) {
+ if (ufs->lower_mnt[i].mnt)
+ free_anon_bdev(ufs->lower_mnt[i].pseudo_dev);
+ mntput(ufs->lower_mnt[i].mnt);
+ }
kfree(ufs->lower_mnt);
out_put_workdir:
dput(ufs->workdir);
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index 1177945..c7d5b4a 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -17,7 +17,6 @@
#include <linux/namei.h>
#include <linux/ratelimit.h>
#include "overlayfs.h"
-#include "ovl_entry.h"
int ovl_want_write(struct dentry *dentry)
{
@@ -125,7 +124,12 @@ void ovl_path_lower(struct dentry *dentry, struct path *path)
{
struct ovl_entry *oe = dentry->d_fsdata;
- *path = oe->numlower ? oe->lowerstack[0] : (struct path) { };
+ if (oe->numlower) {
+ path->mnt = oe->lowerstack[0].layer->mnt;
+ path->dentry = oe->lowerstack[0].dentry;
+ } else {
+ *path = (struct path) { };
+ }
}
enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path)
--
2.9.5
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/3] ovl: relax same fs constrain for constant st_ino
2017-10-06 9:25 [PATCH 1/3] ovl: Allocate anonymous devs for lowerdirs Chandan Rajendra
@ 2017-10-06 9:25 ` Chandan Rajendra
2017-10-06 9:25 ` [PATCH 3/3] ovl: Relax same fs constraint for constant d_ino Chandan Rajendra
1 sibling, 0 replies; 3+ messages in thread
From: Chandan Rajendra @ 2017-10-06 9:25 UTC (permalink / raw)
To: linux-unionfs, amir73il; +Cc: miklos
From: Amir Goldstein <amir73il@gmail.com>
For the case of all layers not on the same fs, use the copy up
origin st_ino for non-dir, if we know it.
This guaranties constant and system-wide unique st_ino/st_dev
for non-dir across copy up. Like the same fs case, st_ino of
non-dir is also persistent. Unlink the same fs case, st_dev is
not persistent.
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
---
fs/overlayfs/inode.c | 36 +++++++++++++++++++++---------------
1 file changed, 21 insertions(+), 15 deletions(-)
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 3091cd6..38aabb0 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -82,6 +82,7 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
struct path realpath;
const struct cred *old_cred;
bool is_dir = S_ISDIR(dentry->d_inode->i_mode);
+ bool samefs = ovl_same_sb(dentry->d_sb);
int err;
type = ovl_path_real(dentry, &realpath);
@@ -91,16 +92,16 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
goto out;
/*
- * When all layers are on the same fs, all real inode number are
- * unique, so we use the overlay st_dev, which is friendly to du -x.
- *
- * We also use st_ino of the copy up origin, if we know it.
- * This guaranties constant st_dev/st_ino across copy up.
+ * For non-dir or same fs, we use st_ino of the copy up origin, if we
+ * know it. This guaranties constant st_dev/st_ino across copy up.
*
* If filesystem supports NFS export ops, this also guaranties
* persistent st_ino across mount cycle.
+ *
+ * When all layers are on the same fs, all real inode number are
+ * unique, so we use the overlay st_dev, which is friendly to du -x.
*/
- if (ovl_same_sb(dentry->d_sb)) {
+ if (!is_dir || samefs) {
if (OVL_TYPE_ORIGIN(type)) {
struct kstat lowerstat;
u32 lowermask = STATX_INO | (!is_dir ? STATX_NLINK : 0);
@@ -111,7 +112,6 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
if (err)
goto out;
- WARN_ON_ONCE(stat->dev != lowerstat.dev);
/*
* Lower hardlinks may be broken on copy up to different
* upper files, so we cannot use the lower origin st_ino
@@ -123,22 +123,28 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
if (is_dir || lowerstat.nlink == 1 ||
ovl_test_flag(OVL_INDEX, d_inode(dentry)))
stat->ino = lowerstat.ino;
+
+ if (samefs)
+ WARN_ON_ONCE(stat->dev != lowerstat.dev);
+ else
+ stat->dev = lowerstat.dev;
}
- stat->dev = dentry->d_sb->s_dev;
- } else if (is_dir) {
+ if (samefs)
+ stat->dev = dentry->d_sb->s_dev;
+ else
+ stat->dev = ovl_get_pseudo_dev(dentry, stat->dev);
+ } else {
/*
- * If not all layers are on the same fs the pair {real st_ino;
- * overlay st_dev} is not unique, so use the non persistent
- * overlay st_ino.
- *
* Always use the overlay st_dev for directories, so 'find
* -xdev' will scan the entire overlay mount and won't cross the
* overlay mount boundaries.
+ *
+ * If not all layers are on the same fs the pair {real st_ino;
+ * overlay st_dev} is not unique, so use the non persistent
+ * overlay st_ino for directories.
*/
stat->dev = dentry->d_sb->s_dev;
stat->ino = dentry->d_inode->i_ino;
- } else {
- stat->dev = ovl_get_pseudo_dev(dentry, stat->dev);
}
/*
--
2.9.5
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 3/3] ovl: Relax same fs constraint for constant d_ino
2017-10-06 9:25 [PATCH 1/3] ovl: Allocate anonymous devs for lowerdirs Chandan Rajendra
2017-10-06 9:25 ` [PATCH 2/3] ovl: relax same fs constrain for constant st_ino Chandan Rajendra
@ 2017-10-06 9:25 ` Chandan Rajendra
1 sibling, 0 replies; 3+ messages in thread
From: Chandan Rajendra @ 2017-10-06 9:25 UTC (permalink / raw)
To: linux-unionfs, amir73il; +Cc: Chandan Rajendra, miklos
For a pure upper dir in a non-samefs setup, ovl_getattr() returns the
overlay inode number as the value of st_ino. To keep in line with this
behaviour, ovl_fill_real() has been modified to return overlay inode
number of the "." entry as the d_ino of a pure upper dir.
Signed-off-by: Chandan Rajendra <chandan@linux.vnet.ibm.com>
---
fs/overlayfs/readdir.c | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
index 02f48cb..21e82ff 100644
--- a/fs/overlayfs/readdir.c
+++ b/fs/overlayfs/readdir.c
@@ -428,7 +428,6 @@ static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry)
* sure that d_ino will be consistent with st_ino from stat(2).
*/
static int ovl_cache_update_ino(struct path *path, struct ovl_cache_entry *p)
-
{
struct dentry *dir = path->dentry;
struct dentry *this = NULL;
@@ -436,9 +435,6 @@ static int ovl_cache_update_ino(struct path *path, struct ovl_cache_entry *p)
u64 ino = p->real_ino;
int err = 0;
- if (!ovl_same_sb(dir->d_sb))
- goto out;
-
if (p->name[0] == '.') {
if (p->len == 1) {
this = dget(dir);
@@ -470,8 +466,8 @@ static int ovl_cache_update_ino(struct path *path, struct ovl_cache_entry *p)
err = vfs_getattr(&statpath, &stat, STATX_INO, 0);
if (err)
goto fail;
-
- WARN_ON_ONCE(dir->d_sb->s_dev != stat.dev);
+ if (d_is_dir(this) || ovl_same_sb(this->d_sb))
+ WARN_ON_ONCE(dir->d_sb->s_dev != stat.dev);
ino = stat.ino;
}
@@ -593,6 +589,7 @@ struct ovl_readdir_translate {
struct ovl_dir_cache *cache;
struct dir_context ctx;
u64 parent_ino;
+ u64 current_ino;
};
static int ovl_fill_real(struct dir_context *ctx, const char *name,
@@ -605,6 +602,8 @@ static int ovl_fill_real(struct dir_context *ctx, const char *name,
if (rdt->parent_ino && strcmp(name, "..") == 0)
ino = rdt->parent_ino;
+ else if (rdt->current_ino && namelen == 1 && name[0] == '.')
+ ino = rdt->current_ino;
else if (rdt->cache) {
struct ovl_cache_entry *p;
@@ -645,6 +644,9 @@ static int ovl_iterate_real(struct file *file, struct dir_context *ctx)
return PTR_ERR(rdt.cache);
}
+ if (!ovl_same_sb(dir->d_sb))
+ rdt.current_ino = dir->d_inode->i_ino;
+
return iterate_dir(od->realfile, &rdt.ctx);
}
@@ -665,9 +667,9 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx)
* dir is impure then need to adjust d_ino for copied up
* entries.
*/
- if (ovl_same_sb(dentry->d_sb) &&
- (ovl_test_flag(OVL_IMPURE, d_inode(dentry)) ||
- OVL_TYPE_MERGE(ovl_path_type(dentry->d_parent)))) {
+ if (ovl_test_flag(OVL_IMPURE, d_inode(dentry)) ||
+ OVL_TYPE_MERGE(ovl_path_type(dentry->d_parent)) ||
+ !ovl_same_sb(dentry->d_sb)) {
return ovl_iterate_real(file, ctx);
}
return iterate_dir(od->realfile, ctx);
--
2.9.5
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2017-10-06 9:25 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-10-06 9:25 [PATCH 1/3] ovl: Allocate anonymous devs for lowerdirs Chandan Rajendra
2017-10-06 9:25 ` [PATCH 2/3] ovl: relax same fs constrain for constant st_ino Chandan Rajendra
2017-10-06 9:25 ` [PATCH 3/3] ovl: Relax same fs constraint for constant d_ino Chandan Rajendra
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).