4558 lines · 112.8 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-only/* * Copyright (C) 2011-2012 Red Hat UK. * * This file is released under the GPL. */ #include "dm-thin-metadata.h"#include "dm-bio-prison-v1.h"#include "dm.h" #include <linux/device-mapper.h>#include <linux/dm-io.h>#include <linux/dm-kcopyd.h>#include <linux/jiffies.h>#include <linux/log2.h>#include <linux/list.h>#include <linux/rculist.h>#include <linux/init.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/sort.h>#include <linux/rbtree.h> #define	DM_MSG_PREFIX	"thin" /* * Tunable constants */#define ENDIO_HOOK_POOL_SIZE 1024#define MAPPING_POOL_SIZE 1024#define COMMIT_PERIOD HZ#define NO_SPACE_TIMEOUT_SECS 60 static unsigned int no_space_timeout_secs = NO_SPACE_TIMEOUT_SECS; DECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM(snapshot_copy_throttle,		"A percentage of time allocated for copy on write"); /* * The block size of the device holding pool data must be * between 64KB and 1GB. */#define DATA_DEV_BLOCK_SIZE_MIN_SECTORS (64 * 1024 >> SECTOR_SHIFT)#define DATA_DEV_BLOCK_SIZE_MAX_SECTORS (1024 * 1024 * 1024 >> SECTOR_SHIFT) /* * Device id is restricted to 24 bits. */#define MAX_DEV_ID ((1 << 24) - 1) /* * How do we handle breaking sharing of data blocks? * ================================================= * * We use a standard copy-on-write btree to store the mappings for the * devices (note I'm talking about copy-on-write of the metadata here, not * the data).  When you take an internal snapshot you clone the root node * of the origin btree.  After this there is no concept of an origin or a * snapshot.  They are just two device trees that happen to point to the * same data blocks. * * When we get a write in we decide if it's to a shared data block using * some timestamp magic.  If it is, we have to break sharing. * * Let's say we write to a shared block in what was the origin.  The * steps are: * * i) plug io further to this physical block. (see bio_prison code). * * ii) quiesce any read io to that shared data block.  Obviously * including all devices that share this block.  (see dm_deferred_set code) * * iii) copy the data block to a newly allocate block.  This step can be * missed out if the io covers the block. (schedule_copy). * * iv) insert the new mapping into the origin's btree * (process_prepared_mapping).  This act of inserting breaks some * sharing of btree nodes between the two devices.  Breaking sharing only * effects the btree of that specific device.  Btrees for the other * devices that share the block never change.  The btree for the origin * device as it was after the last commit is untouched, ie. we're using * persistent data structures in the functional programming sense. * * v) unplug io to this physical block, including the io that triggered * the breaking of sharing. * * Steps (ii) and (iii) occur in parallel. * * The metadata _doesn't_ need to be committed before the io continues.  We * get away with this because the io is always written to a _new_ block. * If there's a crash, then: * * - The origin mapping will point to the old origin block (the shared * one).  This will contain the data as it was before the io that triggered * the breaking of sharing came in. * * - The snap mapping still points to the old block.  As it would after * the commit. * * The downside of this scheme is the timestamp magic isn't perfect, and * will continue to think that data block in the snapshot device is shared * even after the write to the origin has broken sharing.  I suspect data * blocks will typically be shared by many different devices, so we're * breaking sharing n + 1 times, rather than n, where n is the number of * devices that reference this data block.  At the moment I think the * benefits far, far outweigh the disadvantages. */ /*----------------------------------------------------------------*/ /* * Key building. */enum lock_space {	VIRTUAL,	PHYSICAL}; static bool build_key(struct dm_thin_device *td, enum lock_space ls,		      dm_block_t b, dm_block_t e, struct dm_cell_key *key){	key->virtual = (ls == VIRTUAL);	key->dev = dm_thin_dev_id(td);	key->block_begin = b;	key->block_end = e; 	return dm_cell_key_has_valid_range(key);} static void build_data_key(struct dm_thin_device *td, dm_block_t b,			   struct dm_cell_key *key){	(void) build_key(td, PHYSICAL, b, b + 1llu, key);} static void build_virtual_key(struct dm_thin_device *td, dm_block_t b,			      struct dm_cell_key *key){	(void) build_key(td, VIRTUAL, b, b + 1llu, key);} /*----------------------------------------------------------------*/ #define THROTTLE_THRESHOLD (1 * HZ) struct throttle {	struct rw_semaphore lock;	unsigned long threshold;	bool throttle_applied;}; static void throttle_init(struct throttle *t){	init_rwsem(&t->lock);	t->throttle_applied = false;} static void throttle_work_start(struct throttle *t){	t->threshold = jiffies + THROTTLE_THRESHOLD;} static void throttle_work_update(struct throttle *t){	if (!t->throttle_applied && time_is_before_jiffies(t->threshold)) {		down_write(&t->lock);		t->throttle_applied = true;	}} static void throttle_work_complete(struct throttle *t){	if (t->throttle_applied) {		t->throttle_applied = false;		up_write(&t->lock);	}} static void throttle_lock(struct throttle *t){	down_read(&t->lock);} static void throttle_unlock(struct throttle *t){	up_read(&t->lock);} /*----------------------------------------------------------------*/ /* * A pool device ties together a metadata device and a data device.  It * also provides the interface for creating and destroying internal * devices. */struct dm_thin_new_mapping; /* * The pool runs in various modes.  Ordered in degraded order for comparisons. */enum pool_mode {	PM_WRITE,		/* metadata may be changed */	PM_OUT_OF_DATA_SPACE,	/* metadata may be changed, though data may not be allocated */ 	/*	 * Like READ_ONLY, except may switch back to WRITE on metadata resize. Reported as READ_ONLY.	 */	PM_OUT_OF_METADATA_SPACE,	PM_READ_ONLY,		/* metadata may not be changed */ 	PM_FAIL,		/* all I/O fails */}; struct pool_features {	enum pool_mode mode; 	bool zero_new_blocks:1;	bool discard_enabled:1;	bool discard_passdown:1;	bool error_if_no_space:1;}; struct thin_c;typedef void (*process_bio_fn)(struct thin_c *tc, struct bio *bio);typedef void (*process_cell_fn)(struct thin_c *tc, struct dm_bio_prison_cell *cell);typedef void (*process_mapping_fn)(struct dm_thin_new_mapping *m); #define CELL_SORT_ARRAY_SIZE 8192 struct pool {	struct list_head list;	struct dm_target *ti;	/* Only set if a pool target is bound */ 	struct mapped_device *pool_md;	struct block_device *data_dev;	struct block_device *md_dev;	struct dm_pool_metadata *pmd; 	dm_block_t low_water_blocks;	uint32_t sectors_per_block;	int sectors_per_block_shift; 	struct pool_features pf;	bool low_water_triggered:1;	/* A dm event has been sent */	bool suspended:1;	bool out_of_data_space:1; 	struct dm_bio_prison *prison;	struct dm_kcopyd_client *copier; 	struct work_struct worker;	struct workqueue_struct *wq;	struct throttle throttle;	struct delayed_work waker;	struct delayed_work no_space_timeout; 	unsigned long last_commit_jiffies;	unsigned int ref_count; 	spinlock_t lock;	struct bio_list deferred_flush_bios;	struct bio_list deferred_flush_completions;	struct list_head prepared_mappings;	struct list_head prepared_discards;	struct list_head prepared_discards_pt2;	struct list_head active_thins; 	struct dm_deferred_set *shared_read_ds;	struct dm_deferred_set *all_io_ds; 	struct dm_thin_new_mapping *next_mapping; 	process_bio_fn process_bio;	process_bio_fn process_discard; 	process_cell_fn process_cell;	process_cell_fn process_discard_cell; 	process_mapping_fn process_prepared_mapping;	process_mapping_fn process_prepared_discard;	process_mapping_fn process_prepared_discard_pt2; 	struct dm_bio_prison_cell **cell_sort_array; 	mempool_t mapping_pool;}; static void metadata_operation_failed(struct pool *pool, const char *op, int r); static enum pool_mode get_pool_mode(struct pool *pool){	return pool->pf.mode;} static void notify_of_pool_mode_change(struct pool *pool){	static const char *descs[] = {		"write",		"out-of-data-space",		"read-only",		"read-only",		"fail"	};	const char *extra_desc = NULL;	enum pool_mode mode = get_pool_mode(pool); 	if (mode == PM_OUT_OF_DATA_SPACE) {		if (!pool->pf.error_if_no_space)			extra_desc = " (queue IO)";		else			extra_desc = " (error IO)";	} 	dm_table_event(pool->ti->table);	DMINFO("%s: switching pool to %s%s mode",	       dm_device_name(pool->pool_md),	       descs[(int)mode], extra_desc ? : "");} /* * Target context for a pool. */struct pool_c {	struct dm_target *ti;	struct pool *pool;	struct dm_dev *data_dev;	struct dm_dev *metadata_dev; 	dm_block_t low_water_blocks;	struct pool_features requested_pf; /* Features requested during table load */	struct pool_features adjusted_pf;  /* Features used after adjusting for constituent devices */}; /* * Target context for a thin. */struct thin_c {	struct list_head list;	struct dm_dev *pool_dev;	struct dm_dev *origin_dev;	sector_t origin_size;	dm_thin_id dev_id; 	struct pool *pool;	struct dm_thin_device *td;	struct mapped_device *thin_md; 	bool requeue_mode:1;	spinlock_t lock;	struct list_head deferred_cells;	struct bio_list deferred_bio_list;	struct bio_list retry_on_resume_list;	struct rb_root sort_bio_list; /* sorted list of deferred bios */ 	/*	 * Ensures the thin is not destroyed until the worker has finished	 * iterating the active_thins list.	 */	refcount_t refcount;	struct completion can_destroy;}; /*----------------------------------------------------------------*/ static bool block_size_is_power_of_two(struct pool *pool){	return pool->sectors_per_block_shift >= 0;} static sector_t block_to_sectors(struct pool *pool, dm_block_t b){	return block_size_is_power_of_two(pool) ?		(b << pool->sectors_per_block_shift) :		(b * pool->sectors_per_block);} /*----------------------------------------------------------------*/ struct discard_op {	struct thin_c *tc;	struct blk_plug plug;	struct bio *parent_bio;	struct bio *bio;}; static void begin_discard(struct discard_op *op, struct thin_c *tc, struct bio *parent){	BUG_ON(!parent); 	op->tc = tc;	blk_start_plug(&op->plug);	op->parent_bio = parent;	op->bio = NULL;} static void issue_discard(struct discard_op *op, dm_block_t data_b, dm_block_t data_e){	struct thin_c *tc = op->tc;	sector_t s = block_to_sectors(tc->pool, data_b);	sector_t len = block_to_sectors(tc->pool, data_e - data_b); 	__blkdev_issue_discard(tc->pool_dev->bdev, s, len, GFP_NOIO, &op->bio);} static void end_discard(struct discard_op *op, int r){	if (op->bio) {		/*		 * Even if one of the calls to issue_discard failed, we		 * need to wait for the chain to complete.		 */		bio_chain(op->bio, op->parent_bio);		op->bio->bi_opf = REQ_OP_DISCARD;		submit_bio(op->bio);	} 	blk_finish_plug(&op->plug); 	/*	 * Even if r is set, there could be sub discards in flight that we	 * need to wait for.	 */	if (r && !op->parent_bio->bi_status)		op->parent_bio->bi_status = errno_to_blk_status(r);	bio_endio(op->parent_bio);} /*----------------------------------------------------------------*/ /* * wake_worker() is used when new work is queued and when pool_resume is * ready to continue deferred IO processing. */static void wake_worker(struct pool *pool){	queue_work(pool->wq, &pool->worker);} /*----------------------------------------------------------------*/ static int bio_detain(struct pool *pool, struct dm_cell_key *key, struct bio *bio,		      struct dm_bio_prison_cell **cell_result){	int r;	struct dm_bio_prison_cell *cell_prealloc; 	/*	 * Allocate a cell from the prison's mempool.	 * This might block but it can't fail.	 */	cell_prealloc = dm_bio_prison_alloc_cell(pool->prison, GFP_NOIO); 	r = dm_bio_detain(pool->prison, key, bio, cell_prealloc, cell_result);	if (r) {		/*		 * We reused an old cell; we can get rid of		 * the new one.		 */		dm_bio_prison_free_cell(pool->prison, cell_prealloc);	} 	return r;} static void cell_release(struct pool *pool,			 struct dm_bio_prison_cell *cell,			 struct bio_list *bios){	dm_cell_release(pool->prison, cell, bios);	dm_bio_prison_free_cell(pool->prison, cell);} static void cell_visit_release(struct pool *pool,			       void (*fn)(void *, struct dm_bio_prison_cell *),			       void *context,			       struct dm_bio_prison_cell *cell){	dm_cell_visit_release(pool->prison, fn, context, cell);	dm_bio_prison_free_cell(pool->prison, cell);} static void cell_release_no_holder(struct pool *pool,				   struct dm_bio_prison_cell *cell,				   struct bio_list *bios){	dm_cell_release_no_holder(pool->prison, cell, bios);	dm_bio_prison_free_cell(pool->prison, cell);} static void cell_error_with_code(struct pool *pool,		struct dm_bio_prison_cell *cell, blk_status_t error_code){	dm_cell_error(pool->prison, cell, error_code);	dm_bio_prison_free_cell(pool->prison, cell);} static blk_status_t get_pool_io_error_code(struct pool *pool){

Lines 1–500 of 4558.