diff options
Diffstat (limited to 'mm/backing-dev.c')
-rw-r--r-- | mm/backing-dev.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/mm/backing-dev.c b/mm/backing-dev.c new file mode 100644 index 000000000000..f50a2811f9dc --- /dev/null +++ b/mm/backing-dev.c | |||
@@ -0,0 +1,69 @@ | |||
1 | |||
2 | #include <linux/wait.h> | ||
3 | #include <linux/backing-dev.h> | ||
4 | #include <linux/fs.h> | ||
5 | #include <linux/sched.h> | ||
6 | #include <linux/module.h> | ||
7 | |||
8 | static wait_queue_head_t congestion_wqh[2] = { | ||
9 | __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]), | ||
10 | __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1]) | ||
11 | }; | ||
12 | |||
13 | |||
14 | void clear_bdi_congested(struct backing_dev_info *bdi, int rw) | ||
15 | { | ||
16 | enum bdi_state bit; | ||
17 | wait_queue_head_t *wqh = &congestion_wqh[rw]; | ||
18 | |||
19 | bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested; | ||
20 | clear_bit(bit, &bdi->state); | ||
21 | smp_mb__after_clear_bit(); | ||
22 | if (waitqueue_active(wqh)) | ||
23 | wake_up(wqh); | ||
24 | } | ||
25 | EXPORT_SYMBOL(clear_bdi_congested); | ||
26 | |||
27 | void set_bdi_congested(struct backing_dev_info *bdi, int rw) | ||
28 | { | ||
29 | enum bdi_state bit; | ||
30 | |||
31 | bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested; | ||
32 | set_bit(bit, &bdi->state); | ||
33 | } | ||
34 | EXPORT_SYMBOL(set_bdi_congested); | ||
35 | |||
36 | /** | ||
37 | * congestion_wait - wait for a backing_dev to become uncongested | ||
38 | * @rw: READ or WRITE | ||
39 | * @timeout: timeout in jiffies | ||
40 | * | ||
41 | * Waits for up to @timeout jiffies for a backing_dev (any backing_dev) to exit | ||
42 | * write congestion. If no backing_devs are congested then just wait for the | ||
43 | * next write to be completed. | ||
44 | */ | ||
45 | long congestion_wait(int rw, long timeout) | ||
46 | { | ||
47 | long ret; | ||
48 | DEFINE_WAIT(wait); | ||
49 | wait_queue_head_t *wqh = &congestion_wqh[rw]; | ||
50 | |||
51 | prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE); | ||
52 | ret = io_schedule_timeout(timeout); | ||
53 | finish_wait(wqh, &wait); | ||
54 | return ret; | ||
55 | } | ||
56 | EXPORT_SYMBOL(congestion_wait); | ||
57 | |||
58 | /** | ||
59 | * congestion_end - wake up sleepers on a congested backing_dev_info | ||
60 | * @rw: READ or WRITE | ||
61 | */ | ||
62 | void congestion_end(int rw) | ||
63 | { | ||
64 | wait_queue_head_t *wqh = &congestion_wqh[rw]; | ||
65 | |||
66 | if (waitqueue_active(wqh)) | ||
67 | wake_up(wqh); | ||
68 | } | ||
69 | EXPORT_SYMBOL(congestion_end); | ||