aboutsummaryrefslogtreecommitdiffstats
path: root/block/blk-barrier.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2008-10-14 20:31:54 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2008-10-14 20:31:54 -0400
commit6dc6472581f693b5fc95aebedf67b4960fb85cf0 (patch)
tree06a5a9a08519950575505273eabced331ed51405 /block/blk-barrier.c
parentee673eaa72d8d185012b1027a05e25aba18c267f (diff)
parent8acd3a60bcca17c6d89c73cee3ad6057eb83ba1e (diff)
Merge commit 'origin'
Manual fixup of conflicts on: arch/powerpc/include/asm/dcr-regs.h drivers/net/ibm_newemac/core.h
Diffstat (limited to 'block/blk-barrier.c')
-rw-r--r--block/blk-barrier.c72
1 files changed, 71 insertions, 1 deletions
diff --git a/block/blk-barrier.c b/block/blk-barrier.c
index a09ead19f9c5..5c99ff8d2db8 100644
--- a/block/blk-barrier.c
+++ b/block/blk-barrier.c
@@ -293,7 +293,7 @@ int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector)
293 bio->bi_end_io = bio_end_empty_barrier; 293 bio->bi_end_io = bio_end_empty_barrier;
294 bio->bi_private = &wait; 294 bio->bi_private = &wait;
295 bio->bi_bdev = bdev; 295 bio->bi_bdev = bdev;
296 submit_bio(1 << BIO_RW_BARRIER, bio); 296 submit_bio(WRITE_BARRIER, bio);
297 297
298 wait_for_completion(&wait); 298 wait_for_completion(&wait);
299 299
@@ -315,3 +315,73 @@ int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector)
315 return ret; 315 return ret;
316} 316}
317EXPORT_SYMBOL(blkdev_issue_flush); 317EXPORT_SYMBOL(blkdev_issue_flush);
318
319static void blkdev_discard_end_io(struct bio *bio, int err)
320{
321 if (err) {
322 if (err == -EOPNOTSUPP)
323 set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
324 clear_bit(BIO_UPTODATE, &bio->bi_flags);
325 }
326
327 bio_put(bio);
328}
329
330/**
331 * blkdev_issue_discard - queue a discard
332 * @bdev: blockdev to issue discard for
333 * @sector: start sector
334 * @nr_sects: number of sectors to discard
335 * @gfp_mask: memory allocation flags (for bio_alloc)
336 *
337 * Description:
338 * Issue a discard request for the sectors in question. Does not wait.
339 */
340int blkdev_issue_discard(struct block_device *bdev,
341 sector_t sector, sector_t nr_sects, gfp_t gfp_mask)
342{
343 struct request_queue *q;
344 struct bio *bio;
345 int ret = 0;
346
347 if (bdev->bd_disk == NULL)
348 return -ENXIO;
349
350 q = bdev_get_queue(bdev);
351 if (!q)
352 return -ENXIO;
353
354 if (!q->prepare_discard_fn)
355 return -EOPNOTSUPP;
356
357 while (nr_sects && !ret) {
358 bio = bio_alloc(gfp_mask, 0);
359 if (!bio)
360 return -ENOMEM;
361
362 bio->bi_end_io = blkdev_discard_end_io;
363 bio->bi_bdev = bdev;
364
365 bio->bi_sector = sector;
366
367 if (nr_sects > q->max_hw_sectors) {
368 bio->bi_size = q->max_hw_sectors << 9;
369 nr_sects -= q->max_hw_sectors;
370 sector += q->max_hw_sectors;
371 } else {
372 bio->bi_size = nr_sects << 9;
373 nr_sects = 0;
374 }
375 bio_get(bio);
376 submit_bio(DISCARD_BARRIER, bio);
377
378 /* Check if it failed immediately */
379 if (bio_flagged(bio, BIO_EOPNOTSUPP))
380 ret = -EOPNOTSUPP;
381 else if (!bio_flagged(bio, BIO_UPTODATE))
382 ret = -EIO;
383 bio_put(bio);
384 }
385 return ret;
386}
387EXPORT_SYMBOL(blkdev_issue_discard);