vfs: new d_init method
authorMiklos Szeredi <mszeredi@redhat.com>
Tue, 28 Jun 2016 09:47:32 +0000 (11:47 +0200)
committerAl Viro <viro@zeniv.linux.org.uk>
Sun, 24 Jul 2016 20:36:29 +0000 (16:36 -0400)
Allow filesystem to initialize dentry at allocation time.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Documentation/filesystems/Locking
Documentation/filesystems/vfs.txt
fs/dcache.c
include/linux/dcache.h

index a38da93..794adbe 100644 (file)
@@ -15,6 +15,7 @@ prototypes:
        int (*d_compare)(const struct dentry *, const struct dentry *,
                        unsigned int, const char *, const struct qstr *);
        int (*d_delete)(struct dentry *);
+       int (*d_init)(struct dentry *);
        void (*d_release)(struct dentry *);
        void (*d_iput)(struct dentry *, struct inode *);
        char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen);
@@ -30,6 +31,7 @@ d_weak_revalidate:no          no              yes             no
 d_hash         no              no              no              maybe
 d_compare:     yes             no              no              maybe
 d_delete:      no              yes             no              no
+d_init:        no              no              yes             no
 d_release:     no              no              yes             no
 d_prune:        no              yes             no              no
 d_iput:                no              no              yes             no
index 70a056f..15c3fa7 100644 (file)
@@ -923,6 +923,7 @@ struct dentry_operations {
        int (*d_compare)(const struct dentry *, const struct dentry *,
                        unsigned int, const char *, const struct qstr *);
        int (*d_delete)(const struct dentry *);
+       int (*d_init)(struct dentry *);
        void (*d_release)(struct dentry *);
        void (*d_iput)(struct dentry *, struct inode *);
        char *(*d_dname)(struct dentry *, char *, int);
@@ -995,6 +996,8 @@ struct dentry_operations {
        always cache a reachable dentry. d_delete must be constant and
        idempotent.
 
+  d_init: called when a dentry is allocated
+
   d_release: called when a dentry is really deallocated
 
   d_iput: called when a dentry loses its inode (just prior to its
index d5beef0..6d60a76 100644 (file)
@@ -1569,6 +1569,7 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
 {
        struct dentry *dentry;
        char *dname;
+       int err;
 
        dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL);
        if (!dentry)
@@ -1627,6 +1628,16 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
        INIT_LIST_HEAD(&dentry->d_child);
        d_set_d_op(dentry, dentry->d_sb->s_d_op);
 
+       if (dentry->d_op && dentry->d_op->d_init) {
+               err = dentry->d_op->d_init(dentry);
+               if (err) {
+                       if (dname_external(dentry))
+                               kfree(external_name(dentry));
+                       kmem_cache_free(dentry_cache, dentry);
+                       return NULL;
+               }
+       }
+
        this_cpu_inc(nr_dentry);
 
        return dentry;
index 14df836..98044a8 100644 (file)
@@ -133,6 +133,7 @@ struct dentry_operations {
        int (*d_compare)(const struct dentry *, const struct dentry *,
                        unsigned int, const char *, const struct qstr *);
        int (*d_delete)(const struct dentry *);
+       int (*d_init)(struct dentry *);
        void (*d_release)(struct dentry *);
        void (*d_prune)(struct dentry *);
        void (*d_iput)(struct dentry *, struct inode *);