diff options
author | Ian Abbott | 2013-11-08 16:03:34 +0100 |
---|---|---|
committer | Greg Kroah-Hartman | 2013-11-12 01:16:44 +0100 |
commit | fc406986d4115dfbd5e2ea8a0e96920e97162689 (patch) | |
tree | d1a8bcc1be7dcf5bc32140d2a01d8c863c492525 /drivers/staging/comedi/comedi_fops.c | |
parent | staging: comedi: add comedi_dev_get_from_minor() (diff) | |
download | kernel-qcow2-linux-fc406986d4115dfbd5e2ea8a0e96920e97162689.tar.gz kernel-qcow2-linux-fc406986d4115dfbd5e2ea8a0e96920e97162689.tar.xz kernel-qcow2-linux-fc406986d4115dfbd5e2ea8a0e96920e97162689.zip |
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>
Diffstat (limited to 'drivers/staging/comedi/comedi_fops.c')
-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; } |