aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin K. Petersen2012-09-18 11:19:27 -0500
committerJens Axboe2012-09-20 07:31:45 -0500
commit4363ac7c13a9a4b763c6e8d9fdbfc2468f3b8ca4 (patch)
tree010b05699eb9544b9cdfe5e1b3affdaea80132e7 /block/blk-lib.c
parentf31dc1cd490539e2b62a126bc4dc2495b165d772 (diff)
downloadkernel-common-4363ac7c13a9a4b763c6e8d9fdbfc2468f3b8ca4.tar.gz
kernel-common-4363ac7c13a9a4b763c6e8d9fdbfc2468f3b8ca4.tar.xz
kernel-common-4363ac7c13a9a4b763c6e8d9fdbfc2468f3b8ca4.zip
block: Implement support for WRITE SAME
The WRITE SAME command supported on some SCSI devices allows the same block to be efficiently replicated throughout a block range. Only a single logical block is transferred from the host and the storage device writes the same data to all blocks described by the I/O. This patch implements support for WRITE SAME in the block layer. The blkdev_issue_write_same() function can be used by filesystems and block drivers to replicate a buffer across a block range. This can be used to efficiently initialize software RAID devices, etc. Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> Acked-by: Mike Snitzer <snitzer@redhat.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'block/blk-lib.c')
-rw-r--r--block/blk-lib.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/block/blk-lib.c b/block/blk-lib.c
index 19cc761cacb..a062543c58a 100644
--- a/block/blk-lib.c
+++ b/block/blk-lib.c
@@ -130,6 +130,80 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
130EXPORT_SYMBOL(blkdev_issue_discard); 130EXPORT_SYMBOL(blkdev_issue_discard);
131 131
132/** 132/**
133 * blkdev_issue_write_same - queue a write same operation
134 * @bdev: target blockdev
135 * @sector: start sector
136 * @nr_sects: number of sectors to write
137 * @gfp_mask: memory allocation flags (for bio_alloc)
138 * @page: page containing data to write
139 *
140 * Description:
141 * Issue a write same request for the sectors in question.
142 */
143int blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
144 sector_t nr_sects, gfp_t gfp_mask,
145 struct page *page)
146{
147 DECLARE_COMPLETION_ONSTACK(wait);
148 struct request_queue *q = bdev_get_queue(bdev);
149 unsigned int max_write_same_sectors;
150 struct bio_batch bb;
151 struct bio *bio;
152 int ret = 0;
153
154 if (!q)
155 return -ENXIO;
156
157 max_write_same_sectors = q->limits.max_write_same_sectors;
158
159 if (max_write_same_sectors == 0)
160 return -EOPNOTSUPP;
161
162 atomic_set(&bb.done, 1);
163 bb.flags = 1 << BIO_UPTODATE;
164 bb.wait = &wait;
165
166 while (nr_sects) {
167 bio = bio_alloc(gfp_mask, 1);
168 if (!bio) {
169 ret = -ENOMEM;
170 break;
171 }
172
173 bio->bi_sector = sector;
174 bio->bi_end_io = bio_batch_end_io;
175 bio->bi_bdev = bdev;
176 bio->bi_private = &bb;
177 bio->bi_vcnt = 1;
178 bio->bi_io_vec->bv_page = page;
179 bio->bi_io_vec->bv_offset = 0;
180 bio->bi_io_vec->bv_len = bdev_logical_block_size(bdev);
181
182 if (nr_sects > max_write_same_sectors) {
183 bio->bi_size = max_write_same_sectors << 9;
184 nr_sects -= max_write_same_sectors;
185 sector += max_write_same_sectors;
186 } else {
187 bio->bi_size = nr_sects << 9;
188 nr_sects = 0;
189 }
190
191 atomic_inc(&bb.done);
192 submit_bio(REQ_WRITE | REQ_WRITE_SAME, bio);
193 }
194
195 /* Wait for bios in-flight */
196 if (!atomic_dec_and_test(&bb.done))
197 wait_for_completion(&wait);
198
199 if (!test_bit(BIO_UPTODATE, &bb.flags))
200 ret = -ENOTSUPP;
201
202 return ret;
203}
204EXPORT_SYMBOL(blkdev_issue_write_same);
205
206/**
133 * blkdev_issue_zeroout - generate number of zero filed write bios 207 * blkdev_issue_zeroout - generate number of zero filed write bios
134 * @bdev: blockdev to issue 208 * @bdev: blockdev to issue
135 * @sector: start sector 209 * @sector: start sector