Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Thomas Maier and committed by
Linus Torvalds
0a0fc960 2d4eeec5

+41
+32
drivers/block/pktcdvd.c
··· 84 84 static struct pktcdvd_device *pkt_devs[MAX_WRITERS]; 85 85 static struct proc_dir_entry *pkt_proc; 86 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 89 static struct mutex ctl_mutex; /* Serialize open/close/setup/teardown */ 88 90 static mempool_t *psd_pool; 89 91 ··· 896 894 sector_t zone = 0; /* Suppress gcc warning */ 897 895 struct pkt_rb_node *node, *first_node; 898 896 struct rb_node *n; 897 + int wakeup; 899 898 900 899 VPRINTK("handle_queue\n"); 901 900 ··· 969 966 pkt->write_size += bio->bi_size / CD_FRAMESIZE; 970 967 spin_unlock(&pkt->lock); 971 968 } 969 + /* check write congestion marks, and if bio_queue_size is 970 + below, wake up any waiters */ 971 + wakeup = (pd->write_congestion_on > 0 972 + && pd->bio_queue_size <= pd->write_congestion_off); 972 973 spin_unlock(&pd->lock); 974 + if (wakeup) 975 + blk_clear_queue_congested(pd->disk->queue, WRITE); 973 976 974 977 pkt->sleep_time = max(PACKET_WAIT_TIME, 1); 975 978 pkt_set_state(pkt, PACKET_WAITING_STATE); ··· 2188 2179 } 2189 2180 spin_unlock(&pd->cdrw.active_list_lock); 2190 2181 2182 + /* 2183 + * Test if there is enough room left in the bio work queue 2184 + * (queue size >= congestion on mark). 2185 + * If not, wait till the work queue size is below the congestion off mark. 2186 + */ 2187 + spin_lock(&pd->lock); 2188 + if (pd->write_congestion_on > 0 2189 + && pd->bio_queue_size >= pd->write_congestion_on) { 2190 + blk_set_queue_congested(q, WRITE); 2191 + do { 2192 + spin_unlock(&pd->lock); 2193 + congestion_wait(WRITE, HZ); 2194 + spin_lock(&pd->lock); 2195 + } while(pd->bio_queue_size > pd->write_congestion_off); 2196 + } 2197 + spin_unlock(&pd->lock); 2198 + 2191 2199 /* 2192 2200 * No matching packet found. Store the bio in the work queue. 2193 2201 */ ··· 2324 2298 seq_printf(m, "\tstate:\t\t\ti:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n", 2325 2299 states[0], states[1], states[2], states[3], states[4], states[5]); 2326 2300 2301 + seq_printf(m, "\twrite congestion marks:\toff=%d on=%d\n", 2302 + pd->write_congestion_off, 2303 + pd->write_congestion_on); 2327 2304 return 0; 2328 2305 } 2329 2306 ··· 2502 2473 sprintf(pd->name, DRIVER_NAME"%d", idx); 2503 2474 init_waitqueue_head(&pd->wqueue); 2504 2475 pd->bio_queue = RB_ROOT; 2476 + 2477 + pd->write_congestion_on = write_congestion_on; 2478 + pd->write_congestion_off = write_congestion_off; 2505 2479 2506 2480 disk = alloc_disk(1); 2507 2481 if (!disk)
+9
include/linux/pktcdvd.h
··· 112 112 #include <linux/completion.h> 113 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 121 struct packet_settings 116 122 { 117 123 __u32 size; /* packet size in (512 byte) sectors */ ··· 277 271 278 272 struct packet_iosched iosched; 279 273 struct gendisk *disk; 274 + 275 + int write_congestion_off; 276 + int write_congestion_on; 280 277 }; 281 278 282 279 #endif /* __KERNEL__ */