On Thu, Jan 4, 2018 at 7:20 PM, Amir Goldstein <amir73il@xxxxxxxxx> wrote: > Lookup overlay inode in cache by origin inode, so we can decode a file > handle of an open file even if the index has a whiteout index entry to > mark this overlay inode was unlinked. > > Signed-off-by: Amir Goldstein <amir73il@xxxxxxxxx> > --- > fs/overlayfs/export.c | 22 ++++++++++++++++++++-- > fs/overlayfs/inode.c | 16 ++++++++++++++++ > fs/overlayfs/overlayfs.h | 1 + > 3 files changed, 37 insertions(+), 2 deletions(-) > > diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c > index 602bada474ba..6ecb54d4b52c 100644 > --- a/fs/overlayfs/export.c > +++ b/fs/overlayfs/export.c > @@ -385,13 +385,21 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb, > struct ovl_path *stack = &origin; > struct dentry *dentry = NULL; > struct dentry *index = NULL; > + struct inode *inode = NULL; > + bool is_deleted = false; > int err; > > /* First lookup indexed upper by fh */ > index = ovl_get_index_fh(ofs, fh); > err = PTR_ERR(index); > - if (IS_ERR(index)) > - return ERR_PTR(err); > + if (IS_ERR(index)) { > + if (err != -ESTALE) > + return ERR_PTR(err); > + > + /* Found a whiteout index - treat as deleted inode */ > + is_deleted = true; > + index = NULL; Ouch! it seems I was misleading you. If we find a whiteout index for dir, we *do* decode+reconnect origin, because we want to find out if this is an unlinked but open non-dir. I guess there are 2 ways to avoid this unneeded decode: 1. mark a "directory index whiteout" differently than "non-dir index whiteout" 2. lookup icache by file handle > + } > > /* Then lookup origin by fh */ > err = ovl_check_origin_fh(fh, NULL, ofs->lower_layers, ofs->numlower, > @@ -404,6 +412,15 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb, > err = ovl_verify_origin(index, origin.dentry, false, false); > if (err) > goto out_err; > + } else if (is_deleted && origin.dentry && !d_is_dir(origin.dentry)) { > + /* Lookup deleted overlay inode by origin inode */ > + inode = ovl_lookup_inode(sb, origin.dentry); > + err = -ESTALE; > + if (!inode || atomic_read(&inode->i_count) == 1) > + goto out_err; > + > + /* Deleted but still open? */ > + index = dget(ovl_i_dentry_upper(inode)); > } And to top that up, we even try to lookup the origin dir path in overlay instead of returning ESTALE right away. Sheesh! that's embarrassing. Thanks, Amir.