parent
c9cc46e14a
commit
c02f4b604f
@ -1,32 +1,94 @@
|
||||
# Calculate format=diff
|
||||
After rename file dentry still holds reference to lower dentry from
|
||||
previous location. This doesn't matter for data access because data
|
||||
cames from upper dentry. But this stale lower dentry taints dentry
|
||||
at new location and turns it into non-pure upper. Such file leaves
|
||||
visible whiteout entry after remove in directory which shouldn't
|
||||
have whiteouts at all.
|
||||
|
||||
Overlayfs already tracks pureness of file location in oe->opaque.
|
||||
This patch just uses that for detecting actual path type.
|
||||
|
||||
Comment from Vivek Goyal's patch:
|
||||
|
||||
Here are the details of the problem. Do following.
|
||||
|
||||
$ mkdir upper lower work merged upper/dir/
|
||||
$ touch lower/test
|
||||
$ sudo mount -t overlay overlay -olowerdir=lower,upperdir=upper,workdir=work
|
||||
merged
|
||||
$ mv merged/test merged/dir/
|
||||
$ rm merged/dir/test
|
||||
$ ls -l merged/dir/
|
||||
/usr/bin/ls: cannot access merged/dir/test: No such file or directory
|
||||
total 0
|
||||
c????????? ? ? ? ? ? test
|
||||
Basic problem seems to be that once a file has been unlinked, a
|
||||
whiteout has been left behind which was not needed and hence it becomes
|
||||
visible.
|
||||
|
||||
whiteout is visible because parent dir is of not type MERGE, hence
|
||||
od->is_real is set during ovl_dir_open(). And that means ovl_iterate()
|
||||
passes on iterate handling directly to underlying fs. Underlying fs does
|
||||
not know/filter whiteouts so it becomes visible to user.
|
||||
|
||||
Why did we leave a whiteout to begin with when we should not have.
|
||||
ovl_do_remove() checks for OVL_TYPE_PURE_UPPER() and does not leave
|
||||
whiteout if file is pure upper. In this case file is not found to be
|
||||
pure upper hence whiteout is left.
|
||||
|
||||
So why file was not PURE_UPPER in this case? I think because dentry is
|
||||
still carrying some leftover state which was valid before rename. For example,
|
||||
od->numlower was set to 1 as it was a lower file. After rename, this state
|
||||
is not valid anymore as there is no such file in lower.
|
||||
|
||||
Signed-off-by: Konstantin Khlebnikov <koct9i@gmail.com>
|
||||
Reported-by: Viktor Stanchev <me@viktorstanchev.com>
|
||||
Diagnosed-by: Vivek Goyal <vgoyal@redhat.com>
|
||||
Link: https://bugzilla.kernel.org/show_bug.cgi?id=109611
|
||||
---
|
||||
fs/overlayfs/dir.c | 7 +++++++
|
||||
fs/overlayfs/super.c | 12 +++++++-----
|
||||
2 files changed, 14 insertions(+), 5 deletions(-)
|
||||
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
|
||||
index 692ceda..a2fd06b 100644
|
||||
index ed95272d57a6..edf83f325bca 100644
|
||||
--- a/fs/overlayfs/dir.c
|
||||
+++ b/fs/overlayfs/dir.c
|
||||
@@ -637,7 +637,7 @@ static inline int ovl_check_sticky(struct dentry *dentry)
|
||||
@@ -903,6 +903,13 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
|
||||
if (!overwrite && new_is_dir && !old_opaque && new_opaque)
|
||||
ovl_remove_opaque(newdentry);
|
||||
|
||||
static int ovl_do_remove(struct dentry *dentry, bool is_dir)
|
||||
{
|
||||
- enum ovl_path_type type;
|
||||
+ enum ovl_path_type type, parent_type;
|
||||
int err;
|
||||
|
||||
err = ovl_check_sticky(dentry);
|
||||
@@ -653,7 +653,16 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
|
||||
goto out_drop_write;
|
||||
|
||||
type = ovl_path_type(dentry);
|
||||
- if (OVL_TYPE_PURE_UPPER(type)) {
|
||||
+ parent_type = ovl_path_type(dentry->d_parent);
|
||||
+
|
||||
+ /*
|
||||
+ * After rename if a file is removed, it could have out of sync
|
||||
+ * numlower and forced "opaque" set which means file will not be
|
||||
+ * categorized as pure upper. So if parent is not type merge, then
|
||||
+ * it is not present in any of the lower so there should not be
|
||||
+ * any need to leave whiteout.
|
||||
+ * Old dentry now lives in different location. Dentries in
|
||||
+ * lowerstack are stale. We cannot drop them here because
|
||||
+ * access to them is lockless. This could be only pure upper
|
||||
+ * or opaque directory - numlower is zero. Or upper non-dir
|
||||
+ * entry - its pureness is tracked by flag opaque.
|
||||
+ */
|
||||
+ if (OVL_TYPE_PURE_UPPER(type) || !OVL_TYPE_MERGE(parent_type)) {
|
||||
err = ovl_remove_upper(dentry, is_dir);
|
||||
if (old_opaque != new_opaque) {
|
||||
ovl_dentry_set_opaque(old, new_opaque);
|
||||
if (!overwrite)
|
||||
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
|
||||
index 8d826bd56b26..ba28b007005e 100644
|
||||
--- a/fs/overlayfs/super.c
|
||||
+++ b/fs/overlayfs/super.c
|
||||
@@ -76,12 +76,14 @@ enum ovl_path_type ovl_path_type(struct dentry *dentry)
|
||||
if (oe->__upperdentry) {
|
||||
type = __OVL_PATH_UPPER;
|
||||
|
||||
- if (oe->numlower) {
|
||||
- if (S_ISDIR(dentry->d_inode->i_mode))
|
||||
- type |= __OVL_PATH_MERGE;
|
||||
- } else if (!oe->opaque) {
|
||||
+ /*
|
||||
+ * Non-dir dentry can hold lower dentry from previous
|
||||
+ * location. Its purity depends only on opaque flag.
|
||||
+ */
|
||||
+ if (oe->numlower && S_ISDIR(dentry->d_inode->i_mode))
|
||||
+ type |= __OVL_PATH_MERGE;
|
||||
+ else if (!oe->opaque)
|
||||
type |= __OVL_PATH_PURE;
|
||||
- }
|
||||
} else {
|
||||
const struct cred *old_cred;
|
||||
if (oe->numlower > 1)
|
||||
type |= __OVL_PATH_MERGE;
|
||||
|
@ -1,36 +0,0 @@
|
||||
# Copyright 1999-2015 Gentoo Foundation
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# $Header: $
|
||||
|
||||
EAPI=4
|
||||
ETYPE="sources"
|
||||
|
||||
inherit calculate-kernel-6 eutils
|
||||
|
||||
DESCRIPTION="Calculate Linux kernel image"
|
||||
KEYWORDS="amd64 x86"
|
||||
HOMEPAGE="http://www.calculate-linux.org"
|
||||
|
||||
IUSE="themes firmware"
|
||||
|
||||
DEPEND="vmlinuz? ( || ( app-arch/xz-utils app-arch/lzma-utils )
|
||||
sys-apps/v86d
|
||||
sys-boot/grub
|
||||
)
|
||||
firmware? ( sys-kernel/linux-firmware )
|
||||
themes? ( media-gfx/splash-themes-calculate )
|
||||
"
|
||||
|
||||
RDEPEND="${DEPEND}
|
||||
!<app-emulation/virtualbox-modules-4.3.24
|
||||
"
|
||||
|
||||
SRC_URI="${KERNEL_URI} ${ARCH_URI}"
|
||||
|
||||
src_unpack() {
|
||||
calculate-kernel-6_src_unpack
|
||||
}
|
||||
|
||||
pkg_postinst() {
|
||||
calculate-kernel-6_pkg_postinst
|
||||
}
|
Loading…
Reference in new issue