Followup for r1361
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Fri, 27 Nov 2009 18:22:45 +0000 (18:22 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Fri, 27 Nov 2009 18:22:45 +0000 (18:22 +0000)
git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@1364 d57e44dd-8a1f-0410-8b47-8ef2f437770f

scst/include/scst.h
scst/src/dev_handlers/scst_vdisk.c
scst/src/scst_main.c
scst/src/scst_priv.h
scst/src/scst_sysfs.c

index 3785ac9..a0558bc 100644 (file)
@@ -1063,7 +1063,10 @@ struct scst_dev_type {
        /* Optional sysfs attributes */
        const struct attribute **devt_attrs;
 
-       /* Optional sysfs device attributes */
+       /*
+        * Optional sysfs device attributes. They are serialized
+        * by dev_sysfs_mutex.
+        */
        const struct attribute **dev_attrs;
 #endif
 
@@ -1145,6 +1148,9 @@ struct scst_tgt {
        /* Set if tgt_kobj was initialized */
        unsigned int tgt_kobj_initialized:1;
 
+       /* Set if scst_tgt_sysfs_prepare_put() was called for tgt_kobj */
+       unsigned int tgt_kobj_put_prepared:1;
+
        /*
         * Used to protect sysfs attributes to be called after this
         * object was unregistered.
@@ -3218,6 +3224,12 @@ struct scst_trace_log {
        const char *token;
 };
 
+/*
+ * Main SCST mutex. All targets, devices and dev_types management is done
+ * under this mutex.
+ */
+extern struct mutex scst_mutex;
+
 #ifdef CONFIG_SCST_PROC
 
 /*
index 15ac6f7..7fcf4a6 100644 (file)
@@ -212,7 +212,8 @@ struct scst_vdisk_dev {
        int virt_id;
        char name[16+1];        /* Name of the virtual device,
                                   must be <= SCSI Model + 1 */
-       char *file_name;        /* File name */
+       char *file_name;        /* File name, protected by
+                                  scst_mutex and suspended activities */
        char usn[MAX_USN_LEN];
        struct scst_device *dev;
        struct list_head vdisk_dev_list_entry;
@@ -815,7 +816,8 @@ out:
  *
  *  Returns :  None
  *
- *  Description:  Called to detach this device type driver
+ *  Description:  Called to detach this device type driver.
+ *               Scst_mutex supposed to be held.
  ************************************************************/
 static void vdisk_detach(struct scst_device *dev)
 {
@@ -3457,6 +3459,9 @@ static int vcdrom_change(struct scst_vdisk_dev *virt_dev,
        if (res != 0)
                goto out;
 
+       /* To sync with detach*() functions */
+       mutex_lock(&scst_mutex);
+
        if (*file_name == '\0') {
                virt_dev->cdrom_empty = 1;
                TRACE_DBG("%s", "No media");
@@ -3464,7 +3469,7 @@ static int vcdrom_change(struct scst_vdisk_dev *virt_dev,
                PRINT_ERROR("File path \"%s\" is not "
                        "absolute", file_name);
                res = -EINVAL;
-               goto out_resume;
+               goto out_unlock;
        } else
                virt_dev->cdrom_empty = 0;
 
@@ -3477,7 +3482,7 @@ static int vcdrom_change(struct scst_vdisk_dev *virt_dev,
                        TRACE(TRACE_OUT_OF_MEM, "%s",
                                "Allocation of file_name failed");
                        res = -ENOMEM;
-                       goto out_resume;
+                       goto out_unlock;
                }
 
                strncpy(fn, file_name, len);
@@ -3504,6 +3509,8 @@ static int vcdrom_change(struct scst_vdisk_dev *virt_dev,
        if (!virt_dev->cdrom_empty)
                virt_dev->media_changed = 1;
 
+       mutex_unlock(&scst_mutex);
+
        scst_dev_del_all_thr_data(virt_dev->dev);
 
        if (!virt_dev->cdrom_empty) {
@@ -3532,6 +3539,9 @@ out:
 out_free:
        kfree(virt_dev->file_name);
        virt_dev->file_name = old_fn;
+
+out_unlock:
+       mutex_unlock(&scst_mutex);
        goto out_resume;
 }
 
index 02b8576..f647b50 100644 (file)
@@ -79,6 +79,7 @@
  * flush_scheduled_work().
  */
 struct mutex scst_mutex;
+EXPORT_SYMBOL(scst_mutex);
 
  /* All 3 protected by scst_mutex */
 struct list_head scst_template_list;
@@ -494,6 +495,8 @@ void scst_unregister(struct scst_tgt *tgt)
 
        TRACE_ENTRY();
 
+       scst_tgt_sysfs_prepare_put(tgt);
+
        TRACE_DBG("%s", "Calling target driver's release()");
        tgt->tgtt->release(tgt);
        TRACE_DBG("%s", "Target driver's release() returned");
index d2bd953..0c3ff6a 100644 (file)
@@ -144,7 +144,6 @@ extern spinlock_t scst_main_lock;
 extern struct scst_sgv_pools scst_sgv;
 
 extern unsigned long scst_flags;
-extern struct mutex scst_mutex;
 extern atomic_t scst_cmd_count;
 extern struct list_head scst_template_list;
 extern struct list_head scst_dev_list;
@@ -443,6 +442,7 @@ static inline int scst_create_tgt_sysfs(struct scst_tgt *tgt)
 {
        return 0;
 }
+static inline void scst_tgt_sysfs_prepare_put(struct scst_tgt *tgt) { }
 static inline void scst_tgt_sysfs_put(struct scst_tgt *tgt)
 {
        scst_free_tgt(tgt);
@@ -497,6 +497,7 @@ void scst_sysfs_cleanup(void);
 int scst_create_tgtt_sysfs(struct scst_tgt_template *tgtt);
 void scst_tgtt_sysfs_put(struct scst_tgt_template *tgtt);
 int scst_create_tgt_sysfs(struct scst_tgt *tgt);
+void scst_tgt_sysfs_prepare_put(struct scst_tgt *tgt);
 void scst_tgt_sysfs_put(struct scst_tgt *tgt);
 int scst_create_sess_sysfs(struct scst_session *sess);
 void scst_sess_sysfs_put(struct scst_session *sess);
index 85c1740..310729e 100644 (file)
@@ -484,6 +484,20 @@ out_nomem:
        goto out;
 }
 
+/*
+ * Must not be called under scst_mutex or there can be a deadlock with
+ * tgt_attr_rwsem
+ */
+void scst_tgt_sysfs_prepare_put(struct scst_tgt *tgt)
+{
+       if (tgt->tgt_kobj_initialized) {
+               down_write(&tgt->tgt_attr_rwsem);
+               tgt->tgt_kobj_put_prepared = 1;
+       }
+
+       return;
+}
+
 /*
  * Must not be called under scst_mutex or there can be a deadlock with
  * tgt_attr_rwsem
@@ -504,7 +518,8 @@ void scst_tgt_sysfs_put(struct scst_tgt *tgt)
 
                kobject_del(&tgt->tgt_kobj);
 
-               down_write(&tgt->tgt_attr_rwsem);
+               if (!tgt->tgt_kobj_put_prepared)
+                       down_write(&tgt->tgt_attr_rwsem);
                kobject_put(&tgt->tgt_kobj);
        } else
                scst_free_tgt(tgt);