Commit e3e72fe4 authored by Jens Axboe's avatar Jens Axboe
Browse files

Merge branch 'for-6.11/block-limits' into for-6.11/block

Pull in block limits branch, which exists as a shared branch for both
the block and SCSI tree.

* for-6.11/block-limits: (26 commits)
  block: move integrity information into queue_limits
  block: invert the BLK_INTEGRITY_{GENERATE,VERIFY} flags
  block: bypass the STABLE_WRITES flag for protection information
  block: don't require stable pages for non-PI metadata
  block: use kstrtoul in flag_store
  block: factor out flag_{store,show} helper for integrity
  block: remove the blk_flush_integrity call in blk_integrity_unregister
  block: remove the blk_integrity_profile structure
  dm-integrity: use the nop integrity profile
  md/raid1: don't free conf on raid0_run failure
  md/raid0: don't free conf on raid0_run failure
  block: initialize integrity buffer to zero before writing it to media
  block: add special APIs for run-time disabling of discard and friends
  block: remove unused queue limits API
  sr: convert to the atomic queue limits API
  sd: convert to the atomic queue limits API
  sd: cleanup zoned queue limits initialization
  sd: factor out a sd_discard_mode helper
  sd: simplify the disable case in sd_config_discard
  sd: add a sd_disable_write_same helper
  ...
parents d37a9ab8 c6e56cf6
Loading
Loading
Loading
Loading
+3 −46
Original line number Diff line number Diff line
@@ -153,18 +153,11 @@ bio_free() will automatically free the bip.
4.2 Block Device
----------------

Because the format of the protection data is tied to the physical
disk, each block device has been extended with a block integrity
profile (struct blk_integrity).  This optional profile is registered
with the block layer using blk_integrity_register().

The profile contains callback functions for generating and verifying
the protection data, as well as getting and setting application tags.
The profile also contains a few constants to aid in completing,
merging and splitting the integrity metadata.
Block devices can set up the integrity information in the integrity
sub-struture of the queue_limits structure.

Layered block devices will need to pick a profile that's appropriate
for all subdevices.  blk_integrity_compare() can help with that.  DM
for all subdevices.  queue_limits_stack_integrity() can help with that.  DM
and MD linear, RAID0 and RAID1 are currently supported.  RAID4/5/6
will require extra work due to the application tag.

@@ -250,42 +243,6 @@ will require extra work due to the application tag.
      integrity upon completion.


5.4 Registering A Block Device As Capable Of Exchanging Integrity Metadata
--------------------------------------------------------------------------

    To enable integrity exchange on a block device the gendisk must be
    registered as capable:

    `int blk_integrity_register(gendisk, blk_integrity);`

      The blk_integrity struct is a template and should contain the
      following::

        static struct blk_integrity my_profile = {
            .name                   = "STANDARDSBODY-TYPE-VARIANT-CSUM",
            .generate_fn            = my_generate_fn,
	    .verify_fn              = my_verify_fn,
	    .tuple_size             = sizeof(struct my_tuple_size),
	    .tag_size               = <tag bytes per hw sector>,
        };

      'name' is a text string which will be visible in sysfs.  This is
      part of the userland API so chose it carefully and never change
      it.  The format is standards body-type-variant.
      E.g. T10-DIF-TYPE1-IP or T13-EPP-0-CRC.

      'generate_fn' generates appropriate integrity metadata (for WRITE).

      'verify_fn' verifies that the data buffer matches the integrity
      metadata.

      'tuple_size' must be set to match the size of the integrity
      metadata per sector.  I.e. 8 for DIF and EPP.

      'tag_size' must be set to identify how many bytes of tag space
      are available per hardware sector.  For DIF this is either 2 or
      0 depending on the value of the Control Mode Page ATO bit.

----------------------------------------------------------------------

2007-12-24 Martin K. Petersen <martin.petersen@oracle.com>
+19 −31
Original line number Diff line number Diff line
@@ -447,43 +447,31 @@ static int bulk_req_safe_read(
	return n;
}

/* Called without dev->lock held, and only in interrupt context. */
static void ubd_handler(void)
static void ubd_end_request(struct io_thread_req *io_req)
{
	int n;
	int count;

	while(1){
		n = bulk_req_safe_read(
			thread_fd,
			irq_req_buffer,
			&irq_remainder,
			&irq_remainder_size,
			UBD_REQ_BUFFER_SIZE
		);
		if (n < 0) {
			if(n == -EAGAIN)
				break;
			printk(KERN_ERR "spurious interrupt in ubd_handler, "
			       "err = %d\n", -n);
			return;
		}
		for (count = 0; count < n/sizeof(struct io_thread_req *); count++) {
			struct io_thread_req *io_req = (*irq_req_buffer)[count];

			if ((io_req->error == BLK_STS_NOTSUPP) && (req_op(io_req->req) == REQ_OP_DISCARD)) {
				blk_queue_max_discard_sectors(io_req->req->q, 0);
				blk_queue_max_write_zeroes_sectors(io_req->req->q, 0);
	if (io_req->error == BLK_STS_NOTSUPP) {
		if (req_op(io_req->req) == REQ_OP_DISCARD)
			blk_queue_disable_discard(io_req->req->q);
		else if (req_op(io_req->req) == REQ_OP_WRITE_ZEROES)
			blk_queue_disable_write_zeroes(io_req->req->q);
	}
	blk_mq_end_request(io_req->req, io_req->error);
	kfree(io_req);
}
	}
}

static irqreturn_t ubd_intr(int irq, void *dev)
{
	ubd_handler();
	int len, i;

	while ((len = bulk_req_safe_read(thread_fd, irq_req_buffer,
			&irq_remainder, &irq_remainder_size,
			UBD_REQ_BUFFER_SIZE)) >= 0) {
		for (i = 0; i < len / sizeof(struct io_thread_req *); i++)
			ubd_end_request((*irq_req_buffer)[i]);
	}

	if (len < 0 && len != -EAGAIN)
		pr_err("spurious interrupt in %s, err = %d\n", __func__, len);
	return IRQ_HANDLED;
}

+2 −6
Original line number Diff line number Diff line
@@ -62,6 +62,8 @@ config BLK_DEV_BSGLIB

config BLK_DEV_INTEGRITY
	bool "Block layer data integrity support"
	select CRC_T10DIF
	select CRC64_ROCKSOFT
	help
	Some storage devices allow extra information to be
	stored/retrieved to help protect the data.  The block layer
@@ -72,12 +74,6 @@ config BLK_DEV_INTEGRITY
	T10/SCSI Data Integrity Field or the T13/ATA External Path
	Protection.  If in doubt, say N.

config BLK_DEV_INTEGRITY_T10
	tristate
	depends on BLK_DEV_INTEGRITY
	select CRC_T10DIF
	select CRC64_ROCKSOFT

config BLK_DEV_WRITE_MOUNTED
	bool "Allow writing to mounted block devices"
	default y
+1 −2
Original line number Diff line number Diff line
@@ -26,8 +26,7 @@ obj-$(CONFIG_MQ_IOSCHED_KYBER) += kyber-iosched.o
bfq-y				:= bfq-iosched.o bfq-wf2q.o bfq-cgroup.o
obj-$(CONFIG_IOSCHED_BFQ)	+= bfq.o

obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o blk-integrity.o
obj-$(CONFIG_BLK_DEV_INTEGRITY_T10)	+= t10-pi.o
obj-$(CONFIG_BLK_DEV_INTEGRITY) += bio-integrity.o blk-integrity.o t10-pi.o
obj-$(CONFIG_BLK_MQ_PCI)	+= blk-mq-pci.o
obj-$(CONFIG_BLK_MQ_VIRTIO)	+= blk-mq-virtio.o
obj-$(CONFIG_BLK_DEV_ZONED)	+= blk-zoned.o
+23 −20
Original line number Diff line number Diff line
@@ -378,10 +378,9 @@ EXPORT_SYMBOL_GPL(bio_integrity_map_user);
 * bio_integrity_process - Process integrity metadata for a bio
 * @bio:	bio to generate/verify integrity metadata for
 * @proc_iter:  iterator to process
 * @proc_fn:	Pointer to the relevant processing function
 */
static blk_status_t bio_integrity_process(struct bio *bio,
		struct bvec_iter *proc_iter, integrity_processing_fn *proc_fn)
		struct bvec_iter *proc_iter)
{
	struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
	struct blk_integrity_iter iter;
@@ -392,17 +391,18 @@ static blk_status_t bio_integrity_process(struct bio *bio,

	iter.disk_name = bio->bi_bdev->bd_disk->disk_name;
	iter.interval = 1 << bi->interval_exp;
	iter.tuple_size = bi->tuple_size;
	iter.seed = proc_iter->bi_sector;
	iter.prot_buf = bvec_virt(bip->bip_vec);
	iter.pi_offset = bi->pi_offset;

	__bio_for_each_segment(bv, bio, bviter, *proc_iter) {
		void *kaddr = bvec_kmap_local(&bv);

		iter.data_buf = kaddr;
		iter.data_size = bv.bv_len;
		ret = proc_fn(&iter);
		if (bio_data_dir(bio) == WRITE)
			blk_integrity_generate(&iter, bi);
		else
			ret = blk_integrity_verify(&iter, bi);
		kunmap_local(kaddr);

		if (ret)
@@ -432,6 +432,7 @@ bool bio_integrity_prep(struct bio *bio)
	unsigned long start, end;
	unsigned int len, nr_pages;
	unsigned int bytes, offset, i;
	gfp_t gfp = GFP_NOIO;

	if (!bi)
		return true;
@@ -447,18 +448,24 @@ bool bio_integrity_prep(struct bio *bio)
		return true;

	if (bio_data_dir(bio) == READ) {
		if (!bi->profile->verify_fn ||
		    !(bi->flags & BLK_INTEGRITY_VERIFY))
		if (bi->flags & BLK_INTEGRITY_NOVERIFY)
			return true;
	} else {
		if (!bi->profile->generate_fn ||
		    !(bi->flags & BLK_INTEGRITY_GENERATE))
		if (bi->flags & BLK_INTEGRITY_NOGENERATE)
			return true;

		/*
		 * Zero the memory allocated to not leak uninitialized kernel
		 * memory to disk.  For PI this only affects the app tag, but
		 * for non-integrity metadata it affects the entire metadata
		 * buffer.
		 */
		gfp |= __GFP_ZERO;
	}

	/* Allocate kernel buffer for protection data */
	len = bio_integrity_bytes(bi, bio_sectors(bio));
	buf = kmalloc(len, GFP_NOIO);
	buf = kmalloc(len, gfp);
	if (unlikely(buf == NULL)) {
		printk(KERN_ERR "could not allocate integrity buffer\n");
		goto err_end_io;
@@ -479,7 +486,7 @@ bool bio_integrity_prep(struct bio *bio)
	bip->bip_flags |= BIP_BLOCK_INTEGRITY;
	bip_set_seed(bip, bio->bi_iter.bi_sector);

	if (bi->flags & BLK_INTEGRITY_IP_CHECKSUM)
	if (bi->csum_type == BLK_INTEGRITY_CSUM_IP)
		bip->bip_flags |= BIP_IP_CHECKSUM;

	/* Map it */
@@ -502,12 +509,10 @@ bool 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, &bio->bi_iter,
				      bi->profile->generate_fn);
	} else {
	if (bio_data_dir(bio) == WRITE)
		bio_integrity_process(bio, &bio->bi_iter);
	else
		bip->bio_iter = bio->bi_iter;
	}
	return true;

err_end_io:
@@ -530,15 +535,13 @@ static void bio_integrity_verify_fn(struct work_struct *work)
	struct bio_integrity_payload *bip =
		container_of(work, struct bio_integrity_payload, bip_work);
	struct bio *bio = bip->bip_bio;
	struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);

	/*
	 * At the moment verify is called bio's iterator was advanced
	 * during split and completion, we need to rewind iterator to
	 * it's original position.
	 */
	bio->bi_status = bio_integrity_process(bio, &bip->bio_iter,
						bi->profile->verify_fn);
	bio->bi_status = bio_integrity_process(bio, &bip->bio_iter);
	bio_integrity_free(bio);
	bio_endio(bio);
}
@@ -560,7 +563,7 @@ bool __bio_integrity_endio(struct bio *bio)
	struct bio_integrity_payload *bip = bio_integrity(bio);

	if (bio_op(bio) == REQ_OP_READ && !bio->bi_status &&
	    (bip->bip_flags & BIP_BLOCK_INTEGRITY) && bi->profile->verify_fn) {
	    (bip->bip_flags & BIP_BLOCK_INTEGRITY) && bi->csum_type) {
		INIT_WORK(&bip->bip_work, bio_integrity_verify_fn);
		queue_work(kintegrityd_wq, &bip->bip_work);
		return false;
Loading