]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
s390/dasd: add locking for global_profile access
authorSebastian Ott <sebott@linux.vnet.ibm.com>
Wed, 28 Jan 2015 17:44:17 +0000 (18:44 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Thu, 29 Jan 2015 08:19:27 +0000 (09:19 +0100)
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: Sebastian Ott <sebott@linux.vnet.ibm.com>
Reviewed-by: Stefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
drivers/s390/block/dasd.c
drivers/s390/block/dasd_int.h
drivers/s390/block/dasd_proc.c

index 4abf11965484b1e17efef10e44f650293687d816..a67e8dae73c35bf4cfdf58727b5a562cbafc4c45 100644 (file)
@@ -674,8 +674,12 @@ EXPORT_SYMBOL(dasd_enable_device);
 unsigned int dasd_global_profile_level = DASD_PROFILE_OFF;
 
 #ifdef CONFIG_DASD_PROFILE
-struct dasd_profile_info dasd_global_profile_data;
-static struct dentry *dasd_global_profile_dentry;
+static struct dasd_profile_info dasd_global_profile_data;
+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;
 
 /*
@@ -696,11 +700,13 @@ static void dasd_profile_start(struct dasd_block *block,
                        if (++counter >= 31)
                                break;
 
+       spin_lock(&dasd_global_profile.lock);
        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)
-                       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);
        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(endtime, endtime_ind);
 
+       spin_lock(&dasd_global_profile.lock);
        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->cpmode == 1,
                                          rq_data_dir(req) == READ,
@@ -835,6 +842,7 @@ static void dasd_profile_end(struct dasd_block *block,
                                          irqtime_ind, irqtimeps_ind,
                                          endtime_ind);
        }
+       spin_unlock(&dasd_global_profile.lock);
 
        spin_lock(&block->profile.lock);
        if (block->profile.data)
@@ -878,8 +886,7 @@ void dasd_profile_reset(struct dasd_profile *profile)
 
 void dasd_global_profile_reset(void)
 {
-       memset(&dasd_global_profile_data, 0, sizeof(dasd_global_profile_data));
-       getnstimeofday(&dasd_global_profile_data.starttod);
+       dasd_profile_reset(&dasd_global_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");
                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;
 }
 
@@ -1123,8 +1132,8 @@ static void dasd_profile_exit(struct dasd_profile *profile)
 static void dasd_statistics_removeroot(void)
 {
        dasd_global_profile_level = DASD_PROFILE_OFF;
-       debugfs_remove(dasd_global_profile_dentry);
-       dasd_global_profile_dentry = NULL;
+       debugfs_remove(dasd_global_profile.dentry);
+       dasd_global_profile.dentry = NULL;
        debugfs_remove(dasd_debugfs_global_entry);
        debugfs_remove(dasd_debugfs_root_entry);
 }
@@ -1136,7 +1145,6 @@ static void dasd_statistics_createroot(void)
 
        dasd_debugfs_root_entry = NULL;
        dasd_debugfs_global_entry = NULL;
-       dasd_global_profile_dentry = NULL;
        pde = debugfs_create_dir("dasd", NULL);
        if (!pde || IS_ERR(pde))
                goto error;
@@ -1151,7 +1159,7 @@ static void dasd_statistics_createroot(void)
                                  NULL, &dasd_stats_global_fops);
        if (!pde || IS_ERR(pde))
                goto error;
-       dasd_global_profile_dentry = pde;
+       dasd_global_profile.dentry = pde;
        return;
 
 error:
index 8b5d4100abf7c75107b61ce02ed7e7d10c252f81..91731fa05604ad0908c5dd1cc04cfb933d88f975 100644 (file)
@@ -651,7 +651,7 @@ dasd_check_blocksize(int bsize)
 #define DASD_PROFILE_GLOBAL_ONLY 2
 
 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 const struct block_device_operations dasd_device_operations;
 
index 78ac905a5b7f18c046e121ebc41f1e7f37cc84f6..76410084c48f4bac407dc947c207dba8dc67e282 100644 (file)
@@ -219,7 +219,8 @@ static int dasd_stats_proc_show(struct seq_file *m, void *v)
                                    "/proc/dasd/statistics'\n");
                return 0;
        }
-       prof = &dasd_global_profile_data;
+       spin_lock_bh(&dasd_global_profile.lock);
+       prof = dasd_global_profile.data;
 
        /* prevent counter 'overflow' on output */
        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);
        seq_printf(m, "# of req in chanq at enqueuing (1..32) \n");
        dasd_statistics_array(m, prof->dasd_io_nr_req, factor);
+       spin_unlock_bh(&dasd_global_profile.lock);
 #else
        seq_printf(m, "Statistics are not activated in this kernel\n");
 #endif