bio-integrity: fold bio_integrity_enabled to bio_integrity_prep
[sfrench/cifs-2.6.git] / block / bio-integrity.c
index 3a0d71199fb079ada2f94511acf470d70c4fce9f..44c4c52681c208591b6b2e5bdd012adaa68d903f 100644 (file)
@@ -159,44 +159,6 @@ int bio_integrity_add_page(struct bio *bio, struct page *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
  * @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:       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.
  */
-int bio_integrity_prep(struct bio *bio)
+bool bio_integrity_prep(struct bio *bio)
 {
        struct bio_integrity_payload *bip;
        struct blk_integrity *bi;
@@ -279,20 +242,41 @@ int bio_integrity_prep(struct bio *bio)
        unsigned int len, nr_pages;
        unsigned int bytes, offset, i;
        unsigned int intervals;
+       blk_status_t status;
 
        bi = bdev_get_integrity(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));
 
        /* Allocate kernel buffer for protection data */
        len = intervals * bi->tuple_size;
        buf = kmalloc(len, GFP_NOIO | q->bounce_gfp);
+       status = BLK_STS_RESOURCE;
        if (unlikely(buf == NULL)) {
                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;
@@ -304,7 +288,8 @@ int bio_integrity_prep(struct bio *bio)
        if (IS_ERR(bip)) {
                printk(KERN_ERR "could not allocate data integrity bioset\n");
                kfree(buf);
-               return PTR_ERR(bip);
+               status = BLK_STS_RESOURCE;
+               goto err_end_io;
        }
 
        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 */
        if (bio_data_dir(bio) == WRITE)
                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);