aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVivek Goyal <vgoyal@redhat.com>2018-05-11 11:49:30 -0400
committerMiklos Szeredi <mszeredi@redhat.com>2018-07-20 03:56:11 -0400
commit2664bd0897c2889258472a1ee922ef9d4c5fa58f (patch)
tree4451f757dc52c00751c3158c24dc1bb004a6bc59
parent67d756c27ac4f4576dee313579724bd8711bc75e (diff)
ovl: Store lower data inode in ovl_inode
Right now ovl_inode stores inode pointer for lower inode. This helps with quickly getting lower inode given overlay inode (ovl_inode_lower()). Now with metadata only copy-up, we can have metacopy inode in middle layer as well and inode containing data can be different from ->lower. I need to be able to open the real file in ovl_open_realfile() and for that I need to quickly find the lower data inode. Hence store lower data inode also in ovl_inode. Also provide an helper ovl_inode_lowerdata() to access this field. Signed-off-by: Vivek Goyal <vgoyal@redhat.com> Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r--fs/overlayfs/inode.c2
-rw-r--r--fs/overlayfs/namei.c2
-rw-r--r--fs/overlayfs/overlayfs.h4
-rw-r--r--fs/overlayfs/ovl_entry.h5
-rw-r--r--fs/overlayfs/super.c8
-rw-r--r--fs/overlayfs/util.c12
6 files changed, 27 insertions, 6 deletions
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 2a5a38c81961..12553274eae7 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -864,7 +864,7 @@ struct inode *ovl_get_inode(struct super_block *sb,
864 } 864 }
865 } 865 }
866 ovl_fill_inode(inode, realinode->i_mode, realinode->i_rdev, ino, fsid); 866 ovl_fill_inode(inode, realinode->i_mode, realinode->i_rdev, ino, fsid);
867 ovl_inode_init(inode, upperdentry, lowerdentry); 867 ovl_inode_init(inode, upperdentry, lowerdentry, oip->lowerdata);
868 868
869 if (upperdentry && ovl_is_impuredir(upperdentry)) 869 if (upperdentry && ovl_is_impuredir(upperdentry))
870 ovl_set_flag(OVL_IMPURE, inode); 870 ovl_set_flag(OVL_IMPURE, inode);
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index f562bbb59ddb..85ab856dd134 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -1080,6 +1080,8 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
1080 .index = index, 1080 .index = index,
1081 .numlower = ctr, 1081 .numlower = ctr,
1082 .redirect = upperredirect, 1082 .redirect = upperredirect,
1083 .lowerdata = (ctr > 1 && !d.is_dir) ?
1084 stack[ctr - 1].dentry : NULL,
1083 }; 1085 };
1084 1086
1085 inode = ovl_get_inode(dentry->d_sb, &oip); 1087 inode = ovl_get_inode(dentry->d_sb, &oip);
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index de80250b379f..0ad593a85121 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -227,6 +227,7 @@ struct dentry *ovl_dentry_real(struct dentry *dentry);
227struct dentry *ovl_i_dentry_upper(struct inode *inode); 227struct dentry *ovl_i_dentry_upper(struct inode *inode);
228struct inode *ovl_inode_upper(struct inode *inode); 228struct inode *ovl_inode_upper(struct inode *inode);
229struct inode *ovl_inode_lower(struct inode *inode); 229struct inode *ovl_inode_lower(struct inode *inode);
230struct inode *ovl_inode_lowerdata(struct inode *inode);
230struct inode *ovl_inode_real(struct inode *inode); 231struct inode *ovl_inode_real(struct inode *inode);
231struct ovl_dir_cache *ovl_dir_cache(struct inode *inode); 232struct ovl_dir_cache *ovl_dir_cache(struct inode *inode);
232void ovl_set_dir_cache(struct inode *inode, struct ovl_dir_cache *cache); 233void ovl_set_dir_cache(struct inode *inode, struct ovl_dir_cache *cache);
@@ -246,7 +247,7 @@ bool ovl_redirect_dir(struct super_block *sb);
246const char *ovl_dentry_get_redirect(struct dentry *dentry); 247const char *ovl_dentry_get_redirect(struct dentry *dentry);
247void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect); 248void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect);
248void ovl_inode_init(struct inode *inode, struct dentry *upperdentry, 249void ovl_inode_init(struct inode *inode, struct dentry *upperdentry,
249 struct dentry *lowerdentry); 250 struct dentry *lowerdentry, struct dentry *lowerdata);
250void ovl_inode_update(struct inode *inode, struct dentry *upperdentry); 251void ovl_inode_update(struct inode *inode, struct dentry *upperdentry);
251void ovl_dir_modified(struct dentry *dentry, bool impurity); 252void ovl_dir_modified(struct dentry *dentry, bool impurity);
252u64 ovl_dentry_version_get(struct dentry *dentry); 253u64 ovl_dentry_version_get(struct dentry *dentry);
@@ -354,6 +355,7 @@ struct ovl_inode_params {
354 struct dentry *index; 355 struct dentry *index;
355 unsigned int numlower; 356 unsigned int numlower;
356 char *redirect; 357 char *redirect;
358 struct dentry *lowerdata;
357}; 359};
358struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, dev_t rdev); 360struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, dev_t rdev);
359struct inode *ovl_lookup_inode(struct super_block *sb, struct dentry *real, 361struct inode *ovl_lookup_inode(struct super_block *sb, struct dentry *real,
diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
index ea4134e97d0d..ec237035333a 100644
--- a/fs/overlayfs/ovl_entry.h
+++ b/fs/overlayfs/ovl_entry.h
@@ -89,7 +89,10 @@ static inline struct ovl_entry *OVL_E(struct dentry *dentry)
89} 89}
90 90
91struct ovl_inode { 91struct ovl_inode {
92 struct ovl_dir_cache *cache; 92 union {
93 struct ovl_dir_cache *cache; /* directory */
94 struct inode *lowerdata; /* regular file */
95 };
93 const char *redirect; 96 const char *redirect;
94 u64 version; 97 u64 version;
95 unsigned long flags; 98 unsigned long flags;
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index ab0039161f85..6d22bbd5f27f 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -181,6 +181,7 @@ static struct inode *ovl_alloc_inode(struct super_block *sb)
181 oi->flags = 0; 181 oi->flags = 0;
182 oi->__upperdentry = NULL; 182 oi->__upperdentry = NULL;
183 oi->lower = NULL; 183 oi->lower = NULL;
184 oi->lowerdata = NULL;
184 mutex_init(&oi->lock); 185 mutex_init(&oi->lock);
185 186
186 return &oi->vfs_inode; 187 return &oi->vfs_inode;
@@ -199,8 +200,11 @@ static void ovl_destroy_inode(struct inode *inode)
199 200
200 dput(oi->__upperdentry); 201 dput(oi->__upperdentry);
201 iput(oi->lower); 202 iput(oi->lower);
203 if (S_ISDIR(inode->i_mode))
204 ovl_dir_cache_free(inode);
205 else
206 iput(oi->lowerdata);
202 kfree(oi->redirect); 207 kfree(oi->redirect);
203 ovl_dir_cache_free(inode);
204 mutex_destroy(&oi->lock); 208 mutex_destroy(&oi->lock);
205 209
206 call_rcu(&inode->i_rcu, ovl_i_callback); 210 call_rcu(&inode->i_rcu, ovl_i_callback);
@@ -1487,7 +1491,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
1487 ovl_dentry_set_flag(OVL_E_CONNECTED, root_dentry); 1491 ovl_dentry_set_flag(OVL_E_CONNECTED, root_dentry);
1488 ovl_set_upperdata(d_inode(root_dentry)); 1492 ovl_set_upperdata(d_inode(root_dentry));
1489 ovl_inode_init(d_inode(root_dentry), upperpath.dentry, 1493 ovl_inode_init(d_inode(root_dentry), upperpath.dentry,
1490 ovl_dentry_lower(root_dentry)); 1494 ovl_dentry_lower(root_dentry), NULL);
1491 1495
1492 sb->s_root = root_dentry; 1496 sb->s_root = root_dentry;
1493 1497
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index 4f9c2ecee74c..63311c536216 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -247,6 +247,14 @@ struct inode *ovl_inode_real(struct inode *inode)
247 return ovl_inode_upper(inode) ?: ovl_inode_lower(inode); 247 return ovl_inode_upper(inode) ?: ovl_inode_lower(inode);
248} 248}
249 249
250/* Return inode which contains lower data. Do not return metacopy */
251struct inode *ovl_inode_lowerdata(struct inode *inode)
252{
253 if (WARN_ON(!S_ISREG(inode->i_mode)))
254 return NULL;
255
256 return OVL_I(inode)->lowerdata ?: ovl_inode_lower(inode);
257}
250 258
251struct ovl_dir_cache *ovl_dir_cache(struct inode *inode) 259struct ovl_dir_cache *ovl_dir_cache(struct inode *inode)
252{ 260{
@@ -381,7 +389,7 @@ void ovl_dentry_set_redirect(struct dentry *dentry, const char *redirect)
381} 389}
382 390
383void ovl_inode_init(struct inode *inode, struct dentry *upperdentry, 391void ovl_inode_init(struct inode *inode, struct dentry *upperdentry,
384 struct dentry *lowerdentry) 392 struct dentry *lowerdentry, struct dentry *lowerdata)
385{ 393{
386 struct inode *realinode = d_inode(upperdentry ?: lowerdentry); 394 struct inode *realinode = d_inode(upperdentry ?: lowerdentry);
387 395
@@ -389,6 +397,8 @@ void ovl_inode_init(struct inode *inode, struct dentry *upperdentry,
389 OVL_I(inode)->__upperdentry = upperdentry; 397 OVL_I(inode)->__upperdentry = upperdentry;
390 if (lowerdentry) 398 if (lowerdentry)
391 OVL_I(inode)->lower = igrab(d_inode(lowerdentry)); 399 OVL_I(inode)->lower = igrab(d_inode(lowerdentry));
400 if (lowerdata)
401 OVL_I(inode)->lowerdata = igrab(d_inode(lowerdata));
392 402
393 ovl_copyattr(realinode, inode); 403 ovl_copyattr(realinode, inode);
394 ovl_copyflags(realinode, inode); 404 ovl_copyflags(realinode, inode);