From e85fa52760b296d6f7ac7f7cecfd29516f829d36 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Thu, 23 Sep 2010 13:31:54 +0000 Subject: [PATCH] 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 --- scst/include/scst.h | 13 +++++++++++- scst/src/dev_handlers/scst_vdisk.c | 8 +++++--- scst/src/scst_sysfs.c | 33 +++++++++++++++++------------- 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/scst/include/scst.h b/scst/include/scst.h index 708f46818..d30fea0bb 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -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); diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index b01e5bc36..b29adf1fa 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -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; diff --git a/scst/src/scst_sysfs.c b/scst/src/scst_sysfs.c index b3f27fdb3..ac033560c 100644 --- a/scst/src/scst_sysfs.c +++ b/scst/src/scst_sysfs.c @@ -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;