fs: keep domain->dentry backlink
authorDavid Herrmann <dh.herrmann@gmail.com>
Mon, 22 Dec 2014 16:09:50 +0000 (17:09 +0100)
committerDavid Herrmann <dh.herrmann@gmail.com>
Mon, 22 Dec 2014 16:19:39 +0000 (17:19 +0100)
We don't really want backlinks into the VFS, however, we need some way to
thrash old VFS cache entries when objects get destructed. Therefore, safe
a pointer to the root dentry in every domain.

We don't pin the dentry, as this would create circular dependencies.
Instead, we bind the dentry validity to the active lifetime of the domain.
Therefore, you can only access domain->dentry as long as it is active.
Once umount() is called, we deactivate the domain and thus drop the dentry
cache.

This backlink will be needed in a follow-up that flushes caches on object
destruction.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
domain.h
fs.c

index 20c14b055ac53c74dc57fa688d1c9ebdbdff95ae..01bf8cbe8963088c0242bd45ebfc8fae686aacbc 100644 (file)
--- a/domain.h
+++ b/domain.h
@@ -14,6 +14,7 @@
 #ifndef __KDBUS_DOMAIN_H
 #define __KDBUS_DOMAIN_H
 
+#include <linux/fs.h>
 #include <linux/hashtable.h>
 #include <linux/idr.h>
 #include <linux/kref.h>
@@ -31,6 +32,7 @@
  * @user_hash:         Accounting of user resources
  * @user_idr:          Map of all users; smallest possible index
  * @user_namespace:    User namespace, pinned at creation time
+ * @dentry:            Root dentry of VFS mount (dont use outside of kdbusfs)
  */
 struct kdbus_domain {
        struct kdbus_node node;
@@ -41,6 +43,7 @@ struct kdbus_domain {
        DECLARE_HASHTABLE(user_hash, 6);
        struct idr user_idr;
        struct user_namespace *user_namespace;
+       struct dentry *dentry;
 };
 
 /**
diff --git a/fs.c b/fs.c
index 64ebbb05abebfd34af40cffdd51126b0d5b1c471..a3bac17d270720759a2d333d09ab675c1ee67521 100644 (file)
--- a/fs.c
+++ b/fs.c
@@ -12,6 +12,7 @@
  */
 
 #include <linux/backing-dev.h>
+#include <linux/dcache.h>
 #include <linux/fs.h>
 #include <linux/fsnotify.h>
 #include <linux/init.h>
@@ -313,6 +314,9 @@ static int fs_super_fill(struct super_block *sb)
        sb->s_root->d_fsdata = &domain->node;
        sb->s_d_op = &fs_super_dops;
 
+       /* sb holds root reference */
+       domain->dentry = sb->s_root;
+
        ret = kdbus_domain_activate(domain);
        if (ret < 0)
                return ret;
@@ -327,6 +331,7 @@ static void fs_super_kill(struct super_block *sb)
 
        if (domain) {
                kdbus_domain_deactivate(domain);
+               domain->dentry = NULL;
        }
 
        kill_anon_super(sb);