mm: scalable bdi statistics counters
[linux-2.6.git] / mm / backing-dev.c
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 int bdi_init(struct backing_dev_info *bdi)
9 {
10         int i, j;
11         int err;
12
13         for (i = 0; i < NR_BDI_STAT_ITEMS; i++) {
14                 err = percpu_counter_init_irq(&bdi->bdi_stat[i], 0);
15                 if (err) {
16                         for (j = 0; j < i; j++)
17                                 percpu_counter_destroy(&bdi->bdi_stat[i]);
18                         break;
19                 }
20         }
21
22         return err;
23 }
24 EXPORT_SYMBOL(bdi_init);
25
26 void bdi_destroy(struct backing_dev_info *bdi)
27 {
28         int i;
29
30         for (i = 0; i < NR_BDI_STAT_ITEMS; i++)
31                 percpu_counter_destroy(&bdi->bdi_stat[i]);
32 }
33 EXPORT_SYMBOL(bdi_destroy);
34
35 static wait_queue_head_t congestion_wqh[2] = {
36                 __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]),
37                 __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1])
38         };
39
40
41 void clear_bdi_congested(struct backing_dev_info *bdi, int rw)
42 {
43         enum bdi_state bit;
44         wait_queue_head_t *wqh = &congestion_wqh[rw];
45
46         bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested;
47         clear_bit(bit, &bdi->state);
48         smp_mb__after_clear_bit();
49         if (waitqueue_active(wqh))
50                 wake_up(wqh);
51 }
52 EXPORT_SYMBOL(clear_bdi_congested);
53
54 void set_bdi_congested(struct backing_dev_info *bdi, int rw)
55 {
56         enum bdi_state bit;
57
58         bit = (rw == WRITE) ? BDI_write_congested : BDI_read_congested;
59         set_bit(bit, &bdi->state);
60 }
61 EXPORT_SYMBOL(set_bdi_congested);
62
63 /**
64  * congestion_wait - wait for a backing_dev to become uncongested
65  * @rw: READ or WRITE
66  * @timeout: timeout in jiffies
67  *
68  * Waits for up to @timeout jiffies for a backing_dev (any backing_dev) to exit
69  * write congestion.  If no backing_devs are congested then just wait for the
70  * next write to be completed.
71  */
72 long congestion_wait(int rw, long timeout)
73 {
74         long ret;
75         DEFINE_WAIT(wait);
76         wait_queue_head_t *wqh = &congestion_wqh[rw];
77
78         prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE);
79         ret = io_schedule_timeout(timeout);
80         finish_wait(wqh, &wait);
81         return ret;
82 }
83 EXPORT_SYMBOL(congestion_wait);