Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef _LINUX_PART_STAT_H
3#define _LINUX_PART_STAT_H
4
5#include <linux/genhd.h>
6
7/*
8 * Macros to operate on percpu disk statistics:
9 *
10 * {disk|part|all}_stat_{add|sub|inc|dec}() modify the stat counters
11 * and should be called between disk_stat_lock() and
12 * disk_stat_unlock().
13 *
14 * part_stat_read() can be called at any time.
15 *
16 * part_stat_{add|set_all}() and {init|free}_part_stats are for
17 * internal use only.
18 */
19#ifdef CONFIG_SMP
20#define part_stat_lock() ({ rcu_read_lock(); get_cpu(); })
21#define part_stat_unlock() do { put_cpu(); rcu_read_unlock(); } while (0)
22
23#define part_stat_get_cpu(part, field, cpu) \
24 (per_cpu_ptr((part)->dkstats, (cpu))->field)
25
26#define part_stat_get(part, field) \
27 part_stat_get_cpu(part, field, smp_processor_id())
28
29#define part_stat_read(part, field) \
30({ \
31 typeof((part)->dkstats->field) res = 0; \
32 unsigned int _cpu; \
33 for_each_possible_cpu(_cpu) \
34 res += per_cpu_ptr((part)->dkstats, _cpu)->field; \
35 res; \
36})
37
38static inline void part_stat_set_all(struct hd_struct *part, int value)
39{
40 int i;
41
42 for_each_possible_cpu(i)
43 memset(per_cpu_ptr(part->dkstats, i), value,
44 sizeof(struct disk_stats));
45}
46
47static inline int init_part_stats(struct hd_struct *part)
48{
49 part->dkstats = alloc_percpu(struct disk_stats);
50 if (!part->dkstats)
51 return 0;
52 return 1;
53}
54
55static inline void free_part_stats(struct hd_struct *part)
56{
57 free_percpu(part->dkstats);
58}
59
60#else /* !CONFIG_SMP */
61#define part_stat_lock() ({ rcu_read_lock(); 0; })
62#define part_stat_unlock() rcu_read_unlock()
63
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)
67
68static inline void part_stat_set_all(struct hd_struct *part, int value)
69{
70 memset(&part->dkstats, value, sizeof(struct disk_stats));
71}
72
73static inline int init_part_stats(struct hd_struct *part)
74{
75 return 1;
76}
77
78static inline void free_part_stats(struct hd_struct *part)
79{
80}
81
82#endif /* CONFIG_SMP */
83
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]))
88
89#define __part_stat_add(part, field, addnd) \
90 (part_stat_get(part, field) += (addnd))
91
92#define part_stat_add(part, field, addnd) do { \
93 __part_stat_add((part), field, addnd); \
94 if ((part)->partno) \
95 __part_stat_add(&part_to_disk((part))->part0, \
96 field, addnd); \
97} while (0)
98
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)
105
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)))
114
115#endif /* _LINUX_PART_STAT_H */