Commit ebbb9034 authored by Dongsheng Yang's avatar Dongsheng Yang Committed by Mikulas Patocka
Browse files

dm-pcache: advance slot index before writing slot



In dm-pcache, in order to ensure crash-consistency, a dual-copy scheme
is used to alternately update metadata, and there is a slot index that
records the current slot. However, in the write path the current
implementation writes directly to the current slot indexed by slot
index, and then advances the slot — which ends up overwriting the
existing slot, violating the crash-consistency guarantee.

This patch fixes that behavior, preventing metadata from being
overwritten incorrectly.

In addition, this patch add a missing pmem_wmb() after memcpy_flushcache().

Signed-off-by: default avatarDongsheng Yang <dongsheng.yang@linux.dev>
Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
Reviewed-by: default avatarZheng Gu <cengku@gmail.com>
Cc: stable@vger.kernel.org	# 6.18
parent 7799eaec
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -21,10 +21,10 @@ static void cache_info_write(struct pcache_cache *cache)
	cache_info->header.crc = pcache_meta_crc(&cache_info->header,
						sizeof(struct pcache_cache_info));

	cache->info_index = (cache->info_index + 1) % PCACHE_META_INDEX_MAX;
	memcpy_flushcache(get_cache_info_addr(cache), cache_info,
			sizeof(struct pcache_cache_info));

	cache->info_index = (cache->info_index + 1) % PCACHE_META_INDEX_MAX;
	pmem_wmb();
}

static void cache_info_init_default(struct pcache_cache *cache);
@@ -93,10 +93,10 @@ void cache_pos_encode(struct pcache_cache *cache,
	pos_onmedia.header.seq = seq;
	pos_onmedia.header.crc = cache_pos_onmedia_crc(&pos_onmedia);

	*index = (*index + 1) % PCACHE_META_INDEX_MAX;

	memcpy_flushcache(pos_onmedia_addr, &pos_onmedia, sizeof(struct pcache_cache_pos_onmedia));
	pmem_wmb();

	*index = (*index + 1) % PCACHE_META_INDEX_MAX;
}

int cache_pos_decode(struct pcache_cache *cache,
+4 −4
Original line number Diff line number Diff line
@@ -26,11 +26,11 @@ static void cache_seg_info_write(struct pcache_cache_segment *cache_seg)
	seg_info->header.seq++;
	seg_info->header.crc = pcache_meta_crc(&seg_info->header, sizeof(struct pcache_segment_info));

	cache_seg->info_index = (cache_seg->info_index + 1) % PCACHE_META_INDEX_MAX;

	seg_info_addr = get_seg_info_addr(cache_seg);
	memcpy_flushcache(seg_info_addr, seg_info, sizeof(struct pcache_segment_info));
	pmem_wmb();

	cache_seg->info_index = (cache_seg->info_index + 1) % PCACHE_META_INDEX_MAX;
	mutex_unlock(&cache_seg->info_lock);
}

@@ -129,10 +129,10 @@ static void cache_seg_ctrl_write(struct pcache_cache_segment *cache_seg)
	cache_seg_gen.header.crc = pcache_meta_crc(&cache_seg_gen.header,
						 sizeof(struct pcache_cache_seg_gen));

	cache_seg->gen_index = (cache_seg->gen_index + 1) % PCACHE_META_INDEX_MAX;

	memcpy_flushcache(get_cache_seg_gen_addr(cache_seg), &cache_seg_gen, sizeof(struct pcache_cache_seg_gen));
	pmem_wmb();

	cache_seg->gen_index = (cache_seg->gen_index + 1) % PCACHE_META_INDEX_MAX;
}

static void cache_seg_ctrl_init(struct pcache_cache_segment *cache_seg)