Commit 8d01eddf292dcd78b640418c80fb300532799cd4
Exists in
master
and in
7 other branches
Merge branch 'for-2.6.25' of git://git.kernel.dk/linux-2.6-block
* 'for-2.6.25' of git://git.kernel.dk/linux-2.6-block: block: implement drain buffers __bio_clone: don't calculate hw/phys segment counts block: allow queue dma_alignment of zero blktrace: Add blktrace ioctls to SCSI generic devices
Showing 8 changed files Side-by-side Diff
block/blktrace.c
... | ... | @@ -235,7 +235,7 @@ |
235 | 235 | kfree(bt); |
236 | 236 | } |
237 | 237 | |
238 | -static int blk_trace_remove(struct request_queue *q) | |
238 | +int blk_trace_remove(struct request_queue *q) | |
239 | 239 | { |
240 | 240 | struct blk_trace *bt; |
241 | 241 | |
... | ... | @@ -249,6 +249,7 @@ |
249 | 249 | |
250 | 250 | return 0; |
251 | 251 | } |
252 | +EXPORT_SYMBOL_GPL(blk_trace_remove); | |
252 | 253 | |
253 | 254 | static int blk_dropped_open(struct inode *inode, struct file *filp) |
254 | 255 | { |
255 | 256 | |
256 | 257 | |
... | ... | @@ -316,18 +317,17 @@ |
316 | 317 | /* |
317 | 318 | * Setup everything required to start tracing |
318 | 319 | */ |
319 | -int do_blk_trace_setup(struct request_queue *q, struct block_device *bdev, | |
320 | +int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev, | |
320 | 321 | struct blk_user_trace_setup *buts) |
321 | 322 | { |
322 | 323 | struct blk_trace *old_bt, *bt = NULL; |
323 | 324 | struct dentry *dir = NULL; |
324 | - char b[BDEVNAME_SIZE]; | |
325 | 325 | int ret, i; |
326 | 326 | |
327 | 327 | if (!buts->buf_size || !buts->buf_nr) |
328 | 328 | return -EINVAL; |
329 | 329 | |
330 | - strcpy(buts->name, bdevname(bdev, b)); | |
330 | + strcpy(buts->name, name); | |
331 | 331 | |
332 | 332 | /* |
333 | 333 | * some device names have larger paths - convert the slashes |
... | ... | @@ -352,7 +352,7 @@ |
352 | 352 | goto err; |
353 | 353 | |
354 | 354 | bt->dir = dir; |
355 | - bt->dev = bdev->bd_dev; | |
355 | + bt->dev = dev; | |
356 | 356 | atomic_set(&bt->dropped, 0); |
357 | 357 | |
358 | 358 | ret = -EIO; |
... | ... | @@ -399,8 +399,8 @@ |
399 | 399 | return ret; |
400 | 400 | } |
401 | 401 | |
402 | -static int blk_trace_setup(struct request_queue *q, struct block_device *bdev, | |
403 | - char __user *arg) | |
402 | +int blk_trace_setup(struct request_queue *q, char *name, dev_t dev, | |
403 | + char __user *arg) | |
404 | 404 | { |
405 | 405 | struct blk_user_trace_setup buts; |
406 | 406 | int ret; |
... | ... | @@ -409,7 +409,7 @@ |
409 | 409 | if (ret) |
410 | 410 | return -EFAULT; |
411 | 411 | |
412 | - ret = do_blk_trace_setup(q, bdev, &buts); | |
412 | + ret = do_blk_trace_setup(q, name, dev, &buts); | |
413 | 413 | if (ret) |
414 | 414 | return ret; |
415 | 415 | |
416 | 416 | |
... | ... | @@ -418,8 +418,9 @@ |
418 | 418 | |
419 | 419 | return 0; |
420 | 420 | } |
421 | +EXPORT_SYMBOL_GPL(blk_trace_setup); | |
421 | 422 | |
422 | -static int blk_trace_startstop(struct request_queue *q, int start) | |
423 | +int blk_trace_startstop(struct request_queue *q, int start) | |
423 | 424 | { |
424 | 425 | struct blk_trace *bt; |
425 | 426 | int ret; |
... | ... | @@ -452,6 +453,7 @@ |
452 | 453 | |
453 | 454 | return ret; |
454 | 455 | } |
456 | +EXPORT_SYMBOL_GPL(blk_trace_startstop); | |
455 | 457 | |
456 | 458 | /** |
457 | 459 | * blk_trace_ioctl: - handle the ioctls associated with tracing |
... | ... | @@ -464,6 +466,7 @@ |
464 | 466 | { |
465 | 467 | struct request_queue *q; |
466 | 468 | int ret, start = 0; |
469 | + char b[BDEVNAME_SIZE]; | |
467 | 470 | |
468 | 471 | q = bdev_get_queue(bdev); |
469 | 472 | if (!q) |
... | ... | @@ -473,7 +476,8 @@ |
473 | 476 | |
474 | 477 | switch (cmd) { |
475 | 478 | case BLKTRACESETUP: |
476 | - ret = blk_trace_setup(q, bdev, arg); | |
479 | + strcpy(b, bdevname(bdev, b)); | |
480 | + ret = blk_trace_setup(q, b, bdev->bd_dev, arg); | |
477 | 481 | break; |
478 | 482 | case BLKTRACESTART: |
479 | 483 | start = 1; |
block/compat_ioctl.c
... | ... | @@ -545,6 +545,7 @@ |
545 | 545 | struct blk_user_trace_setup buts; |
546 | 546 | struct compat_blk_user_trace_setup cbuts; |
547 | 547 | struct request_queue *q; |
548 | + char b[BDEVNAME_SIZE]; | |
548 | 549 | int ret; |
549 | 550 | |
550 | 551 | q = bdev_get_queue(bdev); |
... | ... | @@ -554,6 +555,8 @@ |
554 | 555 | if (copy_from_user(&cbuts, arg, sizeof(cbuts))) |
555 | 556 | return -EFAULT; |
556 | 557 | |
558 | + strcpy(b, bdevname(bdev, b)); | |
559 | + | |
557 | 560 | buts = (struct blk_user_trace_setup) { |
558 | 561 | .act_mask = cbuts.act_mask, |
559 | 562 | .buf_size = cbuts.buf_size, |
... | ... | @@ -565,7 +568,7 @@ |
565 | 568 | memcpy(&buts.name, &cbuts.name, 32); |
566 | 569 | |
567 | 570 | mutex_lock(&bdev->bd_mutex); |
568 | - ret = do_blk_trace_setup(q, bdev, &buts); | |
571 | + ret = do_blk_trace_setup(q, b, bdev->bd_dev, &buts); | |
569 | 572 | mutex_unlock(&bdev->bd_mutex); |
570 | 573 | if (ret) |
571 | 574 | return ret; |
block/elevator.c
... | ... | @@ -741,9 +741,23 @@ |
741 | 741 | q->boundary_rq = NULL; |
742 | 742 | } |
743 | 743 | |
744 | - if ((rq->cmd_flags & REQ_DONTPREP) || !q->prep_rq_fn) | |
744 | + if (rq->cmd_flags & REQ_DONTPREP) | |
745 | 745 | break; |
746 | 746 | |
747 | + if (q->dma_drain_size && rq->data_len) { | |
748 | + /* | |
749 | + * make sure space for the drain appears we | |
750 | + * know we can do this because max_hw_segments | |
751 | + * has been adjusted to be one fewer than the | |
752 | + * device can handle | |
753 | + */ | |
754 | + rq->nr_phys_segments++; | |
755 | + rq->nr_hw_segments++; | |
756 | + } | |
757 | + | |
758 | + if (!q->prep_rq_fn) | |
759 | + break; | |
760 | + | |
747 | 761 | ret = q->prep_rq_fn(q, rq); |
748 | 762 | if (ret == BLKPREP_OK) { |
749 | 763 | break; |
... | ... | @@ -754,6 +768,16 @@ |
754 | 768 | * avoid resource deadlock. REQ_STARTED will |
755 | 769 | * prevent other fs requests from passing this one. |
756 | 770 | */ |
771 | + if (q->dma_drain_size && rq->data_len && | |
772 | + !(rq->cmd_flags & REQ_DONTPREP)) { | |
773 | + /* | |
774 | + * remove the space for the drain we added | |
775 | + * so that we don't add it again | |
776 | + */ | |
777 | + --rq->nr_phys_segments; | |
778 | + --rq->nr_hw_segments; | |
779 | + } | |
780 | + | |
757 | 781 | rq = NULL; |
758 | 782 | break; |
759 | 783 | } else if (ret == BLKPREP_KILL) { |
block/ll_rw_blk.c
... | ... | @@ -721,6 +721,45 @@ |
721 | 721 | EXPORT_SYMBOL(blk_queue_stack_limits); |
722 | 722 | |
723 | 723 | /** |
724 | + * blk_queue_dma_drain - Set up a drain buffer for excess dma. | |
725 | + * | |
726 | + * @q: the request queue for the device | |
727 | + * @buf: physically contiguous buffer | |
728 | + * @size: size of the buffer in bytes | |
729 | + * | |
730 | + * Some devices have excess DMA problems and can't simply discard (or | |
731 | + * zero fill) the unwanted piece of the transfer. They have to have a | |
732 | + * real area of memory to transfer it into. The use case for this is | |
733 | + * ATAPI devices in DMA mode. If the packet command causes a transfer | |
734 | + * bigger than the transfer size some HBAs will lock up if there | |
735 | + * aren't DMA elements to contain the excess transfer. What this API | |
736 | + * does is adjust the queue so that the buf is always appended | |
737 | + * silently to the scatterlist. | |
738 | + * | |
739 | + * Note: This routine adjusts max_hw_segments to make room for | |
740 | + * appending the drain buffer. If you call | |
741 | + * blk_queue_max_hw_segments() or blk_queue_max_phys_segments() after | |
742 | + * calling this routine, you must set the limit to one fewer than your | |
743 | + * device can support otherwise there won't be room for the drain | |
744 | + * buffer. | |
745 | + */ | |
746 | +int blk_queue_dma_drain(struct request_queue *q, void *buf, | |
747 | + unsigned int size) | |
748 | +{ | |
749 | + if (q->max_hw_segments < 2 || q->max_phys_segments < 2) | |
750 | + return -EINVAL; | |
751 | + /* make room for appending the drain */ | |
752 | + --q->max_hw_segments; | |
753 | + --q->max_phys_segments; | |
754 | + q->dma_drain_buffer = buf; | |
755 | + q->dma_drain_size = size; | |
756 | + | |
757 | + return 0; | |
758 | +} | |
759 | + | |
760 | +EXPORT_SYMBOL_GPL(blk_queue_dma_drain); | |
761 | + | |
762 | +/** | |
724 | 763 | * blk_queue_segment_boundary - set boundary rules for segment merging |
725 | 764 | * @q: the request queue for the device |
726 | 765 | * @mask: the memory boundary mask |
... | ... | @@ -1373,6 +1412,16 @@ |
1373 | 1412 | } |
1374 | 1413 | bvprv = bvec; |
1375 | 1414 | } /* segments in rq */ |
1415 | + | |
1416 | + if (q->dma_drain_size) { | |
1417 | + sg->page_link &= ~0x02; | |
1418 | + sg = sg_next(sg); | |
1419 | + sg_set_page(sg, virt_to_page(q->dma_drain_buffer), | |
1420 | + q->dma_drain_size, | |
1421 | + ((unsigned long)q->dma_drain_buffer) & | |
1422 | + (PAGE_SIZE - 1)); | |
1423 | + nsegs++; | |
1424 | + } | |
1376 | 1425 | |
1377 | 1426 | if (sg) |
1378 | 1427 | sg_mark_end(sg); |
drivers/scsi/sg.c
... | ... | @@ -48,6 +48,7 @@ |
48 | 48 | #include <linux/blkdev.h> |
49 | 49 | #include <linux/delay.h> |
50 | 50 | #include <linux/scatterlist.h> |
51 | +#include <linux/blktrace_api.h> | |
51 | 52 | |
52 | 53 | #include "scsi.h" |
53 | 54 | #include <scsi/scsi_dbg.h> |
... | ... | @@ -1067,6 +1068,17 @@ |
1067 | 1068 | case BLKSECTGET: |
1068 | 1069 | return put_user(sdp->device->request_queue->max_sectors * 512, |
1069 | 1070 | ip); |
1071 | + case BLKTRACESETUP: | |
1072 | + return blk_trace_setup(sdp->device->request_queue, | |
1073 | + sdp->disk->disk_name, | |
1074 | + sdp->device->sdev_gendev.devt, | |
1075 | + (char *)arg); | |
1076 | + case BLKTRACESTART: | |
1077 | + return blk_trace_startstop(sdp->device->request_queue, 1); | |
1078 | + case BLKTRACESTOP: | |
1079 | + return blk_trace_startstop(sdp->device->request_queue, 0); | |
1080 | + case BLKTRACETEARDOWN: | |
1081 | + return blk_trace_remove(sdp->device->request_queue); | |
1070 | 1082 | default: |
1071 | 1083 | if (read_only) |
1072 | 1084 | return -EPERM; /* don't know so take safe approach */ |
fs/bio.c
... | ... | @@ -248,11 +248,13 @@ |
248 | 248 | */ |
249 | 249 | void __bio_clone(struct bio *bio, struct bio *bio_src) |
250 | 250 | { |
251 | - struct request_queue *q = bdev_get_queue(bio_src->bi_bdev); | |
252 | - | |
253 | 251 | memcpy(bio->bi_io_vec, bio_src->bi_io_vec, |
254 | 252 | bio_src->bi_max_vecs * sizeof(struct bio_vec)); |
255 | 253 | |
254 | + /* | |
255 | + * most users will be overriding ->bi_bdev with a new target, | |
256 | + * so we don't set nor calculate new physical/hw segment counts here | |
257 | + */ | |
256 | 258 | bio->bi_sector = bio_src->bi_sector; |
257 | 259 | bio->bi_bdev = bio_src->bi_bdev; |
258 | 260 | bio->bi_flags |= 1 << BIO_CLONED; |
... | ... | @@ -260,8 +262,6 @@ |
260 | 262 | bio->bi_vcnt = bio_src->bi_vcnt; |
261 | 263 | bio->bi_size = bio_src->bi_size; |
262 | 264 | bio->bi_idx = bio_src->bi_idx; |
263 | - bio_phys_segments(q, bio); | |
264 | - bio_hw_segments(q, bio); | |
265 | 265 | } |
266 | 266 | |
267 | 267 | /** |
include/linux/blkdev.h
... | ... | @@ -356,6 +356,8 @@ |
356 | 356 | unsigned int max_segment_size; |
357 | 357 | |
358 | 358 | unsigned long seg_boundary_mask; |
359 | + void *dma_drain_buffer; | |
360 | + unsigned int dma_drain_size; | |
359 | 361 | unsigned int dma_alignment; |
360 | 362 | |
361 | 363 | struct blk_queue_tag *queue_tags; |
... | ... | @@ -692,6 +694,8 @@ |
692 | 694 | extern void blk_queue_max_segment_size(struct request_queue *, unsigned int); |
693 | 695 | extern void blk_queue_hardsect_size(struct request_queue *, unsigned short); |
694 | 696 | extern void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b); |
697 | +extern int blk_queue_dma_drain(struct request_queue *q, void *buf, | |
698 | + unsigned int size); | |
695 | 699 | extern void blk_queue_segment_boundary(struct request_queue *, unsigned long); |
696 | 700 | extern void blk_queue_prep_rq(struct request_queue *, prep_rq_fn *pfn); |
697 | 701 | extern void blk_queue_merge_bvec(struct request_queue *, merge_bvec_fn *); |
... | ... | @@ -768,12 +772,7 @@ |
768 | 772 | |
769 | 773 | static inline int queue_dma_alignment(struct request_queue *q) |
770 | 774 | { |
771 | - int retval = 511; | |
772 | - | |
773 | - if (q && q->dma_alignment) | |
774 | - retval = q->dma_alignment; | |
775 | - | |
776 | - return retval; | |
775 | + return q ? q->dma_alignment : 511; | |
777 | 776 | } |
778 | 777 | |
779 | 778 | /* assumes size > 256 */ |
include/linux/blktrace_api.h
... | ... | @@ -148,7 +148,7 @@ |
148 | 148 | extern void blk_trace_shutdown(struct request_queue *); |
149 | 149 | extern void __blk_add_trace(struct blk_trace *, sector_t, int, int, u32, int, int, void *); |
150 | 150 | extern int do_blk_trace_setup(struct request_queue *q, |
151 | - struct block_device *bdev, struct blk_user_trace_setup *buts); | |
151 | + char *name, dev_t dev, struct blk_user_trace_setup *buts); | |
152 | 152 | |
153 | 153 | |
154 | 154 | /** |
... | ... | @@ -282,6 +282,11 @@ |
282 | 282 | __blk_add_trace(bt, from, bio->bi_size, bio->bi_rw, BLK_TA_REMAP, !bio_flagged(bio, BIO_UPTODATE), sizeof(r), &r); |
283 | 283 | } |
284 | 284 | |
285 | +extern int blk_trace_setup(request_queue_t *q, char *name, dev_t dev, | |
286 | + char __user *arg); | |
287 | +extern int blk_trace_startstop(request_queue_t *q, int start); | |
288 | +extern int blk_trace_remove(request_queue_t *q); | |
289 | + | |
285 | 290 | #else /* !CONFIG_BLK_DEV_IO_TRACE */ |
286 | 291 | #define blk_trace_ioctl(bdev, cmd, arg) (-ENOTTY) |
287 | 292 | #define blk_trace_shutdown(q) do { } while (0) |
... | ... | @@ -290,7 +295,10 @@ |
290 | 295 | #define blk_add_trace_generic(q, rq, rw, what) do { } while (0) |
291 | 296 | #define blk_add_trace_pdu_int(q, what, bio, pdu) do { } while (0) |
292 | 297 | #define blk_add_trace_remap(q, bio, dev, f, t) do {} while (0) |
293 | -#define do_blk_trace_setup(q, bdev, buts) (-ENOTTY) | |
298 | +#define do_blk_trace_setup(q, name, dev, buts) (-ENOTTY) | |
299 | +#define blk_trace_setup(q, name, dev, arg) (-ENOTTY) | |
300 | +#define blk_trace_startstop(q, start) (-ENOTTY) | |
301 | +#define blk_trace_remove(q) (-ENOTTY) | |
294 | 302 | #endif /* CONFIG_BLK_DEV_IO_TRACE */ |
295 | 303 | #endif /* __KERNEL__ */ |
296 | 304 | #endif |