ovl: move ovl_entry into ovl_inode
authorAmir Goldstein <amir73il@gmail.com>
Sat, 8 Apr 2023 09:31:13 +0000 (12:31 +0300)
committerAmir Goldstein <amir73il@gmail.com>
Mon, 19 Jun 2023 11:01:13 +0000 (14:01 +0300)
The lower stacks of all the ovl inode aliases should be identical
and there is redundant information in ovl_entry and ovl_inode.

Move lowerstack into ovl_inode and keep only the OVL_E_FLAGS
per overlay dentry.

Following patches will deduplicate redundant ovl_inode fields.

Note that for pure upper and negative dentries, OVL_E(dentry) may be
NULL now, so it is imporatnt to use the ovl_numlower() accessor.

Reviewed-by: Alexander Larsson <alexl@redhat.com>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/overlayfs/dir.c
fs/overlayfs/export.c
fs/overlayfs/inode.c
fs/overlayfs/namei.c
fs/overlayfs/overlayfs.h
fs/overlayfs/ovl_entry.h
fs/overlayfs/super.c
fs/overlayfs/util.c

index 9be52d8..92bdced 100644 (file)
@@ -269,7 +269,7 @@ static int ovl_instantiate(struct dentry *dentry, struct inode *inode,
 
        ovl_dir_modified(dentry->d_parent, false);
        ovl_dentry_set_upper_alias(dentry);
-       ovl_dentry_init_reval(dentry, newdentry);
+       ovl_dentry_init_reval(dentry, newdentry, NULL);
 
        if (!hardlink) {
                /*
index ddb5466..be142ea 100644 (file)
@@ -286,7 +286,7 @@ static struct dentry *ovl_obtain_alias(struct super_block *sb,
        struct dentry *lower = lowerpath ? lowerpath->dentry : NULL;
        struct dentry *upper = upper_alias ?: index;
        struct dentry *dentry;
-       struct inode *inode;
+       struct inode *inode = NULL;
        struct ovl_entry *oe;
        struct ovl_inode_params oip = {
                .lowerpath = lowerpath,
@@ -298,9 +298,19 @@ static struct dentry *ovl_obtain_alias(struct super_block *sb,
        if (d_is_dir(upper ?: lower))
                return ERR_PTR(-EIO);
 
+       oe = ovl_alloc_entry(!!lower);
+       if (!oe)
+               return ERR_PTR(-ENOMEM);
+
        oip.upperdentry = dget(upper);
+       if (lower) {
+               ovl_lowerstack(oe)->dentry = dget(lower);
+               ovl_lowerstack(oe)->layer = lowerpath->layer;
+       }
+       oip.oe = oe;
        inode = ovl_get_inode(sb, &oip);
        if (IS_ERR(inode)) {
+               ovl_free_entry(oe);
                dput(upper);
                return ERR_CAST(inode);
        }
@@ -315,19 +325,11 @@ static struct dentry *ovl_obtain_alias(struct super_block *sb,
        dentry = d_alloc_anon(inode->i_sb);
        if (unlikely(!dentry))
                goto nomem;
-       oe = ovl_alloc_entry(lower ? 1 : 0);
-       if (!oe)
-               goto nomem;
 
-       if (lower) {
-               ovl_lowerstack(oe)->dentry = dget(lower);
-               ovl_lowerstack(oe)->layer = lowerpath->layer;
-       }
-       dentry->d_fsdata = oe;
        if (upper_alias)
                ovl_dentry_set_upper_alias(dentry);
 
-       ovl_dentry_init_reval(dentry, upper);
+       ovl_dentry_init_reval(dentry, upper, OVL_I_E(inode));
 
        return d_instantiate_anon(dentry, inode);
 
index e7e888d..995135f 100644 (file)
@@ -1002,8 +1002,9 @@ void ovl_inode_init(struct inode *inode, struct ovl_inode_params *oip,
        struct inode *realinode;
        struct ovl_inode *oi = OVL_I(inode);
 
-       if (oip->upperdentry)
-               oi->__upperdentry = oip->upperdentry;
+       oi->__upperdentry = oip->upperdentry;
+       oi->oe = oip->oe;
+       oi->redirect = oip->redirect;
        if (oip->lowerpath && oip->lowerpath->dentry) {
                oi->lowerpath.dentry = dget(oip->lowerpath->dentry);
                oi->lowerpath.layer = oip->lowerpath->layer;
@@ -1368,6 +1369,7 @@ struct inode *ovl_get_inode(struct super_block *sb,
                        }
 
                        dput(upperdentry);
+                       ovl_free_entry(oip->oe);
                        kfree(oip->redirect);
                        goto out;
                }
@@ -1397,8 +1399,6 @@ struct inode *ovl_get_inode(struct super_block *sb,
        if (oip->index)
                ovl_set_flag(OVL_INDEX, inode);
 
-       OVL_I(inode)->redirect = oip->redirect;
-
        if (bylower)
                ovl_set_flag(OVL_CONST_INO, inode);
 
index c237c8d..a7d975b 100644 (file)
@@ -831,7 +831,7 @@ static int ovl_fix_origin(struct ovl_fs *ofs, struct dentry *dentry,
 struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
                          unsigned int flags)
 {
-       struct ovl_entry *oe;
+       struct ovl_entry *oe = NULL;
        const struct cred *old_cred;
        struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
        struct ovl_entry *poe = OVL_E(dentry->d_parent);
@@ -1067,13 +1067,14 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
                }
        }
 
-       oe = ovl_alloc_entry(ctr);
-       err = -ENOMEM;
-       if (!oe)
-               goto out_put;
+       if (ctr) {
+               oe = ovl_alloc_entry(ctr);
+               err = -ENOMEM;
+               if (!oe)
+                       goto out_put;
 
-       ovl_stack_cpy(ovl_lowerstack(oe), stack, ctr);
-       dentry->d_fsdata = oe;
+               ovl_stack_cpy(ovl_lowerstack(oe), stack, ctr);
+       }
 
        if (upperopaque)
                ovl_dentry_set_opaque(dentry);
@@ -1107,6 +1108,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
                struct ovl_inode_params oip = {
                        .upperdentry = upperdentry,
                        .lowerpath = stack,
+                       .oe = oe,
                        .index = index,
                        .numlower = ctr,
                        .redirect = upperredirect,
@@ -1122,7 +1124,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
                        ovl_set_flag(OVL_UPPERDATA, inode);
        }
 
-       ovl_dentry_init_reval(dentry, upperdentry);
+       ovl_dentry_init_reval(dentry, upperdentry, OVL_I_E(inode));
 
        revert_creds(old_cred);
        if (origin_path) {
@@ -1135,7 +1137,6 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
        return d_splice_alias(inode, dentry);
 
 out_free_oe:
-       dentry->d_fsdata = NULL;
        ovl_free_entry(oe);
 out_put:
        dput(index);
index 4f83509..cd74d74 100644 (file)
@@ -381,9 +381,10 @@ struct ovl_entry *ovl_alloc_entry(unsigned int numlower);
 void ovl_free_entry(struct ovl_entry *oe);
 bool ovl_dentry_remote(struct dentry *dentry);
 void ovl_dentry_update_reval(struct dentry *dentry, struct dentry *realdentry);
-void ovl_dentry_init_reval(struct dentry *dentry, struct dentry *upperdentry);
+void ovl_dentry_init_reval(struct dentry *dentry, struct dentry *upperdentry,
+                          struct ovl_entry *oe);
 void ovl_dentry_init_flags(struct dentry *dentry, struct dentry *upperdentry,
-                          unsigned int mask);
+                          struct ovl_entry *oe, unsigned int mask);
 bool ovl_dentry_weird(struct dentry *dentry);
 enum ovl_path_type ovl_path_type(struct dentry *dentry);
 void ovl_path_upper(struct dentry *dentry, struct path *path);
@@ -653,6 +654,7 @@ struct ovl_inode_params {
        struct inode *newinode;
        struct dentry *upperdentry;
        struct ovl_path *lowerpath;
+       struct ovl_entry *oe;
        bool index;
        unsigned int numlower;
        char *redirect;
index 608742f..f511ac7 100644 (file)
@@ -47,6 +47,11 @@ struct ovl_path {
        struct dentry *dentry;
 };
 
+struct ovl_entry {
+       unsigned int __numlower;
+       struct ovl_path __lowerstack[];
+};
+
 /* private information held for overlayfs's superblock */
 struct ovl_fs {
        unsigned int numlayer;
@@ -105,18 +110,6 @@ static inline bool ovl_should_sync(struct ovl_fs *ofs)
        return !ofs->config.ovl_volatile;
 }
 
-/* private information held for every overlayfs dentry */
-struct ovl_entry {
-       union {
-               struct {
-                       unsigned long flags;
-               };
-               struct rcu_head rcu;
-       };
-       unsigned int __numlower;
-       struct ovl_path __lowerstack[];
-};
-
 static inline unsigned int ovl_numlower(struct ovl_entry *oe)
 {
        return oe ? oe->__numlower : 0;
@@ -127,14 +120,10 @@ static inline struct ovl_path *ovl_lowerstack(struct ovl_entry *oe)
        return ovl_numlower(oe) ? oe->__lowerstack : NULL;
 }
 
-static inline struct ovl_entry *OVL_E(struct dentry *dentry)
-{
-       return (struct ovl_entry *) dentry->d_fsdata;
-}
-
+/* private information held for every overlayfs dentry */
 static inline unsigned long *OVL_E_FLAGS(struct dentry *dentry)
 {
-       return &OVL_E(dentry)->flags;
+       return (unsigned long *) &dentry->d_fsdata;
 }
 
 struct ovl_inode {
@@ -148,6 +137,7 @@ struct ovl_inode {
        struct inode vfs_inode;
        struct dentry *__upperdentry;
        struct ovl_path lowerpath;
+       struct ovl_entry *oe;
 
        /* synchronize copy up and more */
        struct mutex lock;
@@ -158,6 +148,16 @@ static inline struct ovl_inode *OVL_I(struct inode *inode)
        return container_of(inode, struct ovl_inode, vfs_inode);
 }
 
+static inline struct ovl_entry *OVL_I_E(struct inode *inode)
+{
+       return inode ? OVL_I(inode)->oe : NULL;
+}
+
+static inline struct ovl_entry *OVL_E(struct dentry *dentry)
+{
+       return OVL_I_E(d_inode(dentry));
+}
+
 static inline struct dentry *ovl_upperdentry_dereference(struct ovl_inode *oi)
 {
        return READ_ONCE(oi->__upperdentry);
index 35ecea4..bb4a062 100644 (file)
@@ -59,16 +59,6 @@ module_param_named(metacopy, ovl_metacopy_def, bool, 0644);
 MODULE_PARM_DESC(metacopy,
                 "Default to on or off for the metadata only copy up feature");
 
-static void ovl_dentry_release(struct dentry *dentry)
-{
-       struct ovl_entry *oe = dentry->d_fsdata;
-
-       if (oe) {
-               ovl_stack_put(ovl_lowerstack(oe), ovl_numlower(oe));
-               kfree_rcu(oe, rcu);
-       }
-}
-
 static struct dentry *ovl_d_real(struct dentry *dentry,
                                 const struct inode *inode)
 {
@@ -162,7 +152,6 @@ static int ovl_dentry_weak_revalidate(struct dentry *dentry, unsigned int flags)
 }
 
 static const struct dentry_operations ovl_dentry_operations = {
-       .d_release = ovl_dentry_release,
        .d_real = ovl_d_real,
        .d_revalidate = ovl_dentry_revalidate,
        .d_weak_revalidate = ovl_dentry_weak_revalidate,
@@ -182,6 +171,7 @@ static struct inode *ovl_alloc_inode(struct super_block *sb)
        oi->version = 0;
        oi->flags = 0;
        oi->__upperdentry = NULL;
+       oi->oe = NULL;
        oi->lowerpath.dentry = NULL;
        oi->lowerpath.layer = NULL;
        oi->lowerdata = NULL;
@@ -205,6 +195,7 @@ static void ovl_destroy_inode(struct inode *inode)
 
        dput(oi->__upperdentry);
        dput(oi->lowerpath.dentry);
+       ovl_free_entry(oi->oe);
        if (S_ISDIR(inode->i_mode))
                ovl_dir_cache_free(inode);
        else
@@ -1849,14 +1840,13 @@ static struct dentry *ovl_get_root(struct super_block *sb,
        struct ovl_inode_params oip = {
                .upperdentry = upperdentry,
                .lowerpath = lowerpath,
+               .oe = oe,
        };
 
        root = d_make_root(ovl_new_inode(sb, S_IFDIR, 0));
        if (!root)
                return NULL;
 
-       root->d_fsdata = oe;
-
        if (upperdentry) {
                /* Root inode uses upper st_ino/i_ino */
                ino = d_inode(upperdentry)->i_ino;
@@ -1871,7 +1861,7 @@ static struct dentry *ovl_get_root(struct super_block *sb,
        ovl_dentry_set_flag(OVL_E_CONNECTED, root);
        ovl_set_upperdata(d_inode(root));
        ovl_inode_init(d_inode(root), &oip, ino, fsid);
-       ovl_dentry_init_flags(root, upperdentry, DCACHE_OP_WEAK_REVALIDATE);
+       ovl_dentry_init_flags(root, upperdentry, oe, DCACHE_OP_WEAK_REVALIDATE);
 
        return root;
 }
index 4ff58f9..c4bd901 100644 (file)
@@ -145,15 +145,15 @@ void ovl_dentry_update_reval(struct dentry *dentry, struct dentry *realdentry)
        spin_unlock(&dentry->d_lock);
 }
 
-void ovl_dentry_init_reval(struct dentry *dentry, struct dentry *upperdentry)
+void ovl_dentry_init_reval(struct dentry *dentry, struct dentry *upperdentry,
+                          struct ovl_entry *oe)
 {
-       return ovl_dentry_init_flags(dentry, upperdentry, OVL_D_REVALIDATE);
+       return ovl_dentry_init_flags(dentry, upperdentry, oe, OVL_D_REVALIDATE);
 }
 
 void ovl_dentry_init_flags(struct dentry *dentry, struct dentry *upperdentry,
-                          unsigned int mask)
+                          struct ovl_entry *oe, unsigned int mask)
 {
-       struct ovl_entry *oe = OVL_E(dentry);
        struct ovl_path *lowerstack = ovl_lowerstack(oe);
        unsigned int i, flags = 0;