drivers/md/dm-pcache/cache_writeback.c

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

File Facts

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

while (node) {
			key = CACHE_KEY(node);
			node = rb_next(node);

			cache_key_writeback(cache, key);
			cache_key_delete(key);
		}
	}
	writeback_ctx_end(cache, 0);
}

static int cache_kset_insert_tree(struct pcache_cache *cache, struct pcache_cache_kset_onmedia *kset_onmedia)
{
	struct pcache_cache_key_onmedia *key_onmedia;
	struct pcache_cache_subtree *cache_subtree;
	struct pcache_cache_key *key;
	int ret;
	u32 i;

	/* Iterate through all keys in the kset and write each back to storage */
	for (i = 0; i < kset_onmedia->key_num; i++) {
		key_onmedia = &kset_onmedia->data[i];

		key = cache_key_alloc(&cache->writeback_key_tree, GFP_NOIO);
		ret = cache_key_decode(cache, key_onmedia, key);
		if (ret) {
			cache_key_put(key);
			goto clear_tree;
		}

		cache_subtree = get_subtree(&cache->writeback_key_tree, key->off);
		spin_lock(&cache_subtree->tree_lock);
		cache_key_insert(&cache->writeback_key_tree, key, true);
		spin_unlock(&cache_subtree->tree_lock);
	}

	return 0;
clear_tree:
	cache_tree_clear(&cache->writeback_key_tree);
	return ret;
}

static void last_kset_writeback(struct pcache_cache *cache,
		struct pcache_cache_kset_onmedia *last_kset_onmedia)
{
	struct dm_pcache *pcache = CACHE_TO_PCACHE(cache);
	struct pcache_cache_segment *next_seg;

	pcache_dev_debug(pcache, "last kset, next: %u\n", last_kset_onmedia->next_cache_seg_id);

	next_seg = &cache->segments[last_kset_onmedia->next_cache_seg_id];

	mutex_lock(&cache->dirty_tail_lock);
	cache->dirty_tail.cache_seg = next_seg;
	cache->dirty_tail.seg_off = 0;
	cache_encode_dirty_tail(cache);
	mutex_unlock(&cache->dirty_tail_lock);
}

void cache_writeback_fn(struct work_struct *work)
{
	struct pcache_cache *cache = container_of(work, struct pcache_cache, writeback_work.work);
	struct dm_pcache *pcache = CACHE_TO_PCACHE(cache);
	struct pcache_cache_pos dirty_tail;
	struct pcache_cache_kset_onmedia *kset_onmedia;
	u32 delay;
	int ret;

	mutex_lock(&cache->writeback_lock);
	if (atomic_read(&cache->writeback_ctx.pending))
		goto unlock;

	if (pcache_is_stopping(pcache))
		goto unlock;

	kset_onmedia = (struct pcache_cache_kset_onmedia *)cache->wb_kset_onmedia_buf;

	mutex_lock(&cache->dirty_tail_lock);
	cache_pos_copy(&dirty_tail, &cache->dirty_tail);
	mutex_unlock(&cache->dirty_tail_lock);

	if (is_cache_clean(cache, &dirty_tail)) {
		delay = PCACHE_CACHE_WRITEBACK_INTERVAL;
		goto queue_work;
	}

	if (kset_onmedia->flags & PCACHE_KSET_FLAGS_LAST) {
		last_kset_writeback(cache, kset_onmedia);
		delay = 0;
		goto queue_work;

Annotation

Implementation Notes