diff options
| author | Ian Abbott <abbotti@mev.co.uk> | 2013-11-08 15:03:34 +0000 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-11-11 16:16:44 -0800 |
| commit | fc406986d4115dfbd5e2ea8a0e96920e97162689 (patch) | |
| tree | d1a8bcc1be7dcf5bc32140d2a01d8c863c492525 | |
| parent | b449c1cad7e3acf80834d4bdb1b6241d5d8dd249 (diff) | |
staging: comedi: increment reference while file open
In the 'open' file operation handler `comedi_open()` in "comedi_fops.c",
call `comedi_dev_get_from_minor()` instead of `comedi_dev_from_minor()`
to get the pointer to the `struct comedi_device`. This increments the
reference to prevent it being freed. Call `comedi_dev_put()` to
decrement the reference on failure, and also call it from the 'release'
file operation handler `comedi_close()`.
Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
| -rw-r--r-- | drivers/staging/comedi/comedi_fops.c | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 5e5ddbdbad0b..0ff69133c212 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -2348,7 +2348,8 @@ out: static int comedi_open(struct inode *inode, struct file *file) { const unsigned minor = iminor(inode); - struct comedi_device *dev = comedi_dev_from_minor(minor); + struct comedi_device *dev = comedi_dev_get_from_minor(minor); + int rc; if (!dev) { DPRINTK("invalid minor number\n"); @@ -2373,8 +2374,8 @@ static int comedi_open(struct inode *inode, struct file *file) goto ok; if (!capable(CAP_NET_ADMIN) && dev->in_request_module) { DPRINTK("in request module\n"); - mutex_unlock(&dev->mutex); - return -ENODEV; + rc = -ENODEV; + goto out; } if (capable(CAP_NET_ADMIN) && dev->in_request_module) goto ok; @@ -2391,8 +2392,8 @@ static int comedi_open(struct inode *inode, struct file *file) if (!dev->attached && !capable(CAP_NET_ADMIN)) { DPRINTK("not attached and not CAP_NET_ADMIN\n"); - mutex_unlock(&dev->mutex); - return -ENODEV; + rc = -ENODEV; + goto out; } ok: __module_get(THIS_MODULE); @@ -2400,26 +2401,28 @@ ok: if (dev->attached) { if (!try_module_get(dev->driver->module)) { module_put(THIS_MODULE); - mutex_unlock(&dev->mutex); - return -ENOSYS; + rc = -ENOSYS; + goto out; } } if (dev->attached && dev->use_count == 0 && dev->open) { - int rc = dev->open(dev); + rc = dev->open(dev); if (rc < 0) { module_put(dev->driver->module); module_put(THIS_MODULE); - mutex_unlock(&dev->mutex); - return rc; + goto out; } } dev->use_count++; + rc = 0; +out: mutex_unlock(&dev->mutex); - - return 0; + if (rc) + comedi_dev_put(dev); + return rc; } static int comedi_fasync(int fd, struct file *file, int on) @@ -2465,6 +2468,7 @@ static int comedi_close(struct inode *inode, struct file *file) dev->use_count--; mutex_unlock(&dev->mutex); + comedi_dev_put(dev); return 0; } |
