diff options
| -rw-r--r-- | fs/overlayfs/copy_up.c | 1 | ||||
| -rw-r--r-- | fs/overlayfs/dir.c | 1 | ||||
| -rw-r--r-- | fs/overlayfs/namei.c | 4 | ||||
| -rw-r--r-- | fs/overlayfs/overlayfs.h | 2 | ||||
| -rw-r--r-- | fs/overlayfs/ovl_entry.h | 5 | ||||
| -rw-r--r-- | fs/overlayfs/super.c | 1 | ||||
| -rw-r--r-- | fs/overlayfs/util.c | 19 |
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); |
| 476 | out: | 477 | out: |
| 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); | |||
| 206 | bool ovl_dentry_is_opaque(struct dentry *dentry); | 206 | bool ovl_dentry_is_opaque(struct dentry *dentry); |
| 207 | bool ovl_dentry_is_whiteout(struct dentry *dentry); | 207 | bool ovl_dentry_is_whiteout(struct dentry *dentry); |
| 208 | void ovl_dentry_set_opaque(struct dentry *dentry); | 208 | void ovl_dentry_set_opaque(struct dentry *dentry); |
| 209 | bool ovl_dentry_has_upper_alias(struct dentry *dentry); | ||
| 210 | void ovl_dentry_set_upper_alias(struct dentry *dentry); | ||
| 209 | bool ovl_redirect_dir(struct super_block *sb); | 211 | bool ovl_redirect_dir(struct super_block *sb); |
| 210 | const char *ovl_dentry_get_redirect(struct dentry *dentry); | 212 | const char *ovl_dentry_get_redirect(struct dentry *dentry); |
| 211 | void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect); | 213 | void 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 */ |
| 43 | struct ovl_entry { | 43 | struct 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 | */ | ||
| 209 | bool 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 | |||
| 216 | void 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 | |||
| 204 | bool ovl_redirect_dir(struct super_block *sb) | 223 | bool 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; |
