The commit is pushed to "branch-rh7-3.10.0-514.6.1.vz7.28.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git after rh7-3.10.0-514.6.1.vz7.28.6 ------> commit ac92f4fd30a80bafb27cac001dba58b2e1f8c812 Author: Miklos Szeredi <mszer...@redhat.com> Date: Mon Feb 20 17:30:09 2017 +0400
ms/ovl: fix d_real() for stacked fs Handling of recursion in d_real() is completely broken. Recursion is only done in the 'inode != NULL' case. But when opening the file we have 'inode == NULL' hence d_real() will return an overlay dentry. This won't work since overlayfs doesn't define its own file operations, so all file ops will fail. Fix by doing the recursion first and the check against the inode second. Bash script to reproduce the issue written by Quentin: - 8< - - - - - 8< - - - - - 8< - - - - - 8< - - - - tmpdir=$(mktemp -d) pushd ${tmpdir} mkdir -p {upper,lower,work} echo -n 'rocks' > lower/ksplice mount -t overlay level_zero upper -o lowerdir=lower,upperdir=upper,workdir=work cat upper/ksplice tmpdir2=$(mktemp -d) pushd ${tmpdir2} mkdir -p {upper,work} mount -t overlay level_one upper -o lowerdir=${tmpdir}/upper,upperdir=upper,workdir=work ls -l upper/ksplice cat upper/ksplice - 8< - - - - - 8< - - - - - 8< - - - - - 8< - - - - Reported-by: Quentin Casasnovas <quentin.casasno...@oracle.com> Signed-off-by: Miklos Szeredi <mszer...@redhat.com> Fixes: 2d902671ce1c ("vfs: merge .d_select_inode() into .d_real()") Cc: <sta...@vger.kernel.org> # v4.8+ Found while investigating https://jira.sw.ru/browse/PSBM-58480 Signed-off-by: Pavel Tikhomirov <ptikhomi...@virtuozzo.com> --- fs/overlayfs/super.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 21db028..ed7b2f3 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -330,12 +330,11 @@ static struct dentry *ovl_d_real(struct dentry *dentry, if (!real) goto bug; - if (!inode || inode == d_inode(real)) - return real; - /* Handle recursion */ - return d_real(real, inode, open_flags); + real = d_real(real, inode, open_flags); + if (!inode || inode == d_inode(real)) + return real; bug: WARN(1, "ovl_d_real(%pd4, %s:%lu\n): real dentry not found\n", dentry, inode ? inode->i_sb->s_id : "NULL", inode ? inode->i_ino : 0); _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel