mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-22 05:01:27 +00:00
Fix race for last_sysfs_mgmt_res between management commands and read-only monitoring actions
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@2201 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -3896,11 +3896,22 @@ unsigned int scst_get_setup_id(void);
|
||||
* (something other than EAGAIN).
|
||||
*/
|
||||
struct scst_sysfs_work_item {
|
||||
/*
|
||||
* If true, then last_sysfs_mgmt_res will not be updated. This is
|
||||
* needed to allow read only sysfs monitoring during management actions.
|
||||
* All management actions are supposed to be externally serialized,
|
||||
* so then last_sysfs_mgmt_res automatically serialized too.
|
||||
* Othewrwise a monitoring action can overwrite value of simultaneous
|
||||
* management action's last_sysfs_mgmt_res.
|
||||
*/
|
||||
bool read_only_action;
|
||||
|
||||
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;
|
||||
@@ -3929,7 +3940,7 @@ struct scst_sysfs_work_item {
|
||||
};
|
||||
|
||||
int scst_alloc_sysfs_work(int (*sysfs_work_fn)(struct scst_sysfs_work_item *),
|
||||
struct scst_sysfs_work_item **res_work);
|
||||
bool read_only_action, 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);
|
||||
|
||||
@@ -3786,7 +3786,8 @@ static ssize_t vcdrom_sysfs_filename_store(struct kobject *kobj,
|
||||
memcpy(i_buf, buf, count);
|
||||
i_buf[count] = '\0';
|
||||
|
||||
res = scst_alloc_sysfs_work(vcdrom_sysfs_process_filename_store, &work);
|
||||
res = scst_alloc_sysfs_work(vcdrom_sysfs_process_filename_store,
|
||||
false, &work);
|
||||
if (res != 0)
|
||||
goto out_free;
|
||||
|
||||
@@ -3996,7 +3997,8 @@ static ssize_t vdev_sysfs_filename_show(struct kobject *kobj,
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
|
||||
res = scst_alloc_sysfs_work(vdev_sysfs_process_get_filename, &work);
|
||||
res = scst_alloc_sysfs_work(vdev_sysfs_process_get_filename,
|
||||
true, &work);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
@@ -4052,7 +4054,7 @@ static ssize_t vdisk_sysfs_resync_size_store(struct kobject *kobj,
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
|
||||
res = scst_alloc_sysfs_work(vdisk_sysfs_process_resync_size_store,
|
||||
&work);
|
||||
false, &work);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
|
||||
@@ -174,7 +174,7 @@ static struct task_struct *sysfs_work_thread;
|
||||
* scst_alloc_sysfs_work() - allocates a sysfs work
|
||||
*/
|
||||
int scst_alloc_sysfs_work(int (*sysfs_work_fn)(struct scst_sysfs_work_item *),
|
||||
struct scst_sysfs_work_item **res_work)
|
||||
bool read_only_action, struct scst_sysfs_work_item **res_work)
|
||||
{
|
||||
int res = 0;
|
||||
struct scst_sysfs_work_item *work;
|
||||
@@ -197,6 +197,7 @@ int scst_alloc_sysfs_work(int (*sysfs_work_fn)(struct scst_sysfs_work_item *),
|
||||
goto out;
|
||||
}
|
||||
|
||||
work->read_only_action = read_only_action;
|
||||
kref_init(&work->sysfs_work_kref);
|
||||
init_completion(&work->sysfs_work_done);
|
||||
work->sysfs_work_fn = sysfs_work_fn;
|
||||
@@ -322,7 +323,8 @@ static void scst_process_sysfs_works(void)
|
||||
work->work_res = work->sysfs_work_fn(work);
|
||||
|
||||
spin_lock(&sysfs_work_lock);
|
||||
last_sysfs_work_res = work->work_res;
|
||||
if (!work->read_only_action)
|
||||
last_sysfs_work_res = work->work_res;
|
||||
active_sysfs_works--;
|
||||
spin_unlock(&sysfs_work_lock);
|
||||
|
||||
@@ -782,7 +784,7 @@ static ssize_t scst_tgtt_mgmt_store(struct kobject *kobj,
|
||||
memcpy(buffer, buf, count);
|
||||
buffer[count] = '\0';
|
||||
|
||||
res = scst_alloc_sysfs_work(scst_tgtt_mgmt_store_work_fn, &work);
|
||||
res = scst_alloc_sysfs_work(scst_tgtt_mgmt_store_work_fn, false, &work);
|
||||
if (res != 0)
|
||||
goto out_free;
|
||||
|
||||
@@ -1066,7 +1068,8 @@ static ssize_t scst_tgt_enable_store(struct kobject *kobj,
|
||||
goto out;
|
||||
}
|
||||
|
||||
res = scst_alloc_sysfs_work(scst_tgt_enable_store_work_fn, &work);
|
||||
res = scst_alloc_sysfs_work(scst_tgt_enable_store_work_fn, false,
|
||||
&work);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
@@ -1421,7 +1424,7 @@ static ssize_t scst_dev_sysfs_threads_num_store(struct kobject *kobj,
|
||||
goto out;
|
||||
|
||||
res = scst_alloc_sysfs_work(scst_dev_sysfs_threads_data_store_work_fn,
|
||||
&work);
|
||||
false, &work);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
@@ -1510,7 +1513,7 @@ static ssize_t scst_dev_sysfs_threads_pool_type_store(struct kobject *kobj,
|
||||
goto out;
|
||||
|
||||
res = scst_alloc_sysfs_work(scst_dev_sysfs_threads_data_store_work_fn,
|
||||
&work);
|
||||
false, &work);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
@@ -2186,7 +2189,7 @@ static ssize_t scst_sess_latency_store(struct kobject *kobj,
|
||||
|
||||
sess = container_of(kobj, struct scst_session, sess_kobj);
|
||||
|
||||
res = scst_alloc_sysfs_work(scst_sess_zero_latency, &work);
|
||||
res = scst_alloc_sysfs_work(scst_sess_zero_latency, false, &work);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
@@ -2270,7 +2273,7 @@ static ssize_t scst_sess_sysfs_active_commands_show(struct kobject *kobj,
|
||||
sess = container_of(kobj, struct scst_session, sess_kobj);
|
||||
|
||||
res = scst_alloc_sysfs_work(scst_sysfs_sess_get_active_commands_work_fn,
|
||||
&work);
|
||||
true, &work);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
@@ -2858,7 +2861,7 @@ static ssize_t __scst_acg_mgmt_store(struct scst_acg *acg,
|
||||
memcpy(buffer, buf, count);
|
||||
buffer[count] = '\0';
|
||||
|
||||
res = scst_alloc_sysfs_work(sysfs_work_fn, &work);
|
||||
res = scst_alloc_sysfs_work(sysfs_work_fn, false, &work);
|
||||
if (res != 0)
|
||||
goto out_free;
|
||||
|
||||
@@ -3095,7 +3098,7 @@ static ssize_t __scst_acg_io_grouping_type_store(struct scst_acg *acg,
|
||||
goto out;
|
||||
|
||||
res = scst_alloc_sysfs_work(__scst_acg_io_grouping_type_store_work_fn,
|
||||
&work);
|
||||
false, &work);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
@@ -3457,7 +3460,8 @@ static ssize_t scst_ini_group_mgmt_store(struct kobject *kobj,
|
||||
memcpy(buffer, buf, count);
|
||||
buffer[count] = '\0';
|
||||
|
||||
res = scst_alloc_sysfs_work(scst_ini_group_mgmt_store_work_fn, &work);
|
||||
res = scst_alloc_sysfs_work(scst_ini_group_mgmt_store_work_fn, false,
|
||||
&work);
|
||||
if (res != 0)
|
||||
goto out_free;
|
||||
|
||||
@@ -3560,7 +3564,8 @@ static ssize_t scst_rel_tgt_id_store(struct kobject *kobj,
|
||||
goto out;
|
||||
}
|
||||
|
||||
res = scst_alloc_sysfs_work(scst_process_rel_tgt_id_store, &work);
|
||||
res = scst_alloc_sysfs_work(scst_process_rel_tgt_id_store, false,
|
||||
&work);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
@@ -4078,7 +4083,7 @@ static ssize_t scst_threads_store(struct kobject *kobj,
|
||||
goto out;
|
||||
}
|
||||
|
||||
res = scst_alloc_sysfs_work(scst_threads_store_work_fn, &work);
|
||||
res = scst_alloc_sysfs_work(scst_threads_store_work_fn, false, &work);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
@@ -4706,7 +4711,7 @@ static ssize_t __scst_devt_mgmt_store(struct kobject *kobj,
|
||||
memcpy(buffer, buf, count);
|
||||
buffer[count] = '\0';
|
||||
|
||||
res = scst_alloc_sysfs_work(sysfs_work_fn, &work);
|
||||
res = scst_alloc_sysfs_work(sysfs_work_fn, false, &work);
|
||||
if (res != 0)
|
||||
goto out_free;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user