From: Ian Abbott Date: Fri, 8 Nov 2013 15:03:38 +0000 (+0000) Subject: staging: comedi: kcomedilib: increment reference while device in use X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=799a66ba36cb51330c53c024dffc6ddb68545c9c;p=linux-beck.git staging: comedi: kcomedilib: increment reference while device in use 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 Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/comedi/kcomedilib/kcomedilib_main.c b/drivers/staging/comedi/kcomedilib/kcomedilib_main.c index cd60677a3ed2..b3a06f2dbad6 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; }