diff options
Diffstat (limited to 'arch/um/drivers/ubd_kern.c')
-rw-r--r-- | arch/um/drivers/ubd_kern.c | 319 |
1 files changed, 175 insertions, 144 deletions
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index bc458f57921b..49c047b75cc5 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c | |||
@@ -106,10 +106,15 @@ static inline void ubd_set_bit(__u64 bit, unsigned char *data) | |||
106 | 106 | ||
107 | #define DRIVER_NAME "uml-blkdev" | 107 | #define DRIVER_NAME "uml-blkdev" |
108 | 108 | ||
109 | /* Can be taken in interrupt context, and is passed to the block layer to lock | ||
110 | * the request queue. Kernel side code knows that. */ | ||
109 | static DEFINE_SPINLOCK(ubd_io_lock); | 111 | static DEFINE_SPINLOCK(ubd_io_lock); |
110 | static DEFINE_SPINLOCK(ubd_lock); | ||
111 | 112 | ||
112 | static void (*do_ubd)(void); | 113 | static DEFINE_MUTEX(ubd_lock); |
114 | |||
115 | /* XXX - this made sense in 2.4 days, now it's only used as a boolean, and | ||
116 | * probably it doesn't make sense even for that. */ | ||
117 | static int do_ubd; | ||
113 | 118 | ||
114 | static int ubd_open(struct inode * inode, struct file * filp); | 119 | static int ubd_open(struct inode * inode, struct file * filp); |
115 | static int ubd_release(struct inode * inode, struct file * file); | 120 | static int ubd_release(struct inode * inode, struct file * file); |
@@ -117,7 +122,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file, | |||
117 | unsigned int cmd, unsigned long arg); | 122 | unsigned int cmd, unsigned long arg); |
118 | static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo); | 123 | static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo); |
119 | 124 | ||
120 | #define MAX_DEV (8) | 125 | #define MAX_DEV (16) |
121 | 126 | ||
122 | static struct block_device_operations ubd_blops = { | 127 | static struct block_device_operations ubd_blops = { |
123 | .owner = THIS_MODULE, | 128 | .owner = THIS_MODULE, |
@@ -150,8 +155,9 @@ static struct gendisk *fake_gendisk[MAX_DEV]; | |||
150 | static struct openflags global_openflags = OPEN_FLAGS; | 155 | static struct openflags global_openflags = OPEN_FLAGS; |
151 | 156 | ||
152 | struct cow { | 157 | struct cow { |
153 | /* This is the backing file, actually */ | 158 | /* backing file name */ |
154 | char *file; | 159 | char *file; |
160 | /* backing file fd */ | ||
155 | int fd; | 161 | int fd; |
156 | unsigned long *bitmap; | 162 | unsigned long *bitmap; |
157 | unsigned long bitmap_len; | 163 | unsigned long bitmap_len; |
@@ -160,14 +166,16 @@ struct cow { | |||
160 | }; | 166 | }; |
161 | 167 | ||
162 | struct ubd { | 168 | struct ubd { |
169 | /* name (and fd, below) of the file opened for writing, either the | ||
170 | * backing or the cow file. */ | ||
163 | char *file; | 171 | char *file; |
164 | int count; | 172 | int count; |
165 | int fd; | 173 | int fd; |
166 | __u64 size; | 174 | __u64 size; |
167 | struct openflags boot_openflags; | 175 | struct openflags boot_openflags; |
168 | struct openflags openflags; | 176 | struct openflags openflags; |
169 | int shared; | 177 | unsigned shared:1; |
170 | int no_cow; | 178 | unsigned no_cow:1; |
171 | struct cow cow; | 179 | struct cow cow; |
172 | struct platform_device pdev; | 180 | struct platform_device pdev; |
173 | }; | 181 | }; |
@@ -192,18 +200,7 @@ struct ubd { | |||
192 | .cow = DEFAULT_COW, \ | 200 | .cow = DEFAULT_COW, \ |
193 | } | 201 | } |
194 | 202 | ||
195 | struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; | 203 | struct ubd ubd_devs[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; |
196 | |||
197 | static int ubd0_init(void) | ||
198 | { | ||
199 | struct ubd *dev = &ubd_dev[0]; | ||
200 | |||
201 | if(dev->file == NULL) | ||
202 | dev->file = "root_fs"; | ||
203 | return(0); | ||
204 | } | ||
205 | |||
206 | __initcall(ubd0_init); | ||
207 | 204 | ||
208 | /* Only changed by fake_ide_setup which is a setup */ | 205 | /* Only changed by fake_ide_setup which is a setup */ |
209 | static int fake_ide = 0; | 206 | static int fake_ide = 0; |
@@ -277,7 +274,7 @@ static int parse_unit(char **ptr) | |||
277 | return(-1); | 274 | return(-1); |
278 | *ptr = end; | 275 | *ptr = end; |
279 | } | 276 | } |
280 | else if (('a' <= *str) && (*str <= 'h')) { | 277 | else if (('a' <= *str) && (*str <= 'z')) { |
281 | n = *str - 'a'; | 278 | n = *str - 'a'; |
282 | str++; | 279 | str++; |
283 | *ptr = str; | 280 | *ptr = str; |
@@ -285,9 +282,13 @@ static int parse_unit(char **ptr) | |||
285 | return(n); | 282 | return(n); |
286 | } | 283 | } |
287 | 284 | ||
285 | /* If *index_out == -1 at exit, the passed option was a general one; | ||
286 | * otherwise, the str pointer is used (and owned) inside ubd_devs array, so it | ||
287 | * should not be freed on exit. | ||
288 | */ | ||
288 | static int ubd_setup_common(char *str, int *index_out) | 289 | static int ubd_setup_common(char *str, int *index_out) |
289 | { | 290 | { |
290 | struct ubd *dev; | 291 | struct ubd *ubd_dev; |
291 | struct openflags flags = global_openflags; | 292 | struct openflags flags = global_openflags; |
292 | char *backing_file; | 293 | char *backing_file; |
293 | int n, err, i; | 294 | int n, err, i; |
@@ -311,7 +312,7 @@ static int ubd_setup_common(char *str, int *index_out) | |||
311 | } | 312 | } |
312 | 313 | ||
313 | err = 1; | 314 | err = 1; |
314 | spin_lock(&ubd_lock); | 315 | mutex_lock(&ubd_lock); |
315 | if(fake_major != MAJOR_NR){ | 316 | if(fake_major != MAJOR_NR){ |
316 | printk(KERN_ERR "Can't assign a fake major twice\n"); | 317 | printk(KERN_ERR "Can't assign a fake major twice\n"); |
317 | goto out1; | 318 | goto out1; |
@@ -323,7 +324,7 @@ static int ubd_setup_common(char *str, int *index_out) | |||
323 | major); | 324 | major); |
324 | err = 0; | 325 | err = 0; |
325 | out1: | 326 | out1: |
326 | spin_unlock(&ubd_lock); | 327 | mutex_unlock(&ubd_lock); |
327 | return(err); | 328 | return(err); |
328 | } | 329 | } |
329 | 330 | ||
@@ -340,10 +341,10 @@ static int ubd_setup_common(char *str, int *index_out) | |||
340 | } | 341 | } |
341 | 342 | ||
342 | err = 1; | 343 | err = 1; |
343 | spin_lock(&ubd_lock); | 344 | mutex_lock(&ubd_lock); |
344 | 345 | ||
345 | dev = &ubd_dev[n]; | 346 | ubd_dev = &ubd_devs[n]; |
346 | if(dev->file != NULL){ | 347 | if(ubd_dev->file != NULL){ |
347 | printk(KERN_ERR "ubd_setup : device already configured\n"); | 348 | printk(KERN_ERR "ubd_setup : device already configured\n"); |
348 | goto out; | 349 | goto out; |
349 | } | 350 | } |
@@ -360,10 +361,10 @@ static int ubd_setup_common(char *str, int *index_out) | |||
360 | flags.s = 1; | 361 | flags.s = 1; |
361 | break; | 362 | break; |
362 | case 'd': | 363 | case 'd': |
363 | dev->no_cow = 1; | 364 | ubd_dev->no_cow = 1; |
364 | break; | 365 | break; |
365 | case 'c': | 366 | case 'c': |
366 | dev->shared = 1; | 367 | ubd_dev->shared = 1; |
367 | break; | 368 | break; |
368 | case '=': | 369 | case '=': |
369 | str++; | 370 | str++; |
@@ -390,7 +391,7 @@ break_loop: | |||
390 | } | 391 | } |
391 | 392 | ||
392 | if(backing_file){ | 393 | if(backing_file){ |
393 | if(dev->no_cow) | 394 | if(ubd_dev->no_cow) |
394 | printk(KERN_ERR "Can't specify both 'd' and a " | 395 | printk(KERN_ERR "Can't specify both 'd' and a " |
395 | "cow file\n"); | 396 | "cow file\n"); |
396 | else { | 397 | else { |
@@ -398,11 +399,11 @@ break_loop: | |||
398 | backing_file++; | 399 | backing_file++; |
399 | } | 400 | } |
400 | } | 401 | } |
401 | dev->file = str; | 402 | ubd_dev->file = str; |
402 | dev->cow.file = backing_file; | 403 | ubd_dev->cow.file = backing_file; |
403 | dev->boot_openflags = flags; | 404 | ubd_dev->boot_openflags = flags; |
404 | out: | 405 | out: |
405 | spin_unlock(&ubd_lock); | 406 | mutex_unlock(&ubd_lock); |
406 | return(err); | 407 | return(err); |
407 | } | 408 | } |
408 | 409 | ||
@@ -472,8 +473,9 @@ int thread_fd = -1; | |||
472 | 473 | ||
473 | /* Changed by ubd_handler, which is serialized because interrupts only | 474 | /* Changed by ubd_handler, which is serialized because interrupts only |
474 | * happen on CPU 0. | 475 | * happen on CPU 0. |
476 | * XXX: currently unused. | ||
475 | */ | 477 | */ |
476 | int intr_count = 0; | 478 | static int intr_count = 0; |
477 | 479 | ||
478 | /* call ubd_finish if you need to serialize */ | 480 | /* call ubd_finish if you need to serialize */ |
479 | static void __ubd_finish(struct request *req, int error) | 481 | static void __ubd_finish(struct request *req, int error) |
@@ -493,6 +495,8 @@ static void __ubd_finish(struct request *req, int error) | |||
493 | end_request(req, 1); | 495 | end_request(req, 1); |
494 | } | 496 | } |
495 | 497 | ||
498 | /* Callable only from interrupt context - otherwise you need to do | ||
499 | * spin_lock_irq()/spin_lock_irqsave() */ | ||
496 | static inline void ubd_finish(struct request *req, int error) | 500 | static inline void ubd_finish(struct request *req, int error) |
497 | { | 501 | { |
498 | spin_lock(&ubd_io_lock); | 502 | spin_lock(&ubd_io_lock); |
@@ -500,14 +504,15 @@ static inline void ubd_finish(struct request *req, int error) | |||
500 | spin_unlock(&ubd_io_lock); | 504 | spin_unlock(&ubd_io_lock); |
501 | } | 505 | } |
502 | 506 | ||
503 | /* Called without ubd_io_lock held */ | 507 | /* XXX - move this inside ubd_intr. */ |
508 | /* Called without ubd_io_lock held, and only in interrupt context. */ | ||
504 | static void ubd_handler(void) | 509 | static void ubd_handler(void) |
505 | { | 510 | { |
506 | struct io_thread_req req; | 511 | struct io_thread_req req; |
507 | struct request *rq = elv_next_request(ubd_queue); | 512 | struct request *rq = elv_next_request(ubd_queue); |
508 | int n; | 513 | int n; |
509 | 514 | ||
510 | do_ubd = NULL; | 515 | do_ubd = 0; |
511 | intr_count++; | 516 | intr_count++; |
512 | n = os_read_file(thread_fd, &req, sizeof(req)); | 517 | n = os_read_file(thread_fd, &req, sizeof(req)); |
513 | if(n != sizeof(req)){ | 518 | if(n != sizeof(req)){ |
@@ -521,7 +526,9 @@ static void ubd_handler(void) | |||
521 | 526 | ||
522 | ubd_finish(rq, req.error); | 527 | ubd_finish(rq, req.error); |
523 | reactivate_fd(thread_fd, UBD_IRQ); | 528 | reactivate_fd(thread_fd, UBD_IRQ); |
529 | spin_lock(&ubd_io_lock); | ||
524 | do_ubd_request(ubd_queue); | 530 | do_ubd_request(ubd_queue); |
531 | spin_unlock(&ubd_io_lock); | ||
525 | } | 532 | } |
526 | 533 | ||
527 | static irqreturn_t ubd_intr(int irq, void *dev) | 534 | static irqreturn_t ubd_intr(int irq, void *dev) |
@@ -541,87 +548,90 @@ void kill_io_thread(void) | |||
541 | 548 | ||
542 | __uml_exitcall(kill_io_thread); | 549 | __uml_exitcall(kill_io_thread); |
543 | 550 | ||
544 | static int ubd_file_size(struct ubd *dev, __u64 *size_out) | 551 | static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out) |
545 | { | 552 | { |
546 | char *file; | 553 | char *file; |
547 | 554 | ||
548 | file = dev->cow.file ? dev->cow.file : dev->file; | 555 | file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file; |
549 | return(os_file_size(file, size_out)); | 556 | return(os_file_size(file, size_out)); |
550 | } | 557 | } |
551 | 558 | ||
552 | static void ubd_close(struct ubd *dev) | 559 | static void ubd_close_dev(struct ubd *ubd_dev) |
553 | { | 560 | { |
554 | os_close_file(dev->fd); | 561 | os_close_file(ubd_dev->fd); |
555 | if(dev->cow.file == NULL) | 562 | if(ubd_dev->cow.file == NULL) |
556 | return; | 563 | return; |
557 | 564 | ||
558 | os_close_file(dev->cow.fd); | 565 | os_close_file(ubd_dev->cow.fd); |
559 | vfree(dev->cow.bitmap); | 566 | vfree(ubd_dev->cow.bitmap); |
560 | dev->cow.bitmap = NULL; | 567 | ubd_dev->cow.bitmap = NULL; |
561 | } | 568 | } |
562 | 569 | ||
563 | static int ubd_open_dev(struct ubd *dev) | 570 | static int ubd_open_dev(struct ubd *ubd_dev) |
564 | { | 571 | { |
565 | struct openflags flags; | 572 | struct openflags flags; |
566 | char **back_ptr; | 573 | char **back_ptr; |
567 | int err, create_cow, *create_ptr; | 574 | int err, create_cow, *create_ptr; |
575 | int fd; | ||
568 | 576 | ||
569 | dev->openflags = dev->boot_openflags; | 577 | ubd_dev->openflags = ubd_dev->boot_openflags; |
570 | create_cow = 0; | 578 | create_cow = 0; |
571 | create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL; | 579 | create_ptr = (ubd_dev->cow.file != NULL) ? &create_cow : NULL; |
572 | back_ptr = dev->no_cow ? NULL : &dev->cow.file; | 580 | back_ptr = ubd_dev->no_cow ? NULL : &ubd_dev->cow.file; |
573 | dev->fd = open_ubd_file(dev->file, &dev->openflags, dev->shared, | 581 | |
574 | back_ptr, &dev->cow.bitmap_offset, | 582 | fd = open_ubd_file(ubd_dev->file, &ubd_dev->openflags, ubd_dev->shared, |
575 | &dev->cow.bitmap_len, &dev->cow.data_offset, | 583 | back_ptr, &ubd_dev->cow.bitmap_offset, |
584 | &ubd_dev->cow.bitmap_len, &ubd_dev->cow.data_offset, | ||
576 | create_ptr); | 585 | create_ptr); |
577 | 586 | ||
578 | if((dev->fd == -ENOENT) && create_cow){ | 587 | if((fd == -ENOENT) && create_cow){ |
579 | dev->fd = create_cow_file(dev->file, dev->cow.file, | 588 | fd = create_cow_file(ubd_dev->file, ubd_dev->cow.file, |
580 | dev->openflags, 1 << 9, PAGE_SIZE, | 589 | ubd_dev->openflags, 1 << 9, PAGE_SIZE, |
581 | &dev->cow.bitmap_offset, | 590 | &ubd_dev->cow.bitmap_offset, |
582 | &dev->cow.bitmap_len, | 591 | &ubd_dev->cow.bitmap_len, |
583 | &dev->cow.data_offset); | 592 | &ubd_dev->cow.data_offset); |
584 | if(dev->fd >= 0){ | 593 | if(fd >= 0){ |
585 | printk(KERN_INFO "Creating \"%s\" as COW file for " | 594 | printk(KERN_INFO "Creating \"%s\" as COW file for " |
586 | "\"%s\"\n", dev->file, dev->cow.file); | 595 | "\"%s\"\n", ubd_dev->file, ubd_dev->cow.file); |
587 | } | 596 | } |
588 | } | 597 | } |
589 | 598 | ||
590 | if(dev->fd < 0){ | 599 | if(fd < 0){ |
591 | printk("Failed to open '%s', errno = %d\n", dev->file, | 600 | printk("Failed to open '%s', errno = %d\n", ubd_dev->file, |
592 | -dev->fd); | 601 | -fd); |
593 | return(dev->fd); | 602 | return fd; |
594 | } | 603 | } |
604 | ubd_dev->fd = fd; | ||
595 | 605 | ||
596 | if(dev->cow.file != NULL){ | 606 | if(ubd_dev->cow.file != NULL){ |
597 | err = -ENOMEM; | 607 | err = -ENOMEM; |
598 | dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len); | 608 | ubd_dev->cow.bitmap = (void *) vmalloc(ubd_dev->cow.bitmap_len); |
599 | if(dev->cow.bitmap == NULL){ | 609 | if(ubd_dev->cow.bitmap == NULL){ |
600 | printk(KERN_ERR "Failed to vmalloc COW bitmap\n"); | 610 | printk(KERN_ERR "Failed to vmalloc COW bitmap\n"); |
601 | goto error; | 611 | goto error; |
602 | } | 612 | } |
603 | flush_tlb_kernel_vm(); | 613 | flush_tlb_kernel_vm(); |
604 | 614 | ||
605 | err = read_cow_bitmap(dev->fd, dev->cow.bitmap, | 615 | err = read_cow_bitmap(ubd_dev->fd, ubd_dev->cow.bitmap, |
606 | dev->cow.bitmap_offset, | 616 | ubd_dev->cow.bitmap_offset, |
607 | dev->cow.bitmap_len); | 617 | ubd_dev->cow.bitmap_len); |
608 | if(err < 0) | 618 | if(err < 0) |
609 | goto error; | 619 | goto error; |
610 | 620 | ||
611 | flags = dev->openflags; | 621 | flags = ubd_dev->openflags; |
612 | flags.w = 0; | 622 | flags.w = 0; |
613 | err = open_ubd_file(dev->cow.file, &flags, dev->shared, NULL, | 623 | err = open_ubd_file(ubd_dev->cow.file, &flags, ubd_dev->shared, NULL, |
614 | NULL, NULL, NULL, NULL); | 624 | NULL, NULL, NULL, NULL); |
615 | if(err < 0) goto error; | 625 | if(err < 0) goto error; |
616 | dev->cow.fd = err; | 626 | ubd_dev->cow.fd = err; |
617 | } | 627 | } |
618 | return(0); | 628 | return(0); |
619 | error: | 629 | error: |
620 | os_close_file(dev->fd); | 630 | os_close_file(ubd_dev->fd); |
621 | return(err); | 631 | return(err); |
622 | } | 632 | } |
623 | 633 | ||
624 | static int ubd_new_disk(int major, u64 size, int unit, | 634 | static int ubd_disk_register(int major, u64 size, int unit, |
625 | struct gendisk **disk_out) | 635 | struct gendisk **disk_out) |
626 | 636 | ||
627 | { | 637 | { |
@@ -642,13 +652,13 @@ static int ubd_new_disk(int major, u64 size, int unit, | |||
642 | 652 | ||
643 | /* sysfs register (not for ide fake devices) */ | 653 | /* sysfs register (not for ide fake devices) */ |
644 | if (major == MAJOR_NR) { | 654 | if (major == MAJOR_NR) { |
645 | ubd_dev[unit].pdev.id = unit; | 655 | ubd_devs[unit].pdev.id = unit; |
646 | ubd_dev[unit].pdev.name = DRIVER_NAME; | 656 | ubd_devs[unit].pdev.name = DRIVER_NAME; |
647 | platform_device_register(&ubd_dev[unit].pdev); | 657 | platform_device_register(&ubd_devs[unit].pdev); |
648 | disk->driverfs_dev = &ubd_dev[unit].pdev.dev; | 658 | disk->driverfs_dev = &ubd_devs[unit].pdev.dev; |
649 | } | 659 | } |
650 | 660 | ||
651 | disk->private_data = &ubd_dev[unit]; | 661 | disk->private_data = &ubd_devs[unit]; |
652 | disk->queue = ubd_queue; | 662 | disk->queue = ubd_queue; |
653 | add_disk(disk); | 663 | add_disk(disk); |
654 | 664 | ||
@@ -660,25 +670,25 @@ static int ubd_new_disk(int major, u64 size, int unit, | |||
660 | 670 | ||
661 | static int ubd_add(int n) | 671 | static int ubd_add(int n) |
662 | { | 672 | { |
663 | struct ubd *dev = &ubd_dev[n]; | 673 | struct ubd *ubd_dev = &ubd_devs[n]; |
664 | int err; | 674 | int err; |
665 | 675 | ||
666 | err = -ENODEV; | 676 | err = -ENODEV; |
667 | if(dev->file == NULL) | 677 | if(ubd_dev->file == NULL) |
668 | goto out; | 678 | goto out; |
669 | 679 | ||
670 | err = ubd_file_size(dev, &dev->size); | 680 | err = ubd_file_size(ubd_dev, &ubd_dev->size); |
671 | if(err < 0) | 681 | if(err < 0) |
672 | goto out; | 682 | goto out; |
673 | 683 | ||
674 | dev->size = ROUND_BLOCK(dev->size); | 684 | ubd_dev->size = ROUND_BLOCK(ubd_dev->size); |
675 | 685 | ||
676 | err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]); | 686 | err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]); |
677 | if(err) | 687 | if(err) |
678 | goto out; | 688 | goto out; |
679 | 689 | ||
680 | if(fake_major != MAJOR_NR) | 690 | if(fake_major != MAJOR_NR) |
681 | ubd_new_disk(fake_major, dev->size, n, | 691 | ubd_disk_register(fake_major, ubd_dev->size, n, |
682 | &fake_gendisk[n]); | 692 | &fake_gendisk[n]); |
683 | 693 | ||
684 | /* perhaps this should also be under the "if (fake_major)" above */ | 694 | /* perhaps this should also be under the "if (fake_major)" above */ |
@@ -693,32 +703,41 @@ out: | |||
693 | 703 | ||
694 | static int ubd_config(char *str) | 704 | static int ubd_config(char *str) |
695 | { | 705 | { |
696 | int n, err; | 706 | int n, ret; |
697 | 707 | ||
698 | str = kstrdup(str, GFP_KERNEL); | 708 | str = kstrdup(str, GFP_KERNEL); |
699 | if(str == NULL){ | 709 | if (str == NULL) { |
700 | printk(KERN_ERR "ubd_config failed to strdup string\n"); | 710 | printk(KERN_ERR "ubd_config failed to strdup string\n"); |
701 | return(1); | 711 | ret = 1; |
712 | goto out; | ||
702 | } | 713 | } |
703 | err = ubd_setup_common(str, &n); | 714 | ret = ubd_setup_common(str, &n); |
704 | if(err){ | 715 | if (ret) { |
705 | kfree(str); | 716 | ret = -1; |
706 | return(-1); | 717 | goto err_free; |
718 | } | ||
719 | if (n == -1) { | ||
720 | ret = 0; | ||
721 | goto err_free; | ||
707 | } | 722 | } |
708 | if(n == -1) return(0); | ||
709 | 723 | ||
710 | spin_lock(&ubd_lock); | 724 | mutex_lock(&ubd_lock); |
711 | err = ubd_add(n); | 725 | ret = ubd_add(n); |
712 | if(err) | 726 | if (ret) |
713 | ubd_dev[n].file = NULL; | 727 | ubd_devs[n].file = NULL; |
714 | spin_unlock(&ubd_lock); | 728 | mutex_unlock(&ubd_lock); |
715 | 729 | ||
716 | return(err); | 730 | out: |
731 | return ret; | ||
732 | |||
733 | err_free: | ||
734 | kfree(str); | ||
735 | goto out; | ||
717 | } | 736 | } |
718 | 737 | ||
719 | static int ubd_get_config(char *name, char *str, int size, char **error_out) | 738 | static int ubd_get_config(char *name, char *str, int size, char **error_out) |
720 | { | 739 | { |
721 | struct ubd *dev; | 740 | struct ubd *ubd_dev; |
722 | int n, len = 0; | 741 | int n, len = 0; |
723 | 742 | ||
724 | n = parse_unit(&name); | 743 | n = parse_unit(&name); |
@@ -727,24 +746,24 @@ static int ubd_get_config(char *name, char *str, int size, char **error_out) | |||
727 | return(-1); | 746 | return(-1); |
728 | } | 747 | } |
729 | 748 | ||
730 | dev = &ubd_dev[n]; | 749 | ubd_dev = &ubd_devs[n]; |
731 | spin_lock(&ubd_lock); | 750 | mutex_lock(&ubd_lock); |
732 | 751 | ||
733 | if(dev->file == NULL){ | 752 | if(ubd_dev->file == NULL){ |
734 | CONFIG_CHUNK(str, size, len, "", 1); | 753 | CONFIG_CHUNK(str, size, len, "", 1); |
735 | goto out; | 754 | goto out; |
736 | } | 755 | } |
737 | 756 | ||
738 | CONFIG_CHUNK(str, size, len, dev->file, 0); | 757 | CONFIG_CHUNK(str, size, len, ubd_dev->file, 0); |
739 | 758 | ||
740 | if(dev->cow.file != NULL){ | 759 | if(ubd_dev->cow.file != NULL){ |
741 | CONFIG_CHUNK(str, size, len, ",", 0); | 760 | CONFIG_CHUNK(str, size, len, ",", 0); |
742 | CONFIG_CHUNK(str, size, len, dev->cow.file, 1); | 761 | CONFIG_CHUNK(str, size, len, ubd_dev->cow.file, 1); |
743 | } | 762 | } |
744 | else CONFIG_CHUNK(str, size, len, "", 1); | 763 | else CONFIG_CHUNK(str, size, len, "", 1); |
745 | 764 | ||
746 | out: | 765 | out: |
747 | spin_unlock(&ubd_lock); | 766 | mutex_unlock(&ubd_lock); |
748 | return(len); | 767 | return(len); |
749 | } | 768 | } |
750 | 769 | ||
@@ -760,22 +779,22 @@ static int ubd_id(char **str, int *start_out, int *end_out) | |||
760 | 779 | ||
761 | static int ubd_remove(int n) | 780 | static int ubd_remove(int n) |
762 | { | 781 | { |
763 | struct ubd *dev; | 782 | struct ubd *ubd_dev; |
764 | int err = -ENODEV; | 783 | int err = -ENODEV; |
765 | 784 | ||
766 | spin_lock(&ubd_lock); | 785 | mutex_lock(&ubd_lock); |
767 | 786 | ||
768 | if(ubd_gendisk[n] == NULL) | 787 | if(ubd_gendisk[n] == NULL) |
769 | goto out; | 788 | goto out; |
770 | 789 | ||
771 | dev = &ubd_dev[n]; | 790 | ubd_dev = &ubd_devs[n]; |
772 | 791 | ||
773 | if(dev->file == NULL) | 792 | if(ubd_dev->file == NULL) |
774 | goto out; | 793 | goto out; |
775 | 794 | ||
776 | /* you cannot remove a open disk */ | 795 | /* you cannot remove a open disk */ |
777 | err = -EBUSY; | 796 | err = -EBUSY; |
778 | if(dev->count > 0) | 797 | if(ubd_dev->count > 0) |
779 | goto out; | 798 | goto out; |
780 | 799 | ||
781 | del_gendisk(ubd_gendisk[n]); | 800 | del_gendisk(ubd_gendisk[n]); |
@@ -788,14 +807,15 @@ static int ubd_remove(int n) | |||
788 | fake_gendisk[n] = NULL; | 807 | fake_gendisk[n] = NULL; |
789 | } | 808 | } |
790 | 809 | ||
791 | platform_device_unregister(&dev->pdev); | 810 | platform_device_unregister(&ubd_dev->pdev); |
792 | *dev = ((struct ubd) DEFAULT_UBD); | 811 | *ubd_dev = ((struct ubd) DEFAULT_UBD); |
793 | err = 0; | 812 | err = 0; |
794 | out: | 813 | out: |
795 | spin_unlock(&ubd_lock); | 814 | mutex_unlock(&ubd_lock); |
796 | return err; | 815 | return err; |
797 | } | 816 | } |
798 | 817 | ||
818 | /* All these are called by mconsole in process context and without ubd-specific locks. */ | ||
799 | static struct mc_device ubd_mc = { | 819 | static struct mc_device ubd_mc = { |
800 | .name = "ubd", | 820 | .name = "ubd", |
801 | .config = ubd_config, | 821 | .config = ubd_config, |
@@ -804,7 +824,7 @@ static struct mc_device ubd_mc = { | |||
804 | .remove = ubd_remove, | 824 | .remove = ubd_remove, |
805 | }; | 825 | }; |
806 | 826 | ||
807 | static int ubd_mc_init(void) | 827 | static int __init ubd_mc_init(void) |
808 | { | 828 | { |
809 | mconsole_register_dev(&ubd_mc); | 829 | mconsole_register_dev(&ubd_mc); |
810 | return 0; | 830 | return 0; |
@@ -812,13 +832,24 @@ static int ubd_mc_init(void) | |||
812 | 832 | ||
813 | __initcall(ubd_mc_init); | 833 | __initcall(ubd_mc_init); |
814 | 834 | ||
835 | static int __init ubd0_init(void) | ||
836 | { | ||
837 | struct ubd *ubd_dev = &ubd_devs[0]; | ||
838 | |||
839 | if(ubd_dev->file == NULL) | ||
840 | ubd_dev->file = "root_fs"; | ||
841 | return(0); | ||
842 | } | ||
843 | |||
844 | __initcall(ubd0_init); | ||
845 | |||
815 | static struct platform_driver ubd_driver = { | 846 | static struct platform_driver ubd_driver = { |
816 | .driver = { | 847 | .driver = { |
817 | .name = DRIVER_NAME, | 848 | .name = DRIVER_NAME, |
818 | }, | 849 | }, |
819 | }; | 850 | }; |
820 | 851 | ||
821 | int ubd_init(void) | 852 | static int __init ubd_init(void) |
822 | { | 853 | { |
823 | int i; | 854 | int i; |
824 | 855 | ||
@@ -846,7 +877,7 @@ int ubd_init(void) | |||
846 | 877 | ||
847 | late_initcall(ubd_init); | 878 | late_initcall(ubd_init); |
848 | 879 | ||
849 | int ubd_driver_init(void){ | 880 | static int __init ubd_driver_init(void){ |
850 | unsigned long stack; | 881 | unsigned long stack; |
851 | int err; | 882 | int err; |
852 | 883 | ||
@@ -867,7 +898,7 @@ int ubd_driver_init(void){ | |||
867 | return(0); | 898 | return(0); |
868 | } | 899 | } |
869 | err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, | 900 | err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, |
870 | IRQF_DISABLED, "ubd", ubd_dev); | 901 | IRQF_DISABLED, "ubd", ubd_devs); |
871 | if(err != 0) | 902 | if(err != 0) |
872 | printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); | 903 | printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); |
873 | return 0; | 904 | return 0; |
@@ -878,24 +909,24 @@ device_initcall(ubd_driver_init); | |||
878 | static int ubd_open(struct inode *inode, struct file *filp) | 909 | static int ubd_open(struct inode *inode, struct file *filp) |
879 | { | 910 | { |
880 | struct gendisk *disk = inode->i_bdev->bd_disk; | 911 | struct gendisk *disk = inode->i_bdev->bd_disk; |
881 | struct ubd *dev = disk->private_data; | 912 | struct ubd *ubd_dev = disk->private_data; |
882 | int err = 0; | 913 | int err = 0; |
883 | 914 | ||
884 | if(dev->count == 0){ | 915 | if(ubd_dev->count == 0){ |
885 | err = ubd_open_dev(dev); | 916 | err = ubd_open_dev(ubd_dev); |
886 | if(err){ | 917 | if(err){ |
887 | printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n", | 918 | printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n", |
888 | disk->disk_name, dev->file, -err); | 919 | disk->disk_name, ubd_dev->file, -err); |
889 | goto out; | 920 | goto out; |
890 | } | 921 | } |
891 | } | 922 | } |
892 | dev->count++; | 923 | ubd_dev->count++; |
893 | set_disk_ro(disk, !dev->openflags.w); | 924 | set_disk_ro(disk, !ubd_dev->openflags.w); |
894 | 925 | ||
895 | /* This should no more be needed. And it didn't work anyway to exclude | 926 | /* This should no more be needed. And it didn't work anyway to exclude |
896 | * read-write remounting of filesystems.*/ | 927 | * read-write remounting of filesystems.*/ |
897 | /*if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){ | 928 | /*if((filp->f_mode & FMODE_WRITE) && !ubd_dev->openflags.w){ |
898 | if(--dev->count == 0) ubd_close(dev); | 929 | if(--ubd_dev->count == 0) ubd_close_dev(ubd_dev); |
899 | err = -EROFS; | 930 | err = -EROFS; |
900 | }*/ | 931 | }*/ |
901 | out: | 932 | out: |
@@ -905,10 +936,10 @@ static int ubd_open(struct inode *inode, struct file *filp) | |||
905 | static int ubd_release(struct inode * inode, struct file * file) | 936 | static int ubd_release(struct inode * inode, struct file * file) |
906 | { | 937 | { |
907 | struct gendisk *disk = inode->i_bdev->bd_disk; | 938 | struct gendisk *disk = inode->i_bdev->bd_disk; |
908 | struct ubd *dev = disk->private_data; | 939 | struct ubd *ubd_dev = disk->private_data; |
909 | 940 | ||
910 | if(--dev->count == 0) | 941 | if(--ubd_dev->count == 0) |
911 | ubd_close(dev); | 942 | ubd_close_dev(ubd_dev); |
912 | return(0); | 943 | return(0); |
913 | } | 944 | } |
914 | 945 | ||
@@ -976,12 +1007,12 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap, | |||
976 | static int prepare_request(struct request *req, struct io_thread_req *io_req) | 1007 | static int prepare_request(struct request *req, struct io_thread_req *io_req) |
977 | { | 1008 | { |
978 | struct gendisk *disk = req->rq_disk; | 1009 | struct gendisk *disk = req->rq_disk; |
979 | struct ubd *dev = disk->private_data; | 1010 | struct ubd *ubd_dev = disk->private_data; |
980 | __u64 offset; | 1011 | __u64 offset; |
981 | int len; | 1012 | int len; |
982 | 1013 | ||
983 | /* This should be impossible now */ | 1014 | /* This should be impossible now */ |
984 | if((rq_data_dir(req) == WRITE) && !dev->openflags.w){ | 1015 | if((rq_data_dir(req) == WRITE) && !ubd_dev->openflags.w){ |
985 | printk("Write attempted on readonly ubd device %s\n", | 1016 | printk("Write attempted on readonly ubd device %s\n", |
986 | disk->disk_name); | 1017 | disk->disk_name); |
987 | end_request(req, 0); | 1018 | end_request(req, 0); |
@@ -991,8 +1022,8 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) | |||
991 | offset = ((__u64) req->sector) << 9; | 1022 | offset = ((__u64) req->sector) << 9; |
992 | len = req->current_nr_sectors << 9; | 1023 | len = req->current_nr_sectors << 9; |
993 | 1024 | ||
994 | io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd; | 1025 | io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd : ubd_dev->fd; |
995 | io_req->fds[1] = dev->fd; | 1026 | io_req->fds[1] = ubd_dev->fd; |
996 | io_req->cow_offset = -1; | 1027 | io_req->cow_offset = -1; |
997 | io_req->offset = offset; | 1028 | io_req->offset = offset; |
998 | io_req->length = len; | 1029 | io_req->length = len; |
@@ -1001,13 +1032,13 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) | |||
1001 | 1032 | ||
1002 | io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE; | 1033 | io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE; |
1003 | io_req->offsets[0] = 0; | 1034 | io_req->offsets[0] = 0; |
1004 | io_req->offsets[1] = dev->cow.data_offset; | 1035 | io_req->offsets[1] = ubd_dev->cow.data_offset; |
1005 | io_req->buffer = req->buffer; | 1036 | io_req->buffer = req->buffer; |
1006 | io_req->sectorsize = 1 << 9; | 1037 | io_req->sectorsize = 1 << 9; |
1007 | 1038 | ||
1008 | if(dev->cow.file != NULL) | 1039 | if(ubd_dev->cow.file != NULL) |
1009 | cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset, | 1040 | cowify_req(io_req, ubd_dev->cow.bitmap, ubd_dev->cow.bitmap_offset, |
1010 | dev->cow.bitmap_len); | 1041 | ubd_dev->cow.bitmap_len); |
1011 | 1042 | ||
1012 | return(0); | 1043 | return(0); |
1013 | } | 1044 | } |
@@ -1033,7 +1064,7 @@ static void do_ubd_request(request_queue_t *q) | |||
1033 | return; | 1064 | return; |
1034 | err = prepare_request(req, &io_req); | 1065 | err = prepare_request(req, &io_req); |
1035 | if(!err){ | 1066 | if(!err){ |
1036 | do_ubd = ubd_handler; | 1067 | do_ubd = 1; |
1037 | n = os_write_file(thread_fd, (char *) &io_req, | 1068 | n = os_write_file(thread_fd, (char *) &io_req, |
1038 | sizeof(io_req)); | 1069 | sizeof(io_req)); |
1039 | if(n != sizeof(io_req)) | 1070 | if(n != sizeof(io_req)) |
@@ -1045,18 +1076,18 @@ static void do_ubd_request(request_queue_t *q) | |||
1045 | 1076 | ||
1046 | static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo) | 1077 | static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo) |
1047 | { | 1078 | { |
1048 | struct ubd *dev = bdev->bd_disk->private_data; | 1079 | struct ubd *ubd_dev = bdev->bd_disk->private_data; |
1049 | 1080 | ||
1050 | geo->heads = 128; | 1081 | geo->heads = 128; |
1051 | geo->sectors = 32; | 1082 | geo->sectors = 32; |
1052 | geo->cylinders = dev->size / (128 * 32 * 512); | 1083 | geo->cylinders = ubd_dev->size / (128 * 32 * 512); |
1053 | return 0; | 1084 | return 0; |
1054 | } | 1085 | } |
1055 | 1086 | ||
1056 | static int ubd_ioctl(struct inode * inode, struct file * file, | 1087 | static int ubd_ioctl(struct inode * inode, struct file * file, |
1057 | unsigned int cmd, unsigned long arg) | 1088 | unsigned int cmd, unsigned long arg) |
1058 | { | 1089 | { |
1059 | struct ubd *dev = inode->i_bdev->bd_disk->private_data; | 1090 | struct ubd *ubd_dev = inode->i_bdev->bd_disk->private_data; |
1060 | struct hd_driveid ubd_id = { | 1091 | struct hd_driveid ubd_id = { |
1061 | .cyls = 0, | 1092 | .cyls = 0, |
1062 | .heads = 128, | 1093 | .heads = 128, |
@@ -1066,7 +1097,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file, | |||
1066 | switch (cmd) { | 1097 | switch (cmd) { |
1067 | struct cdrom_volctrl volume; | 1098 | struct cdrom_volctrl volume; |
1068 | case HDIO_GET_IDENTITY: | 1099 | case HDIO_GET_IDENTITY: |
1069 | ubd_id.cyls = dev->size / (128 * 32 * 512); | 1100 | ubd_id.cyls = ubd_dev->size / (128 * 32 * 512); |
1070 | if(copy_to_user((char __user *) arg, (char *) &ubd_id, | 1101 | if(copy_to_user((char __user *) arg, (char *) &ubd_id, |
1071 | sizeof(ubd_id))) | 1102 | sizeof(ubd_id))) |
1072 | return(-EFAULT); | 1103 | return(-EFAULT); |
@@ -1353,8 +1384,8 @@ void do_io(struct io_thread_req *req) | |||
1353 | */ | 1384 | */ |
1354 | int kernel_fd = -1; | 1385 | int kernel_fd = -1; |
1355 | 1386 | ||
1356 | /* Only changed by the io thread */ | 1387 | /* Only changed by the io thread. XXX: currently unused. */ |
1357 | int io_count = 0; | 1388 | static int io_count = 0; |
1358 | 1389 | ||
1359 | int io_thread(void *arg) | 1390 | int io_thread(void *arg) |
1360 | { | 1391 | { |