diff options
| author | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-21 03:03:38 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-21 03:03:38 -0500 |
| commit | 4604096768d3be37ee1a05aee424aceed3e1b56f (patch) | |
| tree | 56010e180bb32be7e57971e4bb617c28d0d09099 | |
| parent | 8df8bb4adf7e4abb48d29dc16c29eda40a64afed (diff) | |
| parent | 126ec9a676f601818dc3a85af0552b146410d888 (diff) | |
Merge branch 'for-linus' of git://brick.kernel.dk/data/git/linux-2.6-block
* 'for-linus' of git://brick.kernel.dk/data/git/linux-2.6-block:
[PATCH] block: document io scheduler allow_merge_fn hook
[PATCH] cfq-iosched: don't allow sync merges across queues
[PATCH] Fixup blk_rq_unmap_user() API
[PATCH] __blk_rq_unmap_user() fails to return error
[PATCH] __blk_rq_map_user() doesn't need to grab the queue_lock
[PATCH] Remove queue merging hooks
[PATCH] ->nr_sectors and ->hard_nr_sectors are not used for BLOCK_PC requests
[PATCH] cciss: fix XFER_READ/XFER_WRITE in do_cciss_request
[PATCH] cciss: set default raid level when reading geometry fails
| -rw-r--r-- | Documentation/block/biodoc.txt | 7 | ||||
| -rw-r--r-- | block/cfq-iosched.c | 33 | ||||
| -rw-r--r-- | block/elevator.c | 26 | ||||
| -rw-r--r-- | block/ll_rw_blk.c | 67 | ||||
| -rw-r--r-- | block/scsi_ioctl.c | 3 | ||||
| -rw-r--r-- | drivers/block/cciss.c | 3 | ||||
| -rw-r--r-- | drivers/cdrom/cdrom.c | 3 | ||||
| -rw-r--r-- | drivers/scsi/scsi_lib.c | 4 | ||||
| -rw-r--r-- | include/linux/blkdev.h | 14 | ||||
| -rw-r--r-- | include/linux/elevator.h | 3 |
10 files changed, 107 insertions, 56 deletions
diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt index c6c9a9c10d7f..3adaace328a6 100644 --- a/Documentation/block/biodoc.txt +++ b/Documentation/block/biodoc.txt | |||
| @@ -946,6 +946,13 @@ elevator_merged_fn called when a request in the scheduler has been | |||
| 946 | scheduler for example, to reposition the request | 946 | scheduler for example, to reposition the request |
| 947 | if its sorting order has changed. | 947 | if its sorting order has changed. |
| 948 | 948 | ||
| 949 | elevator_allow_merge_fn called whenever the block layer determines | ||
| 950 | that a bio can be merged into an existing | ||
| 951 | request safely. The io scheduler may still | ||
| 952 | want to stop a merge at this point if it | ||
| 953 | results in some sort of conflict internally, | ||
| 954 | this hook allows it to do that. | ||
| 955 | |||
| 949 | elevator_dispatch_fn fills the dispatch queue with ready requests. | 956 | elevator_dispatch_fn fills the dispatch queue with ready requests. |
| 950 | I/O schedulers are free to postpone requests by | 957 | I/O schedulers are free to postpone requests by |
| 951 | not filling the dispatch queue unless @force | 958 | not filling the dispatch queue unless @force |
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 533a2938ffd6..9fc5eafa6c0e 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
| @@ -568,6 +568,38 @@ cfq_merged_requests(request_queue_t *q, struct request *rq, | |||
| 568 | cfq_remove_request(next); | 568 | cfq_remove_request(next); |
| 569 | } | 569 | } |
| 570 | 570 | ||
| 571 | static int cfq_allow_merge(request_queue_t *q, struct request *rq, | ||
| 572 | struct bio *bio) | ||
| 573 | { | ||
| 574 | struct cfq_data *cfqd = q->elevator->elevator_data; | ||
| 575 | const int rw = bio_data_dir(bio); | ||
| 576 | struct cfq_queue *cfqq; | ||
| 577 | pid_t key; | ||
| 578 | |||
| 579 | /* | ||
| 580 | * If bio is async or a write, always allow merge | ||
| 581 | */ | ||
| 582 | if (!bio_sync(bio) || rw == WRITE) | ||
| 583 | return 1; | ||
| 584 | |||
| 585 | /* | ||
| 586 | * bio is sync. if request is not, disallow. | ||
| 587 | */ | ||
| 588 | if (!rq_is_sync(rq)) | ||
| 589 | return 0; | ||
| 590 | |||
| 591 | /* | ||
| 592 | * Ok, both bio and request are sync. Allow merge if they are | ||
| 593 | * from the same queue. | ||
| 594 | */ | ||
| 595 | key = cfq_queue_pid(current, rw, 1); | ||
| 596 | cfqq = cfq_find_cfq_hash(cfqd, key, current->ioprio); | ||
| 597 | if (cfqq != RQ_CFQQ(rq)) | ||
| 598 | return 0; | ||
| 599 | |||
| 600 | return 1; | ||
| 601 | } | ||
| 602 | |||
| 571 | static inline void | 603 | static inline void |
| 572 | __cfq_set_active_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) | 604 | __cfq_set_active_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) |
| 573 | { | 605 | { |
| @@ -2125,6 +2157,7 @@ static struct elevator_type iosched_cfq = { | |||
| 2125 | .elevator_merge_fn = cfq_merge, | 2157 | .elevator_merge_fn = cfq_merge, |
| 2126 | .elevator_merged_fn = cfq_merged_request, | 2158 | .elevator_merged_fn = cfq_merged_request, |
| 2127 | .elevator_merge_req_fn = cfq_merged_requests, | 2159 | .elevator_merge_req_fn = cfq_merged_requests, |
| 2160 | .elevator_allow_merge_fn = cfq_allow_merge, | ||
| 2128 | .elevator_dispatch_fn = cfq_dispatch_requests, | 2161 | .elevator_dispatch_fn = cfq_dispatch_requests, |
| 2129 | .elevator_add_req_fn = cfq_insert_request, | 2162 | .elevator_add_req_fn = cfq_insert_request, |
| 2130 | .elevator_activate_req_fn = cfq_activate_request, | 2163 | .elevator_activate_req_fn = cfq_activate_request, |
diff --git a/block/elevator.c b/block/elevator.c index c0063f345c5d..62c7a3069d3a 100644 --- a/block/elevator.c +++ b/block/elevator.c | |||
| @@ -51,6 +51,21 @@ static const int elv_hash_shift = 6; | |||
| 51 | #define ELV_ON_HASH(rq) (!hlist_unhashed(&(rq)->hash)) | 51 | #define ELV_ON_HASH(rq) (!hlist_unhashed(&(rq)->hash)) |
| 52 | 52 | ||
| 53 | /* | 53 | /* |
| 54 | * Query io scheduler to see if the current process issuing bio may be | ||
| 55 | * merged with rq. | ||
| 56 | */ | ||
| 57 | static int elv_iosched_allow_merge(struct request *rq, struct bio *bio) | ||
| 58 | { | ||
| 59 | request_queue_t *q = rq->q; | ||
| 60 | elevator_t *e = q->elevator; | ||
| 61 | |||
| 62 | if (e->ops->elevator_allow_merge_fn) | ||
| 63 | return e->ops->elevator_allow_merge_fn(q, rq, bio); | ||
| 64 | |||
| 65 | return 1; | ||
| 66 | } | ||
| 67 | |||
| 68 | /* | ||
| 54 | * can we safely merge with this request? | 69 | * can we safely merge with this request? |
| 55 | */ | 70 | */ |
| 56 | inline int elv_rq_merge_ok(struct request *rq, struct bio *bio) | 71 | inline int elv_rq_merge_ok(struct request *rq, struct bio *bio) |
| @@ -65,12 +80,15 @@ inline int elv_rq_merge_ok(struct request *rq, struct bio *bio) | |||
| 65 | return 0; | 80 | return 0; |
| 66 | 81 | ||
| 67 | /* | 82 | /* |
| 68 | * same device and no special stuff set, merge is ok | 83 | * must be same device and not a special request |
| 69 | */ | 84 | */ |
| 70 | if (rq->rq_disk == bio->bi_bdev->bd_disk && !rq->special) | 85 | if (rq->rq_disk != bio->bi_bdev->bd_disk || !rq->special) |
| 71 | return 1; | 86 | return 0; |
| 72 | 87 | ||
| 73 | return 0; | 88 | if (!elv_iosched_allow_merge(rq, bio)) |
| 89 | return 0; | ||
| 90 | |||
| 91 | return 1; | ||
| 74 | } | 92 | } |
| 75 | EXPORT_SYMBOL(elv_rq_merge_ok); | 93 | EXPORT_SYMBOL(elv_rq_merge_ok); |
| 76 | 94 | ||
diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index 79807dbc306e..e07c079e07e6 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c | |||
| @@ -1405,8 +1405,7 @@ static inline int ll_new_hw_segment(request_queue_t *q, | |||
| 1405 | return 1; | 1405 | return 1; |
| 1406 | } | 1406 | } |
| 1407 | 1407 | ||
| 1408 | static int ll_back_merge_fn(request_queue_t *q, struct request *req, | 1408 | int ll_back_merge_fn(request_queue_t *q, struct request *req, struct bio *bio) |
| 1409 | struct bio *bio) | ||
| 1410 | { | 1409 | { |
| 1411 | unsigned short max_sectors; | 1410 | unsigned short max_sectors; |
| 1412 | int len; | 1411 | int len; |
| @@ -1442,6 +1441,7 @@ static int ll_back_merge_fn(request_queue_t *q, struct request *req, | |||
| 1442 | 1441 | ||
| 1443 | return ll_new_hw_segment(q, req, bio); | 1442 | return ll_new_hw_segment(q, req, bio); |
| 1444 | } | 1443 | } |
| 1444 | EXPORT_SYMBOL(ll_back_merge_fn); | ||
| 1445 | 1445 | ||
| 1446 | static int ll_front_merge_fn(request_queue_t *q, struct request *req, | 1446 | static int ll_front_merge_fn(request_queue_t *q, struct request *req, |
| 1447 | struct bio *bio) | 1447 | struct bio *bio) |
| @@ -1912,9 +1912,6 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id) | |||
| 1912 | } | 1912 | } |
| 1913 | 1913 | ||
| 1914 | q->request_fn = rfn; | 1914 | q->request_fn = rfn; |
| 1915 | q->back_merge_fn = ll_back_merge_fn; | ||
| 1916 | q->front_merge_fn = ll_front_merge_fn; | ||
| 1917 | q->merge_requests_fn = ll_merge_requests_fn; | ||
| 1918 | q->prep_rq_fn = NULL; | 1915 | q->prep_rq_fn = NULL; |
| 1919 | q->unplug_fn = generic_unplug_device; | 1916 | q->unplug_fn = generic_unplug_device; |
| 1920 | q->queue_flags = (1 << QUEUE_FLAG_CLUSTER); | 1917 | q->queue_flags = (1 << QUEUE_FLAG_CLUSTER); |
| @@ -2350,40 +2347,29 @@ static int __blk_rq_map_user(request_queue_t *q, struct request *rq, | |||
| 2350 | else | 2347 | else |
| 2351 | bio = bio_copy_user(q, uaddr, len, reading); | 2348 | bio = bio_copy_user(q, uaddr, len, reading); |
| 2352 | 2349 | ||
| 2353 | if (IS_ERR(bio)) { | 2350 | if (IS_ERR(bio)) |
| 2354 | return PTR_ERR(bio); | 2351 | return PTR_ERR(bio); |
| 2355 | } | ||
| 2356 | 2352 | ||
| 2357 | orig_bio = bio; | 2353 | orig_bio = bio; |
| 2358 | blk_queue_bounce(q, &bio); | 2354 | blk_queue_bounce(q, &bio); |
| 2355 | |||
| 2359 | /* | 2356 | /* |
| 2360 | * We link the bounce buffer in and could have to traverse it | 2357 | * We link the bounce buffer in and could have to traverse it |
| 2361 | * later so we have to get a ref to prevent it from being freed | 2358 | * later so we have to get a ref to prevent it from being freed |
| 2362 | */ | 2359 | */ |
| 2363 | bio_get(bio); | 2360 | bio_get(bio); |
| 2364 | 2361 | ||
