|
@@ -159,44 +159,6 @@ int bio_integrity_add_page(struct bio *bio, struct page *page,
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(bio_integrity_add_page);
|
|
EXPORT_SYMBOL(bio_integrity_add_page);
|
|
|
|
|
|
-/**
|
|
|
|
- * bio_integrity_enabled - Check whether integrity can be passed
|
|
|
|
- * @bio: bio to check
|
|
|
|
- *
|
|
|
|
- * Description: Determines whether bio_integrity_prep() can be called
|
|
|
|
- * on this bio or not. bio data direction and target device must be
|
|
|
|
- * set prior to calling. The functions honors the write_generate and
|
|
|
|
- * read_verify flags in sysfs.
|
|
|
|
- */
|
|
|
|
-bool bio_integrity_enabled(struct bio *bio)
|
|
|
|
-{
|
|
|
|
- struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
|
|
|
|
-
|
|
|
|
- if (bio_op(bio) != REQ_OP_READ && bio_op(bio) != REQ_OP_WRITE)
|
|
|
|
- return false;
|
|
|
|
-
|
|
|
|
- if (!bio_sectors(bio))
|
|
|
|
- return false;
|
|
|
|
-
|
|
|
|
- /* Already protected? */
|
|
|
|
- if (bio_integrity(bio))
|
|
|
|
- return false;
|
|
|
|
-
|
|
|
|
- if (bi == NULL)
|
|
|
|
- return false;
|
|
|
|
-
|
|
|
|
- if (bio_data_dir(bio) == READ && bi->profile->verify_fn != NULL &&
|
|
|
|
- (bi->flags & BLK_INTEGRITY_VERIFY))
|
|
|
|
- return true;
|
|
|
|
-
|
|
|
|
- if (bio_data_dir(bio) == WRITE && bi->profile->generate_fn != NULL &&
|
|
|
|
- (bi->flags & BLK_INTEGRITY_GENERATE))
|
|
|
|
- return true;
|
|
|
|
-
|
|
|
|
- return false;
|
|
|
|
-}
|
|
|
|
-EXPORT_SYMBOL(bio_integrity_enabled);
|
|
|
|
-
|
|
|
|
/**
|
|
/**
|
|
* bio_integrity_intervals - Return number of integrity intervals for a bio
|
|
* bio_integrity_intervals - Return number of integrity intervals for a bio
|
|
* @bi: blk_integrity profile for device
|
|
* @bi: blk_integrity profile for device
|
|
@@ -262,14 +224,15 @@ static blk_status_t bio_integrity_process(struct bio *bio,
|
|
* bio_integrity_prep - Prepare bio for integrity I/O
|
|
* bio_integrity_prep - Prepare bio for integrity I/O
|
|
* @bio: bio to prepare
|
|
* @bio: bio to prepare
|
|
*
|
|
*
|
|
- * Description: Allocates a buffer for integrity metadata, maps the
|
|
|
|
- * pages and attaches them to a bio. The bio must have data
|
|
|
|
- * direction, target device and start sector set priot to calling. In
|
|
|
|
- * the WRITE case, integrity metadata will be generated using the
|
|
|
|
- * block device's integrity function. In the READ case, the buffer
|
|
|
|
|
|
+ * Description: Checks if the bio already has an integrity payload attached.
|
|
|
|
+ * If it does, the payload has been generated by another kernel subsystem,
|
|
|
|
+ * and we just pass it through. Otherwise allocates integrity payload.
|
|
|
|
+ * The bio must have data direction, target device and start sector set priot
|
|
|
|
+ * to calling. In the WRITE case, integrity metadata will be generated using
|
|
|
|
+ * the block device's integrity function. In the READ case, the buffer
|
|
* will be prepared for DMA and a suitable end_io handler set up.
|
|
* will be prepared for DMA and a suitable end_io handler set up.
|
|
*/
|
|
*/
|
|
-int bio_integrity_prep(struct bio *bio)
|
|
|
|
|
|
+bool bio_integrity_prep(struct bio *bio)
|
|
{
|
|
{
|
|
struct bio_integrity_payload *bip;
|
|
struct bio_integrity_payload *bip;
|
|
struct blk_integrity *bi;
|
|
struct blk_integrity *bi;
|
|
@@ -279,20 +242,41 @@ int bio_integrity_prep(struct bio *bio)
|
|
unsigned int len, nr_pages;
|
|
unsigned int len, nr_pages;
|
|
unsigned int bytes, offset, i;
|
|
unsigned int bytes, offset, i;
|
|
unsigned int intervals;
|
|
unsigned int intervals;
|
|
|
|
+ blk_status_t status;
|
|
|
|
|
|
bi = bdev_get_integrity(bio->bi_bdev);
|
|
bi = bdev_get_integrity(bio->bi_bdev);
|
|
q = bdev_get_queue(bio->bi_bdev);
|
|
q = bdev_get_queue(bio->bi_bdev);
|
|
- BUG_ON(bi == NULL);
|
|
|
|
- BUG_ON(bio_integrity(bio));
|
|
|
|
|
|
+ if (bio_op(bio) != REQ_OP_READ && bio_op(bio) != REQ_OP_WRITE)
|
|
|
|
+ return true;
|
|
|
|
+
|
|
|
|
+ if (!bio_sectors(bio))
|
|
|
|
+ return true;
|
|
|
|
|
|
|
|
+ /* Already protected? */
|
|
|
|
+ if (bio_integrity(bio))
|
|
|
|
+ return true;
|
|
|
|
+
|
|
|
|
+ if (bi == NULL)
|
|
|
|
+ return true;
|
|
|
|
+
|
|
|
|
+ if (bio_data_dir(bio) == READ) {
|
|
|
|
+ if (!bi->profile->verify_fn ||
|
|
|
|
+ !(bi->flags & BLK_INTEGRITY_VERIFY))
|
|
|
|
+ return true;
|
|
|
|
+ } else {
|
|
|
|
+ if (!bi->profile->generate_fn ||
|
|
|
|
+ !(bi->flags & BLK_INTEGRITY_GENERATE))
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
intervals = bio_integrity_intervals(bi, bio_sectors(bio));
|
|
intervals = bio_integrity_intervals(bi, bio_sectors(bio));
|
|
|
|
|
|
/* Allocate kernel buffer for protection data */
|
|
/* Allocate kernel buffer for protection data */
|
|
len = intervals * bi->tuple_size;
|
|
len = intervals * bi->tuple_size;
|
|
buf = kmalloc(len, GFP_NOIO | q->bounce_gfp);
|
|
buf = kmalloc(len, GFP_NOIO | q->bounce_gfp);
|
|
|
|
+ status = BLK_STS_RESOURCE;
|
|
if (unlikely(buf == NULL)) {
|
|
if (unlikely(buf == NULL)) {
|
|
printk(KERN_ERR "could not allocate integrity buffer\n");
|
|
printk(KERN_ERR "could not allocate integrity buffer\n");
|
|
- return -ENOMEM;
|
|
|
|
|
|
+ goto err_end_io;
|
|
}
|
|
}
|
|
|
|
|
|
end = (((unsigned long) buf) + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
|
end = (((unsigned long) buf) + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
|
@@ -304,7 +288,8 @@ int bio_integrity_prep(struct bio *bio)
|
|
if (IS_ERR(bip)) {
|
|
if (IS_ERR(bip)) {
|
|
printk(KERN_ERR "could not allocate data integrity bioset\n");
|
|
printk(KERN_ERR "could not allocate data integrity bioset\n");
|
|
kfree(buf);
|
|
kfree(buf);
|
|
- return PTR_ERR(bip);
|
|
|
|
|
|
+ status = BLK_STS_RESOURCE;
|
|
|
|
+ goto err_end_io;
|
|
}
|
|
}
|
|
|
|
|
|
bip->bip_flags |= BIP_BLOCK_INTEGRITY;
|
|
bip->bip_flags |= BIP_BLOCK_INTEGRITY;
|
|
@@ -349,8 +334,13 @@ int bio_integrity_prep(struct bio *bio)
|
|
/* Auto-generate integrity metadata if this is a write */
|
|
/* Auto-generate integrity metadata if this is a write */
|
|
if (bio_data_dir(bio) == WRITE)
|
|
if (bio_data_dir(bio) == WRITE)
|
|
bio_integrity_process(bio, bi->profile->generate_fn);
|
|
bio_integrity_process(bio, bi->profile->generate_fn);
|
|
|
|
+ return true;
|
|
|
|
+
|
|
|
|
+err_end_io:
|
|
|
|
+ bio->bi_status = status;
|
|
|
|
+ bio_endio(bio);
|
|
|
|
+ return false;
|
|
|
|
|
|
- return 0;
|
|
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(bio_integrity_prep);
|
|
EXPORT_SYMBOL(bio_integrity_prep);
|
|
|
|
|