mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-21 04:31:26 +00:00
Sysfs cleanups and fixes, part 2, final (hopefully).
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@1985 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -491,11 +491,6 @@ enum scst_exec_context {
|
||||
|
||||
#endif
|
||||
|
||||
/*************************************************************
|
||||
** Activities suspending timeout
|
||||
*************************************************************/
|
||||
#define SCST_SUSPENDING_TIMEOUT (90 * HZ)
|
||||
|
||||
/*************************************************************
|
||||
** Kernel cache creation helper
|
||||
*************************************************************/
|
||||
@@ -955,6 +950,9 @@ struct scst_tgt_template {
|
||||
|
||||
struct kobject tgtt_kobj; /* kobject for this struct */
|
||||
|
||||
/* Number of currently active sysfs mgmt works (scst_sysfs_work_item) */
|
||||
int tgtt_active_sysfs_works_count;
|
||||
|
||||
/* sysfs release completion */
|
||||
struct completion tgtt_kobj_release_cmpl;
|
||||
|
||||
@@ -1122,7 +1120,7 @@ struct scst_dev_type {
|
||||
*/
|
||||
int (*attach) (struct scst_device *dev);
|
||||
|
||||
/* Called when new device is detaching from the dev handler */
|
||||
/* Called when a device is detaching from the dev handler */
|
||||
void (*detach) (struct scst_device *dev);
|
||||
|
||||
/*
|
||||
@@ -1251,7 +1249,7 @@ struct scst_dev_type {
|
||||
|
||||
/** Private, must be inited to 0 by memset() **/
|
||||
|
||||
/* list entry in scst_dev_type_list */
|
||||
/* list entry in scst_(virtual_)dev_type_list */
|
||||
struct list_head dev_type_list_entry;
|
||||
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
@@ -1261,6 +1259,9 @@ struct scst_dev_type {
|
||||
|
||||
struct kobject devt_kobj; /* main handlers/driver */
|
||||
|
||||
/* Number of currently active sysfs mgmt works (scst_sysfs_work_item) */
|
||||
int devt_active_sysfs_works_count;
|
||||
|
||||
/* To wait until devt_kobj released */
|
||||
struct completion devt_kobj_release_compl;
|
||||
};
|
||||
@@ -2317,6 +2318,9 @@ struct scst_acg_dev {
|
||||
* control information.
|
||||
*/
|
||||
struct scst_acg {
|
||||
/* Owner target */
|
||||
struct scst_tgt *tgt;
|
||||
|
||||
/* List of acg_dev's in this acg, protected by scst_mutex */
|
||||
struct list_head acg_dev_list;
|
||||
|
||||
@@ -3681,6 +3685,55 @@ int scst_wait_info_completion(struct scst_sysfs_user_info *info,
|
||||
|
||||
unsigned int scst_get_setup_id(void);
|
||||
|
||||
/*
|
||||
* Needed to avoid potential circular locking dependency between scst_mutex
|
||||
* and internal sysfs locking (s_active). It could be since most sysfs entries
|
||||
* are created and deleted under scst_mutex AND scst_mutex is taken inside
|
||||
* sysfs functions. So, we push from the sysfs functions all the processing
|
||||
* taking scst_mutex. To avoid deadlock, we return from them with EAGAIN
|
||||
* if processing is taking too long. User space then should poll
|
||||
* last_sysfs_mgmt_res until it returns the result of the processing
|
||||
* (something other than EAGAIN).
|
||||
*/
|
||||
struct scst_sysfs_work_item {
|
||||
struct list_head sysfs_work_list_entry;
|
||||
struct kref sysfs_work_kref;
|
||||
int (*sysfs_work_fn)(struct scst_sysfs_work_item *work);
|
||||
struct completion sysfs_work_done;
|
||||
char *buf;
|
||||
union {
|
||||
struct scst_dev_type *devt;
|
||||
struct scst_tgt_template *tgtt;
|
||||
struct {
|
||||
struct scst_tgt *tgt;
|
||||
struct scst_acg *acg;
|
||||
union {
|
||||
bool is_tgt_kobj;
|
||||
int io_grouping_type;
|
||||
bool enable;
|
||||
};
|
||||
};
|
||||
struct {
|
||||
struct scst_device *dev;
|
||||
int new_threads_num;
|
||||
enum scst_dev_type_threads_pool_type new_threads_pool_type;
|
||||
};
|
||||
struct scst_session *sess;
|
||||
struct {
|
||||
struct scst_tgt *tgt;
|
||||
unsigned long l;
|
||||
};
|
||||
};
|
||||
int work_res;
|
||||
char *res_buf;
|
||||
};
|
||||
|
||||
int scst_alloc_sysfs_work(int (*sysfs_work_fn)(struct scst_sysfs_work_item *),
|
||||
struct scst_sysfs_work_item **res_work);
|
||||
int scst_sysfs_queue_wait_work(struct scst_sysfs_work_item *work);
|
||||
void scst_sysfs_work_get(struct scst_sysfs_work_item *work);
|
||||
void scst_sysfs_work_put(struct scst_sysfs_work_item *work);
|
||||
|
||||
#endif /* CONFIG_SCST_PROC */
|
||||
|
||||
char *scst_get_next_lexem(char **token_str);
|
||||
|
||||
@@ -223,7 +223,6 @@ struct scst_vdisk_dev {
|
||||
struct scst_device *dev;
|
||||
struct list_head vdev_list_entry;
|
||||
|
||||
struct mutex vdev_sysfs_mutex;
|
||||
struct scst_dev_type *vdev_devt;
|
||||
};
|
||||
|
||||
@@ -2953,27 +2952,22 @@ static int vdisk_resync_size(struct scst_vdisk_dev *virt_dev)
|
||||
loff_t file_size;
|
||||
int res = 0;
|
||||
|
||||
if (mutex_lock_interruptible(&virt_dev->vdev_sysfs_mutex) != 0) {
|
||||
res = -EINTR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sBUG_ON(virt_dev->nullio);
|
||||
|
||||
res = vdisk_get_file_size(virt_dev->filename,
|
||||
virt_dev->blockio, &file_size);
|
||||
if (res != 0)
|
||||
goto out_unlock;
|
||||
goto out;
|
||||
|
||||
if (file_size == virt_dev->file_size) {
|
||||
PRINT_INFO("Size of virtual disk %s remained the same",
|
||||
virt_dev->name);
|
||||
goto out_unlock;
|
||||
goto out;
|
||||
}
|
||||
|
||||
res = scst_suspend_activity(true);
|
||||
if (res != 0)
|
||||
goto out_unlock;
|
||||
goto out;
|
||||
|
||||
virt_dev->file_size = file_size;
|
||||
virt_dev->nblocks = virt_dev->file_size >> virt_dev->block_shift;
|
||||
@@ -2993,9 +2987,6 @@ static int vdisk_resync_size(struct scst_vdisk_dev *virt_dev)
|
||||
|
||||
scst_resume_activity();
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&virt_dev->vdev_sysfs_mutex);
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
@@ -3019,7 +3010,6 @@ static int vdev_create(struct scst_dev_type *devt,
|
||||
}
|
||||
|
||||
spin_lock_init(&virt_dev->flags_lock);
|
||||
mutex_init(&virt_dev->vdev_sysfs_mutex);
|
||||
virt_dev->vdev_devt = devt;
|
||||
|
||||
virt_dev->rd_only = DEF_RD_ONLY;
|
||||
@@ -3586,46 +3576,32 @@ out:
|
||||
#endif /* CONFIG_SCST_PROC */
|
||||
|
||||
static int vcdrom_change(struct scst_vdisk_dev *virt_dev,
|
||||
const char *buffer, int length)
|
||||
char *buffer)
|
||||
{
|
||||
loff_t err;
|
||||
char *old_fn, *i_buf, *p, *pp;
|
||||
char *old_fn, *p, *pp;
|
||||
const char *filename = NULL;
|
||||
int length = strlen(buffer);
|
||||
int res = 0;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
i_buf = kmalloc(length+1, GFP_KERNEL);
|
||||
if (i_buf == NULL) {
|
||||
PRINT_ERROR("Unable to alloc intermediate buffer with size %d",
|
||||
length+1);
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(i_buf, buffer, length);
|
||||
i_buf[length] = '\0';
|
||||
p = i_buf;
|
||||
p = buffer;
|
||||
|
||||
while (isspace(*p) && *p != '\0')
|
||||
p++;
|
||||
filename = p;
|
||||
p = &i_buf[length-1];
|
||||
pp = &i_buf[length];
|
||||
p = &buffer[length-1];
|
||||
pp = &buffer[length];
|
||||
while (isspace(*p) && (*p != '\0')) {
|
||||
pp = p;
|
||||
p--;
|
||||
}
|
||||
*pp = '\0';
|
||||
|
||||
if (mutex_lock_interruptible(&virt_dev->vdev_sysfs_mutex) != 0) {
|
||||
res = -EINTR;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
res = scst_suspend_activity(true);
|
||||
if (res != 0)
|
||||
goto out_sysfs_unlock;
|
||||
goto out;
|
||||
|
||||
/* To sync with detach*() functions */
|
||||
mutex_lock(&scst_mutex);
|
||||
@@ -3634,8 +3610,7 @@ static int vcdrom_change(struct scst_vdisk_dev *virt_dev,
|
||||
virt_dev->cdrom_empty = 1;
|
||||
TRACE_DBG("%s", "No media");
|
||||
} else if (*filename != '/') {
|
||||
PRINT_ERROR("File path \"%s\" is not "
|
||||
"absolute", filename);
|
||||
PRINT_ERROR("File path \"%s\" is not absolute", filename);
|
||||
res = -EINVAL;
|
||||
goto out_unlock;
|
||||
} else
|
||||
@@ -3701,12 +3676,6 @@ static int vcdrom_change(struct scst_vdisk_dev *virt_dev,
|
||||
out_resume:
|
||||
scst_resume_activity();
|
||||
|
||||
out_sysfs_unlock:
|
||||
mutex_unlock(&virt_dev->vdev_sysfs_mutex);
|
||||
|
||||
out_free:
|
||||
kfree(i_buf);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
@@ -3722,27 +3691,67 @@ out_unlock:
|
||||
|
||||
#ifndef CONFIG_SCST_PROC
|
||||
|
||||
static ssize_t vcdrom_sysfs_filename_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count)
|
||||
static int vcdrom_sysfs_process_filename_store(struct scst_sysfs_work_item *work)
|
||||
{
|
||||
int res;
|
||||
struct scst_device *dev;
|
||||
struct scst_device *dev = work->dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
/* It's safe, since we taken dev_kobj and dh_priv NULLed in attach() */
|
||||
virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
|
||||
|
||||
res = vcdrom_change(virt_dev, buf, count);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
res = vcdrom_change(virt_dev, work->buf);
|
||||
|
||||
res = count;
|
||||
kobject_put(&dev->dev_kobj);
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t vcdrom_sysfs_filename_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int res;
|
||||
char *i_buf;
|
||||
struct scst_sysfs_work_item *work;
|
||||
struct scst_device *dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
|
||||
i_buf = kmalloc(count+1, GFP_KERNEL);
|
||||
if (i_buf == NULL) {
|
||||
PRINT_ERROR("Unable to alloc intermediate buffer with size %d",
|
||||
count+1);
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
memcpy(i_buf, buf, count);
|
||||
i_buf[count] = '\0';
|
||||
|
||||
res = scst_alloc_sysfs_work(vcdrom_sysfs_process_filename_store, &work);
|
||||
if (res != 0)
|
||||
goto out_free;
|
||||
|
||||
work->buf = i_buf;
|
||||
work->dev = dev;
|
||||
|
||||
kobject_get(&dev->dev_kobj);
|
||||
|
||||
res = scst_sysfs_queue_wait_work(work);
|
||||
if (res == 0)
|
||||
res = count;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
|
||||
out_free:
|
||||
kfree(i_buf);
|
||||
goto out;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_size_show(struct kobject *kobj,
|
||||
@@ -3757,16 +3766,8 @@ static ssize_t vdev_sysfs_size_show(struct kobject *kobj,
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
|
||||
|
||||
if (mutex_lock_interruptible(&virt_dev->vdev_sysfs_mutex) != 0) {
|
||||
pos = -EINTR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pos = sprintf(buf, "%lld\n", virt_dev->file_size / 1024 / 1024);
|
||||
|
||||
mutex_unlock(&virt_dev->vdev_sysfs_mutex);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(pos);
|
||||
return pos;
|
||||
}
|
||||
@@ -3893,33 +3894,96 @@ static ssize_t vdisk_sysfs_removable_show(struct kobject *kobj,
|
||||
return pos;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_filename_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
static int vdev_sysfs_process_get_filename(struct scst_sysfs_work_item *work)
|
||||
{
|
||||
int pos = 0;
|
||||
int res = 0;
|
||||
struct scst_device *dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
|
||||
dev = work->dev;
|
||||
|
||||
if (mutex_lock_interruptible(&virt_dev->vdev_sysfs_mutex) != 0) {
|
||||
pos = -EINTR;
|
||||
goto out;
|
||||
if (mutex_lock_interruptible(&scst_vdisk_mutex) != 0) {
|
||||
res = -EINTR;
|
||||
goto out_put;
|
||||
}
|
||||
|
||||
pos = sprintf(buf, "%s\n", vdev_get_filename(virt_dev));
|
||||
virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
|
||||
|
||||
if (virt_dev == NULL)
|
||||
goto out_unlock;
|
||||
|
||||
if (virt_dev->filename != NULL)
|
||||
pos += sprintf(&buf[pos], "%s\n", SCST_SYSFS_KEY_MARK);
|
||||
work->res_buf = kasprintf(GFP_KERNEL, "%s\n%s\n",
|
||||
vdev_get_filename(virt_dev), SCST_SYSFS_KEY_MARK);
|
||||
else
|
||||
work->res_buf = kasprintf(GFP_KERNEL, "%s\n",
|
||||
vdev_get_filename(virt_dev));
|
||||
|
||||
mutex_unlock(&virt_dev->vdev_sysfs_mutex);
|
||||
out_unlock:
|
||||
mutex_unlock(&scst_vdisk_mutex);
|
||||
|
||||
out_put:
|
||||
kobject_put(&dev->dev_kobj);
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_filename_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
int res = 0;
|
||||
struct scst_device *dev;
|
||||
struct scst_sysfs_work_item *work;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
|
||||
res = scst_alloc_sysfs_work(vdev_sysfs_process_get_filename, &work);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
work->dev = dev;
|
||||
|
||||
kobject_get(&dev->dev_kobj);
|
||||
|
||||
scst_sysfs_work_get(work);
|
||||
|
||||
res = scst_sysfs_queue_wait_work(work);
|
||||
if (res != 0)
|
||||
goto out_put;
|
||||
|
||||
res = snprintf(buf, SCST_SYSFS_BLOCK_SIZE, "%s\n", work->res_buf);
|
||||
|
||||
out_put:
|
||||
scst_sysfs_work_put(work);
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(pos);
|
||||
return pos;
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t vdisk_sysfs_process_resync_size_store(
|
||||
struct scst_sysfs_work_item *work)
|
||||
{
|
||||
int res;
|
||||
struct scst_device *dev = work->dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
/* It's safe, since we taken dev_kobj and dh_priv NULLed in attach() */
|
||||
virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
|
||||
|
||||
res = vdisk_resync_size(virt_dev);
|
||||
|
||||
kobject_put(&dev->dev_kobj);
|
||||
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t vdisk_sysfs_resync_size_store(struct kobject *kobj,
|
||||
@@ -3927,18 +3991,24 @@ static ssize_t vdisk_sysfs_resync_size_store(struct kobject *kobj,
|
||||
{
|
||||
int res;
|
||||
struct scst_device *dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
struct scst_sysfs_work_item *work;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
virt_dev = (struct scst_vdisk_dev *)dev->dh_priv;
|
||||
|
||||
res = vdisk_resync_size(virt_dev);
|
||||
res = scst_alloc_sysfs_work(vdisk_sysfs_process_resync_size_store,
|
||||
&work);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
res = count;
|
||||
work->dev = dev;
|
||||
|
||||
kobject_get(&dev->dev_kobj);
|
||||
|
||||
res = scst_sysfs_queue_wait_work(work);
|
||||
if (res == 0)
|
||||
res = count;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
@@ -4586,7 +4656,7 @@ static int vcdrom_proc_change(char *p, const char *name)
|
||||
goto out;
|
||||
}
|
||||
|
||||
res = vcdrom_change(virt_dev, p, strlen(p) + 1);
|
||||
res = vcdrom_change(virt_dev, p);
|
||||
|
||||
out:
|
||||
return res;
|
||||
|
||||
@@ -2786,7 +2786,7 @@ out:
|
||||
|
||||
/* The activity supposed to be suspended and scst_mutex held */
|
||||
struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt,
|
||||
const char *acg_name)
|
||||
const char *acg_name, bool tgt_acg)
|
||||
{
|
||||
struct scst_acg *acg;
|
||||
|
||||
@@ -2798,6 +2798,7 @@ struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt,
|
||||
goto out;
|
||||
}
|
||||
|
||||
acg->tgt = tgt;
|
||||
INIT_LIST_HEAD(&acg->acg_dev_list);
|
||||
INIT_LIST_HEAD(&acg->acg_sess_list);
|
||||
INIT_LIST_HEAD(&acg->acn_list);
|
||||
@@ -2815,12 +2816,11 @@ struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt,
|
||||
|
||||
scst_check_reassign_sessions();
|
||||
#else
|
||||
if (tgt != NULL) {
|
||||
if (tgt_acg) {
|
||||
int rc;
|
||||
|
||||
TRACE_DBG("Adding acg '%s' to device '%s' acg_list", acg_name,
|
||||
tgt->tgt_name);
|
||||
|
||||
list_add_tail(&acg->acg_list_entry, &tgt->tgt_acg_list);
|
||||
acg->tgt_acg = 1;
|
||||
|
||||
@@ -2885,7 +2885,8 @@ void scst_del_free_acg(struct scst_acg *acg)
|
||||
list_del(&acg->acg_list_entry);
|
||||
|
||||
scst_acg_sysfs_del(acg);
|
||||
}
|
||||
} else
|
||||
acg->tgt->default_acg = NULL;
|
||||
#endif
|
||||
|
||||
sBUG_ON(!list_empty(&acg->acg_sess_list));
|
||||
|
||||
@@ -86,6 +86,7 @@ struct list_head scst_dev_list;
|
||||
|
||||
/* Protected by scst_mutex */
|
||||
struct list_head scst_dev_type_list;
|
||||
struct list_head scst_virtual_dev_type_list;
|
||||
|
||||
spinlock_t scst_main_lock;
|
||||
|
||||
@@ -354,6 +355,13 @@ void scst_unregister_target_template(struct scst_tgt_template *vtt)
|
||||
list_del(&vtt->scst_template_list_entry);
|
||||
mutex_unlock(&scst_mutex2);
|
||||
|
||||
/* Wait for outstanding sysfs mgmt calls completed */
|
||||
while (vtt->tgtt_active_sysfs_works_count > 0) {
|
||||
mutex_unlock(&scst_mutex);
|
||||
msleep(100);
|
||||
mutex_lock(&scst_mutex);
|
||||
}
|
||||
|
||||
restart:
|
||||
list_for_each_entry(tgt, &vtt->tgt_list, tgt_list_entry) {
|
||||
mutex_unlock(&scst_mutex);
|
||||
@@ -456,7 +464,7 @@ struct scst_tgt *scst_register_target(struct scst_tgt_template *vtt,
|
||||
if (rc < 0)
|
||||
goto out_unlock;
|
||||
|
||||
tgt->default_acg = scst_alloc_add_acg(NULL, tgt->tgt_name);
|
||||
tgt->default_acg = scst_alloc_add_acg(tgt, tgt->tgt_name, false);
|
||||
if (tgt->default_acg == NULL)
|
||||
goto out_sysfs_del;
|
||||
#endif
|
||||
@@ -1047,10 +1055,12 @@ int scst_register_virtual_device(struct scst_dev_type *dev_handler,
|
||||
res = -ENOMEM;
|
||||
goto out_free_dev;
|
||||
}
|
||||
dev->virt_id = scst_virt_dev_last_id++;
|
||||
if (dev->virt_id <= 0) {
|
||||
|
||||
while (1) {
|
||||
dev->virt_id = scst_virt_dev_last_id++;
|
||||
if (dev->virt_id > 0)
|
||||
break;
|
||||
scst_virt_dev_last_id = 1;
|
||||
dev->virt_id = scst_virt_dev_last_id;
|
||||
}
|
||||
|
||||
list_add_tail(&dev->dev_list_entry, &scst_dev_list);
|
||||
@@ -1372,6 +1382,10 @@ int __scst_register_virtual_dev_driver(struct scst_dev_type *dev_type,
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
mutex_lock(&scst_mutex);
|
||||
list_add_tail(&dev_type->dev_type_list_entry, &scst_virtual_dev_type_list);
|
||||
mutex_unlock(&scst_mutex);
|
||||
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
if (!dev_type->no_proc) {
|
||||
res = scst_build_proc_dev_handler_dir_entries(dev_type);
|
||||
@@ -1406,6 +1420,20 @@ void scst_unregister_virtual_dev_driver(struct scst_dev_type *dev_type)
|
||||
{
|
||||
TRACE_ENTRY();
|
||||
|
||||
mutex_lock(&scst_mutex);
|
||||
|
||||
/* Disable sysfs mgmt calls (e.g. addition of new devices) */
|
||||
list_del(&dev_type->dev_type_list_entry);
|
||||
|
||||
/* Wait for outstanding sysfs mgmt calls completed */
|
||||
while (dev_type->devt_active_sysfs_works_count > 0) {
|
||||
mutex_unlock(&scst_mutex);
|
||||
msleep(100);
|
||||
mutex_lock(&scst_mutex);
|
||||
}
|
||||
|
||||
mutex_unlock(&scst_mutex);
|
||||
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
if (!dev_type->no_proc)
|
||||
scst_cleanup_proc_dev_handler_dir_entries(dev_type);
|
||||
@@ -1472,7 +1500,7 @@ int scst_add_threads(struct scst_cmd_threads *cmd_threads,
|
||||
cmd_threads, "%s%d_%d", nm, tgt_dev_num, n++);
|
||||
} else
|
||||
thr->cmd_thread = kthread_create(scst_cmd_thread,
|
||||
cmd_threads, "scsi_tgt%d", n++);
|
||||
cmd_threads, "scstd%d", n++);
|
||||
|
||||
if (IS_ERR(thr->cmd_thread)) {
|
||||
res = PTR_ERR(thr->cmd_thread);
|
||||
@@ -1639,6 +1667,13 @@ int scst_assign_dev_handler(struct scst_device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* devt_dev sysfs must be created AFTER attach() and deleted BEFORE
|
||||
* detach() to avoid calls from sysfs for not yet ready or already dead
|
||||
* objects.
|
||||
*/
|
||||
scst_devt_dev_sysfs_del(dev);
|
||||
|
||||
if (dev->handler->detach) {
|
||||
TRACE_DBG("%s", "Calling dev handler's detach()");
|
||||
dev->handler->detach(dev);
|
||||
@@ -1647,8 +1682,6 @@ int scst_assign_dev_handler(struct scst_device *dev,
|
||||
|
||||
scst_stop_dev_threads(dev);
|
||||
|
||||
scst_devt_dev_sysfs_del(dev);
|
||||
|
||||
assign:
|
||||
dev->handler = handler;
|
||||
|
||||
@@ -1658,10 +1691,6 @@ assign:
|
||||
dev->threads_num = handler->threads_num;
|
||||
dev->threads_pool_type = handler->threads_pool_type;
|
||||
|
||||
res = scst_devt_dev_sysfs_create(dev);
|
||||
if (res != 0)
|
||||
goto out_null;
|
||||
|
||||
if (handler->attach) {
|
||||
TRACE_DBG("Calling new dev handler's attach(%p)", dev);
|
||||
res = handler->attach(dev);
|
||||
@@ -1669,10 +1698,14 @@ assign:
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("New device handler's %s attach() "
|
||||
"failed: %d", handler->name, res);
|
||||
goto out_remove_sysfs;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
res = scst_devt_dev_sysfs_create(dev);
|
||||
if (res != 0)
|
||||
goto out_detach;
|
||||
|
||||
if (handler->attach_tgt) {
|
||||
list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
|
||||
dev_tgt_dev_list_entry) {
|
||||
@@ -1683,7 +1716,7 @@ assign:
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Device handler's %s attach_tgt() "
|
||||
"failed: %d", handler->name, res);
|
||||
goto out_err_detach_tgt;
|
||||
goto out_err_remove_sysfs;
|
||||
}
|
||||
list_add_tail(&tgt_dev->extra_tgt_dev_list_entry,
|
||||
&attached_tgt_devs);
|
||||
@@ -1708,16 +1741,17 @@ out_err_detach_tgt:
|
||||
TRACE_DBG("%s", "Handler's detach_tgt() returned");
|
||||
}
|
||||
}
|
||||
|
||||
out_err_remove_sysfs:
|
||||
scst_devt_dev_sysfs_del(dev);
|
||||
|
||||
out_detach:
|
||||
if (handler && handler->detach) {
|
||||
TRACE_DBG("%s", "Calling handler's detach()");
|
||||
handler->detach(dev);
|
||||
TRACE_DBG("%s", "Handler's detach() returned");
|
||||
}
|
||||
|
||||
out_remove_sysfs:
|
||||
scst_devt_dev_sysfs_del(dev);
|
||||
|
||||
out_null:
|
||||
dev->handler = &scst_null_devtype;
|
||||
dev->threads_num = scst_null_devtype.threads_num;
|
||||
dev->threads_pool_type = scst_null_devtype.threads_pool_type;
|
||||
@@ -1803,7 +1837,7 @@ static int scst_start_all_threads(int num)
|
||||
goto out_unlock;
|
||||
|
||||
scst_init_cmd_thread = kthread_run(scst_init_thread,
|
||||
NULL, "scsi_tgt_init");
|
||||
NULL, "scst_initd");
|
||||
if (IS_ERR(scst_init_cmd_thread)) {
|
||||
res = PTR_ERR(scst_init_cmd_thread);
|
||||
PRINT_ERROR("kthread_create() for init cmd failed: %d", res);
|
||||
@@ -1821,7 +1855,7 @@ static int scst_start_all_threads(int num)
|
||||
}
|
||||
|
||||
scst_mgmt_thread = kthread_run(scst_global_mgmt_thread,
|
||||
NULL, "scsi_tgt_mgmt");
|
||||
NULL, "scst_mgmtd");
|
||||
if (IS_ERR(scst_mgmt_thread)) {
|
||||
res = PTR_ERR(scst_mgmt_thread);
|
||||
PRINT_ERROR("kthread_create() for mgmt failed: %d", res);
|
||||
@@ -2034,6 +2068,7 @@ static int __init init_scst(void)
|
||||
INIT_LIST_HEAD(&scst_template_list);
|
||||
INIT_LIST_HEAD(&scst_dev_list);
|
||||
INIT_LIST_HEAD(&scst_dev_type_list);
|
||||
INIT_LIST_HEAD(&scst_virtual_dev_type_list);
|
||||
spin_lock_init(&scst_main_lock);
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
INIT_LIST_HEAD(&scst_acg_list);
|
||||
@@ -2175,7 +2210,7 @@ static int __init init_scst(void)
|
||||
goto out_sysfs_cleanup;
|
||||
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
scst_default_acg = scst_alloc_add_acg(NULL, SCST_DEFAULT_ACG_NAME);
|
||||
scst_default_acg = scst_alloc_add_acg(NULL, SCST_DEFAULT_ACG_NAME, false);
|
||||
if (scst_default_acg == NULL) {
|
||||
res = -ENOMEM;
|
||||
goto out_destroy_sgv_pool;
|
||||
|
||||
@@ -125,6 +125,9 @@ extern unsigned long scst_trace_flag;
|
||||
#define SCST_LUN_ADDR_METHOD_PERIPHERAL 0
|
||||
#define SCST_LUN_ADDR_METHOD_FLAT 1
|
||||
|
||||
/* Activities suspending timeout */
|
||||
#define SCST_SUSPENDING_TIMEOUT (90 * HZ)
|
||||
|
||||
extern struct mutex scst_mutex2;
|
||||
|
||||
extern int scst_threads;
|
||||
@@ -151,6 +154,7 @@ extern atomic_t scst_cmd_count;
|
||||
extern struct list_head scst_template_list;
|
||||
extern struct list_head scst_dev_list;
|
||||
extern struct list_head scst_dev_type_list;
|
||||
extern struct list_head scst_virtual_dev_type_list;
|
||||
extern wait_queue_head_t scst_dev_cmd_waitQ;
|
||||
|
||||
#ifdef CONFIG_SCST_PROC
|
||||
@@ -305,7 +309,7 @@ int scst_alloc_device(gfp_t gfp_mask, struct scst_device **out_dev);
|
||||
void scst_free_device(struct scst_device *dev);
|
||||
|
||||
struct scst_acg *scst_alloc_add_acg(struct scst_tgt *tgt,
|
||||
const char *acg_name);
|
||||
const char *acg_name, bool tgt_acg);
|
||||
void scst_del_free_acg(struct scst_acg *acg);
|
||||
|
||||
struct scst_acg *scst_tgt_find_acg(struct scst_tgt *tgt, const char *name);
|
||||
|
||||
@@ -934,7 +934,7 @@ static int scst_proc_group_add(const char *p, unsigned int addr_method)
|
||||
}
|
||||
strlcpy(name, p, len);
|
||||
|
||||
acg = scst_alloc_add_acg(NULL, name);
|
||||
acg = scst_alloc_add_acg(NULL, name, false);
|
||||
if (acg == NULL) {
|
||||
PRINT_ERROR("scst_alloc_add_acg() (name %s) failed", name);
|
||||
goto out_free;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user