aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Osterlund <petero2@telia.com>2006-02-05 02:27:47 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-02-05 14:06:52 -0500
commite1bc89bc9991e994f2b3c60d9ad2fdb5ad9b10fc (patch)
tree22816d5b1979961ec60507e8b6783a02c7fdb283
parentb566ccefd7814e4fa403de81aea299bdc11ceed5 (diff)
[PATCH] pktcdvd: Don't waste kernel memory
Allocate memory for read-gathering at open time, when it is known just how much memory is needed. This avoids wasting kernel memory when the real packet size is smaller than the maximum packet size supported by the driver. This is always the case when using DVD discs. Signed-off-by: Peter Osterlund <petero2@telia.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/block/Kconfig4
-rw-r--r--drivers/block/pktcdvd.c53
-rw-r--r--include/linux/pktcdvd.h4
3 files changed, 32 insertions, 29 deletions
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index db6818fdf15d..8b1331677407 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -433,8 +433,8 @@ config CDROM_PKTCDVD_BUFFERS
433 This controls the maximum number of active concurrent packets. More 433 This controls the maximum number of active concurrent packets. More
434 concurrent packets can increase write performance, but also require 434 concurrent packets can increase write performance, but also require
435 more memory. Each concurrent packet will require approximately 64Kb 435 more memory. Each concurrent packet will require approximately 64Kb
436 of non-swappable kernel memory, memory which will be allocated at 436 of non-swappable kernel memory, memory which will be allocated when
437 pktsetup time. 437 a disc is opened for writing.
438 438
439config CDROM_PKTCDVD_WCACHE 439config CDROM_PKTCDVD_WCACHE
440 bool "Enable write caching (EXPERIMENTAL)" 440 bool "Enable write caching (EXPERIMENTAL)"
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index cd16813effc5..4e7dbcc425ff 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -129,7 +129,7 @@ static struct bio *pkt_bio_alloc(int nr_iovecs)
129/* 129/*
130 * Allocate a packet_data struct 130 * Allocate a packet_data struct
131 */ 131 */
132static struct packet_data *pkt_alloc_packet_data(void) 132static struct packet_data *pkt_alloc_packet_data(int frames)
133{ 133{
134 int i; 134 int i;
135 struct packet_data *pkt; 135 struct packet_data *pkt;
@@ -138,11 +138,12 @@ static struct packet_data *pkt_alloc_packet_data(void)
138 if (!pkt) 138 if (!pkt)
139 goto no_pkt; 139 goto no_pkt;
140 140
141 pkt->w_bio = pkt_bio_alloc(PACKET_MAX_SIZE); 141 pkt->frames = frames;
142 pkt->w_bio = pkt_bio_alloc(frames);
142 if (!pkt->w_bio) 143 if (!pkt->w_bio)
143 goto no_bio; 144 goto no_bio;
144 145
145 for (i = 0; i < PAGES_PER_PACKET; i++) { 146 for (i = 0; i < frames / FRAMES_PER_PAGE; i++) {
146 pkt->pages[i] = alloc_page(GFP_KERNEL|__GFP_ZERO); 147 pkt->pages[i] = alloc_page(GFP_KERNEL|__GFP_ZERO);
147 if (!pkt->pages[i]) 148 if (!pkt->pages[i])
148 goto no_page; 149 goto no_page;
@@ -150,7 +151,7 @@ static struct packet_data *pkt_alloc_packet_data(void)
150 151
151 spin_lock_init(&pkt->lock); 152 spin_lock_init(&pkt->lock);
152 153
153 for (i = 0; i < PACKET_MAX_SIZE; i++) { 154 for (i = 0; i < frames; i++) {
154 struct bio *bio = pkt_bio_alloc(1); 155 struct bio *bio = pkt_bio_alloc(1);
155 if (!bio) 156 if (!bio)
156 goto no_rd_bio; 157 goto no_rd_bio;
@@ -160,14 +161,14 @@ static struct packet_data *pkt_alloc_packet_data(void)
160 return pkt; 161 return pkt;
161 162
162no_rd_bio: 163no_rd_bio:
163 for (i = 0; i < PACKET_MAX_SIZE; i++) { 164 for (i = 0; i < frames; i++) {
164 struct bio *bio = pkt->r_bios[i]; 165 struct bio *bio = pkt->r_bios[i];
165 if (bio) 166 if (bio)
166 bio_put(bio); 167 bio_put(bio);
167 } 168 }
168 169
169no_page: 170no_page:
170 for (i = 0; i < PAGES_PER_PACKET; i++) 171 for (i = 0; i < frames / FRAMES_PER_PAGE; i++)
171 if (pkt->pages[i]) 172 if (pkt->pages[i])
172 __free_page(pkt->pages[i]); 173 __free_page(pkt->pages[i]);
173 bio_put(pkt->w_bio); 174 bio_put(pkt->w_bio);
@@ -184,12 +185,12 @@ static void pkt_free_packet_data(struct packet_data *pkt)
184{ 185{
185 int i; 186 int i;
186 187
187 for (i = 0; i < PACKET_MAX_SIZE; i++) { 188 for (i = 0; i < pkt->frames; i++) {
188 struct bio *bio = pkt->r_bios[i]; 189 struct bio *bio = pkt->r_bios[i];
189 if (bio) 190 if (bio)
190 bio_put(bio); 191 bio_put(bio);
191 } 192 }
192 for (i = 0; i < PAGES_PER_PACKET; i++) 193 for (i = 0; i < pkt->frames / FRAMES_PER_PAGE; i++)
193 __free_page(pkt->pages[i]); 194 __free_page(pkt->pages[i]);
194 bio_put(pkt->w_bio); 195 bio_put(pkt->w_bio);
195 kfree(pkt); 196 kfree(pkt);
@@ -204,17 +205,17 @@ static void pkt_shrink_pktlist(struct pktcdvd_device *pd)
204 list_for_each_entry_safe(pkt, next, &pd->cdrw.pkt_free_list, list) { 205 list_for_each_entry_safe(pkt, next, &pd->cdrw.pkt_free_list, list) {
205 pkt_free_packet_data(pkt); 206 pkt_free_packet_data(pkt);
206 } 207 }
208 INIT_LIST_HEAD(&pd->cdrw.pkt_free_list);
207} 209}
208 210
209static int pkt_grow_pktlist(struct pktcdvd_device *pd, int nr_packets) 211static int pkt_grow_pktlist(struct pktcdvd_device *pd, int nr_packets)
210{ 212{
211 struct packet_data *pkt; 213 struct packet_data *pkt;
212 214
213 INIT_LIST_HEAD(&pd->cdrw.pkt_free_list); 215 BUG_ON(!list_empty(&pd->cdrw.pkt_free_list));
214 INIT_LIST_HEAD(&pd->cdrw.pkt_active_list); 216
215 spin_lock_init(&pd->cdrw.active_list_lock);
216 while (nr_packets > 0) { 217 while (nr_packets > 0) {
217 pkt = pkt_alloc_packet_data(); 218 pkt = pkt_alloc_packet_data(pd->settings.size >> 2);
218 if (!pkt) { 219 if (!pkt) {
219 pkt_shrink_pktlist(pd); 220 pkt_shrink_pktlist(pd);
220 return 0; 221 return 0;
@@ -949,7 +950,7 @@ try_next_bio:
949 950
950 pd->current_sector = zone + pd->settings.size; 951 pd->current_sector = zone + pd->settings.size;
951 pkt->sector = zone; 952 pkt->sector = zone;
952 pkt->frames = pd->settings.size >> 2; 953 BUG_ON(pkt->frames != pd->settings.size >> 2);
953 pkt->write_size = 0; 954 pkt->write_size = 0;
954 955
955 /* 956 /*
@@ -1985,8 +1986,14 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write)
1985 if ((ret = pkt_set_segment_merging(pd, q))) 1986 if ((ret = pkt_set_segment_merging(pd, q)))
1986 goto out_unclaim; 1987 goto out_unclaim;
1987 1988
1988 if (write) 1989 if (write) {
1990 if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) {
1991 printk("pktcdvd: not enough memory for buffers\n");
1992 ret = -ENOMEM;
1993 goto out_unclaim;
1994 }
1989 printk("pktcdvd: %lukB available on disc\n", lba << 1); 1995 printk("pktcdvd: %lukB available on disc\n", lba << 1);
1996 }
1990 1997
1991 return 0; 1998 return 0;
1992 1999
@@ -2012,6 +2019,8 @@ static void pkt_release_dev(struct pktcdvd_device *pd, int flush)
2012 pkt_set_speed(pd, MAX_SPEED, MAX_SPEED); 2019 pkt_set_speed(pd, MAX_SPEED, MAX_SPEED);
2013 bd_release(pd->bdev); 2020 bd_release(pd->bdev);
2014 blkdev_put(pd->bdev); 2021 blkdev_put(pd->bdev);
2022
2023 pkt_shrink_pktlist(pd);
2015} 2024}
2016 2025
2017static struct pktcdvd_device *pkt_find_dev_from_minor(int dev_minor) 2026static struct pktcdvd_device *pkt_find_dev_from_minor(int dev_minor)
@@ -2377,12 +2386,6 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
2377 /* This is safe, since we have a reference from open(). */ 2386 /* This is safe, since we have a reference from open(). */
2378 __module_get(THIS_MODULE); 2387 __module_get(THIS_MODULE);
2379 2388
2380 if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) {
2381 printk("pktcdvd: not enough memory for buffers\n");
2382 ret = -ENOMEM;
2383 goto out_mem;
2384 }
2385
2386 pd->bdev = bdev; 2389 pd->bdev = bdev;
2387 set_blocksize(bdev, CD_FRAMESIZE); 2390 set_blocksize(bdev, CD_FRAMESIZE);
2388 2391
@@ -2393,7 +2396,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
2393 if (IS_ERR(pd->cdrw.thread)) { 2396 if (IS_ERR(pd->cdrw.thread)) {
2394 printk("pktcdvd: can't start kernel thread\n"); 2397 printk("pktcdvd: can't start kernel thread\n");
2395 ret = -ENOMEM; 2398 ret = -ENOMEM;
2396 goto out_thread; 2399 goto out_mem;
2397 } 2400 }
2398 2401
2399 proc = create_proc_entry(pd->name, 0, pkt_proc); 2402 proc = create_proc_entry(pd->name, 0, pkt_proc);
@@ -2404,8 +2407,6 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
2404 DPRINTK("pktcdvd: writer %s mapped to %s\n", pd->name, bdevname(bdev, b)); 2407 DPRINTK("pktcdvd: writer %s mapped to %s\n", pd->name, bdevname(bdev, b));
2405 return 0; 2408 return 0;
2406 2409
2407out_thread:
2408 pkt_shrink_pktlist(pd);
2409out_mem: 2410out_mem:
2410 blkdev_put(bdev); 2411 blkdev_put(bdev);
2411 /* This is safe: open() is still holding a reference. */ 2412 /* This is safe: open() is still holding a reference. */
@@ -2501,6 +2502,10 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd)
2501 goto out_mem; 2502 goto out_mem;
2502 pd->disk = disk; 2503 pd->disk = disk;
2503 2504
2505 INIT_LIST_HEAD(&pd->cdrw.pkt_free_list);
2506 INIT_LIST_HEAD(&pd->cdrw.pkt_active_list);
2507 spin_lock_init(&pd->cdrw.active_list_lock);
2508
2504 spin_lock_init(&pd->lock); 2509 spin_lock_init(&pd->lock);
2505 spin_lock_init(&pd->iosched.lock); 2510 spin_lock_init(&pd->iosched.lock);
2506 sprintf(pd->name, "pktcdvd%d", idx); 2511 sprintf(pd->name, "pktcdvd%d", idx);
@@ -2565,8 +2570,6 @@ static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd)
2565 2570
2566 blkdev_put(pd->bdev); 2571 blkdev_put(pd->bdev);
2567 2572
2568 pkt_shrink_pktlist(pd);
2569
2570 remove_proc_entry(pd->name, pkt_proc); 2573 remove_proc_entry(pd->name, pkt_proc);
2571 DPRINTK("pktcdvd: writer %s unmapped\n", pd->name); 2574 DPRINTK("pktcdvd: writer %s unmapped\n", pd->name);
2572 2575
diff --git a/include/linux/pktcdvd.h b/include/linux/pktcdvd.h
index d1c9c4a86e52..1623da88d6fe 100644
--- a/include/linux/pktcdvd.h
+++ b/include/linux/pktcdvd.h
@@ -170,7 +170,7 @@ struct packet_iosched
170#error "PAGE_SIZE must be a multiple of CD_FRAMESIZE" 170#error "PAGE_SIZE must be a multiple of CD_FRAMESIZE"
171#endif 171#endif
172#define PACKET_MAX_SIZE 32 172#define PACKET_MAX_SIZE 32
173#define PAGES_PER_PACKET (PACKET_MAX_SIZE * CD_FRAMESIZE / PAGE_SIZE) 173#define FRAMES_PER_PAGE (PAGE_SIZE / CD_FRAMESIZE)
174#define PACKET_MAX_SECTORS (PACKET_MAX_SIZE * CD_FRAMESIZE >> 9) 174#define PACKET_MAX_SECTORS (PACKET_MAX_SIZE * CD_FRAMESIZE >> 9)
175 175
176enum packet_data_state { 176enum packet_data_state {
@@ -219,7 +219,7 @@ struct packet_data
219 atomic_t io_errors; /* Number of read/write errors during IO */ 219 atomic_t io_errors; /* Number of read/write errors during IO */
220 220
221 struct bio *r_bios[PACKET_MAX_SIZE]; /* bios to use during data gathering */ 221 struct bio *r_bios[PACKET_MAX_SIZE]; /* bios to use during data gathering */
222 struct page *pages[PAGES_PER_PACKET]; 222 struct page *pages[PACKET_MAX_SIZE / FRAMES_PER_PAGE];
223 223
224 int cache_valid; /* If non-zero, the data for the zone defined */ 224 int cache_valid; /* If non-zero, the data for the zone defined */
225 /* by the sector variable is completely cached */ 225 /* by the sector variable is completely cached */