diff options
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-core.c | 6 | ||||
-rw-r--r-- | block/blk-merge.c | 5 | ||||
-rw-r--r-- | block/blk-settings.c | 20 | ||||
-rw-r--r-- | block/blk-sysfs.c | 4 | ||||
-rw-r--r-- | block/blk-timeout.c | 13 | ||||
-rw-r--r-- | block/blk.h | 7 | ||||
-rw-r--r-- | block/cfq-iosched.c | 66 | ||||
-rw-r--r-- | block/genhd.c | 12 | ||||
-rw-r--r-- | block/scsi_ioctl.c | 13 |
9 files changed, 96 insertions, 50 deletions
diff --git a/block/blk-core.c b/block/blk-core.c index 07ab75403e1a..2998fe3a2377 100644 --- a/block/blk-core.c +++ b/block/blk-core.c | |||
@@ -643,7 +643,7 @@ static inline void blk_free_request(struct request_queue *q, struct request *rq) | |||
643 | } | 643 | } |
644 | 644 | ||
645 | static struct request * | 645 | static struct request * |
646 | blk_alloc_request(struct request_queue *q, int rw, int priv, gfp_t gfp_mask) | 646 | blk_alloc_request(struct request_queue *q, int flags, int priv, gfp_t gfp_mask) |
647 | { | 647 | { |
648 | struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask); | 648 | struct request *rq = mempool_alloc(q->rq.rq_pool, gfp_mask); |
649 | 649 | ||
@@ -652,7 +652,7 @@ blk_alloc_request(struct request_queue *q, int rw, int priv, gfp_t gfp_mask) | |||
652 | 652 | ||
653 | blk_rq_init(q, rq); | 653 | blk_rq_init(q, rq); |
654 | 654 | ||
655 | rq->cmd_flags = rw | REQ_ALLOCED; | 655 | rq->cmd_flags = flags | REQ_ALLOCED; |
656 | 656 | ||
657 | if (priv) { | 657 | if (priv) { |
658 | if (unlikely(elv_set_request(q, rq, gfp_mask))) { | 658 | if (unlikely(elv_set_request(q, rq, gfp_mask))) { |
@@ -792,6 +792,8 @@ static struct request *get_request(struct request_queue *q, int rw_flags, | |||
792 | if (priv) | 792 | if (priv) |
793 | rl->elvpriv++; | 793 | rl->elvpriv++; |
794 | 794 | ||
795 | if (blk_queue_io_stat(q)) | ||
796 | rw_flags |= REQ_IO_STAT; | ||
795 | spin_unlock_irq(q->queue_lock); | 797 | spin_unlock_irq(q->queue_lock); |
796 | 798 | ||
797 | rq = blk_alloc_request(q, rw_flags, priv, gfp_mask); | 799 | rq = blk_alloc_request(q, rw_flags, priv, gfp_mask); |
diff --git a/block/blk-merge.c b/block/blk-merge.c index 63760ca3da0f..23d2a6fe34a3 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c | |||
@@ -402,7 +402,10 @@ static int attempt_merge(struct request_queue *q, struct request *req, | |||
402 | 402 | ||
403 | elv_merge_requests(q, req, next); | 403 | elv_merge_requests(q, req, next); |
404 | 404 | ||
405 | blk_account_io_merge(req); | 405 | /* |
406 | * 'next' is going away, so update stats accordingly | ||
407 | */ | ||
408 | blk_account_io_merge(next); | ||
406 | 409 | ||
407 | req->ioprio = ioprio_best(req->ioprio, next->ioprio); | 410 | req->ioprio = ioprio_best(req->ioprio, next->ioprio); |
408 | if (blk_rq_cpu_valid(next)) | 411 | if (blk_rq_cpu_valid(next)) |
diff --git a/block/blk-settings.c b/block/blk-settings.c index 69c42adde52b..57af728d94bb 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c | |||
@@ -156,26 +156,28 @@ EXPORT_SYMBOL(blk_queue_make_request); | |||
156 | 156 | ||
157 | /** | 157 | /** |
158 | * blk_queue_bounce_limit - set bounce buffer limit for queue | 158 | * blk_queue_bounce_limit - set bounce buffer limit for queue |
159 | * @q: the request queue for the device | 159 | * @q: the request queue for the device |
160 | * @dma_addr: bus address limit | 160 | * @dma_mask: the maximum address the device can handle |
161 | * | 161 | * |
162 | * Description: | 162 | * Description: |
163 | * Different hardware can have different requirements as to what pages | 163 | * Different hardware can have different requirements as to what pages |
164 | * it can do I/O directly to. A low level driver can call | 164 | * it can do I/O directly to. A low level driver can call |
165 | * blk_queue_bounce_limit to have lower memory pages allocated as bounce | 165 | * blk_queue_bounce_limit to have lower memory pages allocated as bounce |
166 | * buffers for doing I/O to pages residing above @dma_addr. | 166 | * buffers for doing I/O to pages residing above @dma_mask. |
167 | **/ | 167 | **/ |
168 | void blk_queue_bounce_limit(struct request_queue *q, u64 dma_addr) | 168 | void blk_queue_bounce_limit(struct request_queue *q, u64 dma_mask) |
169 | { | 169 | { |
170 | unsigned long b_pfn = dma_addr >> PAGE_SHIFT; | 170 | unsigned long b_pfn = dma_mask >> PAGE_SHIFT; |
171 | int dma = 0; | 171 | int dma = 0; |
172 | 172 | ||
173 | q->bounce_gfp = GFP_NOIO; | 173 | q->bounce_gfp = GFP_NOIO; |
174 | #if BITS_PER_LONG == 64 | 174 | #if BITS_PER_LONG == 64 |
175 | /* Assume anything <= 4GB can be handled by IOMMU. | 175 | /* |
176 | Actually some IOMMUs can handle everything, but I don't | 176 | * Assume anything <= 4GB can be handled by IOMMU. Actually |
177 | know of a way to test this here. */ | 177 | * some IOMMUs can handle everything, but I don't know of a |
178 | if (b_pfn < (min_t(u64, 0x100000000UL, BLK_BOUNCE_HIGH) >> PAGE_SHIFT)) | 178 | * way to test this here. |
179 | */ | ||
180 | if (b_pfn < (min_t(u64, 0xffffffffUL, BLK_BOUNCE_HIGH) >> PAGE_SHIFT)) | ||
179 | dma = 1; | 181 | dma = 1; |
180 | q->bounce_pfn = max_low_pfn; | 182 | q->bounce_pfn = max_low_pfn; |
181 | #else | 183 | #else |
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index cac4e9febe6a..3ff9bba3379a 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c | |||
@@ -209,14 +209,10 @@ static ssize_t queue_iostats_store(struct request_queue *q, const char *page, | |||
209 | ssize_t ret = queue_var_store(&stats, page, count); | 209 | ssize_t ret = queue_var_store(&stats, page, count); |
210 | 210 | ||
211 | spin_lock_irq(q->queue_lock); | 211 | spin_lock_irq(q->queue_lock); |
212 | elv_quiesce_start(q); | ||
213 | |||
214 | if (stats) | 212 | if (stats) |
215 | queue_flag_set(QUEUE_FLAG_IO_STAT, q); | 213 | queue_flag_set(QUEUE_FLAG_IO_STAT, q); |
216 | else | 214 | else |
217 | queue_flag_clear(QUEUE_FLAG_IO_STAT, q); | 215 | queue_flag_clear(QUEUE_FLAG_IO_STAT, q); |
218 | |||
219 | elv_quiesce_end(q); | ||
220 | spin_unlock_irq(q->queue_lock); | 216 | spin_unlock_irq(q->queue_lock); |
221 | 217 | ||
222 | return ret; | 218 | return ret; |
diff --git a/block/blk-timeout.c b/block/blk-timeout.c index bbbdc4b8ccf2..1ec0d503cacd 100644 --- a/block/blk-timeout.c +++ b/block/blk-timeout.c | |||
@@ -211,6 +211,12 @@ void blk_abort_queue(struct request_queue *q) | |||
211 | struct request *rq, *tmp; | 211 | struct request *rq, *tmp; |
212 | LIST_HEAD(list); | 212 | LIST_HEAD(list); |
213 | 213 | ||
214 | /* | ||
215 | * Not a request based block device, nothing to abort | ||
216 | */ | ||
217 | if (!q->request_fn) | ||
218 | return; | ||
219 | |||
214 | spin_lock_irqsave(q->queue_lock, flags); | 220 | spin_lock_irqsave(q->queue_lock, flags); |
215 | 221 | ||
216 | elv_abort_queue(q); | 222 | elv_abort_queue(q); |
@@ -224,6 +230,13 @@ void blk_abort_queue(struct request_queue *q) | |||
224 | list_for_each_entry_safe(rq, tmp, &list, timeout_list) | 230 | list_for_each_entry_safe(rq, tmp, &list, timeout_list) |
225 | blk_abort_request(rq); | 231 | blk_abort_request(rq); |
226 | 232 | ||
233 | /* | ||
234 | * Occasionally, blk_abort_request() will return without | ||
235 | * deleting the element from the list. Make sure we add those back | ||
236 | * instead of leaving them on the local stack list. | ||
237 | */ | ||
238 | list_splice(&list, &q->timeout_list); | ||
239 | |||
227 | spin_unlock_irqrestore(q->queue_lock, flags); | 240 | spin_unlock_irqrestore(q->queue_lock, flags); |
228 | 241 | ||
229 | } | 242 | } |
diff --git a/block/blk.h b/block/blk.h index 5dfc41267a08..79c85f7c9ff5 100644 --- a/block/blk.h +++ b/block/blk.h | |||
@@ -114,12 +114,7 @@ static inline int blk_cpu_to_group(int cpu) | |||
114 | 114 | ||
115 | static inline int blk_do_io_stat(struct request *rq) | 115 | static inline int blk_do_io_stat(struct request *rq) |
116 | { | 116 | { |
117 | struct gendisk *disk = rq->rq_disk; | 117 | return rq->rq_disk && blk_rq_io_stat(rq); |
118 | |||
119 | if (!disk || !disk->queue) | ||
120 | return 0; | ||
121 | |||
122 | return blk_queue_io_stat(disk->queue) && (rq->cmd_flags & REQ_ELVPRIV); | ||
123 | } | 118 | } |
124 | 119 | ||
125 | #endif | 120 | #endif |
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 0d3b70de3d80..a55a9bd75bd1 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c | |||
@@ -154,6 +154,8 @@ struct cfq_queue { | |||
154 | unsigned long rb_key; | 154 | unsigned long rb_key; |
155 | /* prio tree member */ | 155 | /* prio tree member */ |
156 | struct rb_node p_node; | 156 | struct rb_node p_node; |
157 | /* prio tree root we belong to, if any */ | ||
158 | struct rb_root *p_root; | ||
157 | /* sorted list of pending requests */ | 159 | /* sorted list of pending requests */ |
158 | struct rb_root sort_list; | 160 | struct rb_root sort_list; |
159 | /* if fifo isn't expired, next request to serve */ | 161 | /* if fifo isn't expired, next request to serve */ |
@@ -558,10 +560,10 @@ static void cfq_service_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq, | |||
558 | } | 560 | } |
559 | 561 | ||
560 | static struct cfq_queue * | 562 | static struct cfq_queue * |
561 | cfq_prio_tree_lookup(struct cfq_data *cfqd, int ioprio, sector_t sector, | 563 | cfq_prio_tree_lookup(struct cfq_data *cfqd, struct rb_root *root, |
562 | struct rb_node **ret_parent, struct rb_node ***rb_link) | 564 | sector_t sector, struct rb_node **ret_parent, |
565 | struct rb_node ***rb_link) | ||
563 | { | 566 | { |
564 | struct rb_root *root = &cfqd->prio_trees[ioprio]; | ||
565 | struct rb_node **p, *parent; | 567 | struct rb_node **p, *parent; |
566 | struct cfq_queue *cfqq = NULL; | 568 | struct cfq_queue *cfqq = NULL; |
567 | 569 | ||
@@ -584,34 +586,38 @@ cfq_prio_tree_lookup(struct cfq_data *cfqd, int ioprio, sector_t sector, | |||
584 | else | 586 | else |
585 | break; | 587 | break; |
586 | p = n; | 588 | p = n; |
589 | cfqq = NULL; | ||
587 | } | 590 | } |
588 | 591 | ||
589 | *ret_parent = parent; | 592 | *ret_parent = parent; |
590 | if (rb_link) | 593 | if (rb_link) |
591 | *rb_link = p; | 594 | *rb_link = p; |
592 | return NULL; | 595 | return cfqq; |
593 | } | 596 | } |
594 | 597 | ||
595 | static void cfq_prio_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq) | 598 | static void cfq_prio_tree_add(struct cfq_data *cfqd, struct cfq_queue *cfqq) |
596 | { | 599 | { |
597 | struct rb_root *root = &cfqd->prio_trees[cfqq->ioprio]; | ||
598 | struct rb_node **p, *parent; | 600 | struct rb_node **p, *parent; |
599 | struct cfq_queue *__cfqq; | 601 | struct cfq_queue *__cfqq; |
600 | 602 | ||
601 | if (!RB_EMPTY_NODE(&cfqq->p_node)) | 603 | if (cfqq->p_root) { |
602 | rb_erase_init(&cfqq->p_node, root); | 604 | rb_erase(&cfqq->p_node, cfqq->p_root); |
605 | cfqq->p_root = NULL; | ||
606 | } | ||
603 | 607 | ||
604 | if (cfq_class_idle(cfqq)) | 608 | if (cfq_class_idle(cfqq)) |
605 | return; | 609 | return; |
606 | if (!cfqq->next_rq) | 610 | if (!cfqq->next_rq) |
607 | return; | 611 | return; |
608 | 612 | ||
609 | __cfqq = cfq_prio_tree_lookup(cfqd, cfqq->ioprio, cfqq->next_rq->sector, | 613 | cfqq->p_root = &cfqd->prio_trees[cfqq->org_ioprio]; |
614 | __cfqq = cfq_prio_tree_lookup(cfqd, cfqq->p_root, cfqq->next_rq->sector, | ||
610 | &parent, &p); | 615 | &parent, &p); |
611 | BUG_ON(__cfqq); | 616 | if (!__cfqq) { |
612 | 617 | rb_link_node(&cfqq->p_node, parent, p); | |
613 | rb_link_node(&cfqq->p_node, parent, p); | 618 | rb_insert_color(&cfqq->p_node, cfqq->p_root); |
614 | rb_insert_color(&cfqq->p_node, root); | 619 | } else |
620 | cfqq->p_root = NULL; | ||
615 | } | 621 | } |
616 | 622 | ||
617 | /* | 623 | /* |
@@ -656,8 +662,10 @@ static void cfq_del_cfqq_rr(struct cfq_data *cfqd, struct cfq_queue *cfqq) | |||
656 | 662 | ||
657 | if (!RB_EMPTY_NODE(&cfqq->rb_node)) | 663 | if (!RB_EMPTY_NODE(&cfqq->rb_node)) |
658 | cfq_rb_erase(&cfqq->rb_node, &cfqd->service_tree); | 664 | cfq_rb_erase(&cfqq->rb_node, &cfqd->service_tree); |
659 | if (!RB_EMPTY_NODE(&cfqq->p_node)) | 665 | if (cfqq->p_root) { |
660 | rb_erase_init(&cfqq->p_node, &cfqd->prio_trees[cfqq->ioprio]); | 666 | rb_erase(&cfqq->p_node, cfqq->p_root); |
667 | cfqq->p_root = NULL; | ||
668 | } | ||
661 | 669 | ||
662 | BUG_ON(!cfqd->busy_queues); | 670 | BUG_ON(!cfqd->busy_queues); |
663 | cfqd->busy_queues--; | 671 | cfqd->busy_queues--; |
@@ -947,20 +955,24 @@ static inline sector_t cfq_dist_from_last(struct cfq_data *cfqd, | |||
947 | return cfqd->last_position - rq->sector; | 955 | return cfqd->last_position - rq->sector; |
948 | } | 956 | } |
949 | 957 | ||
958 | #define CIC_SEEK_THR 8 * 1024 | ||
959 | #define CIC_SEEKY(cic) ((cic)->seek_mean > CIC_SEEK_THR) | ||
960 | |||
950 | static inline int cfq_rq_close(struct cfq_data *cfqd, struct request *rq) | 961 | static inline int cfq_rq_close(struct cfq_data *cfqd, struct request *rq) |
951 | { | 962 | { |
952 | struct cfq_io_context *cic = cfqd->active_cic; | 963 | struct cfq_io_context *cic = cfqd->active_cic; |
964 | sector_t sdist = cic->seek_mean; | ||
953 | 965 | ||
954 | if (!sample_valid(cic->seek_samples)) | 966 | if (!sample_valid(cic->seek_samples)) |
955 | return 0; | 967 | sdist = CIC_SEEK_THR; |
956 | 968 | ||
957 | return cfq_dist_from_last(cfqd, rq) <= cic->seek_mean; | 969 | return cfq_dist_from_last(cfqd, rq) <= sdist; |
958 | } | 970 | } |
959 | 971 | ||
960 | static struct cfq_queue *cfqq_close(struct cfq_data *cfqd, | 972 | static struct cfq_queue *cfqq_close(struct cfq_data *cfqd, |
961 | struct cfq_queue *cur_cfqq) | 973 | struct cfq_queue *cur_cfqq) |
962 | { | 974 | { |
963 | struct rb_root *root = &cfqd->prio_trees[cur_cfqq->ioprio]; | 975 | struct rb_root *root = &cfqd->prio_trees[cur_cfqq->org_ioprio]; |
964 | struct rb_node *parent, *node; | 976 | struct rb_node *parent, *node; |
965 | struct cfq_queue *__cfqq; | 977 | struct cfq_queue *__cfqq; |
966 | sector_t sector = cfqd->last_position; | 978 | sector_t sector = cfqd->last_position; |
@@ -972,8 +984,7 @@ static struct cfq_queue *cfqq_close(struct cfq_data *cfqd, | |||
972 | * First, if we find a request starting at the end of the last | 984 | * First, if we find a request starting at the end of the last |
973 | * request, choose it. | 985 | * request, choose it. |
974 | */ | 986 | */ |
975 | __cfqq = cfq_prio_tree_lookup(cfqd, cur_cfqq->ioprio, | 987 | __cfqq = cfq_prio_tree_lookup(cfqd, root, sector, &parent, NULL); |
976 | sector, &parent, NULL); | ||
977 | if (__cfqq) | 988 | if (__cfqq) |
978 | return __cfqq; | 989 | return __cfqq; |
979 | 990 | ||
@@ -1039,9 +1050,6 @@ static struct cfq_queue *cfq_close_cooperator(struct cfq_data *cfqd, | |||
1039 | return cfqq; | 1050 | return cfqq; |
1040 | } | 1051 | } |
1041 | 1052 | ||
1042 | |||
1043 | #define CIC_SEEKY(cic) ((cic)->seek_mean > (8 * 1024)) | ||
1044 | |||
1045 | static void cfq_arm_slice_timer(struct cfq_data *cfqd) | 1053 | static void cfq_arm_slice_timer(struct cfq_data *cfqd) |
1046 | { | 1054 | { |
1047 | struct cfq_queue *cfqq = cfqd->active_queue; | 1055 | struct cfq_queue *cfqq = cfqd->active_queue; |
@@ -1908,7 +1916,9 @@ cfq_update_io_seektime(struct cfq_data *cfqd, struct cfq_io_context *cic, | |||
1908 | sector_t sdist; | 1916 | sector_t sdist; |
1909 | u64 total; | 1917 | u64 total; |
1910 | 1918 | ||
1911 | if (cic->last_request_pos < rq->sector) | 1919 | if (!cic->last_request_pos) |
1920 | sdist = 0; | ||
1921 | else if (cic->last_request_pos < rq->sector) | ||
1912 | sdist = rq->sector - cic->last_request_pos; | 1922 | sdist = rq->sector - cic->last_request_pos; |
1913 | else | 1923 | else |
1914 | sdist = cic->last_request_pos - rq->sector; | 1924 | sdist = cic->last_request_pos - rq->sector; |
@@ -2443,12 +2453,22 @@ static void cfq_exit_queue(struct elevator_queue *e) | |||
2443 | static void *cfq_init_queue(struct request_queue *q) | 2453 | static void *cfq_init_queue(struct request_queue *q) |
2444 | { | 2454 | { |
2445 | struct cfq_data *cfqd; | 2455 | struct cfq_data *cfqd; |
2456 | int i; | ||
2446 | 2457 | ||
2447 | cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node); | 2458 | cfqd = kmalloc_node(sizeof(*cfqd), GFP_KERNEL | __GFP_ZERO, q->node); |
2448 | if (!cfqd) | 2459 | if (!cfqd) |
2449 | return NULL; | 2460 | return NULL; |
2450 | 2461 | ||
2451 | cfqd->service_tree = CFQ_RB_ROOT; | 2462 | cfqd->service_tree = CFQ_RB_ROOT; |
2463 | |||
2464 | /* | ||
2465 | * Not strictly needed (since RB_ROOT just clears the node and we | ||
2466 | * zeroed cfqd on alloc), but better be safe in case someone decides | ||
2467 | * to add magic to the rb code | ||
2468 | */ | ||
2469 | for (i = 0; i < CFQ_PRIO_LISTS; i++) | ||
2470 | cfqd->prio_trees[i] = RB_ROOT; | ||
2471 | |||
2452 | INIT_LIST_HEAD(&cfqd->cic_list); | 2472 | INIT_LIST_HEAD(&cfqd->cic_list); |
2453 | 2473 | ||
2454 | cfqd->queue = q; | 2474 | cfqd->queue = q; |
diff --git a/block/genhd.c b/block/genhd.c index a9ec910974c1..1a4916e01732 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
@@ -98,7 +98,7 @@ void disk_part_iter_init(struct disk_part_iter *piter, struct gendisk *disk, | |||
98 | 98 | ||
99 | if (flags & DISK_PITER_REVERSE) | 99 | if (flags & DISK_PITER_REVERSE) |
100 | piter->idx = ptbl->len - 1; | 100 | piter->idx = ptbl->len - 1; |
101 | else if (flags & DISK_PITER_INCL_PART0) | 101 | else if (flags & (DISK_PITER_INCL_PART0 | DISK_PITER_INCL_EMPTY_PART0)) |
102 | piter->idx = 0; | 102 | piter->idx = 0; |
103 | else | 103 | else |
104 | piter->idx = 1; | 104 | piter->idx = 1; |
@@ -134,7 +134,8 @@ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter) | |||
134 | /* determine iteration parameters */ | 134 | /* determine iteration parameters */ |
135 | if (piter->flags & DISK_PITER_REVERSE) { | 135 | if (piter->flags & DISK_PITER_REVERSE) { |
136 | inc = -1; | 136 | inc = -1; |
137 | if (piter->flags & DISK_PITER_INCL_PART0) | 137 | if (piter->flags & (DISK_PITER_INCL_PART0 | |
138 | DISK_PITER_INCL_EMPTY_PART0)) | ||
138 | end = -1; | 139 | end = -1; |
139 | else | 140 | else |
140 | end = 0; | 141 | end = 0; |
@@ -150,7 +151,10 @@ struct hd_struct *disk_part_iter_next(struct disk_part_iter *piter) | |||
150 | part = rcu_dereference(ptbl->part[piter->idx]); | 151 | part = rcu_dereference(ptbl->part[piter->idx]); |
151 | if (!part) | 152 | if (!part) |
152 | continue; | 153 | continue; |
153 | if (!(piter->flags & DISK_PITER_INCL_EMPTY) && !part->nr_sects) | 154 | if (!part->nr_sects && |
155 | !(piter->flags & DISK_PITER_INCL_EMPTY) && | ||
156 | !(piter->flags & DISK_PITER_INCL_EMPTY_PART0 && | ||
157 | piter->idx == 0)) | ||
154 | continue; | 158 | continue; |
155 | 159 | ||
156 | get_device(part_to_dev(part)); | 160 | get_device(part_to_dev(part)); |
@@ -1011,7 +1015,7 @@ static int diskstats_show(struct seq_file *seqf, void *v) | |||
1011 | "\n\n"); | 1015 | "\n\n"); |
1012 | */ | 1016 | */ |
1013 | 1017 | ||
1014 | disk_part_iter_init(&piter, gp, DISK_PITER_INCL_PART0); | 1018 | disk_part_iter_init(&piter, gp, DISK_PITER_INCL_EMPTY_PART0); |
1015 | while ((hd = disk_part_iter_next(&piter))) { | 1019 | while ((hd = disk_part_iter_next(&piter))) { |
1016 | cpu = part_stat_lock(); | 1020 | cpu = part_stat_lock(); |
1017 | part_round_stats(cpu, hd); | 1021 | part_round_stats(cpu, hd); |
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 84b7f8709f41..82a0ca2f6729 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c | |||
@@ -290,6 +290,7 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk, | |||
290 | 290 | ||
291 | if (hdr->iovec_count) { | 291 | if (hdr->iovec_count) { |
292 | const int size = sizeof(struct sg_iovec) * hdr->iovec_count; | 292 | const int size = sizeof(struct sg_iovec) * hdr->iovec_count; |
293 | size_t iov_data_len; | ||
293 | struct sg_iovec *iov; | 294 | struct sg_iovec *iov; |
294 | 295 | ||
295 | iov = kmalloc(size, GFP_KERNEL); | 296 | iov = kmalloc(size, GFP_KERNEL); |
@@ -304,8 +305,18 @@ static int sg_io(struct request_queue *q, struct gendisk *bd_disk, | |||
304 | goto out; | 305 | goto out; |
305 | } | 306 | } |
306 | 307 | ||
308 | /* SG_IO howto says that the shorter of the two wins */ | ||
309 | iov_data_len = iov_length((struct iovec *)iov, | ||
310 | hdr->iovec_count); | ||
311 | if (hdr->dxfer_len < iov_data_len) { | ||
312 | hdr->iovec_count = iov_shorten((struct iovec *)iov, | ||
313 | hdr->iovec_count, | ||
314 | hdr->dxfer_len); | ||
315 | iov_data_len = hdr->dxfer_len; | ||
316 | } | ||
317 | |||
307 | ret = blk_rq_map_user_iov(q, rq, NULL, iov, hdr->iovec_count, | 318 | ret = blk_rq_map_user_iov(q, rq, NULL, iov, hdr->iovec_count, |
308 | hdr->dxfer_len, GFP_KERNEL); | 319 | iov_data_len, GFP_KERNEL); |
309 | kfree(iov); | 320 | kfree(iov); |
310 | } else if (hdr->dxfer_len) | 321 | } else if (hdr->dxfer_len) |
311 | ret = blk_rq_map_user(q, rq, NULL, hdr->dxferp, hdr->dxfer_len, | 322 | ret = blk_rq_map_user(q, rq, NULL, hdr->dxferp, hdr->dxfer_len, |