In order to support object migration on the dentry cache we need to have
a determined object state at all times. Without a constructor the object
would have a random state after allocation.

Provide a dentry constructor.

Signed-off-by: Tobin C. Harding <to...@kernel.org>
---
 fs/dcache.c | 30 +++++++++++++++++++++---------
 1 file changed, 21 insertions(+), 9 deletions(-)

diff --git a/fs/dcache.c b/fs/dcache.c
index aac41adf4743..3d6cc06eca56 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1603,6 +1603,16 @@ void d_invalidate(struct dentry *dentry)
 }
 EXPORT_SYMBOL(d_invalidate);
 
+static void dcache_ctor(void *p)
+{
+       struct dentry *dentry = p;
+
+       /* Mimic lockref_mark_dead() */
+       dentry->d_lockref.count = -128;
+
+       spin_lock_init(&dentry->d_lock);
+}
+
 /**
  * __d_alloc   -       allocate a dcache entry
  * @sb: filesystem it will belong to
@@ -1658,7 +1668,6 @@ struct dentry *__d_alloc(struct super_block *sb, const 
struct qstr *name)
 
        dentry->d_lockref.count = 1;
        dentry->d_flags = 0;
-       spin_lock_init(&dentry->d_lock);
        seqcount_init(&dentry->d_seq);
        dentry->d_inode = NULL;
        dentry->d_parent = dentry;
@@ -3091,14 +3100,17 @@ static void __init dcache_init_early(void)
 
 static void __init dcache_init(void)
 {
-       /*
-        * A constructor could be added for stable state like the lists,
-        * but it is probably not worth it because of the cache nature
-        * of the dcache.
-        */
-       dentry_cache = KMEM_CACHE_USERCOPY(dentry,
-               SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD|SLAB_ACCOUNT,
-               d_iname);
+       slab_flags_t flags =
+               SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | SLAB_MEM_SPREAD | 
SLAB_ACCOUNT;
+
+       dentry_cache =
+               kmem_cache_create_usercopy("dentry",
+                                          sizeof(struct dentry),
+                                          __alignof__(struct dentry),
+                                          flags,
+                                          offsetof(struct dentry, d_iname),
+                                          sizeof_field(struct dentry, d_iname),
+                                          dcache_ctor);
 
        /* Hash may have been set up in dcache_init_early */
        if (!hashdist)
-- 
2.21.0

Reply via email to