mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-20 04:01:26 +00:00
- Fix possible deadlock between vdev_sysfs_process_get_filename() and vdisk_del_device()
- Cleanups git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@3833 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -2224,6 +2224,14 @@ struct scst_device {
|
||||
/* Set, if a strictly serialized cmd is waiting blocked */
|
||||
unsigned short strictly_serialized_cmd_waiting:1;
|
||||
|
||||
/*
|
||||
* Set, if this device is being unregistered. Useful to let sysfs
|
||||
* attributes know when they should exit immediatelly to prevent
|
||||
* possible deadlocks with their device unregistration waiting for
|
||||
* their kobj last put.
|
||||
*/
|
||||
unsigned short dev_unregistering:1;
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
/*************************************************************
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/delay.h>
|
||||
#ifndef INSIDE_KERNEL_TREE
|
||||
#include <linux/version.h>
|
||||
#endif
|
||||
@@ -4416,9 +4417,24 @@ static int vdev_sysfs_process_get_filename(struct scst_sysfs_work_item *work)
|
||||
|
||||
dev = work->dev;
|
||||
|
||||
if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) {
|
||||
res = -EINTR;
|
||||
goto out_put;
|
||||
/*
|
||||
* Since we have a get() on dev->dev_kobj, we can not simply mutex_lock
|
||||
* scst_vdisk_mutex, because otherwise we can fall in a deadlock with
|
||||
* vdisk_del_device(), which is waiting for the last ref to dev_kobj
|
||||
* under scst_vdisk_mutex.
|
||||
*/
|
||||
while (!mutex_trylock(&scst_vdisk_mutex)) {
|
||||
if ((volatile bool)(dev->dev_unregistering)) {
|
||||
TRACE_MGMT_DBG("Skipping being unregistered dev %s",
|
||||
dev->virt_name);
|
||||
res = -ENOENT;
|
||||
goto out_put;
|
||||
}
|
||||
if (signal_pending(current)) {
|
||||
res = -EINTR;
|
||||
goto out_put;
|
||||
}
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
virt_dev = dev->dh_priv;
|
||||
|
||||
@@ -1006,6 +1006,8 @@ static void scst_unregister_device(struct scsi_device *scsidp)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
dev->dev_unregistering = 1;
|
||||
|
||||
list_del(&dev->dev_list_entry);
|
||||
|
||||
scst_dg_dev_remove_by_dev(dev);
|
||||
@@ -1254,6 +1256,8 @@ void scst_unregister_virtual_device(int id)
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
dev->dev_unregistering = 1;
|
||||
|
||||
list_del(&dev->dev_list_entry);
|
||||
|
||||
scst_pr_clear_dev(dev);
|
||||
|
||||
@@ -522,9 +522,9 @@ int scst_sysfs_queue_wait_work(struct scst_sysfs_work_item *work)
|
||||
* for the last put during some object unregistration and at the same
|
||||
* time another queued work is having reference on that object taken and
|
||||
* waiting for attention from the sysfs thread. Generally, all sysfs
|
||||
* function calling kobject_get() and then queuing sysfs thread job. For
|
||||
* instance. This is especially dangerous in read only cases, like
|
||||
* vdev_sysfs_filename_show().
|
||||
* functions calling kobject_get() and then queuing sysfs thread job
|
||||
* affected by this. This is especially dangerous in read only cases,
|
||||
* like vdev_sysfs_filename_show().
|
||||
*
|
||||
* So, to eliminate that deadlock we will create an extra sysfs thread
|
||||
* for each queued sysfs work. This thread will quit as soon as it will
|
||||
@@ -548,8 +548,7 @@ int scst_sysfs_queue_wait_work(struct scst_sysfs_work_item *work)
|
||||
timeout = 5*HZ;
|
||||
continue;
|
||||
}
|
||||
TRACE_MGMT_DBG("Time out waiting for work %p",
|
||||
work);
|
||||
TRACE_MGMT_DBG("Time out waiting for work %p", work);
|
||||
res = -EAGAIN;
|
||||
goto out_put;
|
||||
} else if (rc < 0) {
|
||||
|
||||
Reference in New Issue
Block a user