Commit 8d01eddf292dcd78b640418c80fb300532799cd4

Authored by Linus Torvalds

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

... ... @@ -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;
... ... @@ -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) {
... ... @@ -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);
... ... @@ -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 */
... ... @@ -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