block/blk-zoned.c

Source file repositories/reference/linux-study-clean/block/blk-zoned.c

File Facts

System
Linux kernel
Corpus path
block/blk-zoned.c
Extension
.c
Size
72358 bytes
Lines
2498
Domain
Representative Device Path
Bucket
PCIe NVMe Storage Path
Inferred role
Representative Device Path: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.

Dependency Surface

Detected Declarations

Annotated Snippet

blk_mq_submit_bio(bio);
	}

	return true;
}

static struct blk_zone_wplug *disk_get_zone_wplugs_work(struct gendisk *disk)
{
	struct blk_zone_wplug *zwplug;

	spin_lock_irq(&disk->zone_wplugs_list_lock);
	zwplug = list_first_entry_or_null(&disk->zone_wplugs_list,
					  struct blk_zone_wplug, entry);
	if (zwplug)
		list_del_init(&zwplug->entry);
	spin_unlock_irq(&disk->zone_wplugs_list_lock);

	return zwplug;
}

static int disk_zone_wplugs_worker(void *data)
{
	struct gendisk *disk = data;
	struct blk_zone_wplug *zwplug;
	unsigned int noio_flag;

	noio_flag = memalloc_noio_save();
	set_user_nice(current, MIN_NICE);
	set_freezable();

	for (;;) {
		set_current_state(TASK_INTERRUPTIBLE | TASK_FREEZABLE);

		zwplug = disk_get_zone_wplugs_work(disk);
		if (zwplug) {
			/*
			 * Process all BIOs of this zone write plug and then
			 * drop the reference we took when adding the zone write
			 * plug to the active list.
			 */
			set_current_state(TASK_RUNNING);
			while (disk_zone_wplug_submit_bio(disk, zwplug))
				blk_wait_io(&disk->zone_wplugs_worker_bio_done);
			disk_put_zone_wplug(zwplug);
			continue;
		}

		/*
		 * Only sleep if nothing sets the state to running. Else check
		 * for zone write plugs work again as a newly submitted BIO
		 * might have added a zone write plug to the work list.
		 */
		if (get_current_state() == TASK_RUNNING) {
			try_to_freeze();
		} else {
			if (kthread_should_stop()) {
				set_current_state(TASK_RUNNING);
				break;
			}
			schedule();
		}
	}

	WARN_ON_ONCE(!list_empty(&disk->zone_wplugs_list));
	memalloc_noio_restore(noio_flag);

	return 0;
}

void disk_init_zone_resources(struct gendisk *disk)
{
	spin_lock_init(&disk->zone_wplugs_hash_lock);
	spin_lock_init(&disk->zone_wplugs_list_lock);
	INIT_LIST_HEAD(&disk->zone_wplugs_list);
	init_completion(&disk->zone_wplugs_worker_bio_done);
}

/*
 * For the size of a disk zone write plug hash table, use the size of the
 * zone write plug mempool, which is the maximum of the disk open zones and
 * active zones limits. But do not exceed 4KB (512 hlist head entries), that is,
 * 9 bits. For a disk that has no limits, mempool size defaults to 128.
 */
#define BLK_ZONE_WPLUG_MAX_HASH_BITS		9
#define BLK_ZONE_WPLUG_DEFAULT_POOL_SIZE	128

static int disk_alloc_zone_resources(struct gendisk *disk,
				     unsigned int pool_size)
{
	unsigned int i;

Annotation

Implementation Notes