| 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 | long congestion_wait_interruptible(int rw, long timeout)
|
| 59 | {
|
| 60 | long ret;
|
| 61 | DEFINE_WAIT(wait);
|
| 62 | wait_queue_head_t *wqh = &congestion_wqh[rw];
|
| 63 |
|
| 64 | prepare_to_wait(wqh, &wait, TASK_INTERRUPTIBLE);
|
| 65 | if (signal_pending(current))
|
| 66 | ret = -ERESTARTSYS;
|
| 67 | else
|
| 68 | ret = io_schedule_timeout(timeout);
|
| 69 | finish_wait(wqh, &wait);
|
| 70 | return ret;
|
| 71 | }
|
| 72 | EXPORT_SYMBOL(congestion_wait_interruptible);
|
| 73 |
|
| 74 | |
| 75 | * congestion_end - wake up sleepers on a congested backing_dev_info
|
| 76 | * @rw: READ or WRITE
|
| 77 |
|
| 78 | void congestion_end(int rw)
|
| 79 | {
|
| 80 | wait_queue_head_t *wqh = &congestion_wqh[rw];
|
| 81 |
|
| 82 | if (waitqueue_active(wqh))
|
| 83 | wake_up(wqh);
|
| 84 | }
|
| 85 | EXPORT_SYMBOL(congestion_end);
|