domain: embed 'struct device'
authorDavid Herrmann <dh.herrmann@gmail.com>
Tue, 30 Sep 2014 15:15:14 +0000 (17:15 +0200)
committerDavid Herrmann <dh.herrmann@gmail.com>
Tue, 30 Sep 2014 15:57:23 +0000 (17:57 +0200)
We currently allocate a dynamic "struct device" object as domain->dev.
There is really no need to do that. We can safely embed it as part of
"struct kdbus_domain" and get rid of our own ref-counter. Instead, use the
ref-counter of the device.

This way, container_of(device, struct kdbus_domain, dev) on "struct
device" will return a pointer to our kdbus-domain. This will be very handy
once we embed char-devs, too. We can finally get rid of our own IDRs and
use the char-dev IDRs for lookup.

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

index 0aacdd06da9000134804e9855fd4e81857229374..c459d3777482330b3a82dbf16a6abd37435a59f8 100644 (file)
--- a/domain.c
+++ b/domain.c
@@ -46,7 +46,8 @@ struct bus_type kdbus_subsys = {
 static char *kdbus_devnode_control(struct device *dev, umode_t *mode,
                                   kuid_t *uid, kgid_t *gid)
 {
-       struct kdbus_domain *domain = dev_get_drvdata(dev);
+       struct kdbus_domain *domain = container_of(dev, struct kdbus_domain,
+                                                  dev);
 
        if (mode)
                *mode = domain->mode;
@@ -73,7 +74,7 @@ static struct device_type kdbus_devtype_control = {
  */
 struct kdbus_domain *kdbus_domain_ref(struct kdbus_domain *domain)
 {
-       kref_get(&domain->kref);
+       get_device(&domain->dev);
        return domain;
 }
 
@@ -98,18 +99,16 @@ void kdbus_domain_disconnect(struct kdbus_domain *domain)
                mutex_unlock(&domain->parent->lock);
        }
 
-       mutex_lock(&kdbus_subsys_lock);
-       if (domain->dev) {
-               device_unregister(domain->dev);
-               domain->dev = NULL;
-       }
-
        if (domain->major > 0) {
+               mutex_lock(&kdbus_subsys_lock);
+
+               device_del(&domain->dev);
                idr_remove(&kdbus_domain_major_idr, domain->major);
                unregister_chrdev(domain->major, KBUILD_MODNAME);
                domain->major = 0;
+
+               mutex_unlock(&kdbus_subsys_lock);
        }
-       mutex_unlock(&kdbus_subsys_lock);
 
        /* disconnect all sub-domains */
        for (;;) {
@@ -154,10 +153,10 @@ void kdbus_domain_disconnect(struct kdbus_domain *domain)
        }
 }
 
-static void __kdbus_domain_free(struct kref *kref)
+static void __kdbus_domain_free(struct device *dev)
 {
-       struct kdbus_domain *domain =
-               container_of(kref, struct kdbus_domain, kref);
+       struct kdbus_domain *domain = container_of(dev, struct kdbus_domain,
+                                                  dev);
 
        BUG_ON(!domain->disconnected);
        BUG_ON(!list_empty(&domain->domain_list));
@@ -181,10 +180,8 @@ static void __kdbus_domain_free(struct kref *kref)
  */
 struct kdbus_domain *kdbus_domain_unref(struct kdbus_domain *domain)
 {
-       if (!domain)
-               return NULL;
-
-       kref_put(&domain->kref, __kdbus_domain_free);
+       if (domain)
+               put_device(&domain->dev);
        return NULL;
 }
 
@@ -247,22 +244,27 @@ int kdbus_domain_new(struct kdbus_domain *parent, const char *name,
        if (!d)
                return -ENOMEM;
 
+       d->disconnected = true;
        INIT_LIST_HEAD(&d->bus_list);
        INIT_LIST_HEAD(&d->domain_list);
-       kref_init(&d->kref);
        d->mode = mode;
        idr_init(&d->idr);
        mutex_init(&d->lock);
        atomic64_set(&d->msg_seq_last, 0);
        idr_init(&d->user_idr);
 
+       device_initialize(&d->dev);
+       d->dev.bus = &kdbus_subsys;
+       d->dev.type = &kdbus_devtype_control;
+       d->dev.release = __kdbus_domain_free;
+
        /* compose name and path of base directory in /dev */
        if (!parent) {
                /* initial domain */
                d->devpath = kstrdup(KBUILD_MODNAME, GFP_KERNEL);
                if (!d->devpath) {
                        ret = -ENOMEM;
-                       goto exit_free;
+                       goto exit_put;
                }
 
                mutex_lock(&kdbus_subsys_lock);
@@ -273,7 +275,7 @@ int kdbus_domain_new(struct kdbus_domain *parent, const char *name,
                if (parent->disconnected) {
                        mutex_unlock(&parent->lock);
                        ret = -ESHUTDOWN;
-                       goto exit_free;
+                       goto exit_put;
                }
 
                mutex_lock(&kdbus_subsys_lock);
@@ -292,7 +294,6 @@ int kdbus_domain_new(struct kdbus_domain *parent, const char *name,
 
                d->name = kstrdup(name, GFP_KERNEL);
                if (!d->name) {
-                       kfree(d->devpath);
                        ret = -ENOMEM;
                        goto exit_unlock;
                }
@@ -301,9 +302,14 @@ int kdbus_domain_new(struct kdbus_domain *parent, const char *name,
        /* get dynamic major */
        ret = register_chrdev(0, d->devpath, &kdbus_device_ops);
        if (ret < 0)
-               goto exit_free_devpath;
+               goto exit_unlock;
 
        d->major = ret;
+       d->dev.devt = MKDEV(d->major, 0);
+
+       ret = dev_set_name(&d->dev, "%s/control", d->devpath);
+       if (ret < 0)
+               goto exit_chrdev;
 
        /*
         * kdbus_device_ops' dev_t finds the domain in the major map,
@@ -319,24 +325,9 @@ int kdbus_domain_new(struct kdbus_domain *parent, const char *name,
        /* get id for this domain */
        d->id = ++kdbus_domain_seq_last;
 
-       /* register control device for this domain */
-       d->dev = kzalloc(sizeof(*d->dev), GFP_KERNEL);
-       if (!d->dev) {
-               ret = -ENOMEM;
-               goto exit_idr;
-       }
-
-       dev_set_name(d->dev, "%s/control", d->devpath);
-       d->dev->bus = &kdbus_subsys;
-       d->dev->type = &kdbus_devtype_control;
-       d->dev->devt = MKDEV(d->major, 0);
-       dev_set_drvdata(d->dev, d);
-       ret = device_register(d->dev);
-       if (ret < 0) {
-               put_device(d->dev);
-               d->dev = NULL;
+       ret = device_add(&d->dev);
+       if (ret < 0)
                goto exit_idr;
-       }
 
        /* link into parent domain */
        if (parent) {
@@ -344,6 +335,8 @@ int kdbus_domain_new(struct kdbus_domain *parent, const char *name,
                list_add_tail(&d->domain_entry, &parent->domain_list);
        }
 
+       d->disconnected = false;
+
        mutex_unlock(&kdbus_subsys_lock);
        if (parent)
                mutex_unlock(&parent->lock);
@@ -355,15 +348,12 @@ exit_idr:
        idr_remove(&kdbus_domain_major_idr, d->major);
 exit_chrdev:
        unregister_chrdev(d->major, d->devpath);
-exit_free_devpath:
-       kfree(d->name);
-       kfree(d->devpath);
 exit_unlock:
        mutex_unlock(&kdbus_subsys_lock);
        if (parent)
                mutex_unlock(&parent->lock);
-exit_free:
-       kfree(d);
+exit_put:
+       put_device(&d->dev);
        return ret;
 }
 
index ad78b8888d1b75bc1bf6c098e593b6efad24075f..beb0e41c26baee2c670d4471ee23a9b0ad09dbd0 100644 (file)
--- a/domain.h
+++ b/domain.h
 #ifndef __KDBUS_DOMAIN_H
 #define __KDBUS_DOMAIN_H
 
+#include <linux/device.h>
 #include <linux/hashtable.h>
 #include <linux/idr.h>
 
 /**
  * struct kdbus_domain - domain for buses
- * @kref:              Reference counter
+ * @dev:               Underlying device
  * @disconnected:      Invalidated data
  * @name:              Name of the domain
  * @devpath:           /dev base directory path
@@ -28,7 +29,6 @@
  * @major:             Device major number for all nodes
  * @mode:              Device node access mode
  * @idr:               Map of endpoint minors to buses
- * @dev:               Control device node, minor == 0
  * @lock:              Domain data lock
  * @bus_seq_last:      Last used bus id sequence number
  * @msg_seq_last:      Last used message id sequence number
@@ -49,7 +49,7 @@
  * file immediately destroys the entire domain.
  */
 struct kdbus_domain {
-       struct kref kref;
+       struct device dev;
        bool disconnected;
        const char *name;
        const char *devpath;
@@ -58,7 +58,6 @@ struct kdbus_domain {
        unsigned int major;
        umode_t mode;
        struct idr idr;
-       struct device *dev;
        struct mutex lock;
        u64 bus_seq_last;
        atomic64_t msg_seq_last;