Rewrote checking in comedi_fop_open(), fixed spinlock init
authorDavid Schleef <ds@schleef.org>
Thu, 5 Jul 2001 05:33:16 +0000 (05:33 +0000)
committerDavid Schleef <ds@schleef.org>
Thu, 5 Jul 2001 05:33:16 +0000 (05:33 +0000)
problem.

comedi/comedi_fops.c
comedi/drivers.c
include/linux/comedidev.h

index 57b5d18c692aa115770e003c50cf626cdec45154..bf39580052cd218ad234b2cb701d101bf4f6f5d3 100644 (file)
@@ -1621,25 +1621,40 @@ static int comedi_fop_open(struct inode *inode,struct file *file)
 {
        kdev_t minor=MINOR(inode->i_rdev);
        comedi_device *dev;
-       static int in_comedi_open=0;
        char mod[32];
 
        if(minor>=COMEDI_NDEVICES)return -ENODEV;
 
        dev=comedi_get_device_by_minor(minor);
+
+       /* This is slightly hacky, but we want module autoloading
+        * to work for root. 
+        * case: user opens device, attached -> ok
+        * case: user opens device, unattached, in_request_module=0 -> autoload
+        * case: user opens device, unattached, in_request_module=1 -> fail
+        * case: root opens device, attached -> ok
+        * case: root opens device, unattached, in_request_module=1 -> ok
+        *   (typically called from modprobe)
+        * case: root opens device, unattached, in_request_module=0 -> autoload
+        *
+        * The last could be changed to "-> ok", which would deny root
+        * autoloading.
+        */
        if(dev->attached)
                goto ok;
-       if(in_comedi_open && suser())
+       if(!suser() && dev->in_request_module)
+               return -ENODEV;
+       if(suser() && dev->in_request_module)
                goto ok;
 
-       in_comedi_open=1;
+       dev->in_request_module=1;
 
        sprintf(mod,"char-major-%i-%i",COMEDI_MAJOR,minor);
 #ifdef CONFIG_KMOD
        request_module(mod);
 #endif
 
-       in_comedi_open=0;
+       dev->in_request_module=0;
 
        if(dev->attached || suser())
                goto ok;
@@ -1775,6 +1790,7 @@ int comedi_init(void)
        memset(comedi_devices,0,sizeof(comedi_device)*COMEDI_NDEVICES);
        for(i=0;i<COMEDI_NDEVICES;i++){
                comedi_devices[i].minor=i;
+               spin_lock_init(&(comedi_devices[i].spinlock));
        }
 #if 0
        init_polling();
index 6967bd350559c9ff97e46a1597bf841e4fb6741e..01b9707f6b4e8ad40d0f0af55c03df04fc4cf3c9 100644 (file)
@@ -107,6 +107,7 @@ int comedi_device_attach(comedi_device *dev,comedi_devconfig *it)
        minor = dev->minor;
        use_count = dev->use_count;
        memset(dev,0,sizeof(comedi_device));
+       spin_lock_init(&dev->spinlock);
        dev->minor=minor;
        dev->use_count = use_count;
 
index 5df9e90878bac7ae6e5bcc04aa95f7b706de275c..df5fd928ae659c6b82acab9f8b173ab63c457bf4 100644 (file)
@@ -162,6 +162,7 @@ struct comedi_device_struct{
        int attached;
        int rt;
        spinlock_t spinlock;
+       int in_request_module;
 
        int n_subdevices;
        comedi_subdevice *subdevices;