1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
---|---|
2 | /* |
3 | * Copyright (C) 2021 Red Hat, Inc. All rights reserved. |
4 | * |
5 | * This file is released under the GPL. |
6 | */ |
7 | |
8 | #ifndef DM_IO_TRACKER_H |
9 | #define DM_IO_TRACKER_H |
10 | |
11 | #include <linux/jiffies.h> |
12 | |
13 | struct dm_io_tracker { |
14 | spinlock_t lock; |
15 | |
16 | /* |
17 | * Sectors of in-flight IO. |
18 | */ |
19 | sector_t in_flight; |
20 | |
21 | /* |
22 | * The time, in jiffies, when this device became idle |
23 | * (if it is indeed idle). |
24 | */ |
25 | unsigned long idle_time; |
26 | unsigned long last_update_time; |
27 | }; |
28 | |
29 | static inline void dm_iot_init(struct dm_io_tracker *iot) |
30 | { |
31 | spin_lock_init(&iot->lock); |
32 | iot->in_flight = 0ul; |
33 | iot->idle_time = 0ul; |
34 | iot->last_update_time = jiffies; |
35 | } |
36 | |
37 | static inline bool dm_iot_idle_for(struct dm_io_tracker *iot, unsigned long j) |
38 | { |
39 | bool r = false; |
40 | |
41 | spin_lock_irq(lock: &iot->lock); |
42 | if (!iot->in_flight) |
43 | r = time_after(jiffies, iot->idle_time + j); |
44 | spin_unlock_irq(lock: &iot->lock); |
45 | |
46 | return r; |
47 | } |
48 | |
49 | static inline unsigned long dm_iot_idle_time(struct dm_io_tracker *iot) |
50 | { |
51 | unsigned long r = 0; |
52 | |
53 | spin_lock_irq(lock: &iot->lock); |
54 | if (!iot->in_flight) |
55 | r = jiffies - iot->idle_time; |
56 | spin_unlock_irq(lock: &iot->lock); |
57 | |
58 | return r; |
59 | } |
60 | |
61 | static inline void dm_iot_io_begin(struct dm_io_tracker *iot, sector_t len) |
62 | { |
63 | spin_lock_irq(lock: &iot->lock); |
64 | iot->in_flight += len; |
65 | spin_unlock_irq(lock: &iot->lock); |
66 | } |
67 | |
68 | static inline void dm_iot_io_end(struct dm_io_tracker *iot, sector_t len) |
69 | { |
70 | unsigned long flags; |
71 | |
72 | if (!len) |
73 | return; |
74 | |
75 | spin_lock_irqsave(&iot->lock, flags); |
76 | iot->in_flight -= len; |
77 | if (!iot->in_flight) |
78 | iot->idle_time = jiffies; |
79 | spin_unlock_irqrestore(lock: &iot->lock, flags); |
80 | } |
81 | |
82 | #endif |
83 |