diff options
author | Martin K. Petersen <martin.petersen@oracle.com> | 2012-09-18 12:19:27 -0400 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2012-09-20 08:31:45 -0400 |
commit | 4363ac7c13a9a4b763c6e8d9fdbfc2468f3b8ca4 (patch) | |
tree | 010b05699eb9544b9cdfe5e1b3affdaea80132e7 /block/blk-lib.c | |
parent | f31dc1cd490539e2b62a126bc4dc2495b165d772 (diff) |
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.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/block/blk-lib.c b/block/blk-lib.c index 19cc761cacb2..a062543c58ac 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, | |||
130 | EXPORT_SYMBOL(blkdev_issue_discard); | 130 | EXPORT_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 | */ | ||
143 | int 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 | } | ||
204 | EXPORT_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 |