]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - block/blk-cgroup.c
blk-cgroup: Make 64bit per cpu stats safe on 32bit arch
[mv-sheeva.git] / block / blk-cgroup.c
index 34bfcefdd924c0c5e7f222c726ca5d30f05aed26..3622518e1c23d998e97685480951b74a5af1778c 100644 (file)
@@ -400,14 +400,25 @@ void blkiocg_update_dispatch_stats(struct blkio_group *blkg,
                                uint64_t bytes, bool direction, bool sync)
 {
        struct blkio_group_stats_cpu *stats_cpu;
+       unsigned long flags;
+
+       /*
+        * Disabling interrupts to provide mutual exclusion between two
+        * writes on same cpu. It probably is not needed for 64bit. Not
+        * optimizing that case yet.
+        */
+       local_irq_save(flags);
 
        stats_cpu = this_cpu_ptr(blkg->stats_cpu);
 
+       u64_stats_update_begin(&stats_cpu->syncp);
        stats_cpu->sectors += bytes >> 9;
        blkio_add_stat(stats_cpu->stat_arr_cpu[BLKIO_STAT_CPU_SERVICED],
                        1, direction, sync);
        blkio_add_stat(stats_cpu->stat_arr_cpu[BLKIO_STAT_CPU_SERVICE_BYTES],
                        bytes, direction, sync);
+       u64_stats_update_end(&stats_cpu->syncp);
+       local_irq_restore(flags);
 }
 EXPORT_SYMBOL_GPL(blkiocg_update_dispatch_stats);
 
@@ -622,15 +633,21 @@ static uint64_t blkio_read_stat_cpu(struct blkio_group *blkg,
 {
        int cpu;
        struct blkio_group_stats_cpu *stats_cpu;
-       uint64_t val = 0;
+       u64 val = 0, tval;
 
        for_each_possible_cpu(cpu) {
+               unsigned int start;
                stats_cpu  = per_cpu_ptr(blkg->stats_cpu, cpu);
 
-               if (type == BLKIO_STAT_CPU_SECTORS)
-                       val += stats_cpu->sectors;
-               else
-                       val += stats_cpu->stat_arr_cpu[type][sub_type];
+               do {
+                       start = u64_stats_fetch_begin(&stats_cpu->syncp);
+                       if (type == BLKIO_STAT_CPU_SECTORS)
+                               tval = stats_cpu->sectors;
+                       else
+                               tval = stats_cpu->stat_arr_cpu[type][sub_type];
+               } while(u64_stats_fetch_retry(&stats_cpu->syncp, start));
+
+               val += tval;
        }
 
        return val;