1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _LINUX_PART_STAT_H
3 #define _LINUX_PART_STAT_H
5 #include <linux/genhd.h>
8 * Macros to operate on percpu disk statistics:
10 * {disk|part|all}_stat_{add|sub|inc|dec}() modify the stat counters
11 * and should be called between disk_stat_lock() and
14 * part_stat_read() can be called at any time.
16 * part_stat_{add|set_all}() and {init|free}_part_stats are for
20 #define part_stat_lock() ({ rcu_read_lock(); get_cpu(); })
21 #define part_stat_unlock() do { put_cpu(); rcu_read_unlock(); } while (0)
23 #define part_stat_get_cpu(part, field, cpu) \
24 (per_cpu_ptr((part)->dkstats, (cpu))->field)
26 #define part_stat_get(part, field) \
27 part_stat_get_cpu(part, field, smp_processor_id())
29 #define part_stat_read(part, field) \
31 typeof((part)->dkstats->field) res = 0; \
33 for_each_possible_cpu(_cpu) \
34 res += per_cpu_ptr((part)->dkstats, _cpu)->field; \
38 static inline void part_stat_set_all(struct hd_struct *part, int value)
42 for_each_possible_cpu(i)
43 memset(per_cpu_ptr(part->dkstats, i), value,
44 sizeof(struct disk_stats));
47 static inline int init_part_stats(struct hd_struct *part)
49 part->dkstats = alloc_percpu(struct disk_stats);
55 static inline void free_part_stats(struct hd_struct *part)
57 free_percpu(part->dkstats);
60 #else /* !CONFIG_SMP */
61 #define part_stat_lock() ({ rcu_read_lock(); 0; })
62 #define part_stat_unlock() rcu_read_unlock()
64 #define part_stat_get(part, field) ((part)->dkstats.field)
65 #define part_stat_get_cpu(part, field, cpu) part_stat_get(part, field)
66 #define part_stat_read(part, field) part_stat_get(part, field)
68 static inline void part_stat_set_all(struct hd_struct *part, int value)
70 memset(&part->dkstats, value, sizeof(struct disk_stats));
73 static inline int init_part_stats(struct hd_struct *part)
78 static inline void free_part_stats(struct hd_struct *part)
82 #endif /* CONFIG_SMP */
84 #define part_stat_read_accum(part, field) \
85 (part_stat_read(part, field[STAT_READ]) + \
86 part_stat_read(part, field[STAT_WRITE]) + \
87 part_stat_read(part, field[STAT_DISCARD]))
89 #define __part_stat_add(part, field, addnd) \
90 (part_stat_get(part, field) += (addnd))
92 #define part_stat_add(part, field, addnd) do { \
93 __part_stat_add((part), field, addnd); \
95 __part_stat_add(&part_to_disk((part))->part0, \
99 #define part_stat_dec(gendiskp, field) \
100 part_stat_add(gendiskp, field, -1)
101 #define part_stat_inc(gendiskp, field) \
102 part_stat_add(gendiskp, field, 1)
103 #define part_stat_sub(gendiskp, field, subnd) \
104 part_stat_add(gendiskp, field, -subnd)
106 #define part_stat_local_dec(gendiskp, field) \
107 local_dec(&(part_stat_get(gendiskp, field)))
108 #define part_stat_local_inc(gendiskp, field) \
109 local_inc(&(part_stat_get(gendiskp, field)))
110 #define part_stat_local_read(gendiskp, field) \
111 local_read(&(part_stat_get(gendiskp, field)))
112 #define part_stat_local_read_cpu(gendiskp, field, cpu) \
113 local_read(&(part_stat_get_cpu(gendiskp, field, cpu)))
115 #endif /* _LINUX_PART_STAT_H */