[PATCH 17/22] staging: comedi: kcomedilib: increment reference while device in use

Ian Abbott abbotti at mev.co.uk
Fri Nov 8 15:03:38 UTC 2013


Low-level comedi drivers that use the "kcomedilib" module (currently only
the "comedi_bond" driver) call `comedi_open()` to "open" another comedi
device (not as a file) and `comedi_close()` to "close" it.  (Note: these
are the functions exported by the "kcomedilib" module, not the
identically named, statically linked functions in the core "comedi"
module.)

In `comedi_open()`, call `comedi_dev_get_from_minor()` instead of
`comedi_dev_from_minor()` to get the pointer to the `struct
comedi_device` being "opened".  This increments its reference count to
prevent it being freed.  Call `comedi_dev_put()` if `comedi_open()`
returns `NULL`, and also call it from `comedi_close()`.  This decrements
the reference count.

Note that although we now protect against the `struct comedi_device`
being freed, we do not yet protect against it being "detached" while it
is being used.  This will be addressed by a later patch.

Signed-off-by: Ian Abbott <abbotti at mev.co.uk>
---
 drivers/staging/comedi/kcomedilib/kcomedilib_main.c | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
index cd60677..b3a06f2 100644
--- a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
+++ b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c
@@ -35,7 +35,7 @@ MODULE_LICENSE("GPL");
 
 struct comedi_device *comedi_open(const char *filename)
 {
-	struct comedi_device *dev;
+	struct comedi_device *dev, *retval = NULL;
 	unsigned int minor;
 
 	if (strncmp(filename, "/dev/comedi", 11) != 0)
@@ -46,15 +46,19 @@ struct comedi_device *comedi_open(const char *filename)
 	if (minor >= COMEDI_NUM_BOARD_MINORS)
 		return NULL;
 
-	dev = comedi_dev_from_minor(minor);
-
-	if (!dev || !dev->attached)
+	dev = comedi_dev_get_from_minor(minor);
+	if (!dev)
 		return NULL;
 
-	if (!try_module_get(dev->driver->module))
-		return NULL;
+	if (dev->attached && try_module_get(dev->driver->module))
+		retval = dev;
+	else
+		retval = NULL;
+
+	if (retval == NULL)
+		comedi_dev_put(dev);
 
-	return dev;
+	return retval;
 }
 EXPORT_SYMBOL_GPL(comedi_open);
 
@@ -63,6 +67,7 @@ int comedi_close(struct comedi_device *d)
 	struct comedi_device *dev = (struct comedi_device *)d;
 
 	module_put(dev->driver->module);
+	comedi_dev_put(dev);
 
 	return 0;
 }
-- 
1.8.4.2



More information about the devel mailing list