Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+20 −12
Original line number Original line Diff line number Diff line
@@ -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,
			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,
	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,
					  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)


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)
		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)
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)


	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)
				  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:
+1 −1
Original line number Original line Diff line number Diff line
@@ -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;


+3 −1
Original line number Original line Diff line number Diff line
@@ -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)
	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