mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-17 10:41:26 +00:00
Merge of r972 and r977:
- Fixes a race, which can lead to a hang, if a user space handler with >1 devices gets killed under load - Fix double free git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/1.0.1.x@978 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -196,6 +196,7 @@ static unsigned int dev_user_poll(struct file *filp, poll_table *wait);
|
||||
static long dev_user_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
static int dev_user_release(struct inode *inode, struct file *file);
|
||||
static int dev_user_exit_dev(struct scst_user_dev *dev);
|
||||
static int dev_user_read_proc(struct seq_file *seq,
|
||||
struct scst_dev_type *dev_type);
|
||||
|
||||
@@ -2819,7 +2820,25 @@ static int dev_user_unregister_dev(struct file *file)
|
||||
|
||||
up_read(&dev->dev_rwsem);
|
||||
|
||||
dev_user_release(NULL, file);
|
||||
mutex_lock(&dev_priv_mutex);
|
||||
dev = (struct scst_user_dev *)file->private_data;
|
||||
if (dev == NULL) {
|
||||
mutex_unlock(&dev_priv_mutex);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev->blocking = 0;
|
||||
wake_up_all(&dev->cmd_lists.cmd_list_waitQ);
|
||||
|
||||
down_write(&dev->dev_rwsem);
|
||||
file->private_data = NULL;
|
||||
mutex_unlock(&dev_priv_mutex);
|
||||
|
||||
dev_user_exit_dev(dev);
|
||||
|
||||
up_write(&dev->dev_rwsem); /* to make lockdep happy */
|
||||
|
||||
kfree(dev);
|
||||
|
||||
scst_resume_activity();
|
||||
|
||||
@@ -3051,21 +3070,10 @@ static int dev_usr_parse(struct scst_cmd *cmd)
|
||||
|
||||
static struct scst_dev_type dev_user_devtype = USR_TYPE;
|
||||
|
||||
static int dev_user_release(struct inode *inode, struct file *file)
|
||||
static int dev_user_exit_dev(struct scst_user_dev *dev)
|
||||
{
|
||||
int res = 0;
|
||||
struct scst_user_dev *dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
mutex_lock(&dev_priv_mutex);
|
||||
dev = (struct scst_user_dev *)file->private_data;
|
||||
if (dev == NULL) {
|
||||
mutex_unlock(&dev_priv_mutex);
|
||||
goto out;
|
||||
}
|
||||
file->private_data = NULL;
|
||||
|
||||
TRACE(TRACE_MGMT, "Releasing dev %s", dev->name);
|
||||
|
||||
spin_lock(&dev_list_lock);
|
||||
@@ -3075,9 +3083,6 @@ static int dev_user_release(struct inode *inode, struct file *file)
|
||||
dev->blocking = 0;
|
||||
wake_up_all(&dev->cmd_lists.cmd_list_waitQ);
|
||||
|
||||
down_write(&dev->dev_rwsem);
|
||||
mutex_unlock(&dev_priv_mutex);
|
||||
|
||||
spin_lock(&cleanup_lock);
|
||||
list_add_tail(&dev->cleanup_list_entry, &cleanup_list);
|
||||
spin_unlock(&cleanup_lock);
|
||||
@@ -3102,17 +3107,49 @@ static int dev_user_release(struct inode *inode, struct file *file)
|
||||
sgv_pool_destroy(dev->pool_clust);
|
||||
sgv_pool_destroy(dev->pool);
|
||||
|
||||
up_write(&dev->dev_rwsem); /* to make lockdep happy */
|
||||
|
||||
TRACE_MGMT_DBG("Releasing completed (dev %p)", dev);
|
||||
|
||||
kfree(dev);
|
||||
|
||||
module_put(THIS_MODULE);
|
||||
|
||||
TRACE_EXIT();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __dev_user_release(void *arg)
|
||||
{
|
||||
struct scst_user_dev *dev = (struct scst_user_dev *)arg;
|
||||
dev_user_exit_dev(dev);
|
||||
kfree(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dev_user_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct scst_user_dev *dev;
|
||||
struct task_struct *t;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
dev = (struct scst_user_dev *)file->private_data;
|
||||
if (dev == NULL) {
|
||||
mutex_unlock(&dev_priv_mutex);
|
||||
goto out;
|
||||
}
|
||||
file->private_data = NULL;
|
||||
|
||||
TRACE_MGMT_DBG("Going to release dev %s", dev->name);
|
||||
|
||||
t = kthread_run(__dev_user_release, dev, "scst_usr_released");
|
||||
if (IS_ERR(t)) {
|
||||
PRINT_CRIT_ERROR("kthread_run() failed (%ld), releasing device "
|
||||
"%p directly. If you have several devices under load "
|
||||
"it might deadlock!", PTR_ERR(t), dev);
|
||||
__dev_user_release(dev);
|
||||
}
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
TRACE_EXIT();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dev_user_process_cleanup(struct scst_user_dev *dev)
|
||||
|
||||
Reference in New Issue
Block a user