From: Alex Hornung Date: Fri, 11 Sep 2009 06:10:09 +0000 (+0100) Subject: devfs - Add new make_dev_covering X-Git-Tag: v2.4.0~30^2~3 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/47ae500fd01ad33b1d1c66e8c07e38876dab6f02 devfs - Add new make_dev_covering * Add a new make_dev_covering which is used by systems such as the disk subsystem, that make_dev for an underlying device. --- diff --git a/sys/kern/kern_conf.c b/sys/kern/kern_conf.c index c9f458535a..d933a97ec3 100644 --- a/sys/kern/kern_conf.c +++ b/sys/kern/kern_conf.c @@ -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; diff --git a/sys/sys/conf.h b/sys/sys/conf.h index 9522deabbb..6d4e052c2c 100644 --- a/sys/sys/conf.h +++ b/sys/sys/conf.h @@ -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; diff --git a/sys/sys/devfs.h b/sys/sys/devfs.h index ebd5967be7..cd2815937d 100644 --- a/sys/sys/devfs.h +++ b/sys/sys/devfs.h @@ -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); diff --git a/sys/sys/device.h b/sys/sys/device.h index 169bc446a6..ef46a0b3a0 100644 --- a/sys/sys/device.h +++ b/sys/sys/device.h @@ -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, diff --git a/sys/vfs/devfs/devfs_core.c b/sys/vfs/devfs/devfs_core.c index 4a38783b59..7230e644e5 100644 --- a/sys/vfs/devfs/devfs_core.c +++ b/sys/vfs/devfs/devfs_core.c @@ -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);