3615 lines · 86.4 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* * Copyright (C) 2012 Red Hat. All rights reserved. * * This file is released under the GPL. */ #include "dm.h"#include "dm-bio-prison-v2.h"#include "dm-bio-record.h"#include "dm-cache-metadata.h"#include "dm-io-tracker.h"#include "dm-cache-background-tracker.h" #include <linux/dm-io.h>#include <linux/dm-kcopyd.h>#include <linux/jiffies.h>#include <linux/init.h>#include <linux/kstrtox.h>#include <linux/mempool.h>#include <linux/module.h>#include <linux/rwsem.h>#include <linux/slab.h>#include <linux/vmalloc.h> #define DM_MSG_PREFIX "cache" DECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM(cache_copy_throttle,	"A percentage of time allocated for copying to and/or from cache"); /*----------------------------------------------------------------*/ /* * Glossary: * * oblock: index of an origin block * cblock: index of a cache block * promotion: movement of a block from origin to cache * demotion: movement of a block from cache to origin * migration: movement of a block between the origin and cache device, *	      either direction */ /*----------------------------------------------------------------*/ /* * Represents a chunk of future work.  'input' allows continuations to pass * values between themselves, typically error values. */struct continuation {	struct work_struct ws;	blk_status_t input;}; static inline void init_continuation(struct continuation *k,				     void (*fn)(struct work_struct *)){	INIT_WORK(&k->ws, fn);	k->input = 0;} static inline void queue_continuation(struct workqueue_struct *wq,				      struct continuation *k){	queue_work(wq, &k->ws);} /*----------------------------------------------------------------*/ /* * The batcher collects together pieces of work that need a particular * operation to occur before they can proceed (typically a commit). */struct batcher {	/*	 * The operation that everyone is waiting for.	 */	blk_status_t (*commit_op)(void *context);	void *commit_context; 	/*	 * This is how bios should be issued once the commit op is complete	 * (accounted_request).	 */	void (*issue_op)(struct bio *bio, void *context);	void *issue_context; 	/*	 * Queued work gets put on here after commit.	 */	struct workqueue_struct *wq; 	spinlock_t lock;	struct list_head work_items;	struct bio_list bios;	struct work_struct commit_work; 	bool commit_scheduled;}; static void __commit(struct work_struct *_ws){	struct batcher *b = container_of(_ws, struct batcher, commit_work);	blk_status_t r;	struct list_head work_items;	struct work_struct *ws, *tmp;	struct continuation *k;	struct bio *bio;	struct bio_list bios; 	INIT_LIST_HEAD(&work_items);	bio_list_init(&bios); 	/*	 * We have to grab these before the commit_op to avoid a race	 * condition.	 */	spin_lock_irq(&b->lock);	list_splice_init(&b->work_items, &work_items);	bio_list_merge_init(&bios, &b->bios);	b->commit_scheduled = false;	spin_unlock_irq(&b->lock); 	r = b->commit_op(b->commit_context); 	list_for_each_entry_safe(ws, tmp, &work_items, entry) {		k = container_of(ws, struct continuation, ws);		k->input = r;		INIT_LIST_HEAD(&ws->entry); /* to avoid a WARN_ON */		queue_work(b->wq, ws);	} 	while ((bio = bio_list_pop(&bios))) {		if (r) {			bio->bi_status = r;			bio_endio(bio);		} else			b->issue_op(bio, b->issue_context);	}} static void batcher_init(struct batcher *b,			 blk_status_t (*commit_op)(void *),			 void *commit_context,			 void (*issue_op)(struct bio *bio, void *),			 void *issue_context,			 struct workqueue_struct *wq){	b->commit_op = commit_op;	b->commit_context = commit_context;	b->issue_op = issue_op;	b->issue_context = issue_context;	b->wq = wq; 	spin_lock_init(&b->lock);	INIT_LIST_HEAD(&b->work_items);	bio_list_init(&b->bios);	INIT_WORK(&b->commit_work, __commit);	b->commit_scheduled = false;} static void async_commit(struct batcher *b){	queue_work(b->wq, &b->commit_work);} static void continue_after_commit(struct batcher *b, struct continuation *k){	bool commit_scheduled; 	spin_lock_irq(&b->lock);	commit_scheduled = b->commit_scheduled;	list_add_tail(&k->ws.entry, &b->work_items);	spin_unlock_irq(&b->lock); 	if (commit_scheduled)		async_commit(b);} /* * Bios are errored if commit failed. */static void issue_after_commit(struct batcher *b, struct bio *bio){	bool commit_scheduled; 	spin_lock_irq(&b->lock);	commit_scheduled = b->commit_scheduled;	bio_list_add(&b->bios, bio);	spin_unlock_irq(&b->lock); 	if (commit_scheduled)		async_commit(b);} /* * Call this if some urgent work is waiting for the commit to complete. */static void schedule_commit(struct batcher *b){	bool immediate; 	spin_lock_irq(&b->lock);	immediate = !list_empty(&b->work_items) || !bio_list_empty(&b->bios);	b->commit_scheduled = true;	spin_unlock_irq(&b->lock); 	if (immediate)		async_commit(b);} /* * There are a couple of places where we let a bio run, but want to do some * work before calling its endio function.  We do this by temporarily * changing the endio fn. */struct dm_hook_info {	bio_end_io_t *bi_end_io;}; static void dm_hook_bio(struct dm_hook_info *h, struct bio *bio,			bio_end_io_t *bi_end_io, void *bi_private){	h->bi_end_io = bio->bi_end_io; 	bio->bi_end_io = bi_end_io;	bio->bi_private = bi_private;} static void dm_unhook_bio(struct dm_hook_info *h, struct bio *bio){	bio->bi_end_io = h->bi_end_io;} /*----------------------------------------------------------------*/ #define MIGRATION_POOL_SIZE 128#define COMMIT_PERIOD HZ#define MIGRATION_COUNT_WINDOW 10 /* * The block size of the device holding cache data must be * between 32KB and 1GB. */#define DATA_DEV_BLOCK_SIZE_MIN_SECTORS (32 * 1024 >> SECTOR_SHIFT)#define DATA_DEV_BLOCK_SIZE_MAX_SECTORS (1024 * 1024 * 1024 >> SECTOR_SHIFT) enum cache_metadata_mode {	CM_WRITE,		/* metadata may be changed */	CM_READ_ONLY,		/* metadata may not be changed */	CM_FAIL}; enum cache_io_mode {	/*	 * Data is written to cached blocks only.  These blocks are marked	 * dirty.  If you lose the cache device you will lose data.	 * Potential performance increase for both reads and writes.	 */	CM_IO_WRITEBACK, 	/*	 * Data is written to both cache and origin.  Blocks are never	 * dirty.  Potential performance benfit for reads only.	 */	CM_IO_WRITETHROUGH, 	/*	 * A degraded mode useful for various cache coherency situations	 * (eg, rolling back snapshots).  Reads and writes always go to the	 * origin.  If a write goes to a cached oblock, then the cache	 * block is invalidated.	 */	CM_IO_PASSTHROUGH}; struct cache_features {	enum cache_metadata_mode mode;	enum cache_io_mode io_mode;	unsigned int metadata_version;	bool discard_passdown:1;}; struct cache_stats {	atomic_t read_hit;	atomic_t read_miss;	atomic_t write_hit;	atomic_t write_miss;	atomic_t demotion;	atomic_t promotion;	atomic_t writeback;	atomic_t copies_avoided;	atomic_t cache_cell_clash;	atomic_t commit_count;	atomic_t discard_count;}; struct cache {	struct dm_target *ti;	spinlock_t lock; 	/*	 * Fields for converting from sectors to blocks.	 */	int sectors_per_block_shift;	sector_t sectors_per_block; 	struct dm_cache_metadata *cmd; 	/*	 * Metadata is written to this device.	 */	struct dm_dev *metadata_dev; 	/*	 * The slower of the two data devices.  Typically a spindle.	 */	struct dm_dev *origin_dev; 	/*	 * The faster of the two data devices.  Typically an SSD.	 */	struct dm_dev *cache_dev; 	/*	 * Size of the origin device in _complete_ blocks and native sectors.	 */	dm_oblock_t origin_blocks;	sector_t origin_sectors; 	/*	 * Size of the cache device in blocks.	 */	dm_cblock_t cache_size; 	/*	 * Invalidation fields.	 */	spinlock_t invalidation_lock;	struct list_head invalidation_requests; 	sector_t migration_threshold; 	/*	 * The number of in flight migrations that are performing	 * background io. eg, promotion, writeback.	 */	atomic_t nr_io_migrations; 	struct bio_list deferred_bios; 	struct rw_semaphore quiesce_lock; 	/*	 * origin_blocks entries, discarded if set.	 */	dm_dblock_t discard_nr_blocks;	unsigned long *discard_bitset;	uint32_t discard_block_size; /* a power of 2 times sectors per block */ 	/*	 * Rather than reconstructing the table line for the status we just	 * save it and regurgitate.	 */	unsigned int nr_ctr_args;	const char **ctr_args; 	struct dm_kcopyd_client *copier;	struct work_struct deferred_bio_worker;	struct work_struct migration_worker;	struct workqueue_struct *wq;	struct delayed_work waker;	struct dm_bio_prison_v2 *prison; 	/*	 * cache_size entries, dirty if set	 */	unsigned long *dirty_bitset;	atomic_t nr_dirty; 	unsigned int policy_nr_args;	struct dm_cache_policy *policy; 	/*	 * Cache features such as write-through.	 */	struct cache_features features; 	struct cache_stats stats; 	bool need_tick_bio:1;	bool sized:1;	bool invalidate:1;	bool commit_requested:1;	bool loaded_mappings:1;	bool loaded_discards:1; 	/* background work management */	bool background_work_allowed;	unsigned background_work_nr;	spinlock_t background_work_lock;	wait_queue_head_t background_work_wait; 	struct batcher committer;	struct work_struct commit_ws; 	struct dm_io_tracker tracker; 	mempool_t migration_pool; 	struct bio_set bs; 	/*	 * Cache_size entries. Set bits indicate blocks mapped beyond the	 * target length, which are marked for invalidation.	 */	unsigned long *invalid_bitset;}; struct per_bio_data {	bool tick:1;	unsigned int req_nr:2;	struct dm_bio_prison_cell_v2 *cell;	struct dm_hook_info hook_info;	sector_t len;}; struct dm_cache_migration {	struct continuation k;	struct cache *cache; 	struct policy_work *op;	struct bio *overwrite_bio;	struct dm_bio_prison_cell_v2 *cell; 	dm_cblock_t invalidate_cblock;	dm_oblock_t invalidate_oblock;}; /*----------------------------------------------------------------*/ static bool writethrough_mode(struct cache *cache){	return cache->features.io_mode == CM_IO_WRITETHROUGH;} static bool writeback_mode(struct cache *cache){	return cache->features.io_mode == CM_IO_WRITEBACK;} static inline bool passthrough_mode(struct cache *cache){	return unlikely(cache->features.io_mode == CM_IO_PASSTHROUGH);} /*----------------------------------------------------------------*/ static void wake_deferred_bio_worker(struct cache *cache){	queue_work(cache->wq, &cache->deferred_bio_worker);} static void wake_migration_worker(struct cache *cache){	if (passthrough_mode(cache))		return; 	queue_work(cache->wq, &cache->migration_worker);} /*----------------------------------------------------------------*/ static struct dm_bio_prison_cell_v2 *alloc_prison_cell(struct cache *cache){	return dm_bio_prison_alloc_cell_v2(cache->prison, GFP_NOIO);} static void free_prison_cell(struct cache *cache, struct dm_bio_prison_cell_v2 *cell){	dm_bio_prison_free_cell_v2(cache->prison, cell);} static struct dm_cache_migration *alloc_migration(struct cache *cache){	struct dm_cache_migration *mg; 	mg = mempool_alloc(&cache->migration_pool, GFP_NOIO); 	memset(mg, 0, sizeof(*mg)); 	mg->cache = cache; 	return mg;} static void free_migration(struct dm_cache_migration *mg){	mempool_free(mg, &mg->cache->migration_pool);}

Lines 1–500 of 3615.