diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index 4654c03dd508..23d64d51f331 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -490,6 +490,10 @@ struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry) } ovl_fill_inode(inode, realinode->i_mode, realinode->i_rdev); ovl_inode_init(inode, upperdentry, lowerdentry); + + if (upperdentry && ovl_is_impuredir(upperdentry)) + ovl_set_flag(OVL_IMPURE, inode); + if (inode->i_state & I_NEW) unlock_new_inode(inode); out: diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c index 1b6092b80330..277a55c8299a 100644 --- a/fs/overlayfs/namei.c +++ b/fs/overlayfs/namei.c @@ -341,7 +341,6 @@ 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; @@ -386,8 +385,6 @@ 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) { @@ -434,7 +431,6 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, goto out_put; oe->opaque = upperopaque; - oe->impure = upperimpure; memcpy(oe->lowerstack, stack, sizeof(struct path) * ctr); dentry->d_fsdata = oe; diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 83607f883ace..b1be3d39ac9d 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -26,6 +26,10 @@ enum ovl_path_type { #define OVL_XATTR_ORIGIN OVL_XATTR_PREFIX "origin" #define OVL_XATTR_IMPURE OVL_XATTR_PREFIX "impure" +enum ovl_flag { + OVL_IMPURE, +}; + /* * The tuple (fh,uuid) is a universal unique identifier for a copy up origin, * where: @@ -195,7 +199,6 @@ struct inode *ovl_inode_real(struct inode *inode); struct ovl_dir_cache *ovl_dir_cache(struct dentry *dentry); void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache); bool ovl_dentry_is_opaque(struct dentry *dentry); -bool ovl_dentry_is_impure(struct dentry *dentry); bool ovl_dentry_is_whiteout(struct dentry *dentry); void ovl_dentry_set_opaque(struct dentry *dentry); bool ovl_redirect_dir(struct super_block *sb); @@ -215,6 +218,8 @@ int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry, const char *name, const void *value, size_t size, int xerr); int ovl_set_impure(struct dentry *dentry, struct dentry *upperdentry); +void ovl_set_flag(unsigned long flag, struct inode *inode); +bool ovl_test_flag(unsigned long flag, struct inode *inode); static inline bool ovl_is_impuredir(struct dentry *dentry) { diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h index 477d21738656..50dfa4826152 100644 --- a/fs/overlayfs/ovl_entry.h +++ b/fs/overlayfs/ovl_entry.h @@ -41,7 +41,6 @@ struct ovl_entry { struct { u64 version; bool opaque; - bool impure; bool copying; }; struct rcu_head rcu; @@ -54,6 +53,7 @@ struct ovl_entry *ovl_alloc_entry(unsigned int numlower); struct ovl_inode { const char *redirect; + unsigned long flags; struct inode vfs_inode; struct dentry *__upperdentry; struct inode *lower; diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 7346518846c5..7c7b946b063f 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -170,6 +170,7 @@ static struct inode *ovl_alloc_inode(struct super_block *sb) struct ovl_inode *oi = kmem_cache_alloc(ovl_inode_cachep, GFP_KERNEL); oi->redirect = NULL; + oi->flags = 0; oi->__upperdentry = NULL; oi->lower = NULL; @@ -1004,7 +1005,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) kfree(lowertmp); if (upperpath.dentry) { - oe->impure = ovl_is_impuredir(upperpath.dentry); + if (ovl_is_impuredir(upperpath.dentry)) + ovl_set_flag(OVL_IMPURE, d_inode(root_dentry)); } for (i = 0; i < numlower; i++) { oe->lowerstack[i].dentry = stack[i].dentry; diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index be0670f1addf..2fc4c22707aa 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -178,13 +178,6 @@ bool ovl_dentry_is_opaque(struct dentry *dentry) return oe->opaque; } -bool ovl_dentry_is_impure(struct dentry *dentry) -{ - struct ovl_entry *oe = dentry->d_fsdata; - - return oe->impure; -} - bool ovl_dentry_is_whiteout(struct dentry *dentry) { return !dentry->d_inode && ovl_dentry_is_opaque(dentry); @@ -344,9 +337,8 @@ int ovl_check_setxattr(struct dentry *dentry, struct dentry *upperdentry, int ovl_set_impure(struct dentry *dentry, struct dentry *upperdentry) { int err; - struct ovl_entry *oe = dentry->d_fsdata; - if (oe->impure) + if (ovl_test_flag(OVL_IMPURE, d_inode(dentry))) return 0; /* @@ -356,7 +348,17 @@ int ovl_set_impure(struct dentry *dentry, struct dentry *upperdentry) err = ovl_check_setxattr(dentry, upperdentry, OVL_XATTR_IMPURE, "y", 1, 0); if (!err) - oe->impure = true; + ovl_set_flag(OVL_IMPURE, d_inode(dentry)); return err; } + +void ovl_set_flag(unsigned long flag, struct inode *inode) +{ + set_bit(flag, &OVL_I(inode)->flags); +} + +bool ovl_test_flag(unsigned long flag, struct inode *inode) +{ + return test_bit(flag, &OVL_I(inode)->flags); +}