drivers/md/dm-pcache/cache_req.c

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

File Facts

System
Linux kernel
Corpus path
drivers/md/dm-pcache/cache_req.c
Extension
.c
Size
26699 bytes
Lines
837
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

if (cache_key_empty(key)) {
			/* Check if the backing request was successful. */
			if (read_ret) {
				cache_key_delete(key);
				goto unlock;
			}

			/* Allocate cache space for the key and copy data from the backing_dev. */
			ret = cache_data_alloc(cache, key);
			if (ret) {
				cache_key_delete(key);
				goto unlock;
			}

			ret = cache_copy_from_req_bio(cache, key, pcache_req, backing_req->req.bio_off);
			if (ret) {
				cache_seg_put(key->cache_pos.cache_seg);
				cache_key_delete(key);
				goto unlock;
			}
			key->flags &= ~PCACHE_CACHE_KEY_FLAGS_EMPTY;
			key->flags |= PCACHE_CACHE_KEY_FLAGS_CLEAN;

			/* Append the key to the cache. */
			ret = cache_key_append(cache, key, false);
			if (ret) {
				cache_seg_put(key->cache_pos.cache_seg);
				cache_key_delete(key);
				goto unlock;
			}
		}
unlock:
		spin_unlock(&cache_subtree->tree_lock);
		cache_key_put(key);
	}
}

/**
 * submit_cache_miss_req - Submit a backing request when cache data is missing
 * @cache: The cache context that manages cache operations
 * @backing_req: The cache request containing information about the read request
 *
 * This function is used to handle cases where a cache read request cannot locate
 * the required data in the cache. When such a miss occurs during `cache_subtree_walk`,
 * it triggers a backing read request to fetch data from the backing storage.
 *
 * If `pcache_req->priv_data` is set, it points to a `pcache_cache_key`, representing
 * a new cache key to be inserted into the cache. The function calls `cache_key_insert`
 * to attempt adding the key. On insertion failure, it releases the key reference and
 * clears `priv_data` to avoid further processing.
 */
static void submit_cache_miss_req(struct pcache_cache *cache, struct pcache_backing_dev_req *backing_req)
{
	if (backing_req->priv_data) {
		struct pcache_cache_key *key;

		/* Attempt to insert the key into the cache if priv_data is set */
		key = (struct pcache_cache_key *)backing_req->priv_data;
		cache_key_insert(&cache->req_key_tree, key, true);
	}
	backing_dev_req_submit(backing_req, false);
}

static void cache_miss_req_free(struct pcache_backing_dev_req *backing_req)
{
	struct pcache_cache_key *key;

	if (backing_req->priv_data) {
		key = backing_req->priv_data;
		backing_req->priv_data = NULL;
		cache_key_put(key); /* for ->priv_data */
		cache_key_put(key); /* for init ref in alloc */
	}

	backing_dev_req_end(backing_req);
}

static struct pcache_backing_dev_req *cache_miss_req_alloc(struct pcache_cache *cache,
							   struct pcache_request *parent,
							   gfp_t gfp_mask)
{
	struct pcache_backing_dev *backing_dev = cache->backing_dev;
	struct pcache_backing_dev_req *backing_req;
	struct pcache_cache_key *key = NULL;
	struct pcache_backing_dev_req_opts req_opts = { 0 };

	req_opts.type = BACKING_DEV_REQ_TYPE_REQ;
	req_opts.gfp_mask = gfp_mask;
	req_opts.req.upper_req = parent;

Annotation

Implementation Notes