devfs - Add new make_dev_covering
authorAlex Hornung <ahornung@gmail.com>
Fri, 11 Sep 2009 06:10:09 +0000 (07:10 +0100)
committerAlex Hornung <ahornung@gmail.com>
Fri, 11 Sep 2009 06:40:50 +0000 (07:40 +0100)
* Add a new make_dev_covering which is used by systems such as the disk
  subsystem, that make_dev for an underlying device.

sys/kern/kern_conf.c
sys/sys/conf.h
sys/sys/devfs.h
sys/sys/device.h
sys/vfs/devfs/devfs_core.c

index c9f4585..d933a97 100644 (file)
@@ -186,7 +186,7 @@ make_dev(struct dev_ops *ops, int minor, uid_t uid, gid_t gid,
         */
        compile_dev_ops(ops);
 
-       devfs_dev = devfs_new_cdev(ops, minor);
+       devfs_dev = devfs_new_cdev(ops, minor, NULL);
        __va_start(ap, fmt);
        kvsnrprintf(devfs_dev->si_name, sizeof(devfs_dev->si_name),
                    32, fmt, ap);
@@ -200,6 +200,38 @@ make_dev(struct dev_ops *ops, int minor, uid_t uid, gid_t gid,
        return (devfs_dev);
 }
 
+/*
+ * make_dev_covering has equivalent functionality to make_dev, except that it
+ * also takes the cdev of the underlying device. Hence this function should
+ * only be used by systems and drivers which create devices covering others
+ */
+cdev_t
+make_dev_covering(struct dev_ops *ops, cdev_t rdev, int minor, uid_t uid,
+           gid_t gid, int perms, const char *fmt, ...)
+{
+       cdev_t  devfs_dev;
+       __va_list ap;
+
+       /*
+        * compile the cdevsw and install the device
+        */
+       compile_dev_ops(ops);
+
+       devfs_dev = devfs_new_cdev(ops, minor, rdev);
+       __va_start(ap, fmt);
+       kvsnrprintf(devfs_dev->si_name, sizeof(devfs_dev->si_name),
+                   32, fmt, ap);
+       __va_end(ap);
+
+       devfs_debug(DEVFS_DEBUG_INFO,
+                   "make_dev called for %s\n",
+                   devfs_dev->si_name);
+       devfs_create_dev(devfs_dev, uid, gid, perms);
+
+       return (devfs_dev);
+}
+
+
 
 cdev_t
 make_only_devfs_dev(struct dev_ops *ops, int minor, uid_t uid, gid_t gid,
@@ -212,7 +244,7 @@ make_only_devfs_dev(struct dev_ops *ops, int minor, uid_t uid, gid_t gid,
         * compile the cdevsw and install the device
         */
        compile_dev_ops(ops);
-       devfs_dev = devfs_new_cdev(ops, minor);
+       devfs_dev = devfs_new_cdev(ops, minor, NULL);
 
        /*
         * Set additional fields (XXX DEVFS interface goes here)
@@ -239,7 +271,7 @@ make_only_dev(struct dev_ops *ops, int minor, uid_t uid, gid_t gid,
         * compile the cdevsw and install the device
         */
        compile_dev_ops(ops);
-       devfs_dev = devfs_new_cdev(ops, minor);
+       devfs_dev = devfs_new_cdev(ops, minor, NULL);
        devfs_dev->si_perms = perms;
        devfs_dev->si_uid = uid;
        devfs_dev->si_gid = gid;
index 9522dea..6d4e052 100644 (file)
@@ -71,6 +71,7 @@ struct cdev {
        uid_t           si_uid;
        gid_t           si_gid;
        int             si_perms;
+       cdev_t  si_rdev;
        TAILQ_ENTRY(cdev) link;
        int             si_uminor;
        int             si_umajor;
index ebd5967..cd28159 100644 (file)
@@ -390,7 +390,7 @@ int devfs_destroy_subnames(char *);
 int devfs_destroy_dev_by_ops(struct dev_ops *, int);
 struct devfs_node *devfs_find_device_node_by_name(struct devfs_node *, char *);
 
-cdev_t devfs_new_cdev(struct dev_ops *, int);
+cdev_t devfs_new_cdev(struct dev_ops *, int, cdev_t);
 
 cdev_t devfs_find_device_by_name(const char *, ...);
 cdev_t devfs_find_device_by_udev(udev_t);
index 169bc44..ef46a0b 100644 (file)
@@ -364,6 +364,8 @@ void dev_ops_restore(cdev_t, struct dev_ops *);
 
 cdev_t make_dev(struct dev_ops *ops, int minor, uid_t uid, gid_t gid,
                int perms, const char *fmt, ...) __printflike(6, 7);
+cdev_t make_dev_covering(struct dev_ops *ops, cdev_t rdev, int minor, uid_t uid,
+           gid_t gid, int perms, const char *fmt, ...) __printflike(7, 8);
 cdev_t make_only_dev(struct dev_ops *ops, int minor, uid_t uid, gid_t gid,
                int perms, const char *fmt, ...) __printflike(6, 7);
 cdev_t make_only_devfs_dev(struct dev_ops *ops, int minor, uid_t uid, gid_t gid,
index 4a38783..7230e64 100644 (file)
@@ -2067,7 +2067,7 @@ devfs_fetch_ino(void)
  * fields.
  */
 cdev_t
-devfs_new_cdev(struct dev_ops *ops, int minor)
+devfs_new_cdev(struct dev_ops *ops, int minor, cdev_t rdev)
 {
        cdev_t dev = sysref_alloc(&cdev_sysref_class);
 
@@ -2087,7 +2087,11 @@ devfs_new_cdev(struct dev_ops *ops, int minor)
        dev->si_flags = 0;
        dev->si_umajor = 0;
        dev->si_uminor = minor;
-       dev->si_inode = makeudev(devfs_reference_ops(ops), minor);
+       dev->si_rdev = rdev;
+       /* If there is a backing device, we reference its ops */
+       dev->si_inode = makeudev(
+                   devfs_reference_ops((rdev)?(rdev->si_ops):(ops)),
+                   minor );
 
        return dev;
 }
@@ -2110,7 +2114,8 @@ devfs_cdev_terminate(cdev_t dev)
        if (locked)
                lockmgr(&devfs_lock, LK_RELEASE);
 
-       devfs_release_ops(dev->si_ops);
+       /* If there is a backing device, we release the backing device's ops */
+       devfs_release_ops((dev->si_rdev)?(dev->si_rdev->si_ops):(dev->si_ops));
 
        /* Finally destroy the device */
        sysref_put(&dev->si_sysref);