aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/overlayfs/copy_up.c1
-rw-r--r--fs/overlayfs/dir.c1
-rw-r--r--fs/overlayfs/namei.c4
-rw-r--r--fs/overlayfs/overlayfs.h2
-rw-r--r--fs/overlayfs/ovl_entry.h5
-rw-r--r--fs/overlayfs/super.c1
-rw-r--r--fs/overlayfs/util.c19
7 files changed, 31 insertions, 2 deletions
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 8f9e26e91386..58c06bd58a96 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -472,6 +472,7 @@ static int ovl_copy_up_locked(struct ovl_copy_up_ctx *c)
472 if (err) 472 if (err)
473 goto out_cleanup; 473 goto out_cleanup;
474 474
475 ovl_dentry_set_upper_alias(c->dentry);
475 ovl_inode_update(d_inode(c->dentry), newdentry); 476 ovl_inode_update(d_inode(c->dentry), newdentry);
476out: 477out:
477 dput(temp); 478 dput(temp);
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index a072c27e03bc..8b2b23181b19 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -156,6 +156,7 @@ static void ovl_instantiate(struct dentry *dentry, struct inode *inode,
156 struct dentry *newdentry, bool hardlink) 156 struct dentry *newdentry, bool hardlink)
157{ 157{
158 ovl_dentry_version_inc(dentry->d_parent); 158 ovl_dentry_version_inc(dentry->d_parent);
159 ovl_dentry_set_upper_alias(dentry);
159 if (!hardlink) { 160 if (!hardlink) {
160 ovl_inode_update(inode, newdentry); 161 ovl_inode_update(inode, newdentry);
161 ovl_copyattr(newdentry->d_inode, inode); 162 ovl_copyattr(newdentry->d_inode, inode);
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index f7fb0c919419..2d8b6292fe21 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -674,7 +674,9 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
674 memcpy(oe->lowerstack, stack, sizeof(struct path) * ctr); 674 memcpy(oe->lowerstack, stack, sizeof(struct path) * ctr);
675 dentry->d_fsdata = oe; 675 dentry->d_fsdata = oe;
676 676
677 if (index && !upperdentry) 677 if (upperdentry)
678 ovl_dentry_set_upper_alias(dentry);
679 else if (index)
678 upperdentry = dget(index); 680 upperdentry = dget(index);
679 681
680 if (upperdentry || ctr) { 682 if (upperdentry || ctr) {
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index f3e49cf34517..751b36a5c22f 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -206,6 +206,8 @@ void ovl_set_dir_cache(struct dentry *dentry, struct ovl_dir_cache *cache);
206bool ovl_dentry_is_opaque(struct dentry *dentry); 206bool ovl_dentry_is_opaque(struct dentry *dentry);
207bool ovl_dentry_is_whiteout(struct dentry *dentry); 207bool ovl_dentry_is_whiteout(struct dentry *dentry);
208void ovl_dentry_set_opaque(struct dentry *dentry); 208void ovl_dentry_set_opaque(struct dentry *dentry);
209bool ovl_dentry_has_upper_alias(struct dentry *dentry);
210void ovl_dentry_set_upper_alias(struct dentry *dentry);
209bool ovl_redirect_dir(struct super_block *sb); 211bool ovl_redirect_dir(struct super_block *sb);
210const char *ovl_dentry_get_redirect(struct dentry *dentry); 212const char *ovl_dentry_get_redirect(struct dentry *dentry);
211void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect); 213void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect);
diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
index 9642ec64467b..878a750986dd 100644
--- a/fs/overlayfs/ovl_entry.h
+++ b/fs/overlayfs/ovl_entry.h
@@ -42,7 +42,10 @@ struct ovl_fs {
42/* private information held for every overlayfs dentry */ 42/* private information held for every overlayfs dentry */
43struct ovl_entry { 43struct ovl_entry {
44 union { 44 union {
45 bool opaque; 45 struct {
46 unsigned long has_upper;
47 bool opaque;
48 };
46 struct rcu_head rcu; 49 struct rcu_head rcu;
47 }; 50 };
48 unsigned numlower; 51 unsigned numlower;
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 791581c370f5..f29ee08cf99f 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -1119,6 +1119,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
1119 kfree(lowertmp); 1119 kfree(lowertmp);
1120 1120
1121 if (upperpath.dentry) { 1121 if (upperpath.dentry) {
1122 oe->has_upper = true;
1122 if (ovl_is_impuredir(upperpath.dentry)) 1123 if (ovl_is_impuredir(upperpath.dentry))
1123 ovl_set_flag(OVL_IMPURE, d_inode(root_dentry)); 1124 ovl_set_flag(OVL_IMPURE, d_inode(root_dentry));
1124 } 1125 }
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index c80b4bf1e64f..38fa75228c66 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -201,6 +201,25 @@ void ovl_dentry_set_opaque(struct dentry *dentry)
201 oe->opaque = true; 201 oe->opaque = true;
202} 202}
203 203
204/*
205 * For hard links it's possible for ovl_dentry_upper() to return positive, while
206 * there's no actual upper alias for the inode. Copy up code needs to know
207 * about the existence of the upper alias, so it can't use ovl_dentry_upper().
208 */
209bool ovl_dentry_has_upper_alias(struct dentry *dentry)
210{
211 struct ovl_entry *oe = dentry->d_fsdata;
212
213 return oe->has_upper;
214}
215
216void ovl_dentry_set_upper_alias(struct dentry *dentry)
217{
218 struct ovl_entry *oe = dentry->d_fsdata;
219
220 oe->has_upper = true;
221}
222
204bool ovl_redirect_dir(struct super_block *sb) 223bool ovl_redirect_dir(struct super_block *sb)
205{ 224{
206 struct ovl_fs *ofs = sb->s_fs_info; 225 struct ovl_fs *ofs = sb->s_fs_info;