[PATCH 37/37] staging: comedi: add comedi_clear_board_dev()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add local function `comedi_clear_board_dev()` as a safer alternative to
`comedi_clear_board_minor()` when we already have a pointer to a `struct
comedi_device`.  It uses the board minor device number stored in the
`struct comedi_device` (which must have already been initialized) and
only clears the entry in `comedi_board_minor_table[]` if it points to
the specified `struct comedi_device`.  Rather than returning the old
table entry, it returns `true` if the entry matched (and so has just
been cleared) and returns `false` otherwise.

Call `comedi_clear_board_dev()` instead of `comedi_clear_board_minor()`
in `comedi_unlocked_ioctl()` (in the code that frees a dynamically
allocated comedi device detached by the `COMEDI_DEVCONFIG` ioctl).  That
ought to return `true` but check it just in case before freeing the
device.  There is still a race condition here which needs to be dealt
with once we've implemented reference counting for `struct
comedi_device`s.

Signed-off-by: Ian Abbott <abbotti@xxxxxxxxx>
---
 drivers/staging/comedi/comedi_fops.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index b5e4bf1..dec04b9 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -120,6 +120,20 @@ static void comedi_device_cleanup(struct comedi_device *dev)
 	mutex_destroy(&dev->mutex);
 }
 
+static bool comedi_clear_board_dev(struct comedi_device *dev)
+{
+	unsigned int i = dev->minor;
+	bool cleared = false;
+
+	mutex_lock(&comedi_board_minor_table_lock);
+	if (dev == comedi_board_minor_table[i]) {
+		comedi_board_minor_table[i] = NULL;
+		cleared = true;
+	}
+	mutex_unlock(&comedi_board_minor_table_lock);
+	return cleared;
+}
+
 static struct comedi_device *comedi_clear_board_minor(unsigned minor)
 {
 	struct comedi_device *dev;
@@ -1766,9 +1780,7 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
 			    dev->minor >= comedi_num_legacy_minors) {
 				/* Successfully unconfigured a dynamically
 				 * allocated device.  Try and remove it. */
-				struct comedi_device *devr;
-				devr = comedi_clear_board_minor(dev->minor);
-				if (dev == devr) {
+				if (comedi_clear_board_dev(dev)) {
 					mutex_unlock(&dev->mutex);
 					comedi_free_board_dev(dev);
 					return rc;
-- 
1.8.1.5

_______________________________________________
devel mailing list
devel@xxxxxxxxxxxxxxxxxxxxxx
http://driverdev.linuxdriverproject.org/mailman/listinfo/devel




[Index of Archives]     [Linux Driver Backports]     [DMA Engine]     [Linux GPIO]     [Linux SPI]     [Video for Linux]     [Linux USB Devel]     [Linux Coverity]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux