From 2c94b9eeb85c6cfa5ff918aa58ce484b27fc7c91 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Sun, 4 Jan 2015 20:54:56 -0800 Subject: [PATCH] devfs - Allow clone code to reuse an existing device * Allow the clone code to set a replacement device which already exists in devfs. * This will allow the sound code to cache virtual channel devices after use. --- sys/vfs/devfs/devfs_core.c | 29 +++++++++++++++++++++++------ sys/vfs/devfs/devfs_vnops.c | 18 +++++++++++------- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/sys/vfs/devfs/devfs_core.c b/sys/vfs/devfs/devfs_core.c index 1767864b63..76b1ad1ec1 100644 --- a/sys/vfs/devfs/devfs_core.c +++ b/sys/vfs/devfs/devfs_core.c @@ -1430,7 +1430,7 @@ devfs_create_all_dev_worker(struct devfs_node *root) KKASSERT(root); TAILQ_FOREACH(dev, &devfs_dev_list, link) { - devfs_create_device_node(root, dev, NULL, NULL); + devfs_create_device_node(root, dev, NULL, NULL, NULL); } return 0; @@ -1965,7 +1965,7 @@ devfs_resolve_name_path(char *fullpath, char *buf, char **pathp, char **namep) */ struct devfs_node * devfs_create_device_node(struct devfs_node *root, cdev_t dev, - char *dev_name, char *path_fmt, ...) + int *existsp, char *dev_name, char *path_fmt, ...) { struct devfs_node *parent, *node = NULL; char *path = NULL; @@ -1978,6 +1978,9 @@ devfs_create_device_node(struct devfs_node *root, cdev_t dev, name_buf = kmalloc(PATH_MAX, M_TEMP, M_WAITOK); + if (existsp) + *existsp = 0; + if (path_fmt != NULL) { __va_start(ap, path_fmt); kvasnrprintf(&path, PATH_MAX, 10, path_fmt, ap); @@ -1995,9 +1998,23 @@ devfs_create_device_node(struct devfs_node *root, cdev_t dev, parent = devfs_resolve_or_create_path(parent, create_path, 1); - if (devfs_find_device_node_by_name(parent, name)) { - devfs_debug(DEVFS_DEBUG_WARNING, "devfs_create_device_node: " - "DEVICE %s ALREADY EXISTS!!! Ignoring creation request.\n", name); + node = devfs_find_device_node_by_name(parent, name); + if (node) { + if (node->d_dev == dev) { + /* + * Allow case where device caches dev after the + * close and might desire to reuse it. + */ + if (existsp) + *existsp = 1; + } else { + devfs_debug(DEVFS_DEBUG_WARNING, + "devfs_create_device_node: " + "DEVICE %s ALREADY EXISTS!!! " + "Ignoring creation request.\n", + name); + node = NULL; + } goto out; } @@ -2175,7 +2192,7 @@ devfs_propagate_dev(cdev_t dev, int attach) if (attach) { /* Device is being attached */ devfs_create_device_node(mnt->root_node, dev, - NULL, NULL ); + NULL, NULL, NULL); } else { /* Device is being detached */ devfs_alias_remove(dev); diff --git a/sys/vfs/devfs/devfs_vnops.c b/sys/vfs/devfs/devfs_vnops.c index 2430be7b17..d0894dd214 100644 --- a/sys/vfs/devfs/devfs_vnops.c +++ b/sys/vfs/devfs/devfs_vnops.c @@ -865,6 +865,8 @@ devfs_spec_open(struct vop_open_args *ap) vn_lock(vp, LK_UPGRADE | LK_RETRY); if (node && ap->a_fp) { + int exists; + devfs_debug(DEVFS_DEBUG_DEBUG, "devfs_spec_open: -1.1-\n"); lockmgr(&devfs_lock, LK_EXCLUSIVE); @@ -874,12 +876,13 @@ devfs_spec_open(struct vop_open_args *ap) if (ndev != NULL) { newnode = devfs_create_device_node( DEVFS_MNTDATA(vp->v_mount)->root_node, - ndev, NULL, NULL); + ndev, &exists, NULL, NULL); /* XXX: possibly destroy device if this happens */ if (newnode != NULL) { dev = ndev; - devfs_link_dev(dev); + if (exists == 0) + devfs_link_dev(dev); devfs_debug(DEVFS_DEBUG_DEBUG, "parent here is: %s, node is: |%s|\n", @@ -891,7 +894,8 @@ devfs_spec_open(struct vop_open_args *ap) ((struct devfs_node *)(TAILQ_LAST(DEVFS_DENODE_HEAD(node->parent), devfs_node_head)))->d_dir.d_name); /* - * orig_vp is set to the original vp if we cloned. + * orig_vp is set to the original vp if we + * cloned. */ /* node->flags |= DEVFS_CLONED; */ devfs_allocv(&vp, newnode); @@ -901,10 +905,10 @@ devfs_spec_open(struct vop_open_args *ap) } lockmgr(&devfs_lock, LK_RELEASE); /* - * Synchronize devfs here to make sure that, if the cloned device - * creates other device nodes in addition to the cloned one, - * all of them are created by the time we return from opening - * the cloned one. + * Synchronize devfs here to make sure that, if the cloned + * device creates other device nodes in addition to the + * cloned one, all of them are created by the time we return + * from opening the cloned one. */ if (ndev) devfs_config(); -- 2.41.0