diff options
author | Thomas Maier <balagi@justmail.de> | 2006-12-08 05:36:11 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-08 11:28:38 -0500 |
commit | 0a0fc9601dd1024ec7171993bf075a789246e1ed (patch) | |
tree | c606a35beb9c56ccfeff57cb594e6a7e5b12a80c | |
parent | 2d4eeec563a0472b68de3597c17f2d3b11c49c00 (diff) |
[PATCH] pktcdvd: bio write congestion using congestion_wait()
This adds a bio write queue congestion control to the pktcdvd driver with
fixed on/off marks. It prevents that the driver consumes a unlimited
amount of write requests.
[akpm@osdl.org: sync with congestion_wait() renaming]
Signed-off-by: Thomas Maier <balagi@justmail.de>
Cc: Peter Osterlund <petero2@telia.com>
Cc: Jens Axboe <jens.axboe@oracle.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/block/pktcdvd.c | 32 | ||||
-rw-r--r-- | include/linux/pktcdvd.h | 9 |
2 files changed, 41 insertions, 0 deletions
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 7e7b892f621a..91fbe7fd6d0b 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
@@ -84,6 +84,8 @@ | |||
84 | static struct pktcdvd_device *pkt_devs[MAX_WRITERS]; | 84 | static struct pktcdvd_device *pkt_devs[MAX_WRITERS]; |
85 | static struct proc_dir_entry *pkt_proc; | 85 | static struct proc_dir_entry *pkt_proc; |
86 | static int pktdev_major; | 86 | static int pktdev_major; |
87 | static int write_congestion_on = PKT_WRITE_CONGESTION_ON; | ||
88 | static int write_congestion_off = PKT_WRITE_CONGESTION_OFF; | ||
87 | static struct mutex ctl_mutex; /* Serialize open/close/setup/teardown */ | 89 | static struct mutex ctl_mutex; /* Serialize open/close/setup/teardown */ |
88 | static mempool_t *psd_pool; | 90 | static mempool_t *psd_pool; |
89 | 91 | ||
@@ -894,6 +896,7 @@ static int pkt_handle_queue(struct pktcdvd_device *pd) | |||
894 | sector_t zone = 0; /* Suppress gcc warning */ | 896 | sector_t zone = 0; /* Suppress gcc warning */ |
895 | struct pkt_rb_node *node, *first_node; | 897 | struct pkt_rb_node *node, *first_node; |
896 | struct rb_node *n; | 898 | struct rb_node *n; |
899 | int wakeup; | ||
897 | 900 | ||
898 | VPRINTK("handle_queue\n"); | 901 | VPRINTK("handle_queue\n"); |
899 | 902 | ||
@@ -966,7 +969,13 @@ try_next_bio: | |||
966 | pkt->write_size += bio->bi_size / CD_FRAMESIZE; | 969 | pkt->write_size += bio->bi_size / CD_FRAMESIZE; |
967 | spin_unlock(&pkt->lock); | 970 | spin_unlock(&pkt->lock); |
968 | } | 971 | } |
972 | /* check write congestion marks, and if bio_queue_size is | ||
973 | below, wake up any waiters */ | ||
974 | wakeup = (pd->write_congestion_on > 0 | ||
975 | && pd->bio_queue_size <= pd->write_congestion_off); | ||
969 | spin_unlock(&pd->lock); | 976 | spin_unlock(&pd->lock); |
977 | if (wakeup) | ||
978 | blk_clear_queue_congested(pd->disk->queue, WRITE); | ||
970 | 979 | ||
971 | pkt->sleep_time = max(PACKET_WAIT_TIME, 1); | 980 | pkt->sleep_time = max(PACKET_WAIT_TIME, 1); |
972 | pkt_set_state(pkt, PACKET_WAITING_STATE); | 981 | pkt_set_state(pkt, PACKET_WAITING_STATE); |
@@ -2179,6 +2188,23 @@ static int pkt_make_request(request_queue_t *q, struct bio *bio) | |||
2179 | } | 2188 | } |
2180 | spin_unlock(&pd->cdrw.active_list_lock); | 2189 | spin_unlock(&pd->cdrw.active_list_lock); |
2181 | 2190 | ||
2191 | /* | ||
2192 | * Test if there is enough room left in the bio work queue | ||
2193 | * (queue size >= congestion on mark). | ||
2194 | * If not, wait till the work queue size is below the congestion off mark. | ||
2195 | */ | ||
2196 | spin_lock(&pd->lock); | ||
2197 | if (pd->write_congestion_on > 0 | ||
2198 | && pd->bio_queue_size >= pd->write_congestion_on) { | ||
2199 | blk_set_queue_congested(q, WRITE); | ||
2200 | do { | ||
2201 | spin_unlock(&pd->lock); | ||
2202 | congestion_wait(WRITE, HZ); | ||
2203 | spin_lock(&pd->lock); | ||
2204 | } while(pd->bio_queue_size > pd->write_congestion_off); | ||
2205 | } | ||
2206 | spin_unlock(&pd->lock); | ||
2207 | |||
2182 | /* | 2208 | /* |
2183 | * No matching packet found. Store the bio in the work queue. | 2209 | * No matching packet found. Store the bio in the work queue. |
2184 | */ | 2210 | */ |
@@ -2298,6 +2324,9 @@ static int pkt_seq_show(struct seq_file *m, void *p) | |||
2298 | seq_printf(m, "\tstate:\t\t\ti:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n", | 2324 | seq_printf(m, "\tstate:\t\t\ti:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n", |
2299 | states[0], states[1], states[2], states[3], states[4], states[5]); | 2325 | states[0], states[1], states[2], states[3], states[4], states[5]); |
2300 | 2326 | ||
2327 | seq_printf(m, "\twrite congestion marks:\toff=%d on=%d\n", | ||
2328 | pd->write_congestion_off, | ||
2329 | pd->write_congestion_on); | ||
2301 | return 0; | 2330 | return 0; |
2302 | } | 2331 | } |
2303 | 2332 | ||
@@ -2474,6 +2503,9 @@ static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev) | |||
2474 | init_waitqueue_head(&pd->wqueue); | 2503 | init_waitqueue_head(&pd->wqueue); |
2475 | pd->bio_queue = RB_ROOT; | 2504 | pd->bio_queue = RB_ROOT; |
2476 | 2505 | ||
2506 | pd->write_congestion_on = write_congestion_on; | ||
2507 | pd->write_congestion_off = write_congestion_off; | ||
2508 | |||
2477 | disk = alloc_disk(1); | 2509 | disk = alloc_disk(1); |
2478 | if (!disk) | 2510 | if (!disk) |
2479 | goto out_mem; | 2511 | goto out_mem; |
diff --git a/include/linux/pktcdvd.h b/include/linux/pktcdvd.h index 8a94c717c266..9b1a185fb1e5 100644 --- a/include/linux/pktcdvd.h +++ b/include/linux/pktcdvd.h | |||
@@ -112,6 +112,12 @@ struct pkt_ctrl_command { | |||
112 | #include <linux/completion.h> | 112 | #include <linux/completion.h> |
113 | #include <linux/cdrom.h> | 113 | #include <linux/cdrom.h> |
114 | 114 | ||
115 | |||
116 | /* default bio write queue congestion marks */ | ||
117 | #define PKT_WRITE_CONGESTION_ON 10000 | ||
118 | #define PKT_WRITE_CONGESTION_OFF 9000 | ||
119 | |||
120 | |||
115 | struct packet_settings | 121 | struct packet_settings |
116 | { | 122 | { |
117 | __u32 size; /* packet size in (512 byte) sectors */ | 123 | __u32 size; /* packet size in (512 byte) sectors */ |
@@ -271,6 +277,9 @@ struct pktcdvd_device | |||
271 | 277 | ||
272 | struct packet_iosched iosched; | 278 | struct packet_iosched iosched; |
273 | struct gendisk *disk; | 279 | struct gendisk *disk; |
280 | |||
281 | int write_congestion_off; | ||
282 | int write_congestion_on; | ||
274 | }; | 283 | }; |
275 | 284 | ||
276 | #endif /* __KERNEL__ */ | 285 | #endif /* __KERNEL__ */ |