@@ -412,7 +412,8 @@ void ovl_inode_init(struct inode *inode, struct inode *realinode, bool is_upper)
{
ovl_inode_init_ino(inode, realinode);
ovl_set_inode_data(inode, realinode, is_upper);
- if (is_upper && !S_ISDIR(realinode->i_mode))
+ if (ovl_redirect_fh(inode->i_sb) ||
+ (is_upper && !S_ISDIR(realinode->i_mode)))
ovl_insert_inode_hash(inode, realinode);
}
@@ -420,13 +421,24 @@ void ovl_inode_update(struct inode *inode, struct inode *upperinode)
{
WARN_ON(!upperinode);
ovl_set_inode_data(inode, upperinode, true);
- if (!S_ISDIR(upperinode->i_mode))
+ if (!S_ISDIR(upperinode->i_mode) && !ovl_redirect_fh(inode->i_sb))
ovl_insert_inode_hash(inode, upperinode);
}
static int ovl_inode_test(struct inode *inode, void *data)
{
- return ovl_inode_real(inode, NULL) == OVL_INODE_REAL(data);
+ struct inode *realinode = OVL_INODE_REAL(data);
+
+ /*
+ * When all layers on same fs, compare by ino/generation of stable
+ * real inode, because i_private may get updated on copy up, but
+ * overlay inode ino/generation does not get updated.
+ */
+ if (ovl_same_sb(inode->i_sb))
+ return (inode->i_ino == realinode->i_ino &&
+ inode->i_generation == realinode->i_generation);
+ else
+ return ovl_inode_real(inode, NULL) == realinode;
}
static int ovl_inode_set(struct inode *inode, void *data)
@@ -469,7 +469,18 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
realinode = d_inode(realdentry);
err = -ENOMEM;
- if (upperdentry && !d_is_dir(upperdentry)) {
+ /* When redirect_fh is enabled, hash inodes by stable inode */
+ if (ofs->config.redirect_fh) {
+ struct dentry *stable = ctr ? stack[0].dentry :
+ upperdentry;
+
+ inode = ovl_get_inode(dentry->d_sb, d_inode(stable),
+ !!upperdentry);
+ /* ovl_inode_real() may not be the stable inode */
+ if (realinode != d_inode(stable))
+ ovl_inode_update(inode, realinode);
+
+ } else if (upperdentry && !d_is_dir(upperdentry)) {
inode = ovl_get_inode(dentry->d_sb, realinode, true);
} else {
inode = ovl_new_inode(dentry->d_sb, realinode->i_mode,
Non directory pure upper overlay inodes are hashed by the address of the upper real inode. When redirect_fh feature is enabled, hash all overlay inodes by the address of the 'stable' real inode. The stable real inode is the pre copy up inode if it stored in overlay.fh xattr or the pure upper real inode otherwise. This is going to be used for looking up an overlay inode from a real stable inode for exportfs operations. Signed-off-by: Amir Goldstein <amir73il@gmail.com> --- fs/overlayfs/inode.c | 18 +++++++++++++++--- fs/overlayfs/namei.c | 13 ++++++++++++- 2 files changed, 27 insertions(+), 4 deletions(-)