|
@@ -192,3 +192,129 @@ int blk_integrity_merge_rq(struct request_queue *q, struct request *req,
|
|
|
q->limits.max_integrity_segments)
|
|
|
return -1;
|
|
|
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(blk_integrity_merge_rq);
|
|
|
+
|
|
|
+int blk_integrity_merge_bio(struct request_queue *q, struct request *req,
|
|
|
+ struct bio *bio)
|
|
|
+{
|
|
|
+ int nr_integrity_segs;
|
|
|
+ struct bio *next = bio->bi_next;
|
|
|
+
|
|
|
+ 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)
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ req->nr_integrity_segments += nr_integrity_segs;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(blk_integrity_merge_bio);
|
|
|
+
|
|
|
+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)
|
|
|
+{
|
|
|
+ struct blk_integrity *bi =
|
|
|
+ container_of(kobj, struct blk_integrity, kobj);
|
|
|
+ struct integrity_sysfs_entry *entry =
|
|
|
+ container_of(attr, struct integrity_sysfs_entry, attr);
|
|
|
+
|
|
|
+ return entry->show(bi, page);
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t integrity_attr_store(struct kobject *kobj,
|
|
|
+ struct attribute *attr, const char *page,
|
|
|
+ size_t count)
|
|
|
+{
|
|
|
+ struct blk_integrity *bi =
|
|
|
+ container_of(kobj, struct blk_integrity, kobj);
|
|
|
+ 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)
|
|
|
+{
|
|
|
+ if (bi != NULL && bi->name != NULL)
|
|
|
+ return sprintf(page, "%s\n", bi->name);
|
|
|
+ else
|
|
|
+ return sprintf(page, "none\n");
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t integrity_tag_size_show(struct blk_integrity *bi, char *page)
|
|
|
+{
|
|
|
+ if (bi != NULL)
|
|
|
+ return sprintf(page, "%u\n", bi->tag_size);
|
|
|
+ else
|
|
|
+ return sprintf(page, "0\n");
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t integrity_read_store(struct blk_integrity *bi,
|
|
|
+ const char *page, size_t count)
|
|
|
+{
|
|
|
+ char *p = (char *) page;
|
|
|
+ unsigned long val = simple_strtoul(p, &p, 10);
|
|
|
+
|
|
|
+ if (val)
|
|
|
+ bi->flags |= INTEGRITY_FLAG_READ;
|
|
|
+ else
|
|
|
+ bi->flags &= ~INTEGRITY_FLAG_READ;
|
|
|
+
|
|
|
+ return count;
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t integrity_read_show(struct blk_integrity *bi, char *page)
|
|
|
+{
|
|
|
+ return sprintf(page, "%d\n", (bi->flags & INTEGRITY_FLAG_READ) != 0);
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t integrity_write_store(struct blk_integrity *bi,
|
|
|
+ const char *page, size_t count)
|
|
|
+{
|
|
|
+ char *p = (char *) page;
|
|
|
+ unsigned long val = simple_strtoul(p, &p, 10);
|
|
|
+
|
|
|
+ if (val)
|
|
|
+ bi->flags |= INTEGRITY_FLAG_WRITE;
|
|
|
+ else
|
|
|
+ bi->flags &= ~INTEGRITY_FLAG_WRITE;
|
|
|
+
|
|
|
+ return count;
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t integrity_write_show(struct blk_integrity *bi, char *page)
|
|
|
+{
|
|
|
+ return sprintf(page, "%d\n", (bi->flags & INTEGRITY_FLAG_WRITE) != 0);
|
|
|
+}
|
|
|
+
|
|
|
+static struct integrity_sysfs_entry integrity_format_entry = {
|
|
|
+ .attr = { .name = "format", .mode = S_IRUGO },
|
|
|
+ .show = integrity_format_show,
|
|
|
+};
|
|
|
+
|
|
|
+static struct integrity_sysfs_entry integrity_tag_size_entry = {
|
|
|
+ .attr = { .name = "tag_size", .mode = S_IRUGO },
|
|
|
+ .show = integrity_tag_size_show,
|
|
|
+};
|
|
|
+
|
|
|
+static struct integrity_sysfs_entry integrity_read_entry = {
|
|
|
+ .attr = { .name = "read_verify", .mode = S_IRUGO | S_IWUSR },
|
|
|
+ .show = integrity_read_show,
|
|
|
+ .store = integrity_read_store,
|
|
|
+};
|