diff options
| author | Serge E. Hallyn <serue@us.ibm.com> | 2006-09-29 04:59:11 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-29 12:18:06 -0400 |
| commit | 6c9979185c7ef4feeb7f8d29be032b8f032a1838 (patch) | |
| tree | dd6d45dc21adf280164ba840ae0c954dd0c94233 | |
| parent | 5b217fa75c3aea381f1f5fa7ff09e7b4019ea374 (diff) | |
[PATCH] kthread: convert loop.c to kthread
Convert loop.c from the deprecated kernel_thread to kthread. This patch
simplifies the code quite a bit and passes similar testing to the previous
submission on both emulated x86 and s390.
Changes since last submission:
switched to using a rather simple loop based on
wait_event_interruptible.
Signed-off-by: Serge E. Hallyn <serue@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | drivers/block/loop.c | 69 | ||||
| -rw-r--r-- | include/linux/loop.h | 5 |
2 files changed, 26 insertions, 48 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index c774121684d7..e87b88731adc 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
| @@ -72,6 +72,7 @@ | |||
| 72 | #include <linux/completion.h> | 72 | #include <linux/completion.h> |
| 73 | #include <linux/highmem.h> | 73 | #include <linux/highmem.h> |
| 74 | #include <linux/gfp.h> | 74 | #include <linux/gfp.h> |
| 75 | #include <linux/kthread.h> | ||
| 75 | 76 | ||
| 76 | #include <asm/uaccess.h> | 77 | #include <asm/uaccess.h> |
| 77 | 78 | ||
| @@ -522,15 +523,12 @@ static int loop_make_request(request_queue_t *q, struct bio *old_bio) | |||
| 522 | goto out; | 523 | goto out; |
| 523 | if (unlikely(rw == WRITE && (lo->lo_flags & LO_FLAGS_READ_ONLY))) | 524 | if (unlikely(rw == WRITE && (lo->lo_flags & LO_FLAGS_READ_ONLY))) |
| 524 | goto out; | 525 | goto out; |
| 525 | lo->lo_pending++; | ||
| 526 | loop_add_bio(lo, old_bio); | 526 | loop_add_bio(lo, old_bio); |
| 527 | wake_up(&lo->lo_event); | ||
| 527 | spin_unlock_irq(&lo->lo_lock); | 528 | spin_unlock_irq(&lo->lo_lock); |
| 528 | complete(&lo->lo_bh_done); | ||
| 529 | return 0; | 529 | return 0; |
| 530 | 530 | ||
| 531 | out: | 531 | out: |
| 532 | if (lo->lo_pending == 0) | ||
| 533 | complete(&lo->lo_bh_done); | ||
| 534 | spin_unlock_irq(&lo->lo_lock); | 532 | spin_unlock_irq(&lo->lo_lock); |
| 535 | bio_io_error(old_bio, old_bio->bi_size); | 533 | bio_io_error(old_bio, old_bio->bi_size); |
| 536 | return 0; | 534 | return 0; |
| @@ -570,14 +568,18 @@ static inline void loop_handle_bio(struct loop_device *lo, struct bio *bio) | |||
| 570 | * to avoid blocking in our make_request_fn. it also does loop decrypting | 568 | * to avoid blocking in our make_request_fn. it also does loop decrypting |
| 571 | * on reads for block backed loop, as that is too heavy to do from | 569 | * on reads for block backed loop, as that is too heavy to do from |
| 572 | * b_end_io context where irqs may be disabled. | 570 | * b_end_io context where irqs may be disabled. |
| 571 | * | ||
| 572 | * Loop explanation: loop_clr_fd() sets lo_state to Lo_rundown before | ||
| 573 | * calling kthread_stop(). Therefore once kthread_should_stop() is | ||
| 574 | * true, make_request will not place any more requests. Therefore | ||
| 575 | * once kthread_should_stop() is true and lo_bio is NULL, we are | ||
| 576 | * done with the loop. | ||
| 573 | */ | 577 | */ |
| 574 | static int loop_thread(void *data) | 578 | static int loop_thread(void *data) |
| 575 | { | 579 | { |
| 576 | struct loop_device *lo = data; | 580 | struct loop_device *lo = data; |
| 577 | struct bio *bio; | 581 | struct bio *bio; |
| 578 | 582 | ||
| 579 | daemonize("loop%d", lo->lo_number); | ||
| 580 | |||
| 581 | /* | 583 | /* |
| 582 | * loop can be used in an encrypted device, | 584 | * loop can be used in an encrypted device, |
| 583 | * hence, it mustn't be stopped at all | 585 | * hence, it mustn't be stopped at all |
| @@ -587,47 +589,21 @@ static int loop_thread(void *data) | |||
| 587 | 589 | ||
| 588 | set_user_nice(current, -20); | 590 | set_user_nice(current, -20); |
| 589 | 591 | ||
| 590 | lo->lo_state = Lo_bound; | 592 | while (!kthread_should_stop() || lo->lo_bio) { |
| 591 | lo->lo_pending = 1; | ||
| 592 | |||
| 593 | /* | ||
| 594 | * complete it, we are running | ||
| 595 | */ | ||
| 596 | complete(&lo->lo_done); | ||
| 597 | 593 | ||
| 598 | for (;;) { | 594 | wait_event_interruptible(lo->lo_event, |
| 599 | int pending; | 595 | lo->lo_bio || kthread_should_stop()); |
| 600 | 596 | ||
| 601 | if (wait_for_completion_interruptible(&lo->lo_bh_done)) | 597 | if (!lo->lo_bio) |
| 602 | continue; | 598 | continue; |
| 603 | |||
| 604 | spin_lock_irq(&lo->lo_lock); | 599 | spin_lock_irq(&lo->lo_lock); |
| 605 | |||
| 606 | /* | ||
| 607 | * could be completed because of tear-down, not pending work | ||
| 608 | */ | ||
| 609 | if (unlikely(!lo->lo_pending)) { | ||
| 610 | spin_unlock_irq(&lo->lo_lock); | ||
| 611 | break; | ||
| 612 | } | ||
| 613 | |||
| 614 | bio = loop_get_bio(lo); | 600 | bio = loop_get_bio(lo); |
| 615 | lo->lo_pending--; | ||
| 616 | pending = lo->lo_pending; | ||
| 617 | spin_unlock_irq(&lo->lo_lock); | 601 | spin_unlock_irq(&lo->lo_lock); |
| 618 | 602 | ||
| 619 | BUG_ON(!bio); | 603 | BUG_ON(!bio); |
| 620 | loop_handle_bio(lo, bio); | 604 | loop_handle_bio(lo, bio); |
| 621 | |||
| 622 | /* | ||
| 623 | * upped both for pending work and tear-down, lo_pending | ||
| 624 | * will hit zero then | ||
| 625 | */ | ||
| 626 | if (unlikely(!pending)) | ||
| 627 | break; | ||
| 628 | } | 605 | } |
| 629 | 606 | ||
| 630 | complete(&lo->lo_done); | ||
| 631 | return 0; | 607 | return 0; |
| 632 | } | 608 | } |
| 633 | 609 | ||
| @@ -840,10 +816,15 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file, | |||
| 840 | 816 | ||
| 841 | set_blocksize(bdev, lo_blocksize); | 817 | set_blocksize(bdev, lo_blocksize); |
| 842 | 818 | ||
| 843 | error = kernel_thread(loop_thread, lo, CLONE_KERNEL); | 819 | lo->lo_thread = kthread_create(loop_thread, lo, "loop%d", |
| 844 | if (error < 0) | 820 | lo->lo_number); |
| 821 | if (IS_ERR(lo->lo_thread)) { | ||
| 822 | error = PTR_ERR(lo->lo_thread); | ||
| 823 | lo->lo_thread = NULL; | ||
| 845 | goto out_putf; | 824 | goto out_putf; |
| 846 | wait_for_completion(&lo->lo_done); | 825 | } |
| 826 | lo->lo_state = Lo_bound; | ||
| 827 | wake_up_process(lo->lo_thread); | ||
| 847 | return 0; | 828 | return 0; |
| 848 | 829 | ||
| 849 | out_putf: | 830 | out_putf: |
| @@ -907,12 +888,9 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) | |||
| 907 | 888 | ||
| 908 | spin_lock_irq(&lo->lo_lock); | 889 | spin_lock_irq(&lo->lo_lock); |
| 909 | lo->lo_state = Lo_rundown; | 890 | lo->lo_state = Lo_rundown; |
| 910 | lo->lo_pending--; | ||
| 911 | if (!lo->lo_pending) | ||
| 912 | complete(&lo->lo_bh_done); | ||
| 913 | spin_unlock_irq(&lo->lo_lock); | 891 | spin_unlock_irq(&lo->lo_lock); |
| 914 | 892 | ||
| 915 | wait_for_completion(&lo->lo_done); | 893 | kthread_stop(lo->lo_thread); |
| 916 | 894 | ||
| 917 | lo->lo_backing_file = NULL; | 895 | lo->lo_backing_file = NULL; |
| 918 | 896 | ||
| @@ -925,6 +903,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) | |||
| 925 | lo->lo_sizelimit = 0; | 903 | lo->lo_sizelimit = 0; |
| 926 | lo->lo_encrypt_key_size = 0; | 904 | lo->lo_encrypt_key_size = 0; |
| 927 | lo->lo_flags = 0; | 905 | lo->lo_flags = 0; |
| 906 | lo->lo_thread = NULL; | ||
| 928 | memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE); | 907 | memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE); |
| 929 | memset(lo->lo_crypt_name, 0, LO_NAME_SIZE); | 908 | memset(lo->lo_crypt_name, 0, LO_NAME_SIZE); |
| 930 | memset(lo->lo_file_name, 0, LO_NAME_SIZE); | 909 | memset(lo->lo_file_name, 0, LO_NAME_SIZE); |
| @@ -1287,9 +1266,9 @@ static int __init loop_init(void) | |||
| 1287 | if (!lo->lo_queue) | 1266 | if (!lo->lo_queue) |
| 1288 | goto out_mem4; | 1267 | goto out_mem4; |
| 1289 | mutex_init(&lo->lo_ctl_mutex); | 1268 | mutex_init(&lo->lo_ctl_mutex); |
| 1290 | init_completion(&lo->lo_done); | ||
| 1291 | init_completion(&lo->lo_bh_done); | ||
| 1292 | lo->lo_number = i; | 1269 | lo->lo_number = i; |
| 1270 | lo->lo_thread = NULL; | ||
| 1271 | init_waitqueue_head(&lo->lo_event); | ||
| 1293 | spin_lock_init(&lo->lo_lock); | 1272 | spin_lock_init(&lo->lo_lock); |
| 1294 | disk->major = LOOP_MAJOR; | 1273 | disk->major = LOOP_MAJOR; |
| 1295 | disk->first_minor = i; | 1274 | disk->first_minor = i; |
diff --git a/include/linux/loop.h b/include/linux/loop.h index e76c7611d6cc..191a595055f0 100644 --- a/include/linux/loop.h +++ b/include/linux/loop.h | |||
| @@ -59,10 +59,9 @@ struct loop_device { | |||
| 59 | struct bio *lo_bio; | 59 | struct bio *lo_bio; |
| 60 | struct bio *lo_biotail; | 60 | struct bio *lo_biotail; |
| 61 | int lo_state; | 61 | int lo_state; |
| 62 | struct completion lo_done; | ||
| 63 | struct completion lo_bh_done; | ||
| 64 | struct mutex lo_ctl_mutex; | 62 | struct mutex lo_ctl_mutex; |
| 65 | int lo_pending; | 63 | struct task_struct *lo_thread; |
| 64 | wait_queue_head_t lo_event; | ||
| 66 | 65 | ||
| 67 | request_queue_t *lo_queue; | 66 | request_queue_t *lo_queue; |
| 68 | }; | 67 | }; |
