drivers/md/dm-pcache/backing_dev.c

Source file repositories/reference/linux-study-clean/drivers/md/dm-pcache/backing_dev.c

File Facts

System
Linux kernel
Corpus path
drivers/md/dm-pcache/backing_dev.c
Extension
.c
Size
10445 bytes
Lines
375
Domain
Driver Families
Bucket
drivers/md
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-or-later
#include <linux/blkdev.h>

#include "../dm-core.h"
#include "pcache_internal.h"
#include "cache_dev.h"
#include "backing_dev.h"
#include "cache.h"
#include "dm_pcache.h"

static struct kmem_cache *backing_req_cache;
static struct kmem_cache *backing_bvec_cache;

static void backing_dev_exit(struct pcache_backing_dev *backing_dev)
{
	mempool_exit(&backing_dev->req_pool);
	mempool_exit(&backing_dev->bvec_pool);
}

static void req_submit_fn(struct work_struct *work);
static void req_complete_fn(struct work_struct *work);
static int backing_dev_init(struct dm_pcache *pcache)
{
	struct pcache_backing_dev *backing_dev = &pcache->backing_dev;
	int ret;

	ret = mempool_init_slab_pool(&backing_dev->req_pool, 128, backing_req_cache);
	if (ret)
		goto err;

	ret = mempool_init_slab_pool(&backing_dev->bvec_pool, 128, backing_bvec_cache);
	if (ret)
		goto req_pool_exit;

	INIT_LIST_HEAD(&backing_dev->submit_list);
	INIT_LIST_HEAD(&backing_dev->complete_list);
	spin_lock_init(&backing_dev->submit_lock);
	spin_lock_init(&backing_dev->complete_lock);
	INIT_WORK(&backing_dev->req_submit_work, req_submit_fn);
	INIT_WORK(&backing_dev->req_complete_work, req_complete_fn);
	atomic_set(&backing_dev->inflight_reqs, 0);
	init_waitqueue_head(&backing_dev->inflight_wq);

	return 0;

req_pool_exit:
	mempool_exit(&backing_dev->req_pool);
err:
	return ret;
}

int backing_dev_start(struct dm_pcache *pcache)
{
	struct pcache_backing_dev *backing_dev = &pcache->backing_dev;
	int ret;

	ret = backing_dev_init(pcache);
	if (ret)
		return ret;

	backing_dev->dev_size = bdev_nr_sectors(backing_dev->dm_dev->bdev);

	return 0;
}

void backing_dev_stop(struct dm_pcache *pcache)
{
	struct pcache_backing_dev *backing_dev = &pcache->backing_dev;

	/*
	 * There should not be any new request comming, just wait
	 * inflight requests done.
	 */
	wait_event(backing_dev->inflight_wq,
			atomic_read(&backing_dev->inflight_reqs) == 0);

	flush_work(&backing_dev->req_submit_work);
	flush_work(&backing_dev->req_complete_work);

	backing_dev_exit(backing_dev);
}

/* pcache_backing_dev_req functions */
void backing_dev_req_end(struct pcache_backing_dev_req *backing_req)
{
	struct pcache_backing_dev *backing_dev = backing_req->backing_dev;

	if (backing_req->end_req)
		backing_req->end_req(backing_req, backing_req->ret);

Annotation

Implementation Notes