Commit 8ea55c95 authored by Sebastian Ott's avatar Sebastian Ott Committed by Martin Schwidefsky

s390/dasd: add locking for global_profile access

Access to DASDs global statistics is done without locking which
can lead to inconsistent data. Add locking to fix this. Also move
the relevant structs in a global dasd_profile struct.
Signed-off-by: default avatarSebastian Ott <sebott@linux.vnet.ibm.com>
Reviewed-by: default avatarStefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent e6d60b36
...@@ -674,8 +674,12 @@ EXPORT_SYMBOL(dasd_enable_device); ...@@ -674,8 +674,12 @@ EXPORT_SYMBOL(dasd_enable_device);
unsigned int dasd_global_profile_level = DASD_PROFILE_OFF; unsigned int dasd_global_profile_level = DASD_PROFILE_OFF;
#ifdef CONFIG_DASD_PROFILE #ifdef CONFIG_DASD_PROFILE
struct dasd_profile_info dasd_global_profile_data; static struct dasd_profile_info dasd_global_profile_data;
static struct dentry *dasd_global_profile_dentry; struct dasd_profile dasd_global_profile = {
.dentry = NULL,
.data = &dasd_global_profile_data,
.lock = __SPIN_LOCK_UNLOCKED(dasd_global_profile.lock),
};
static struct dentry *dasd_debugfs_global_entry; static struct dentry *dasd_debugfs_global_entry;
/* /*
...@@ -696,11 +700,13 @@ static void dasd_profile_start(struct dasd_block *block, ...@@ -696,11 +700,13 @@ static void dasd_profile_start(struct dasd_block *block,
if (++counter >= 31) if (++counter >= 31)
break; break;
spin_lock(&dasd_global_profile.lock);
if (dasd_global_profile_level) { if (dasd_global_profile_level) {
dasd_global_profile_data.dasd_io_nr_req[counter]++; dasd_global_profile.data->dasd_io_nr_req[counter]++;
if (rq_data_dir(req) == READ) if (rq_data_dir(req) == READ)
dasd_global_profile_data.dasd_read_nr_req[counter]++; dasd_global_profile.data->dasd_read_nr_req[counter]++;
} }
spin_unlock(&dasd_global_profile.lock);
spin_lock(&block->profile.lock); spin_lock(&block->profile.lock);
if (block->profile.data) { if (block->profile.data) {
...@@ -825,8 +831,9 @@ static void dasd_profile_end(struct dasd_block *block, ...@@ -825,8 +831,9 @@ static void dasd_profile_end(struct dasd_block *block,
dasd_profile_counter(irqtime / sectors, irqtimeps_ind); dasd_profile_counter(irqtime / sectors, irqtimeps_ind);
dasd_profile_counter(endtime, endtime_ind); dasd_profile_counter(endtime, endtime_ind);
spin_lock(&dasd_global_profile.lock);
if (dasd_global_profile_level) { if (dasd_global_profile_level) {
dasd_profile_end_add_data(&dasd_global_profile_data, dasd_profile_end_add_data(dasd_global_profile.data,
cqr->startdev != block->base, cqr->startdev != block->base,
cqr->cpmode == 1, cqr->cpmode == 1,
rq_data_dir(req) == READ, rq_data_dir(req) == READ,
...@@ -835,6 +842,7 @@ static void dasd_profile_end(struct dasd_block *block, ...@@ -835,6 +842,7 @@ static void dasd_profile_end(struct dasd_block *block,
irqtime_ind, irqtimeps_ind, irqtime_ind, irqtimeps_ind,
endtime_ind); endtime_ind);
} }
spin_unlock(&dasd_global_profile.lock);
spin_lock(&block->profile.lock); spin_lock(&block->profile.lock);
if (block->profile.data) if (block->profile.data)
...@@ -878,8 +886,7 @@ void dasd_profile_reset(struct dasd_profile *profile) ...@@ -878,8 +886,7 @@ void dasd_profile_reset(struct dasd_profile *profile)
void dasd_global_profile_reset(void) void dasd_global_profile_reset(void)
{ {
memset(&dasd_global_profile_data, 0, sizeof(dasd_global_profile_data)); dasd_profile_reset(&dasd_global_profile);
getnstimeofday(&dasd_global_profile_data.starttod);
} }
int dasd_profile_on(struct dasd_profile *profile) int dasd_profile_on(struct dasd_profile *profile)
...@@ -1077,7 +1084,9 @@ static int dasd_stats_global_show(struct seq_file *m, void *v) ...@@ -1077,7 +1084,9 @@ static int dasd_stats_global_show(struct seq_file *m, void *v)
seq_puts(m, "disabled\n"); seq_puts(m, "disabled\n");
return 0; return 0;
} }
dasd_stats_seq_print(m, &dasd_global_profile_data); spin_lock_bh(&dasd_global_profile.lock);
dasd_stats_seq_print(m, dasd_global_profile.data);
spin_unlock_bh(&dasd_global_profile.lock);
return 0; return 0;
} }
...@@ -1123,8 +1132,8 @@ static void dasd_profile_exit(struct dasd_profile *profile) ...@@ -1123,8 +1132,8 @@ static void dasd_profile_exit(struct dasd_profile *profile)
static void dasd_statistics_removeroot(void) static void dasd_statistics_removeroot(void)
{ {
dasd_global_profile_level = DASD_PROFILE_OFF; dasd_global_profile_level = DASD_PROFILE_OFF;
debugfs_remove(dasd_global_profile_dentry); debugfs_remove(dasd_global_profile.dentry);
dasd_global_profile_dentry = NULL; dasd_global_profile.dentry = NULL;
debugfs_remove(dasd_debugfs_global_entry); debugfs_remove(dasd_debugfs_global_entry);
debugfs_remove(dasd_debugfs_root_entry); debugfs_remove(dasd_debugfs_root_entry);
} }
...@@ -1136,7 +1145,6 @@ static void dasd_statistics_createroot(void) ...@@ -1136,7 +1145,6 @@ static void dasd_statistics_createroot(void)
dasd_debugfs_root_entry = NULL; dasd_debugfs_root_entry = NULL;
dasd_debugfs_global_entry = NULL; dasd_debugfs_global_entry = NULL;
dasd_global_profile_dentry = NULL;
pde = debugfs_create_dir("dasd", NULL); pde = debugfs_create_dir("dasd", NULL);
if (!pde || IS_ERR(pde)) if (!pde || IS_ERR(pde))
goto error; goto error;
...@@ -1151,7 +1159,7 @@ static void dasd_statistics_createroot(void) ...@@ -1151,7 +1159,7 @@ static void dasd_statistics_createroot(void)
NULL, &dasd_stats_global_fops); NULL, &dasd_stats_global_fops);
if (!pde || IS_ERR(pde)) if (!pde || IS_ERR(pde))
goto error; goto error;
dasd_global_profile_dentry = pde; dasd_global_profile.dentry = pde;
return; return;
error: error:
......
...@@ -651,7 +651,7 @@ dasd_check_blocksize(int bsize) ...@@ -651,7 +651,7 @@ dasd_check_blocksize(int bsize)
#define DASD_PROFILE_GLOBAL_ONLY 2 #define DASD_PROFILE_GLOBAL_ONLY 2
extern debug_info_t *dasd_debug_area; extern debug_info_t *dasd_debug_area;
extern struct dasd_profile_info dasd_global_profile_data; extern struct dasd_profile dasd_global_profile;
extern unsigned int dasd_global_profile_level; extern unsigned int dasd_global_profile_level;
extern const struct block_device_operations dasd_device_operations; extern const struct block_device_operations dasd_device_operations;
......
...@@ -219,7 +219,8 @@ static int dasd_stats_proc_show(struct seq_file *m, void *v) ...@@ -219,7 +219,8 @@ static int dasd_stats_proc_show(struct seq_file *m, void *v)
"/proc/dasd/statistics'\n"); "/proc/dasd/statistics'\n");
return 0; return 0;
} }
prof = &dasd_global_profile_data; spin_lock_bh(&dasd_global_profile.lock);
prof = dasd_global_profile.data;
/* prevent counter 'overflow' on output */ /* prevent counter 'overflow' on output */
for (factor = 1; (prof->dasd_io_reqs / factor) > 9999999; for (factor = 1; (prof->dasd_io_reqs / factor) > 9999999;
...@@ -255,6 +256,7 @@ static int dasd_stats_proc_show(struct seq_file *m, void *v) ...@@ -255,6 +256,7 @@ static int dasd_stats_proc_show(struct seq_file *m, void *v)
dasd_statistics_array(m, prof->dasd_io_time3, factor); dasd_statistics_array(m, prof->dasd_io_time3, factor);
seq_printf(m, "# of req in chanq at enqueuing (1..32) \n"); seq_printf(m, "# of req in chanq at enqueuing (1..32) \n");
dasd_statistics_array(m, prof->dasd_io_nr_req, factor); dasd_statistics_array(m, prof->dasd_io_nr_req, factor);
spin_unlock_bh(&dasd_global_profile.lock);
#else #else
seq_printf(m, "Statistics are not activated in this kernel\n"); seq_printf(m, "Statistics are not activated in this kernel\n");
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment