blk-integrity.c 12 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * blk-integrity.c - Block layer data integrity extensions
 *
 * Copyright (C) 2007, 2008 Oracle Corporation
 * Written by: Martin K. Petersen <martin.petersen@oracle.com>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version
 * 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; see the file COPYING.  If not, write to
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
 * USA.
 *
 */

#include <linux/blkdev.h>
24
#include <linux/backing-dev.h>
25 26 27
#include <linux/mempool.h>
#include <linux/bio.h>
#include <linux/scatterlist.h>
28
#include <linux/export.h>
29
#include <linux/slab.h>
30 31 32 33 34

#include "blk.h"

/**
 * blk_rq_count_integrity_sg - Count number of integrity scatterlist elements
35 36
 * @q:		request queue
 * @bio:	bio with integrity metadata attached
37 38
 *
 * Description: Returns the number of elements required in a
39
 * scatterlist corresponding to the integrity metadata in a bio.
40
 */
41
int blk_rq_count_integrity_sg(struct request_queue *q, struct bio *bio)
42
{
43
	struct bio_vec iv, ivprv = { NULL };
44 45
	unsigned int segments = 0;
	unsigned int seg_size = 0;
46 47
	struct bvec_iter iter;
	int prev = 0;
48

49
	bio_for_each_integrity_vec(iv, bio, iter) {
50

51
		if (prev) {
52
			if (!biovec_phys_mergeable(q, &ivprv, &iv))
53
				goto new_segment;
54
			if (seg_size + iv.bv_len > queue_max_segment_size(q))
55
				goto new_segment;
56

57
			seg_size += iv.bv_len;
58 59
		} else {
new_segment:
60
			segments++;
61
			seg_size = iv.bv_len;
62
		}
63

64
		prev = 1;
65 66 67 68 69 70 71 72 73
		ivprv = iv;
	}

	return segments;
}
EXPORT_SYMBOL(blk_rq_count_integrity_sg);

/**
 * blk_rq_map_integrity_sg - Map integrity metadata into a scatterlist
74 75
 * @q:		request queue
 * @bio:	bio with integrity metadata attached
76 77 78 79 80 81
 * @sglist:	target scatterlist
 *
 * Description: Map the integrity vectors in request into a
 * scatterlist.  The scatterlist must be big enough to hold all
 * elements.  I.e. sized using blk_rq_count_integrity_sg().
 */
82 83
int blk_rq_map_integrity_sg(struct request_queue *q, struct bio *bio,
			    struct scatterlist *sglist)
84
{
85
	struct bio_vec iv, ivprv = { NULL };
86 87
	struct scatterlist *sg = NULL;
	unsigned int segments = 0;
88 89
	struct bvec_iter iter;
	int prev = 0;
90

91
	bio_for_each_integrity_vec(iv, bio, iter) {
92

93
		if (prev) {
94
			if (!biovec_phys_mergeable(q, &ivprv, &iv))
95
				goto new_segment;
96
			if (sg->length + iv.bv_len > queue_max_segment_size(q))
97 98
				goto new_segment;

99
			sg->length += iv.bv_len;
100 101 102 103 104
		} else {
new_segment:
			if (!sg)
				sg = sglist;
			else {
105
				sg_unmark_end(sg);
106 107 108
				sg = sg_next(sg);
			}

109
			sg_set_page(sg, iv.bv_page, iv.bv_len, iv.bv_offset);
110 111 112
			segments++;
		}

113
		prev = 1;
114 115 116 117 118 119 120 121 122 123 124
		ivprv = iv;
	}

	if (sg)
		sg_mark_end(sg);

	return segments;
}
EXPORT_SYMBOL(blk_rq_map_integrity_sg);

/**
125 126 127
 * blk_integrity_compare - Compare integrity profile of two disks
 * @gd1:	Disk to compare
 * @gd2:	Disk to compare
128 129 130 131
 *
 * Description: Meta-devices like DM and MD need to verify that all
 * sub-devices use the same integrity format before advertising to
 * upper layers that they can send/receive integrity metadata.  This
132
 * function can be used to check whether two gendisk devices have
133 134
 * compatible integrity formats.
 */
135
int blk_integrity_compare(struct gendisk *gd1, struct gendisk *gd2)
136
{
137 138
	struct blk_integrity *b1 = &gd1->queue->integrity;
	struct blk_integrity *b2 = &gd2->queue->integrity;
139

140
	if (!b1->profile && !b2->profile)
141
		return 0;
142

143
	if (!b1->profile || !b2->profile)
144
		return -1;
145

146
	if (b1->interval_exp != b2->interval_exp) {
147 148
		pr_err("%s: %s/%s protection interval %u != %u\n",
		       __func__, gd1->disk_name, gd2->disk_name,
149
		       1 << b1->interval_exp, 1 << b2->interval_exp);
150 151 152 153
		return -1;
	}

	if (b1->tuple_size != b2->tuple_size) {
154
		pr_err("%s: %s/%s tuple sz %u != %u\n", __func__,
155
		       gd1->disk_name, gd2->disk_name,
156 157 158 159 160
		       b1->tuple_size, b2->tuple_size);
		return -1;
	}

	if (b1->tag_size && b2->tag_size && (b1->tag_size != b2->tag_size)) {
161
		pr_err("%s: %s/%s tag sz %u != %u\n", __func__,
162
		       gd1->disk_name, gd2->disk_name,
163 164 165 166
		       b1->tag_size, b2->tag_size);
		return -1;
	}

167
	if (b1->profile != b2->profile) {
168
		pr_err("%s: %s/%s type %s != %s\n", __func__,
169
		       gd1->disk_name, gd2->disk_name,
170
		       b1->profile->name, b2->profile->name);
171 172 173 174 175 176 177
		return -1;
	}

	return 0;
}
EXPORT_SYMBOL(blk_integrity_compare);

178 179
bool blk_integrity_merge_rq(struct request_queue *q, struct request *req,
			    struct request *next)
180
{
181 182 183 184 185 186 187 188 189
	if (blk_integrity_rq(req) == 0 && blk_integrity_rq(next) == 0)
		return true;

	if (blk_integrity_rq(req) == 0 || blk_integrity_rq(next) == 0)
		return false;

	if (bio_integrity(req->bio)->bip_flags !=
	    bio_integrity(next->bio)->bip_flags)
		return false;
190 191 192

	if (req->nr_integrity_segments + next->nr_integrity_segments >
	    q->limits.max_integrity_segments)
193
		return false;
194

195 196 197
	if (integrity_req_gap_back_merge(req, next->bio))
		return false;

198
	return true;
199 200 201
}
EXPORT_SYMBOL(blk_integrity_merge_rq);

202 203
bool blk_integrity_merge_bio(struct request_queue *q, struct request *req,
			     struct bio *bio)
204 205 206 207
{
	int nr_integrity_segs;
	struct bio *next = bio->bi_next;

208 209 210 211 212 213 214 215 216
	if (blk_integrity_rq(req) == 0 && bio_integrity(bio) == NULL)
		return true;

	if (blk_integrity_rq(req) == 0 || bio_integrity(bio) == NULL)
		return false;

	if (bio_integrity(req->bio)->bip_flags != bio_integrity(bio)->bip_flags)
		return false;

217 218 219 220 221 222
	bio->bi_next = NULL;
	nr_integrity_segs = blk_rq_count_integrity_sg(q, bio);
	bio->bi_next = next;

	if (req->nr_integrity_segments + nr_integrity_segs >
	    q->limits.max_integrity_segments)
223
		return false;
224 225 226

	req->nr_integrity_segments += nr_integrity_segs;

227
	return true;
228 229 230
}
EXPORT_SYMBOL(blk_integrity_merge_bio);

231 232 233 234 235 236 237 238 239
struct integrity_sysfs_entry {
	struct attribute attr;
	ssize_t (*show)(struct blk_integrity *, char *);
	ssize_t (*store)(struct blk_integrity *, const char *, size_t);
};

static ssize_t integrity_attr_show(struct kobject *kobj, struct attribute *attr,
				   char *page)
{
240
	struct gendisk *disk = container_of(kobj, struct gendisk, integrity_kobj);
241
	struct blk_integrity *bi = &disk->queue->integrity;
242 243 244 245 246 247
	struct integrity_sysfs_entry *entry =
		container_of(attr, struct integrity_sysfs_entry, attr);

	return entry->show(bi, page);
}

248 249 250
static ssize_t integrity_attr_store(struct kobject *kobj,
				    struct attribute *attr, const char *page,
				    size_t count)
251
{
252
	struct gendisk *disk = container_of(kobj, struct gendisk, integrity_kobj);
253
	struct blk_integrity *bi = &disk->queue->integrity;
254 255 256 257 258 259 260 261 262 263 264 265
	struct integrity_sysfs_entry *entry =
		container_of(attr, struct integrity_sysfs_entry, attr);
	ssize_t ret = 0;

	if (entry->store)
		ret = entry->store(bi, page, count);

	return ret;
}

static ssize_t integrity_format_show(struct blk_integrity *bi, char *page)
{
266
	if (bi->profile && bi->profile->name)
267
		return sprintf(page, "%s\n", bi->profile->name);
268 269 270 271 272 273
	else
		return sprintf(page, "none\n");
}

static ssize_t integrity_tag_size_show(struct blk_integrity *bi, char *page)
{
274
	return sprintf(page, "%u\n", bi->tag_size);
275 276
}

277 278
static ssize_t integrity_interval_show(struct blk_integrity *bi, char *page)
{
279 280
	return sprintf(page, "%u\n",
		       bi->interval_exp ? 1 << bi->interval_exp : 0);
281 282
}

283 284
static ssize_t integrity_verify_store(struct blk_integrity *bi,
				      const char *page, size_t count)
285 286 287 288 289
{
	char *p = (char *) page;
	unsigned long val = simple_strtoul(p, &p, 10);

	if (val)
290
		bi->flags |= BLK_INTEGRITY_VERIFY;
291
	else
292
		bi->flags &= ~BLK_INTEGRITY_VERIFY;
293 294 295 296

	return count;
}

297
static ssize_t integrity_verify_show(struct blk_integrity *bi, char *page)
298
{
299
	return sprintf(page, "%d\n", (bi->flags & BLK_INTEGRITY_VERIFY) != 0);
300 301
}

302 303
static ssize_t integrity_generate_store(struct blk_integrity *bi,
					const char *page, size_t count)
304 305 306 307 308
{
	char *p = (char *) page;
	unsigned long val = simple_strtoul(p, &p, 10);

	if (val)
309
		bi->flags |= BLK_INTEGRITY_GENERATE;
310
	else
311
		bi->flags &= ~BLK_INTEGRITY_GENERATE;
312 313 314 315

	return count;
}

316
static ssize_t integrity_generate_show(struct blk_integrity *bi, char *page)
317
{
318
	return sprintf(page, "%d\n", (bi->flags & BLK_INTEGRITY_GENERATE) != 0);
319 320
}

321 322 323 324 325 326
static ssize_t integrity_device_show(struct blk_integrity *bi, char *page)
{
	return sprintf(page, "%u\n",
		       (bi->flags & BLK_INTEGRITY_DEVICE_CAPABLE) != 0);
}

327
static struct integrity_sysfs_entry integrity_format_entry = {
328
	.attr = { .name = "format", .mode = 0444 },
329 330 331 332
	.show = integrity_format_show,
};

static struct integrity_sysfs_entry integrity_tag_size_entry = {
333
	.attr = { .name = "tag_size", .mode = 0444 },
334 335 336
	.show = integrity_tag_size_show,
};

337
static struct integrity_sysfs_entry integrity_interval_entry = {
338
	.attr = { .name = "protection_interval_bytes", .mode = 0444 },
339 340 341
	.show = integrity_interval_show,
};

342
static struct integrity_sysfs_entry integrity_verify_entry = {
343
	.attr = { .name = "read_verify", .mode = 0644 },
344 345
	.show = integrity_verify_show,
	.store = integrity_verify_store,
346 347
};

348
static struct integrity_sysfs_entry integrity_generate_entry = {
349
	.attr = { .name = "write_generate", .mode = 0644 },
350 351
	.show = integrity_generate_show,
	.store = integrity_generate_store,
352 353
};

354
static struct integrity_sysfs_entry integrity_device_entry = {
355
	.attr = { .name = "device_is_integrity_capable", .mode = 0444 },
356 357 358
	.show = integrity_device_show,
};

359 360 361
static struct attribute *integrity_attrs[] = {
	&integrity_format_entry.attr,
	&integrity_tag_size_entry.attr,
362
	&integrity_interval_entry.attr,
363 364
	&integrity_verify_entry.attr,
	&integrity_generate_entry.attr,
365
	&integrity_device_entry.attr,
366 367 368
	NULL,
};

369
static const struct sysfs_ops integrity_ops = {
370 371 372 373 374 375 376 377 378
	.show	= &integrity_attr_show,
	.store	= &integrity_attr_store,
};

static struct kobj_type integrity_ktype = {
	.default_attrs	= integrity_attrs,
	.sysfs_ops	= &integrity_ops,
};

379
static blk_status_t blk_integrity_nop_fn(struct blk_integrity_iter *iter)
380
{
381
	return BLK_STS_OK;
382 383
}

384
static const struct blk_integrity_profile nop_profile = {
385 386 387 388 389
	.name = "nop",
	.generate_fn = blk_integrity_nop_fn,
	.verify_fn = blk_integrity_nop_fn,
};

390 391 392
/**
 * blk_integrity_register - Register a gendisk as being integrity-capable
 * @disk:	struct gendisk pointer to make integrity-aware
393
 * @template:	block integrity profile to register
394
 *
395 396 397 398 399
 * Description: When a device needs to advertise itself as being able to
 * send/receive integrity metadata it must use this function to register
 * the capability with the block layer. The template is a blk_integrity
 * struct with values appropriate for the underlying hardware. See
 * Documentation/block/data-integrity.txt.
400
 */
401
void blk_integrity_register(struct gendisk *disk, struct blk_integrity *template)
402
{
403
	struct blk_integrity *bi = &disk->queue->integrity;
404

405 406
	bi->flags = BLK_INTEGRITY_VERIFY | BLK_INTEGRITY_GENERATE |
		template->flags;
407 408
	bi->interval_exp = template->interval_exp ? :
		ilog2(queue_logical_block_size(disk->queue));
409
	bi->profile = template->profile ? template->profile : &nop_profile;
410 411
	bi->tuple_size = template->tuple_size;
	bi->tag_size = template->tag_size;
412

413
	disk->queue->backing_dev_info->capabilities |= BDI_CAP_STABLE_WRITES;
414 415 416 417
}
EXPORT_SYMBOL(blk_integrity_register);

/**
418 419
 * blk_integrity_unregister - Unregister block integrity profile
 * @disk:	disk whose integrity profile to unregister
420
 *
421 422
 * Description: This function unregisters the integrity capability from
 * a block device.
423 424 425
 */
void blk_integrity_unregister(struct gendisk *disk)
{
426
	disk->queue->backing_dev_info->capabilities &= ~BDI_CAP_STABLE_WRITES;
427
	memset(&disk->queue->integrity, 0, sizeof(struct blk_integrity));
428 429
}
EXPORT_SYMBOL(blk_integrity_unregister);
430

431 432 433 434 435
void blk_integrity_add(struct gendisk *disk)
{
	if (kobject_init_and_add(&disk->integrity_kobj, &integrity_ktype,
				 &disk_to_dev(disk)->kobj, "%s", "integrity"))
		return;
436

437 438 439 440 441
	kobject_uevent(&disk->integrity_kobj, KOBJ_ADD);
}

void blk_integrity_del(struct gendisk *disk)
{
442 443 444
	kobject_uevent(&disk->integrity_kobj, KOBJ_REMOVE);
	kobject_del(&disk->integrity_kobj);
	kobject_put(&disk->integrity_kobj);
445
}