]>
Commit | Line | Data |
---|---|---|
2ab4c71a | 1 | diff -Nur linux-2.4.18/drivers/block/loop.c linux-int-2.4.18/drivers/block/loop.c |
2 | --- linux-2.4.18/drivers/block/loop.c Fri Dec 21 18:41:53 2001 | |
3 | +++ linux-int-2.4.18/drivers/block/loop.c Thu May 30 14:50:16 2002 | |
4 | @@ -49,6 +49,18 @@ | |
5 | * problem above. Encryption modules that used to rely on the old scheme | |
6 | * should just call ->i_mapping->bmap() to calculate the physical block | |
7 | * number. | |
8 | + * | |
9 | + * AES transfer added. IV is now passed as (512 byte) sector number. | |
10 | + * Jari Ruusu <jari.ruusu@pp.inet.fi>, May 18 2001 | |
11 | + * | |
12 | + * External encryption module locking bug fixed. | |
13 | + * Ingo Rohloff <rohloff@in.tum.de>, June 21 2001 | |
14 | + * | |
15 | + * Make device backed loop work with swap (pre-allocated buffers + queue rewrite). | |
16 | + * Jari Ruusu <jari.ruusu@pp.inet.fi>, September 2 2001 | |
17 | + * | |
18 | + * File backed code now uses file->f_op->read/write. Based on Andrew Morton's idea. | |
19 | + * Jari Ruusu <jari.ruusu@pp.inet.fi>, May 23 2002 | |
20 | */ | |
21 | ||
22 | #include <linux/config.h> | |
23 | @@ -79,6 +91,7 @@ | |
24 | static struct loop_device *loop_dev; | |
25 | static int *loop_sizes; | |
26 | static int *loop_blksizes; | |
27 | +static int *loop_hardsizes; | |
28 | static devfs_handle_t devfs_handle; /* For the directory */ | |
29 | ||
30 | /* | |
31 | @@ -93,7 +106,8 @@ | |
32 | else | |
33 | memcpy(raw_buf, loop_buf, size); | |
34 | } | |
35 | - | |
36 | + if (current->need_resched) | |
37 | + schedule(); | |
38 | return 0; | |
39 | } | |
40 | ||
41 | @@ -115,12 +129,13 @@ | |
42 | keysize = lo->lo_encrypt_key_size; | |
43 | for (i = 0; i < size; i++) | |
44 | *out++ = *in++ ^ key[(i & 511) % keysize]; | |
45 | + if (current->need_resched) | |
46 | + schedule(); | |
47 | return 0; | |
48 | } | |
49 | ||
50 | static int none_status(struct loop_device *lo, struct loop_info *info) | |
51 | { | |
52 | - lo->lo_flags |= LO_FLAGS_BH_REMAP; | |
53 | return 0; | |
54 | } | |
55 | ||
56 | @@ -146,316 +161,332 @@ | |
57 | /* xfer_funcs[0] is special - its release function is never called */ | |
58 | struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = { | |
59 | &none_funcs, | |
60 | - &xor_funcs | |
61 | + &xor_funcs, | |
62 | }; | |
63 | ||
64 | -#define MAX_DISK_SIZE 1024*1024*1024 | |
65 | - | |
66 | -static int compute_loop_size(struct loop_device *lo, struct dentry * lo_dentry, kdev_t lodev) | |
67 | -{ | |
68 | - if (S_ISREG(lo_dentry->d_inode->i_mode)) | |
69 | - return (lo_dentry->d_inode->i_size - lo->lo_offset) >> BLOCK_SIZE_BITS; | |
70 | - if (blk_size[MAJOR(lodev)]) | |
71 | - return blk_size[MAJOR(lodev)][MINOR(lodev)] - | |
72 | - (lo->lo_offset >> BLOCK_SIZE_BITS); | |
73 | - return MAX_DISK_SIZE; | |
74 | +/* | |
75 | + * First number of 'lo_prealloc' is the default number of RAM pages | |
76 | + * to pre-allocate for each device backed loop. Every (configured) | |
77 | + * device backed loop pre-allocates this amount of RAM pages unless | |
78 | + * later 'lo_prealloc' numbers provide an override. 'lo_prealloc' | |
79 | + * overrides are defined in pairs: loop_index,number_of_pages | |
80 | + */ | |
81 | +static int lo_prealloc[9] = { 125, 999, 0, 999, 0, 999, 0, 999, 0 }; | |
82 | +#define LO_PREALLOC_MIN 4 /* minimum user defined pre-allocated RAM pages */ | |
83 | +#define LO_PREALLOC_MAX 512 /* maximum user defined pre-allocated RAM pages */ | |
84 | + | |
85 | +#ifdef MODULE | |
86 | +MODULE_PARM(lo_prealloc, "1-9i"); | |
87 | +MODULE_PARM_DESC(lo_prealloc, "Number of pre-allocated pages [,index,pages]..."); | |
88 | +#else | |
89 | +static int __init lo_prealloc_setup(char *str) | |
90 | +{ | |
91 | + int x, y, z; | |
92 | + | |
93 | + for (x = 0; x < (sizeof(lo_prealloc) / sizeof(int)); x++) { | |
94 | + z = get_option(&str, &y); | |
95 | + if (z > 0) | |
96 | + lo_prealloc[x] = y; | |
97 | + if (z < 2) | |
98 | + break; | |
99 | + } | |
100 | + return 1; | |
101 | } | |
102 | +__setup("lo_prealloc=", lo_prealloc_setup); | |
103 | +#endif | |
104 | ||
105 | -static void figure_loop_size(struct loop_device *lo) | |
106 | +typedef struct { | |
107 | + struct buffer_head **q0; | |
108 | + struct buffer_head **q1; | |
109 | + struct buffer_head **q2; | |
110 | + int x0; | |
111 | + int x1; | |
112 | + int x2; | |
113 | +} que_look_up_table; | |
114 | + | |
115 | +static void loop_prealloc_cleanup(struct loop_device *lo) | |
116 | { | |
117 | - loop_sizes[lo->lo_number] = compute_loop_size(lo, | |
118 | - lo->lo_backing_file->f_dentry, | |
119 | - lo->lo_device); | |
120 | + struct buffer_head *bh; | |
121 | + | |
122 | + while ((bh = lo->lo_bh_free)) { | |
123 | + __free_page(bh->b_page); | |
124 | + lo->lo_bh_free = bh->b_reqnext; | |
125 | + bh->b_reqnext = NULL; | |
126 | + kmem_cache_free(bh_cachep, bh); | |
127 | + } | |
128 | } | |
129 | ||
130 | -static int lo_send(struct loop_device *lo, struct buffer_head *bh, int bsize, | |
131 | - loff_t pos) | |
132 | +static int loop_prealloc_init(struct loop_device *lo, int y) | |
133 | { | |
134 | - struct file *file = lo->lo_backing_file; /* kudos to NFsckingS */ | |
135 | - struct address_space *mapping = file->f_dentry->d_inode->i_mapping; | |
136 | - struct address_space_operations *aops = mapping->a_ops; | |
137 | - struct page *page; | |
138 | - char *kaddr, *data; | |
139 | - unsigned long index; | |
140 | - unsigned size, offset; | |
141 | - int len; | |
142 | - | |
143 | - down(&mapping->host->i_sem); | |
144 | - index = pos >> PAGE_CACHE_SHIFT; | |
145 | - offset = pos & (PAGE_CACHE_SIZE - 1); | |
146 | - len = bh->b_size; | |
147 | - data = bh->b_data; | |
148 | - while (len > 0) { | |
149 | - int IV = index * (PAGE_CACHE_SIZE/bsize) + offset/bsize; | |
150 | - int transfer_result; | |
151 | + struct buffer_head *bh; | |
152 | + int x; | |
153 | ||
154 | - size = PAGE_CACHE_SIZE - offset; | |
155 | - if (size > len) | |
156 | - size = len; | |
157 | + if(!y) { | |
158 | + y = lo_prealloc[0]; | |
159 | + for (x = 1; x < (sizeof(lo_prealloc) / sizeof(int)); x += 2) { | |
160 | + if (lo_prealloc[x + 1] && (lo->lo_number == lo_prealloc[x])) { | |
161 | + y = lo_prealloc[x + 1]; | |
162 | + break; | |
163 | + } | |
164 | + } | |
165 | + } | |
166 | + lo->lo_bh_flsh = (y * 3) / 4; | |
167 | ||
168 | - page = grab_cache_page(mapping, index); | |
169 | - if (!page) | |
170 | - goto fail; | |
171 | - if (aops->prepare_write(file, page, offset, offset+size)) | |
172 | - goto unlock; | |
173 | - kaddr = page_address(page); | |
174 | - flush_dcache_page(page); | |
175 | - transfer_result = lo_do_transfer(lo, WRITE, kaddr + offset, data, size, IV); | |
176 | - if (transfer_result) { | |
177 | - /* | |
178 | - * The transfer failed, but we still write the data to | |
179 | - * keep prepare/commit calls balanced. | |
180 | - */ | |
181 | - printk(KERN_ERR "loop: transfer error block %ld\n", index); | |
182 | - memset(kaddr + offset, 0, size); | |
183 | + for (x = 0; x < y; x++) { | |
184 | + bh = kmem_cache_alloc(bh_cachep, SLAB_KERNEL); | |
185 | + if (!bh) { | |
186 | + loop_prealloc_cleanup(lo); | |
187 | + return 1; | |
188 | } | |
189 | - if (aops->commit_write(file, page, offset, offset+size)) | |
190 | - goto unlock; | |
191 | - if (transfer_result) | |
192 | - goto unlock; | |
193 | - data += size; | |
194 | - len -= size; | |
195 | - offset = 0; | |
196 | - index++; | |
197 | - pos += size; | |
198 | - UnlockPage(page); | |
199 | - page_cache_release(page); | |
200 | + bh->b_page = alloc_page(GFP_KERNEL); | |
201 | + if (!bh->b_page) { | |
202 | + bh->b_reqnext = NULL; | |
203 | + kmem_cache_free(bh_cachep, bh); | |
204 | + loop_prealloc_cleanup(lo); | |
205 | + return 1; | |
206 | + } | |
207 | + bh->b_reqnext = lo->lo_bh_free; | |
208 | + lo->lo_bh_free = bh; | |
209 | } | |
210 | - up(&mapping->host->i_sem); | |
211 | return 0; | |
212 | - | |
213 | -unlock: | |
214 | - UnlockPage(page); | |
215 | - page_cache_release(page); | |
216 | -fail: | |
217 | - up(&mapping->host->i_sem); | |
218 | - return -1; | |
219 | -} | |
220 | - | |
221 | -struct lo_read_data { | |
222 | - struct loop_device *lo; | |
223 | - char *data; | |
224 | - int bsize; | |
225 | -}; | |
226 | - | |
227 | -static int lo_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size) | |
228 | -{ | |
229 | - char *kaddr; | |
230 | - unsigned long count = desc->count; | |
231 | - struct lo_read_data *p = (struct lo_read_data*)desc->buf; | |
232 | - struct loop_device *lo = p->lo; | |
233 | - int IV = page->index * (PAGE_CACHE_SIZE/p->bsize) + offset/p->bsize; | |
234 | - | |
235 | - if (size > count) | |
236 | - size = count; | |
237 | - | |
238 | - kaddr = kmap(page); | |
239 | - if (lo_do_transfer(lo, READ, kaddr + offset, p->data, size, IV)) { | |
240 | - size = 0; | |
241 | - printk(KERN_ERR "loop: transfer error block %ld\n",page->index); | |
242 | - desc->error = -EINVAL; | |
243 | - } | |
244 | - kunmap(page); | |
245 | - | |
246 | - desc->count = count - size; | |
247 | - desc->written += size; | |
248 | - p->data += size; | |
249 | - return size; | |
250 | -} | |
251 | - | |
252 | -static int lo_receive(struct loop_device *lo, struct buffer_head *bh, int bsize, | |
253 | - loff_t pos) | |
254 | -{ | |
255 | - struct lo_read_data cookie; | |
256 | - read_descriptor_t desc; | |
257 | - struct file *file; | |
258 | - | |
259 | - cookie.lo = lo; | |
260 | - cookie.data = bh->b_data; | |
261 | - cookie.bsize = bsize; | |
262 | - desc.written = 0; | |
263 | - desc.count = bh->b_size; | |
264 | - desc.buf = (char*)&cookie; | |
265 | - desc.error = 0; | |
266 | - spin_lock_irq(&lo->lo_lock); | |
267 | - file = lo->lo_backing_file; | |
268 | - spin_unlock_irq(&lo->lo_lock); | |
269 | - do_generic_file_read(file, &pos, &desc, lo_read_actor); | |
270 | - return desc.error; | |
271 | } | |
272 | ||
273 | -static inline int loop_get_bs(struct loop_device *lo) | |
274 | +static void loop_add_queue_last(struct loop_device *lo, struct buffer_head *bh, struct buffer_head **q) | |
275 | { | |
276 | - int bs = 0; | |
277 | + unsigned long flags; | |
278 | ||
279 | - if (blksize_size[MAJOR(lo->lo_device)]) | |
280 | - bs = blksize_size[MAJOR(lo->lo_device)][MINOR(lo->lo_device)]; | |
281 | - if (!bs) | |
282 | - bs = BLOCK_SIZE; | |
283 | + spin_lock_irqsave(&lo->lo_lock, flags); | |
284 | + if (*q) { | |
285 | + bh->b_reqnext = (*q)->b_reqnext; | |
286 | + (*q)->b_reqnext = bh; | |
287 | + } else { | |
288 | + bh->b_reqnext = bh; | |
289 | + } | |
290 | + *q = bh; | |
291 | + spin_unlock_irqrestore(&lo->lo_lock, flags); | |
292 | ||
293 | - return bs; | |
294 | + if (waitqueue_active(&lo->lo_bh_wait)) | |
295 | + wake_up_interruptible(&lo->lo_bh_wait); | |
296 | } | |
297 | ||
298 | -static inline unsigned long loop_get_iv(struct loop_device *lo, | |
299 | - unsigned long sector) | |
300 | +static void loop_add_queue_first(struct loop_device *lo, struct buffer_head *bh, struct buffer_head **q) | |
301 | { | |
302 | - int bs = loop_get_bs(lo); | |
303 | - unsigned long offset, IV; | |
304 | - | |
305 | - IV = sector / (bs >> 9) + lo->lo_offset / bs; | |
306 | - offset = ((sector % (bs >> 9)) << 9) + lo->lo_offset % bs; | |
307 | - if (offset >= bs) | |
308 | - IV++; | |
309 | - | |
310 | - return IV; | |
311 | + spin_lock_irq(&lo->lo_lock); | |
312 | + if (*q) { | |
313 | + bh->b_reqnext = (*q)->b_reqnext; | |
314 | + (*q)->b_reqnext = bh; | |
315 | + } else { | |
316 | + bh->b_reqnext = bh; | |
317 | + *q = bh; | |
318 | + } | |
319 | + spin_unlock_irq(&lo->lo_lock); | |
320 | } | |
321 | ||
322 | -static int do_bh_filebacked(struct loop_device *lo, struct buffer_head *bh, int rw) | |
323 | +static struct buffer_head *loop_get_bh(struct loop_device *lo, int *list_nr, | |
324 | + que_look_up_table *qt) | |
325 | { | |
326 | - loff_t pos; | |
327 | - int ret; | |
328 | - | |
329 | - pos = ((loff_t) bh->b_rsector << 9) + lo->lo_offset; | |
330 | + struct buffer_head *bh = NULL, *last; | |
331 | ||
332 | - if (rw == WRITE) | |
333 | - ret = lo_send(lo, bh, loop_get_bs(lo), pos); | |
334 | - else | |
335 | - ret = lo_receive(lo, bh, loop_get_bs(lo), pos); | |
336 | - | |
337 | - return ret; | |
338 | -} | |
339 | - | |
340 | -static void loop_end_io_transfer(struct buffer_head *bh, int uptodate); | |
341 | -static void loop_put_buffer(struct buffer_head *bh) | |
342 | -{ | |
343 | - /* | |
344 | - * check b_end_io, may just be a remapped bh and not an allocated one | |
345 | - */ | |
346 | - if (bh && bh->b_end_io == loop_end_io_transfer) { | |
347 | - __free_page(bh->b_page); | |
348 | - kmem_cache_free(bh_cachep, bh); | |
349 | + spin_lock_irq(&lo->lo_lock); | |
350 | + if ((last = *qt->q0)) { | |
351 | + bh = last->b_reqnext; | |
352 | + if (bh == last) | |
353 | + *qt->q0 = NULL; | |
354 | + else | |
355 | + last->b_reqnext = bh->b_reqnext; | |
356 | + bh->b_reqnext = NULL; | |
357 | + *list_nr = qt->x0; | |
358 | + } else if ((last = *qt->q1)) { | |
359 | + bh = last->b_reqnext; | |
360 | + if (bh == last) | |
361 | + *qt->q1 = NULL; | |
362 | + else | |
363 | + last->b_reqnext = bh->b_reqnext; | |
364 | + bh->b_reqnext = NULL; | |
365 | + *list_nr = qt->x1; | |
366 | + } else if ((last = *qt->q2)) { | |
367 | + bh = last->b_reqnext; | |
368 | + if (bh == last) | |
369 | + *qt->q2 = NULL; | |
370 | + else | |
371 | + last->b_reqnext = bh->b_reqnext; | |
372 | + bh->b_reqnext = NULL; | |
373 | + *list_nr = qt->x2; | |
374 | } | |
375 | + spin_unlock_irq(&lo->lo_lock); | |
376 | + return bh; | |
377 | } | |
378 | ||
379 | -/* | |
380 | - * Add buffer_head to back of pending list | |
381 | - */ | |
382 | -static void loop_add_bh(struct loop_device *lo, struct buffer_head *bh) | |
383 | +static void loop_put_buffer(struct loop_device *lo, struct buffer_head *b) | |
384 | { | |
385 | unsigned long flags; | |
386 | + int wk; | |
387 | ||
388 | spin_lock_irqsave(&lo->lo_lock, flags); | |
389 | - if (lo->lo_bhtail) { | |
390 | - lo->lo_bhtail->b_reqnext = bh; | |
391 | - lo->lo_bhtail = bh; | |
392 | - } else | |
393 | - lo->lo_bh = lo->lo_bhtail = bh; | |
394 | + b->b_reqnext = lo->lo_bh_free; | |
395 | + lo->lo_bh_free = b; | |
396 | + wk = lo->lo_bh_need; | |
397 | spin_unlock_irqrestore(&lo->lo_lock, flags); | |
398 | ||
399 | - up(&lo->lo_bh_mutex); | |
400 | + if (wk && waitqueue_active(&lo->lo_bh_wait)) | |
401 | + wake_up_interruptible(&lo->lo_bh_wait); | |
402 | } | |
403 | ||
404 | -/* | |
405 | - * Grab first pending buffer | |
406 | - */ | |
407 | -static struct buffer_head *loop_get_bh(struct loop_device *lo) | |
408 | +static void loop_end_io_transfer_wr(struct buffer_head *bh, int uptodate) | |
409 | { | |
410 | - struct buffer_head *bh; | |
411 | - | |
412 | - spin_lock_irq(&lo->lo_lock); | |
413 | - if ((bh = lo->lo_bh)) { | |
414 | - if (bh == lo->lo_bhtail) | |
415 | - lo->lo_bhtail = NULL; | |
416 | - lo->lo_bh = bh->b_reqnext; | |
417 | - bh->b_reqnext = NULL; | |
418 | - } | |
419 | - spin_unlock_irq(&lo->lo_lock); | |
420 | + struct loop_device *lo = &loop_dev[MINOR(bh->b_dev)]; | |
421 | + struct buffer_head *rbh = bh->b_private; | |
422 | ||
423 | - return bh; | |
424 | + rbh->b_reqnext = NULL; | |
425 | + rbh->b_end_io(rbh, uptodate); | |
426 | + loop_put_buffer(lo, bh); | |
427 | + if (atomic_dec_and_test(&lo->lo_pending)) | |
428 | + wake_up_interruptible(&lo->lo_bh_wait); | |
429 | } | |
430 | ||
431 | -/* | |
432 | - * when buffer i/o has completed. if BH_Dirty is set, this was a WRITE | |
433 | - * and lo->transfer stuff has already been done. if not, it was a READ | |
434 | - * so queue it for the loop thread and let it do the transfer out of | |
435 | - * b_end_io context (we don't want to do decrypt of a page with irqs | |
436 | - * disabled) | |
437 | - */ | |
438 | -static void loop_end_io_transfer(struct buffer_head *bh, int uptodate) | |
439 | +static void loop_end_io_transfer_rd(struct buffer_head *bh, int uptodate) | |
440 | { | |
441 | struct loop_device *lo = &loop_dev[MINOR(bh->b_dev)]; | |
442 | ||
443 | - if (!uptodate || test_bit(BH_Dirty, &bh->b_state)) { | |
444 | - struct buffer_head *rbh = bh->b_private; | |
445 | - | |
446 | - rbh->b_end_io(rbh, uptodate); | |
447 | - if (atomic_dec_and_test(&lo->lo_pending)) | |
448 | - up(&lo->lo_bh_mutex); | |
449 | - loop_put_buffer(bh); | |
450 | - } else | |
451 | - loop_add_bh(lo, bh); | |
452 | + if (!uptodate) | |
453 | + loop_end_io_transfer_wr(bh, uptodate); | |
454 | + else | |
455 | + loop_add_queue_last(lo, bh, &lo->lo_bhQue0); | |
456 | } | |
457 | ||
458 | static struct buffer_head *loop_get_buffer(struct loop_device *lo, | |
459 | - struct buffer_head *rbh) | |
460 | + struct buffer_head *rbh, int from_thread, int rw) | |
461 | { | |
462 | struct buffer_head *bh; | |
463 | + struct page *p; | |
464 | + unsigned long flags; | |
465 | ||
466 | - /* | |
467 | - * for xfer_funcs that can operate on the same bh, do that | |
468 | - */ | |
469 | - if (lo->lo_flags & LO_FLAGS_BH_REMAP) { | |
470 | - bh = rbh; | |
471 | - goto out_bh; | |
472 | + spin_lock_irqsave(&lo->lo_lock, flags); | |
473 | + bh = lo->lo_bh_free; | |
474 | + if (bh) { | |
475 | + lo->lo_bh_free = bh->b_reqnext; | |
476 | + if (from_thread) | |
477 | + lo->lo_bh_need = 0; | |
478 | + } else { | |
479 | + if (from_thread) | |
480 | + lo->lo_bh_need = 1; | |
481 | } | |
482 | + spin_unlock_irqrestore(&lo->lo_lock, flags); | |
483 | + if (!bh) | |
484 | + return (struct buffer_head *)0; | |
485 | ||
486 | - do { | |
487 | - bh = kmem_cache_alloc(bh_cachep, SLAB_NOIO); | |
488 | - if (bh) | |
489 | - break; | |
490 | - | |
491 | - run_task_queue(&tq_disk); | |
492 | - schedule_timeout(HZ); | |
493 | - } while (1); | |
494 | - memset(bh, 0, sizeof(*bh)); | |
495 | + p = bh->b_page; | |
496 | + memset(bh, 0, sizeof(struct buffer_head)); | |
497 | + bh->b_page = p; | |
498 | ||
499 | + bh->b_private = rbh; | |
500 | bh->b_size = rbh->b_size; | |
501 | bh->b_dev = rbh->b_rdev; | |
502 | + bh->b_rdev = lo->lo_device; | |
503 | bh->b_state = (1 << BH_Req) | (1 << BH_Mapped) | (1 << BH_Lock); | |
504 | + bh->b_data = page_address(bh->b_page); | |
505 | + bh->b_end_io = (rw == WRITE) ? loop_end_io_transfer_wr : loop_end_io_transfer_rd; | |
506 | + bh->b_rsector = rbh->b_rsector + (lo->lo_offset >> 9); | |
507 | + init_waitqueue_head(&bh->b_wait); | |
508 | ||
509 | - /* | |
510 | - * easy way out, although it does waste some memory for < PAGE_SIZE | |
511 | - * blocks... if highmem bounce buffering can get away with it, | |
512 | - * so can we :-) | |
513 | - */ | |
514 | - do { | |
515 | - bh->b_page = alloc_page(GFP_NOIO); | |
516 | - if (bh->b_page) | |
517 | - break; | |
518 | + return bh; | |
519 | +} | |
520 | ||
521 | - run_task_queue(&tq_disk); | |
522 | - schedule_timeout(HZ); | |
523 | - } while (1); | |
524 | +#define MAX_DISK_SIZE 1024*1024*1024 | |
525 | ||
526 | - bh->b_data = page_address(bh->b_page); | |
527 | - bh->b_end_io = loop_end_io_transfer; | |
528 | - bh->b_private = rbh; | |
529 | - init_waitqueue_head(&bh->b_wait); | |
530 | +static unsigned long compute_loop_size(struct loop_device *lo, struct dentry * lo_dentry, kdev_t lodev) | |
531 | +{ | |
532 | + if (S_ISREG(lo_dentry->d_inode->i_mode)) | |
533 | + return (lo_dentry->d_inode->i_size - lo->lo_offset) >> BLOCK_SIZE_BITS; | |
534 | + if (blk_size[MAJOR(lodev)]) | |
535 | + return blk_size[MAJOR(lodev)][MINOR(lodev)] - | |
536 | + (lo->lo_offset >> BLOCK_SIZE_BITS); | |
537 | + return MAX_DISK_SIZE; | |
538 | +} | |
539 | ||
540 | -out_bh: | |
541 | - bh->b_rsector = rbh->b_rsector + (lo->lo_offset >> 9); | |
542 | - spin_lock_irq(&lo->lo_lock); | |
543 | - bh->b_rdev = lo->lo_device; | |
544 | - spin_unlock_irq(&lo->lo_lock); | |
545 | +static void figure_loop_size(struct loop_device *lo) | |
546 | +{ | |
547 | + loop_sizes[lo->lo_number] = compute_loop_size(lo, | |
548 | + lo->lo_backing_file->f_dentry, | |
549 | + lo->lo_device); | |
550 | +} | |
551 | ||
552 | - return bh; | |
553 | +static int loop_file_io(struct file *file, char *buf, int size, loff_t *ppos, int w) | |
554 | +{ | |
555 | + mm_segment_t fs; | |
556 | + int x, y, z; | |
557 | + | |
558 | + y = 0; | |
559 | + do { | |
560 | + z = size - y; | |
561 | + fs = get_fs(); | |
562 | + set_fs(get_ds()); | |
563 | + if (w) | |
564 | + x = file->f_op->write(file, buf + y, z, ppos); | |
565 | + else | |
566 | + x = file->f_op->read(file, buf + y, z, ppos); | |
567 | + set_fs(fs); | |
568 | + if (x < 0) { | |
569 | + if ((x == -EAGAIN) || (x == -ENOMEM) || (x == -ERESTART) || (x == -EINTR)) { | |
570 | + run_task_queue(&tq_disk); | |
571 | + set_current_state(TASK_INTERRUPTIBLE); | |
572 | + schedule_timeout(HZ / 2); | |
573 | + continue; | |
574 | + } | |
575 | + return 1; | |
576 | + } | |
577 | + y += x; | |
578 | + } while (y < size); | |
579 | + return 0; | |
580 | +} | |
581 | + | |
582 | +static int do_bh_filebacked(struct loop_device *lo, struct buffer_head *bh, int rw) | |
583 | +{ | |
584 | + loff_t pos; | |
585 | + struct file *file = lo->lo_backing_file; | |
586 | + char *data, *buf; | |
587 | + unsigned int size, len; | |
588 | + int IV; | |
589 | + | |
590 | + pos = ((loff_t) bh->b_rsector << 9) + lo->lo_offset; | |
591 | + buf = page_address(lo->lo_bh_free->b_page); | |
592 | + len = bh->b_size; | |
593 | + data = bh->b_data; | |
594 | + IV = bh->b_rsector + (lo->lo_offset >> 9); | |
595 | + while (len > 0) { | |
596 | + size = PAGE_CACHE_SIZE; | |
597 | + if (size > len) | |
598 | + size = len; | |
599 | + if (rw == WRITE) { | |
600 | + if (lo_do_transfer(lo, WRITE, buf, data, size, IV)) { | |
601 | + printk(KERN_ERR "loop: write transfer error, sector %d\n", IV); | |
602 | + return 1; | |
603 | + } | |
604 | + if (loop_file_io(file, buf, size, &pos, 1)) { | |
605 | + printk(KERN_ERR "loop: write i/o error, sector %d\n", IV); | |
606 | + return 1; | |
607 | + } | |
608 | + } else { | |
609 | + if (loop_file_io(file, buf, size, &pos, 0)) { | |
610 | + printk(KERN_ERR "loop: read i/o error, sector %d\n", IV); | |
611 | + return 1; | |
612 | + } | |
613 | + if (lo_do_transfer(lo, READ, buf, data, size, IV)) { | |
614 | + printk(KERN_ERR "loop: read transfer error, sector %d\n", IV); | |
615 | + return 1; | |
616 | + } | |
617 | + } | |
618 | + data += size; | |
619 | + len -= size; | |
620 | + IV += size >> 9; | |
621 | + } | |
622 | + return 0; | |
623 | } | |
624 | ||
625 | static int loop_make_request(request_queue_t *q, int rw, struct buffer_head *rbh) | |
626 | { | |
627 | - struct buffer_head *bh = NULL; | |
628 | + struct buffer_head *bh; | |
629 | struct loop_device *lo; | |
630 | - unsigned long IV; | |
631 | ||
632 | if (!buffer_locked(rbh)) | |
633 | BUG(); | |
634 | @@ -488,35 +519,43 @@ | |
635 | * file backed, queue for loop_thread to handle | |
636 | */ | |
637 | if (lo->lo_flags & LO_FLAGS_DO_BMAP) { | |
638 | - /* | |
639 | - * rbh locked at this point, noone else should clear | |
640 | - * the dirty flag | |
641 | - */ | |
642 | - if (rw == WRITE) | |
643 | - set_bit(BH_Dirty, &rbh->b_state); | |
644 | - loop_add_bh(lo, rbh); | |
645 | + loop_add_queue_last(lo, rbh, (rw == WRITE) ? &lo->lo_bhQue1 : &lo->lo_bhQue0); | |
646 | + return 0; | |
647 | + } | |
648 | + | |
649 | + /* | |
650 | + * device backed, just remap rdev & rsector for NONE transfer | |
651 | + */ | |
652 | + if (lo->lo_encrypt_type == LO_CRYPT_NONE) { | |
653 | + rbh->b_rsector += lo->lo_offset >> 9; | |
654 | + rbh->b_rdev = lo->lo_device; | |
655 | + generic_make_request(rw, rbh); | |
656 | + if (atomic_dec_and_test(&lo->lo_pending)) | |
657 | + wake_up_interruptible(&lo->lo_bh_wait); | |
658 | return 0; | |
659 | } | |
660 | ||
661 | /* | |
662 | - * piggy old buffer on original, and submit for I/O | |
663 | + * device backed, start reads and writes now if buffer available | |
664 | */ | |
665 | - bh = loop_get_buffer(lo, rbh); | |
666 | - IV = loop_get_iv(lo, rbh->b_rsector); | |
667 | + bh = loop_get_buffer(lo, rbh, 0, rw); | |
668 | + if (!bh) { | |
669 | + /* just queue request and let thread handle alloc later */ | |
670 | + loop_add_queue_last(lo, rbh, (rw == WRITE) ? &lo->lo_bhQue1 : &lo->lo_bhQue2); | |
671 | + return 0; | |
672 | + } | |
673 | if (rw == WRITE) { | |
674 | - set_bit(BH_Dirty, &bh->b_state); | |
675 | - if (lo_do_transfer(lo, WRITE, bh->b_data, rbh->b_data, | |
676 | - bh->b_size, IV)) | |
677 | + if (lo_do_transfer(lo, WRITE, bh->b_data, rbh->b_data, bh->b_size, bh->b_rsector)) { | |
678 | + loop_put_buffer(lo, bh); | |
679 | goto err; | |
680 | + } | |
681 | } | |
682 | - | |
683 | generic_make_request(rw, bh); | |
684 | return 0; | |
685 | ||
686 | err: | |
687 | if (atomic_dec_and_test(&lo->lo_pending)) | |
688 | - up(&lo->lo_bh_mutex); | |
689 | - loop_put_buffer(bh); | |
690 | + wake_up_interruptible(&lo->lo_bh_wait); | |
691 | out: | |
692 | buffer_IO_error(rbh); | |
693 | return 0; | |
694 | @@ -525,30 +564,6 @@ | |
695 | goto out; | |
696 | } | |
697 | ||
698 | -static inline void loop_handle_bh(struct loop_device *lo,struct buffer_head *bh) | |
699 | -{ | |
700 | - int ret; | |
701 | - | |
702 | - /* | |
703 | - * For block backed loop, we know this is a READ | |
704 | - */ | |
705 | - if (lo->lo_flags & LO_FLAGS_DO_BMAP) { | |
706 | - int rw = !!test_and_clear_bit(BH_Dirty, &bh->b_state); | |
707 | - | |
708 | - ret = do_bh_filebacked(lo, bh, rw); | |
709 | - bh->b_end_io(bh, !ret); | |
710 | - } else { | |
711 | - struct buffer_head *rbh = bh->b_private; | |
712 | - unsigned long IV = loop_get_iv(lo, rbh->b_rsector); | |
713 | - | |
714 | - ret = lo_do_transfer(lo, READ, bh->b_data, rbh->b_data, | |
715 | - bh->b_size, IV); | |
716 | - | |
717 | - rbh->b_end_io(rbh, !ret); | |
718 | - loop_put_buffer(bh); | |
719 | - } | |
720 | -} | |
721 | - | |
722 | /* | |
723 | * worker thread that handles reads/writes to file backed loop devices, | |
724 | * to avoid blocking in our make_request_fn. it also does loop decrypting | |
725 | @@ -558,10 +573,20 @@ | |
726 | static int loop_thread(void *data) | |
727 | { | |
728 | struct loop_device *lo = data; | |
729 | - struct buffer_head *bh; | |
730 | + struct buffer_head *bh, *xbh; | |
731 | + int x, rw, qi = 0, flushcnt = 0; | |
732 | + wait_queue_t waitq; | |
733 | + que_look_up_table qt[4] = { | |
734 | + { &lo->lo_bhQue0, &lo->lo_bhQue1, &lo->lo_bhQue2, 0, 1, 2 }, | |
735 | + { &lo->lo_bhQue2, &lo->lo_bhQue0, &lo->lo_bhQue1, 2, 0, 1 }, | |
736 | + { &lo->lo_bhQue0, &lo->lo_bhQue2, &lo->lo_bhQue1, 0, 2, 1 }, | |
737 | + { &lo->lo_bhQue1, &lo->lo_bhQue0, &lo->lo_bhQue2, 1, 0, 2 } | |
738 | + }; | |
739 | ||
740 | + init_waitqueue_entry(&waitq, current); | |
741 | daemonize(); | |
742 | exit_files(current); | |
743 | + reparent_to_init(); | |
744 | ||
745 | sprintf(current->comm, "loop%d", lo->lo_number); | |
746 | ||
747 | @@ -586,23 +611,104 @@ | |
748 | up(&lo->lo_sem); | |
749 | ||
750 | for (;;) { | |
751 | - down_interruptible(&lo->lo_bh_mutex); | |
752 | + add_wait_queue(&lo->lo_bh_wait, &waitq); | |
753 | + for (;;) { | |
754 | + set_current_state(TASK_INTERRUPTIBLE); | |
755 | + if (!atomic_read(&lo->lo_pending)) | |
756 | + break; | |
757 | + | |
758 | + x = 0; | |
759 | + spin_lock_irq(&lo->lo_lock); | |
760 | + if (lo->lo_bhQue0) { | |
761 | + x = 1; | |
762 | + } else if (lo->lo_bhQue1 || lo->lo_bhQue2) { | |
763 | + /* file backed works too because lo->lo_bh_need == 0 */ | |
764 | + if (lo->lo_bh_free || !lo->lo_bh_need) | |
765 | + x = 1; | |
766 | + } | |
767 | + spin_unlock_irq(&lo->lo_lock); | |
768 | + if (x) | |
769 | + break; | |
770 | + | |
771 | + schedule(); | |
772 | + } | |
773 | + current->state = TASK_RUNNING; | |
774 | + remove_wait_queue(&lo->lo_bh_wait, &waitq); | |
775 | + | |
776 | /* | |
777 | - * could be upped because of tear-down, not because of | |
778 | + * could be woken because of tear-down, not because of | |
779 | * pending work | |
780 | */ | |
781 | if (!atomic_read(&lo->lo_pending)) | |
782 | break; | |
783 | ||
784 | - bh = loop_get_bh(lo); | |
785 | - if (!bh) { | |
786 | - printk("loop: missing bh\n"); | |
787 | + /* | |
788 | + * read queues using alternating order to prevent starvation | |
789 | + */ | |
790 | + bh = loop_get_bh(lo, &x, &qt[++qi & 3]); | |
791 | + if (!bh) | |
792 | + continue; | |
793 | + | |
794 | + /* | |
795 | + * x list tag usage(buffer-allocated) | |
796 | + * --- ------------- ----------------------- | |
797 | + * 0 lo->lo_bhQue0 dev-read(y) / file-read | |
798 | + * 1 lo->lo_bhQue1 dev-write(n) / file-write | |
799 | + * 2 lo->lo_bhQue2 dev-read(n) | |
800 | + */ | |
801 | + rw = (x == 1) ? WRITE : READ; | |
802 | + if ((x >= 1) && !(lo->lo_flags & LO_FLAGS_DO_BMAP)) { | |
803 | + /* loop_make_request didn't allocate a buffer, do that now */ | |
804 | + xbh = loop_get_buffer(lo, bh, 1, rw); | |
805 | + if (!xbh) { | |
806 | + run_task_queue(&tq_disk); | |
807 | + flushcnt = 0; | |
808 | + loop_add_queue_first(lo, bh, (rw == WRITE) ? &lo->lo_bhQue1 : &lo->lo_bhQue2); | |
809 | + /* lo->lo_bh_need should be 1 now, go back to sleep */ | |
810 | + continue; | |
811 | + } | |
812 | + if (rw == WRITE) { | |
813 | + if (lo_do_transfer(lo, WRITE, xbh->b_data, bh->b_data, xbh->b_size, xbh->b_rsector)) { | |
814 | + loop_put_buffer(lo, xbh); | |
815 | + buffer_IO_error(bh); | |
816 | + atomic_dec(&lo->lo_pending); | |
817 | + continue; | |
818 | + } | |
819 | + } | |
820 | + generic_make_request(rw, xbh); | |
821 | + | |
822 | + /* start I/O if there are no more requests lacking buffers */ | |
823 | + x = 0; | |
824 | + spin_lock_irq(&lo->lo_lock); | |
825 | + if (!lo->lo_bhQue1 && !lo->lo_bhQue2) | |
826 | + x = 1; | |
827 | + spin_unlock_irq(&lo->lo_lock); | |
828 | + if (x || (++flushcnt >= lo->lo_bh_flsh)) { | |
829 | + run_task_queue(&tq_disk); | |
830 | + flushcnt = 0; | |
831 | + } | |
832 | + | |
833 | + /* request not completely processed yet */ | |
834 | continue; | |
835 | } | |
836 | - loop_handle_bh(lo, bh); | |
837 | + if (lo->lo_flags & LO_FLAGS_DO_BMAP) { | |
838 | + /* request is for file backed device */ | |
839 | + x = do_bh_filebacked(lo, bh, rw); | |
840 | + bh->b_reqnext = NULL; | |
841 | + bh->b_end_io(bh, !x); | |
842 | + } else { | |
843 | + /* device backed read has completed, do decrypt now */ | |
844 | + xbh = bh->b_private; | |
845 | + /* must not use bh->b_rsector as IV, as it may be modified by LVM at this point */ | |
846 | + /* instead, recompute IV from original request */ | |
847 | + x = lo_do_transfer(lo, READ, bh->b_data, xbh->b_data, bh->b_size, xbh->b_rsector + (lo->lo_offset >> 9)); | |
848 | + xbh->b_reqnext = NULL; | |
849 | + xbh->b_end_io(xbh, !x); | |
850 | + loop_put_buffer(lo, bh); | |
851 | + } | |
852 | ||
853 | /* | |
854 | - * upped both for pending work and tear-down, lo_pending | |
855 | + * woken both for pending work and tear-down, lo_pending | |
856 | * will hit zero then | |
857 | */ | |
858 | if (atomic_dec_and_test(&lo->lo_pending)) | |
859 | @@ -619,7 +725,7 @@ | |
860 | struct file *file; | |
861 | struct inode *inode; | |
862 | kdev_t lo_device; | |
863 | - int lo_flags = 0; | |
864 | + int lo_flags = 0, hardsz = 512; | |
865 | int error; | |
866 | int bs; | |
867 | ||
868 | @@ -640,33 +746,44 @@ | |
869 | if (!(file->f_mode & FMODE_WRITE)) | |
870 | lo_flags |= LO_FLAGS_READ_ONLY; | |
871 | ||
872 | + lo->lo_bh_free = lo->lo_bhQue2 = lo->lo_bhQue1 = lo->lo_bhQue0 = NULL; | |
873 | + lo->lo_bh_need = lo->lo_bh_flsh = 0; | |
874 | + init_waitqueue_head(&lo->lo_bh_wait); | |
875 | if (S_ISBLK(inode->i_mode)) { | |
876 | lo_device = inode->i_rdev; | |
877 | if (lo_device == dev) { | |
878 | error = -EBUSY; | |
879 | - goto out; | |
880 | + goto out_putf; | |
881 | + } | |
882 | + if (loop_prealloc_init(lo, 0)) { | |
883 | + error = -ENOMEM; | |
884 | + goto out_putf; | |
885 | } | |
886 | + hardsz = get_hardsect_size(lo_device); | |
887 | } else if (S_ISREG(inode->i_mode)) { | |
888 | - struct address_space_operations *aops = inode->i_mapping->a_ops; | |
889 | /* | |
890 | * If we can't read - sorry. If we only can't write - well, | |
891 | * it's going to be read-only. | |
892 | */ | |
893 | - if (!aops->readpage) | |
894 | + if (!file->f_op || !file->f_op->read) | |
895 | goto out_putf; | |
896 | ||
897 | - if (!aops->prepare_write || !aops->commit_write) | |
898 | + if (!file->f_op->write) | |
899 | lo_flags |= LO_FLAGS_READ_ONLY; | |
900 | ||
901 | lo_device = inode->i_dev; | |
902 | lo_flags |= LO_FLAGS_DO_BMAP; | |
903 | + if (loop_prealloc_init(lo, 1)) { | |
904 | + error = -ENOMEM; | |
905 | + goto out_putf; | |
906 | + } | |
907 | error = 0; | |
908 | } else | |
909 | goto out_putf; | |
910 | ||
911 | get_file(file); | |
912 | ||
913 | - if (IS_RDONLY (inode) || is_read_only(lo_device) | |
914 | + if ((S_ISREG(inode->i_mode) && IS_RDONLY(inode)) || is_read_only(lo_device) | |
915 | || !(lo_file->f_mode & FMODE_WRITE)) | |
916 | lo_flags |= LO_FLAGS_READ_ONLY; | |
917 | ||
918 | @@ -687,9 +804,19 @@ | |
919 | if (!bs) | |
920 | bs = BLOCK_SIZE; | |
921 | ||
922 | + if (S_ISREG(inode->i_mode)) { | |
923 | + int x = loop_sizes[lo->lo_number]; | |
924 | + | |
925 | + if ((bs == 8192) && (x & 7)) | |
926 | + bs = 4096; | |
927 | + if ((bs == 4096) && (x & 3)) | |
928 | + bs = 2048; | |
929 | + if ((bs == 2048) && (x & 1)) | |
930 | + bs = 1024; | |
931 | + } | |
932 | + loop_hardsizes[MINOR(dev)] = hardsz; | |
933 | set_blocksize(dev, bs); | |
934 | ||
935 | - lo->lo_bh = lo->lo_bhtail = NULL; | |
936 | kernel_thread(loop_thread, lo, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); | |
937 | down(&lo->lo_sem); | |
938 | ||
939 | @@ -748,11 +875,12 @@ | |
940 | spin_lock_irq(&lo->lo_lock); | |
941 | lo->lo_state = Lo_rundown; | |
942 | if (atomic_dec_and_test(&lo->lo_pending)) | |
943 | - up(&lo->lo_bh_mutex); | |
944 | + wake_up_interruptible(&lo->lo_bh_wait); | |
945 | spin_unlock_irq(&lo->lo_lock); | |
946 | ||
947 | down(&lo->lo_sem); | |
948 | ||
949 | + loop_prealloc_cleanup(lo); | |
950 | lo->lo_backing_file = NULL; | |
951 | ||
952 | loop_release_xfer(lo); | |
953 | @@ -902,7 +1030,7 @@ | |
954 | static int lo_open(struct inode *inode, struct file *file) | |
955 | { | |
956 | struct loop_device *lo; | |
957 | - int dev, type; | |
958 | + int dev; | |
959 | ||
960 | if (!inode) | |
961 | return -EINVAL; | |
962 | @@ -917,10 +1045,6 @@ | |
963 | lo = &loop_dev[dev]; | |
964 | MOD_INC_USE_COUNT; | |
965 | down(&lo->lo_ctl_mutex); | |
966 | - | |
967 | - type = lo->lo_encrypt_type; | |
968 | - if (type && xfer_funcs[type] && xfer_funcs[type]->lock) | |
969 | - xfer_funcs[type]->lock(lo); | |
970 | lo->lo_refcnt++; | |
971 | up(&lo->lo_ctl_mutex); | |
972 | return 0; | |
973 | @@ -929,7 +1053,7 @@ | |
974 | static int lo_release(struct inode *inode, struct file *file) | |
975 | { | |
976 | struct loop_device *lo; | |
977 | - int dev, type; | |
978 | + int dev; | |
979 | ||
980 | if (!inode) | |
981 | return 0; | |
982 | @@ -944,11 +1068,7 @@ | |
983 | ||
984 | lo = &loop_dev[dev]; | |
985 | down(&lo->lo_ctl_mutex); | |
986 | - type = lo->lo_encrypt_type; | |
987 | --lo->lo_refcnt; | |
988 | - if (xfer_funcs[type] && xfer_funcs[type]->unlock) | |
989 | - xfer_funcs[type]->unlock(lo); | |
990 | - | |
991 | up(&lo->lo_ctl_mutex); | |
992 | MOD_DEC_USE_COUNT; | |
993 | return 0; | |
994 | @@ -1031,6 +1151,10 @@ | |
995 | if (!loop_blksizes) | |
996 | goto out_blksizes; | |
997 | ||
998 | + loop_hardsizes = kmalloc(max_loop * sizeof(int), GFP_KERNEL); | |
999 | + if (!loop_hardsizes) | |
1000 | + goto out_hardsizes; | |
1001 | + | |
1002 | blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), loop_make_request); | |
1003 | ||
1004 | for (i = 0; i < max_loop; i++) { | |
1005 | @@ -1038,25 +1162,36 @@ | |
1006 | memset(lo, 0, sizeof(struct loop_device)); | |
1007 | init_MUTEX(&lo->lo_ctl_mutex); | |
1008 | init_MUTEX_LOCKED(&lo->lo_sem); | |
1009 | - init_MUTEX_LOCKED(&lo->lo_bh_mutex); | |
1010 | lo->lo_number = i; | |
1011 | spin_lock_init(&lo->lo_lock); | |
1012 | } | |
1013 | ||
1014 | memset(loop_sizes, 0, max_loop * sizeof(int)); | |
1015 | memset(loop_blksizes, 0, max_loop * sizeof(int)); | |
1016 | + memset(loop_hardsizes, 0, max_loop * sizeof(int)); | |
1017 | blk_size[MAJOR_NR] = loop_sizes; | |
1018 | blksize_size[MAJOR_NR] = loop_blksizes; | |
1019 | + hardsect_size[MAJOR_NR] = loop_hardsizes; | |
1020 | for (i = 0; i < max_loop; i++) | |
1021 | register_disk(NULL, MKDEV(MAJOR_NR, i), 1, &lo_fops, 0); | |
1022 | ||
1023 | + for (i = 0; i < (sizeof(lo_prealloc) / sizeof(int)); i += 2) { | |
1024 | + if (!lo_prealloc[i]) | |
1025 | + continue; | |
1026 | + if (lo_prealloc[i] < LO_PREALLOC_MIN) | |
1027 | + lo_prealloc[i] = LO_PREALLOC_MIN; | |
1028 | + if (lo_prealloc[i] > LO_PREALLOC_MAX) | |
1029 | + lo_prealloc[i] = LO_PREALLOC_MAX; | |
1030 | + } | |
1031 | printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop); | |
1032 | return 0; | |
1033 | ||
1034 | -out_sizes: | |
1035 | - kfree(loop_dev); | |
1036 | +out_hardsizes: | |
1037 | + kfree(loop_blksizes); | |
1038 | out_blksizes: | |
1039 | kfree(loop_sizes); | |
1040 | +out_sizes: | |
1041 | + kfree(loop_dev); | |
1042 | printk(KERN_ERR "loop: ran out of memory\n"); | |
1043 | return -ENOMEM; | |
1044 | } | |
1045 | @@ -1067,9 +1202,13 @@ | |
1046 | if (devfs_unregister_blkdev(MAJOR_NR, "loop")) | |
1047 | printk(KERN_WARNING "loop: cannot unregister blkdev\n"); | |
1048 | ||
1049 | + blk_size[MAJOR_NR] = 0; | |
1050 | + blksize_size[MAJOR_NR] = 0; | |
1051 | + hardsect_size[MAJOR_NR] = 0; | |
1052 | kfree(loop_dev); | |
1053 | kfree(loop_sizes); | |
1054 | kfree(loop_blksizes); | |
1055 | + kfree(loop_hardsizes); | |
1056 | } | |
1057 | ||
1058 | module_init(loop_init); | |
1059 | diff -Nur linux-2.4.18/include/linux/loop.h linux-int-2.4.18/include/linux/loop.h | |
1060 | --- linux-2.4.18/include/linux/loop.h Mon Sep 17 22:16:30 2001 | |
1061 | +++ linux-int-2.4.18/include/linux/loop.h Thu May 30 14:48:01 2002 | |
1062 | @@ -17,6 +17,11 @@ | |
1063 | ||
1064 | #ifdef __KERNEL__ | |
1065 | ||
1066 | +/* definitions for IV metric -- cryptoapi specific */ | |
1067 | +#define LOOP_IV_SECTOR_BITS 9 | |
1068 | +#define LOOP_IV_SECTOR_SIZE (1 << LOOP_IV_SECTOR_BITS) | |
1069 | +typedef int loop_iv_t; | |
1070 | + | |
1071 | /* Possible states of device */ | |
1072 | enum { | |
1073 | Lo_unbound, | |
1074 | @@ -49,13 +54,17 @@ | |
1075 | int old_gfp_mask; | |
1076 | ||
1077 | spinlock_t lo_lock; | |
1078 | - struct buffer_head *lo_bh; | |
1079 | - struct buffer_head *lo_bhtail; | |
1080 | + struct buffer_head *lo_bhQue0; | |
1081 | + struct buffer_head *lo_bhQue1; | |
1082 | int lo_state; | |
1083 | struct semaphore lo_sem; | |
1084 | struct semaphore lo_ctl_mutex; | |
1085 | - struct semaphore lo_bh_mutex; | |
1086 | atomic_t lo_pending; | |
1087 | + struct buffer_head *lo_bhQue2; | |
1088 | + struct buffer_head *lo_bh_free; | |
1089 | + int lo_bh_flsh; | |
1090 | + int lo_bh_need; | |
1091 | + wait_queue_head_t lo_bh_wait; | |
1092 | }; | |
1093 | ||
1094 | typedef int (* transfer_proc_t)(struct loop_device *, int cmd, | |
1095 | @@ -77,7 +86,6 @@ | |
1096 | */ | |
1097 | #define LO_FLAGS_DO_BMAP 1 | |
1098 | #define LO_FLAGS_READ_ONLY 2 | |
1099 | -#define LO_FLAGS_BH_REMAP 4 | |
1100 | ||
1101 | /* | |
1102 | * Note that this structure gets the wrong offsets when directly used | |
1103 | @@ -122,6 +130,8 @@ | |
1104 | #define LO_CRYPT_IDEA 6 | |
1105 | #define LO_CRYPT_DUMMY 9 | |
1106 | #define LO_CRYPT_SKIPJACK 10 | |
1107 | +#define LO_CRYPT_AES 16 | |
1108 | +#define LO_CRYPT_CRYPTOAPI 18 | |
1109 | #define MAX_LO_CRYPT 20 | |
1110 | ||
1111 | #ifdef __KERNEL__ |