aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2018-01-14 19:25:31 +0200
committerMiklos Szeredi <mszeredi@redhat.com>2018-01-24 11:25:58 +0100
commitc62520a83bceae0bb0b7b3de10c3e81205cd3823 (patch)
treef94b1fca8653e0a659d729859b188a74caaebaec
parentovl: copy up of disconnected dentries (diff)
downloadlinux-dev-c62520a83bceae0bb0b7b3de10c3e81205cd3823.tar.xz
linux-dev-c62520a83bceae0bb0b7b3de10c3e81205cd3823.zip
ovl: store 'has_upper' and 'opaque' as bit flags
We need to make some room in struct ovl_entry to store information about redirected ancestors for NFS export, so cram two booleans as bit flags. Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r--fs/overlayfs/namei.c7
-rw-r--r--fs/overlayfs/overlayfs.h10
-rw-r--r--fs/overlayfs/ovl_entry.h8
-rw-r--r--fs/overlayfs/super.c6
-rw-r--r--fs/overlayfs/util.c30
5 files changed, 41 insertions, 20 deletions
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index 9d3ccbd95dde..ca15893cfaa9 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -957,10 +957,12 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
if (!oe)
goto out_put;
- oe->opaque = upperopaque;
memcpy(oe->lowerstack, stack, sizeof(struct ovl_path) * ctr);
dentry->d_fsdata = oe;
+ if (upperopaque)
+ ovl_dentry_set_opaque(dentry);
+
if (upperdentry)
ovl_dentry_set_upper_alias(dentry);
else if (index)
@@ -1003,7 +1005,6 @@ out:
bool ovl_lower_positive(struct dentry *dentry)
{
- struct ovl_entry *oe = dentry->d_fsdata;
struct ovl_entry *poe = dentry->d_parent->d_fsdata;
const struct qstr *name = &dentry->d_name;
const struct cred *old_cred;
@@ -1016,7 +1017,7 @@ bool ovl_lower_positive(struct dentry *dentry)
* whiteout.
*/
if (!dentry->d_inode)
- return oe->opaque;
+ return ovl_dentry_is_opaque(dentry);
/* Negative upper -> positive lower */
if (!ovl_dentry_upper(dentry))
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index f9fce7a680cd..2dddcd257eb3 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -29,7 +29,7 @@ enum ovl_path_type {
#define OVL_XATTR_NLINK OVL_XATTR_PREFIX "nlink"
#define OVL_XATTR_UPPER OVL_XATTR_PREFIX "upper"
-enum ovl_flag {
+enum ovl_inode_flag {
/* Pure upper dir that may contain non pure upper entries */
OVL_IMPURE,
/* Non-merge dir that may contain whiteout entries */
@@ -37,6 +37,11 @@ enum ovl_flag {
OVL_INDEX,
};
+enum ovl_entry_flag {
+ OVL_E_UPPER_ALIAS,
+ OVL_E_OPAQUE,
+};
+
/*
* The tuple (fh,uuid) is a universal unique identifier for a copy up origin,
* where:
@@ -213,6 +218,9 @@ struct inode *ovl_inode_lower(struct inode *inode);
struct inode *ovl_inode_real(struct inode *inode);
struct ovl_dir_cache *ovl_dir_cache(struct inode *inode);
void ovl_set_dir_cache(struct inode *inode, struct ovl_dir_cache *cache);
+void ovl_dentry_set_flag(unsigned long flag, struct dentry *dentry);
+void ovl_dentry_clear_flag(unsigned long flag, struct dentry *dentry);
+bool ovl_dentry_test_flag(unsigned long flag, struct dentry *dentry);
bool ovl_dentry_is_opaque(struct dentry *dentry);
bool ovl_dentry_is_whiteout(struct dentry *dentry);
void ovl_dentry_set_opaque(struct dentry *dentry);
diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
index 6dd60fcf8cb7..bfef6edcc111 100644
--- a/fs/overlayfs/ovl_entry.h
+++ b/fs/overlayfs/ovl_entry.h
@@ -61,8 +61,7 @@ struct ovl_fs {
struct ovl_entry {
union {
struct {
- unsigned long has_upper;
- bool opaque;
+ unsigned long flags;
};
struct rcu_head rcu;
};
@@ -72,6 +71,11 @@ struct ovl_entry {
struct ovl_entry *ovl_alloc_entry(unsigned int numlower);
+static inline struct ovl_entry *OVL_E(struct dentry *dentry)
+{
+ return (struct ovl_entry *) dentry->d_fsdata;
+}
+
struct ovl_inode {
struct ovl_dir_cache *cache;
const char *redirect;
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 170c184a9f43..fccdcfae68e9 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -1345,15 +1345,15 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
if (!root_dentry)
goto out_free_oe;
+ root_dentry->d_fsdata = oe;
+
mntput(upperpath.mnt);
if (upperpath.dentry) {
- oe->has_upper = true;
+ ovl_dentry_set_upper_alias(root_dentry);
if (ovl_is_impuredir(upperpath.dentry))
ovl_set_flag(OVL_IMPURE, d_inode(root_dentry));
}
- root_dentry->d_fsdata = oe;
-
/* Root is always merge -> can have whiteouts */
ovl_set_flag(OVL_WHITEOUTS, d_inode(root_dentry));
ovl_inode_init(d_inode(root_dentry), upperpath.dentry,
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index 68541eb5be8e..930784a26623 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -210,10 +210,24 @@ void ovl_set_dir_cache(struct inode *inode, struct ovl_dir_cache *cache)
OVL_I(inode)->cache = cache;
}
+void ovl_dentry_set_flag(unsigned long flag, struct dentry *dentry)
+{
+ set_bit(flag, &OVL_E(dentry)->flags);
+}
+
+void ovl_dentry_clear_flag(unsigned long flag, struct dentry *dentry)
+{
+ clear_bit(flag, &OVL_E(dentry)->flags);
+}
+
+bool ovl_dentry_test_flag(unsigned long flag, struct dentry *dentry)
+{
+ return test_bit(flag, &OVL_E(dentry)->flags);
+}
+
bool ovl_dentry_is_opaque(struct dentry *dentry)
{
- struct ovl_entry *oe = dentry->d_fsdata;
- return oe->opaque;
+ return ovl_dentry_test_flag(OVL_E_OPAQUE, dentry);
}
bool ovl_dentry_is_whiteout(struct dentry *dentry)
@@ -223,9 +237,7 @@ bool ovl_dentry_is_whiteout(struct dentry *dentry)
void ovl_dentry_set_opaque(struct dentry *dentry)
{
- struct ovl_entry *oe = dentry->d_fsdata;
-
- oe->opaque = true;
+ ovl_dentry_set_flag(OVL_E_OPAQUE, dentry);
}
/*
@@ -236,16 +248,12 @@ void ovl_dentry_set_opaque(struct dentry *dentry)
*/
bool ovl_dentry_has_upper_alias(struct dentry *dentry)
{
- struct ovl_entry *oe = dentry->d_fsdata;
-
- return oe->has_upper;
+ return ovl_dentry_test_flag(OVL_E_UPPER_ALIAS, dentry);
}
void ovl_dentry_set_upper_alias(struct dentry *dentry)
{
- struct ovl_entry *oe = dentry->d_fsdata;
-
- oe->has_upper = true;
+ ovl_dentry_set_flag(OVL_E_UPPER_ALIAS, dentry);
}
bool ovl_redirect_dir(struct super_block *sb)