diff options
| -rw-r--r-- | block/blk-core.c | 25 | ||||
| -rw-r--r-- | drivers/block/umem.c | 35 | ||||
| -rw-r--r-- | drivers/md/md.c | 56 | ||||
| -rw-r--r-- | drivers/md/md.h | 8 | ||||
| -rw-r--r-- | include/linux/blkdev.h | 8 |
5 files changed, 49 insertions, 83 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index dd134d834d58..177ddcf356e6 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
| @@ -2927,6 +2927,31 @@ static void flush_plug_callbacks(struct blk_plug *plug) | |||
| 2927 | } | 2927 | } |
| 2928 | } | 2928 | } |
| 2929 | 2929 | ||
| 2930 | struct blk_plug_cb *blk_check_plugged(blk_plug_cb_fn unplug, void *data, | ||
| 2931 | int size) | ||
| 2932 | { | ||
| 2933 | struct blk_plug *plug = current->plug; | ||
| 2934 | struct blk_plug_cb *cb; | ||
| 2935 | |||
| 2936 | if (!plug) | ||
| 2937 | return NULL; | ||
| 2938 | |||
| 2939 | list_for_each_entry(cb, &plug->cb_list, list) | ||
| 2940 | if (cb->callback == unplug && cb->data == data) | ||
| 2941 | return cb; | ||
| 2942 | |||
| 2943 | /* Not currently on the callback list */ | ||
| 2944 | BUG_ON(size < sizeof(*cb)); | ||
| 2945 | cb = kzalloc(size, GFP_ATOMIC); | ||
| 2946 | if (cb) { | ||
| 2947 | cb->data = data; | ||
| 2948 | cb->callback = unplug; | ||
| 2949 | list_add(&cb->list, &plug->cb_list); | ||
| 2950 | } | ||
| 2951 | return cb; | ||
| 2952 | } | ||
| 2953 | EXPORT_SYMBOL(blk_check_plugged); | ||
| 2954 | |||
| 2930 | void blk_flush_plug_list(struct blk_plug *plug, bool from_schedule) | 2955 | void blk_flush_plug_list(struct blk_plug *plug, bool from_schedule) |
| 2931 | { | 2956 | { |
| 2932 | struct request_queue *q; | 2957 | struct request_queue *q; |
diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 9a72277a31df..6ef3489568e3 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c | |||
| @@ -513,42 +513,19 @@ static void process_page(unsigned long data) | |||
| 513 | } | 513 | } |
| 514 | } | 514 | } |
| 515 | 515 | ||
| 516 | struct mm_plug_cb { | ||
| 517 | struct blk_plug_cb cb; | ||
| 518 | struct cardinfo *card; | ||
| 519 | }; | ||
| 520 | |||
| 521 | static void mm_unplug(struct blk_plug_cb *cb) | 516 | static void mm_unplug(struct blk_plug_cb *cb) |
| 522 | { | 517 | { |
| 523 | struct mm_plug_cb *mmcb = container_of(cb, struct mm_plug_cb, cb); | 518 | struct cardinfo *card = cb->data; |
| 524 | 519 | ||
| 525 | spin_lock_irq(&mmcb->card->lock); | 520 | spin_lock_irq(&card->lock); |
| 526 | activate(mmcb->card); | 521 | activate(card); |
| 527 | spin_unlock_irq(&mmcb->card->lock); | 522 | spin_unlock_irq(&card->lock); |
| 528 | kfree(mmcb); | 523 | kfree(cb); |
| 529 | } | 524 | } |
| 530 | 525 | ||
| 531 | static int mm_check_plugged(struct cardinfo *card) | 526 | static int mm_check_plugged(struct cardinfo *card) |
| 532 | { | 527 | { |
| 533 | struct blk_plug *plug = current->plug; | 528 | return !!blk_check_plugged(mm_unplug, card, sizeof(struct blk_plug_cb)); |
| 534 | struct mm_plug_cb *mmcb; | ||
| 535 | |||
| 536 | if (!plug) | ||
| 537 | return 0; | ||
| 538 | |||
| 539 | list_for_each_entry(mmcb, &plug->cb_list, cb.list) { | ||
| 540 | if (mmcb->cb.callback == mm_unplug && mmcb->card == card) | ||
| 541 | return 1; | ||
| 542 | } | ||
| 543 | /* Not currently on the callback list */ | ||
| 544 | mmcb = kmalloc(sizeof(*mmcb), GFP_ATOMIC); | ||
| 545 | if (!mmcb) | ||
| 546 | return 0; | ||
| 547 | |||
| 548 | mmcb->card = card; | ||
| 549 | mmcb->cb.callback = mm_unplug; | ||
| 550 | list_add(&mmcb->cb.list, &plug->cb_list); | ||
| 551 | return 1; | ||
| 552 | } | 529 | } |
| 553 | 530 | ||
| 554 | static void mm_make_request(struct request_queue *q, struct bio *bio) | 531 | static void mm_make_request(struct request_queue *q, struct bio *bio) |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 34381172a947..b493fa417387 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
| @@ -498,59 +498,13 @@ void md_flush_request(struct mddev *mddev, struct bio *bio) | |||
| 498 | } | 498 | } |
| 499 | EXPORT_SYMBOL(md_flush_request); | 499 | EXPORT_SYMBOL(md_flush_request); |
| 500 | 500 | ||
| 501 | /* Support for plugging. | 501 | void md_unplug(struct blk_plug_cb *cb) |
| 502 | * This mirrors the plugging support in request_queue, but does not | ||
| 503 | * require having a whole queue or request structures. | ||
| 504 | * We allocate an md_plug_cb for each md device and each thread it gets | ||
| 505 | * plugged on. This links tot the private plug_handle structure in the | ||
| 506 | * personality data where we keep a count of the number of outstanding | ||
| 507 | * plugs so other code can see if a plug is active. | ||
| 508 | */ | ||
| 509 | struct md_plug_cb { | ||
| 510 | struct blk_plug_cb cb; | ||
| 511 | struct mddev *mddev; | ||
| 512 | }; | ||
| 513 | |||
| 514 | static void plugger_unplug(struct blk_plug_cb *cb) | ||
| 515 | { | 502 | { |
| 516 | struct md_plug_cb *mdcb = container_of(cb, struct md_plug_cb, cb); | 503 | struct mddev *mddev = cb->data; |
| 517 | md_wakeup_thread(mdcb->mddev->thread); | 504 | md_wakeup_thread(mddev->thread); |
| 518 | kfree(mdcb); | 505 | kfree(cb); |
| 519 | } | ||
| 520 | |||
| 521 | /* Check that an unplug wakeup will come shortly. | ||
| 522 | * If not, wakeup the md thread immediately | ||
| 523 | */ | ||
| 524 | int mddev_check_plugged(struct mddev *mddev) | ||
| 525 | { | ||
| 526 | struct blk_plug *plug = current->plug; | ||
| 527 | struct md_plug_cb *mdcb; | ||
| 528 | |||
| 529 | if (!plug) | ||
| 530 | return 0; | ||
| 531 | |||
| 532 | list_for_each_entry(mdcb, &plug->cb_list, cb.list) { | ||
| 533 | if (mdcb->cb.callback == plugger_unplug && | ||
| 534 | mdcb->mddev == mddev) { | ||
| 535 | /* Already on the list, move to top */ | ||
| 536 | if (mdcb != list_first_entry(&plug->cb_list, | ||
| 537 | struct md_plug_cb, | ||
| 538 | cb.list)) | ||
| 539 | list_move(&mdcb->cb.list, &plug->cb_list); | ||
| 540 | return 1; | ||
| 541 | } | ||
| 542 | } | ||
| 543 | /* Not currently on the callback list */ | ||
| 544 | mdcb = kmalloc(sizeof(*mdcb), GFP_ATOMIC); | ||
| 545 | if (!mdcb) | ||
| 546 | return 0; | ||
| 547 | |||
| 548 | mdcb->mddev = mddev; | ||
| 549 | mdcb->cb.callback = plugger_unplug; | ||
| 550 | list_add(&mdcb->cb.list, &plug->cb_list); | ||
| 551 | return 1; | ||
| 552 | } | 506 | } |
| 553 | EXPORT_SYMBOL_GPL(mddev_check_plugged); | 507 | EXPORT_SYMBOL(md_unplug); |
| 554 | 508 | ||
| 555 | static inline struct mddev *mddev_get(struct mddev *mddev) | 509 | static inline struct mddev *mddev_get(struct mddev *mddev) |
| 556 | { | 510 | { |
diff --git a/drivers/md/md.h b/drivers/md/md.h index 91786c46b85c..8f998e08fb87 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h | |||
| @@ -627,6 +627,12 @@ extern struct bio *bio_clone_mddev(struct bio *bio, gfp_t gfp_mask, | |||
| 627 | struct mddev *mddev); | 627 | struct mddev *mddev); |
| 628 | extern struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs, | 628 | extern struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs, |
| 629 | struct mddev *mddev); | 629 | struct mddev *mddev); |
| 630 | extern int mddev_check_plugged(struct mddev *mddev); | ||
| 631 | extern void md_trim_bio(struct bio *bio, int offset, int size); | 630 | extern void md_trim_bio(struct bio *bio, int offset, int size); |
| 631 | |||
| 632 | extern void md_unplug(struct blk_plug_cb *cb); | ||
| 633 | static inline int mddev_check_plugged(struct mddev *mddev) | ||
| 634 | { | ||
| 635 | return !!blk_check_plugged(md_unplug, mddev, | ||
| 636 | sizeof(struct blk_plug_cb)); | ||
| 637 | } | ||
| 632 | #endif /* _MD_MD_H */ | 638 | #endif /* _MD_MD_H */ |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 3816ce8a08fc..607ca228f47e 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
| @@ -922,11 +922,15 @@ struct blk_plug { | |||
| 922 | }; | 922 | }; |
| 923 | #define BLK_MAX_REQUEST_COUNT 16 | 923 | #define BLK_MAX_REQUEST_COUNT 16 |
| 924 | 924 | ||
| 925 | struct blk_plug_cb; | ||
| 926 | typedef void (*blk_plug_cb_fn)(struct blk_plug_cb *); | ||
| 925 | struct blk_plug_cb { | 927 | struct blk_plug_cb { |
| 926 | struct list_head list; | 928 | struct list_head list; |
| 927 | void (*callback)(struct blk_plug_cb *); | 929 | blk_plug_cb_fn callback; |
| 930 | void *data; | ||
| 928 | }; | 931 | }; |
| 929 | 932 | extern struct blk_plug_cb *blk_check_plugged(blk_plug_cb_fn unplug, | |
| 933 | void *data, int size); | ||
| 930 | extern void blk_start_plug(struct blk_plug *); | 934 | extern void blk_start_plug(struct blk_plug *); |
| 931 | extern void blk_finish_plug(struct blk_plug *); | 935 | extern void blk_finish_plug(struct blk_plug *); |
| 932 | extern void blk_flush_plug_list(struct blk_plug *, bool); | 936 | extern void blk_flush_plug_list(struct blk_plug *, bool); |
