summaryrefslogtreecommitdiffstats
path: root/fs/overlayfs/namei.c
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2017-05-11 16:42:26 +0300
committerMiklos Szeredi <mszeredi@redhat.com>2017-05-19 09:33:49 +0200
commitee1d6d37b6b884383b501089be93ce94f2153028 (patch)
treefd490f8a866c66e17883c240e1caffff1896c2c8 /fs/overlayfs/namei.c
parent3d27573ce32b47ba54e6680c77c26a700d67cc16 (diff)
downloadlinux-stable-ee1d6d37b6b884383b501089be93ce94f2153028.tar.gz
linux-stable-ee1d6d37b6b884383b501089be93ce94f2153028.tar.bz2
linux-stable-ee1d6d37b6b884383b501089be93ce94f2153028.zip
ovl: mark upper dir with type origin entries "impure"
When moving a merge dir or non-dir with copy up origin into a non-merge upper dir (a.k.a pure upper dir), we are marking the target parent dir "impure". ovl_iterate() iterates pure upper dirs directly, because there is no need to filter out whiteouts and merge dir content with lower dir. But for the case of an "impure" upper dir, ovl_iterate() will not be able to iterate the real upper dir directly, because it will need to lookup the origin inode and use it to fill d_ino. Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/overlayfs/namei.c')
-rw-r--r--fs/overlayfs/namei.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index bad0f665a635..0c72a5909db2 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -167,7 +167,7 @@ invalid:
goto out;
}
-static bool ovl_is_opaquedir(struct dentry *dentry)
+static bool ovl_check_dir_xattr(struct dentry *dentry, const char *name)
{
int res;
char val;
@@ -175,13 +175,23 @@ static bool ovl_is_opaquedir(struct dentry *dentry)
if (!d_is_dir(dentry))
return false;
- res = vfs_getxattr(dentry, OVL_XATTR_OPAQUE, &val, 1);
+ res = vfs_getxattr(dentry, name, &val, 1);
if (res == 1 && val == 'y')
return true;
return false;
}
+static bool ovl_is_opaquedir(struct dentry *dentry)
+{
+ return ovl_check_dir_xattr(dentry, OVL_XATTR_OPAQUE);
+}
+
+static bool ovl_is_impuredir(struct dentry *dentry)
+{
+ return ovl_check_dir_xattr(dentry, OVL_XATTR_IMPURE);
+}
+
static int ovl_lookup_single(struct dentry *base, struct ovl_lookup_data *d,
const char *name, unsigned int namelen,
size_t prelen, const char *post,
@@ -351,6 +361,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
unsigned int ctr = 0;
struct inode *inode = NULL;
bool upperopaque = false;
+ bool upperimpure = false;
char *upperredirect = NULL;
struct dentry *this;
unsigned int i;
@@ -395,6 +406,8 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
poe = roe;
}
upperopaque = d.opaque;
+ if (upperdentry && d.is_dir)
+ upperimpure = ovl_is_impuredir(upperdentry);
}
if (!d.stop && poe->numlower) {
@@ -463,6 +476,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
revert_creds(old_cred);
oe->opaque = upperopaque;
+ oe->impure = upperimpure;
oe->redirect = upperredirect;
oe->__upperdentry = upperdentry;
memcpy(oe->lowerstack, stack, sizeof(struct path) * ctr);