18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (C) 2001-2002 Sistina Software (UK) Limited. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * This file is released under the GPL. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 88c2ecf20Sopenharmony_ci#include <linux/device-mapper.h> 98c2ecf20Sopenharmony_ci#include <linux/delay.h> 108c2ecf20Sopenharmony_ci#include <linux/fs.h> 118c2ecf20Sopenharmony_ci#include <linux/init.h> 128c2ecf20Sopenharmony_ci#include <linux/kdev_t.h> 138c2ecf20Sopenharmony_ci#include <linux/list.h> 148c2ecf20Sopenharmony_ci#include <linux/list_bl.h> 158c2ecf20Sopenharmony_ci#include <linux/mempool.h> 168c2ecf20Sopenharmony_ci#include <linux/module.h> 178c2ecf20Sopenharmony_ci#include <linux/slab.h> 188c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 198c2ecf20Sopenharmony_ci#include <linux/log2.h> 208c2ecf20Sopenharmony_ci#include <linux/dm-kcopyd.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include "dm.h" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include "dm-exception-store.h" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define DM_MSG_PREFIX "snapshots" 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic const char dm_snapshot_merge_target_name[] = "snapshot-merge"; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define dm_target_is_snapshot_merge(ti) \ 318c2ecf20Sopenharmony_ci ((ti)->type->name == dm_snapshot_merge_target_name) 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci/* 348c2ecf20Sopenharmony_ci * The size of the mempool used to track chunks in use. 358c2ecf20Sopenharmony_ci */ 368c2ecf20Sopenharmony_ci#define MIN_IOS 256 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#define DM_TRACKED_CHUNK_HASH_SIZE 16 398c2ecf20Sopenharmony_ci#define DM_TRACKED_CHUNK_HASH(x) ((unsigned long)(x) & \ 408c2ecf20Sopenharmony_ci (DM_TRACKED_CHUNK_HASH_SIZE - 1)) 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistruct dm_exception_table { 438c2ecf20Sopenharmony_ci uint32_t hash_mask; 448c2ecf20Sopenharmony_ci unsigned hash_shift; 458c2ecf20Sopenharmony_ci struct hlist_bl_head *table; 468c2ecf20Sopenharmony_ci}; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistruct dm_snapshot { 498c2ecf20Sopenharmony_ci struct rw_semaphore lock; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci struct dm_dev *origin; 528c2ecf20Sopenharmony_ci struct dm_dev *cow; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci struct dm_target *ti; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci /* List of snapshots per Origin */ 578c2ecf20Sopenharmony_ci struct list_head list; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci /* 608c2ecf20Sopenharmony_ci * You can't use a snapshot if this is 0 (e.g. if full). 618c2ecf20Sopenharmony_ci * A snapshot-merge target never clears this. 628c2ecf20Sopenharmony_ci */ 638c2ecf20Sopenharmony_ci int valid; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci /* 668c2ecf20Sopenharmony_ci * The snapshot overflowed because of a write to the snapshot device. 678c2ecf20Sopenharmony_ci * We don't have to invalidate the snapshot in this case, but we need 688c2ecf20Sopenharmony_ci * to prevent further writes. 698c2ecf20Sopenharmony_ci */ 708c2ecf20Sopenharmony_ci int snapshot_overflowed; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci /* Origin writes don't trigger exceptions until this is set */ 738c2ecf20Sopenharmony_ci int active; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci atomic_t pending_exceptions_count; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci spinlock_t pe_allocation_lock; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci /* Protected by "pe_allocation_lock" */ 808c2ecf20Sopenharmony_ci sector_t exception_start_sequence; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci /* Protected by kcopyd single-threaded callback */ 838c2ecf20Sopenharmony_ci sector_t exception_complete_sequence; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci /* 868c2ecf20Sopenharmony_ci * A list of pending exceptions that completed out of order. 878c2ecf20Sopenharmony_ci * Protected by kcopyd single-threaded callback. 888c2ecf20Sopenharmony_ci */ 898c2ecf20Sopenharmony_ci struct rb_root out_of_order_tree; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci mempool_t pending_pool; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci struct dm_exception_table pending; 948c2ecf20Sopenharmony_ci struct dm_exception_table complete; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci /* 978c2ecf20Sopenharmony_ci * pe_lock protects all pending_exception operations and access 988c2ecf20Sopenharmony_ci * as well as the snapshot_bios list. 998c2ecf20Sopenharmony_ci */ 1008c2ecf20Sopenharmony_ci spinlock_t pe_lock; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci /* Chunks with outstanding reads */ 1038c2ecf20Sopenharmony_ci spinlock_t tracked_chunk_lock; 1048c2ecf20Sopenharmony_ci struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE]; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci /* The on disk metadata handler */ 1078c2ecf20Sopenharmony_ci struct dm_exception_store *store; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci unsigned in_progress; 1108c2ecf20Sopenharmony_ci struct wait_queue_head in_progress_wait; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci struct dm_kcopyd_client *kcopyd_client; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci /* Wait for events based on state_bits */ 1158c2ecf20Sopenharmony_ci unsigned long state_bits; 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci /* Range of chunks currently being merged. */ 1188c2ecf20Sopenharmony_ci chunk_t first_merging_chunk; 1198c2ecf20Sopenharmony_ci int num_merging_chunks; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci /* 1228c2ecf20Sopenharmony_ci * The merge operation failed if this flag is set. 1238c2ecf20Sopenharmony_ci * Failure modes are handled as follows: 1248c2ecf20Sopenharmony_ci * - I/O error reading the header 1258c2ecf20Sopenharmony_ci * => don't load the target; abort. 1268c2ecf20Sopenharmony_ci * - Header does not have "valid" flag set 1278c2ecf20Sopenharmony_ci * => use the origin; forget about the snapshot. 1288c2ecf20Sopenharmony_ci * - I/O error when reading exceptions 1298c2ecf20Sopenharmony_ci * => don't load the target; abort. 1308c2ecf20Sopenharmony_ci * (We can't use the intermediate origin state.) 1318c2ecf20Sopenharmony_ci * - I/O error while merging 1328c2ecf20Sopenharmony_ci * => stop merging; set merge_failed; process I/O normally. 1338c2ecf20Sopenharmony_ci */ 1348c2ecf20Sopenharmony_ci bool merge_failed:1; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci bool discard_zeroes_cow:1; 1378c2ecf20Sopenharmony_ci bool discard_passdown_origin:1; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci /* 1408c2ecf20Sopenharmony_ci * Incoming bios that overlap with chunks being merged must wait 1418c2ecf20Sopenharmony_ci * for them to be committed. 1428c2ecf20Sopenharmony_ci */ 1438c2ecf20Sopenharmony_ci struct bio_list bios_queued_during_merge; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci /* 1468c2ecf20Sopenharmony_ci * Flush data after merge. 1478c2ecf20Sopenharmony_ci */ 1488c2ecf20Sopenharmony_ci struct bio flush_bio; 1498c2ecf20Sopenharmony_ci}; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci/* 1528c2ecf20Sopenharmony_ci * state_bits: 1538c2ecf20Sopenharmony_ci * RUNNING_MERGE - Merge operation is in progress. 1548c2ecf20Sopenharmony_ci * SHUTDOWN_MERGE - Set to signal that merge needs to be stopped; 1558c2ecf20Sopenharmony_ci * cleared afterwards. 1568c2ecf20Sopenharmony_ci */ 1578c2ecf20Sopenharmony_ci#define RUNNING_MERGE 0 1588c2ecf20Sopenharmony_ci#define SHUTDOWN_MERGE 1 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci/* 1618c2ecf20Sopenharmony_ci * Maximum number of chunks being copied on write. 1628c2ecf20Sopenharmony_ci * 1638c2ecf20Sopenharmony_ci * The value was decided experimentally as a trade-off between memory 1648c2ecf20Sopenharmony_ci * consumption, stalling the kernel's workqueues and maintaining a high enough 1658c2ecf20Sopenharmony_ci * throughput. 1668c2ecf20Sopenharmony_ci */ 1678c2ecf20Sopenharmony_ci#define DEFAULT_COW_THRESHOLD 2048 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic unsigned cow_threshold = DEFAULT_COW_THRESHOLD; 1708c2ecf20Sopenharmony_cimodule_param_named(snapshot_cow_threshold, cow_threshold, uint, 0644); 1718c2ecf20Sopenharmony_ciMODULE_PARM_DESC(snapshot_cow_threshold, "Maximum number of chunks being copied on write"); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ciDECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM(snapshot_copy_throttle, 1748c2ecf20Sopenharmony_ci "A percentage of time allocated for copy on write"); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_cistruct dm_dev *dm_snap_origin(struct dm_snapshot *s) 1778c2ecf20Sopenharmony_ci{ 1788c2ecf20Sopenharmony_ci return s->origin; 1798c2ecf20Sopenharmony_ci} 1808c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dm_snap_origin); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistruct dm_dev *dm_snap_cow(struct dm_snapshot *s) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci return s->cow; 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dm_snap_cow); 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistatic sector_t chunk_to_sector(struct dm_exception_store *store, 1898c2ecf20Sopenharmony_ci chunk_t chunk) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci return chunk << store->chunk_shift; 1928c2ecf20Sopenharmony_ci} 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_cistatic int bdev_equal(struct block_device *lhs, struct block_device *rhs) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci /* 1978c2ecf20Sopenharmony_ci * There is only ever one instance of a particular block 1988c2ecf20Sopenharmony_ci * device so we can compare pointers safely. 1998c2ecf20Sopenharmony_ci */ 2008c2ecf20Sopenharmony_ci return lhs == rhs; 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cistruct dm_snap_pending_exception { 2048c2ecf20Sopenharmony_ci struct dm_exception e; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci /* 2078c2ecf20Sopenharmony_ci * Origin buffers waiting for this to complete are held 2088c2ecf20Sopenharmony_ci * in a bio list 2098c2ecf20Sopenharmony_ci */ 2108c2ecf20Sopenharmony_ci struct bio_list origin_bios; 2118c2ecf20Sopenharmony_ci struct bio_list snapshot_bios; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci /* Pointer back to snapshot context */ 2148c2ecf20Sopenharmony_ci struct dm_snapshot *snap; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci /* 2178c2ecf20Sopenharmony_ci * 1 indicates the exception has already been sent to 2188c2ecf20Sopenharmony_ci * kcopyd. 2198c2ecf20Sopenharmony_ci */ 2208c2ecf20Sopenharmony_ci int started; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci /* There was copying error. */ 2238c2ecf20Sopenharmony_ci int copy_error; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci /* A sequence number, it is used for in-order completion. */ 2268c2ecf20Sopenharmony_ci sector_t exception_sequence; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci struct rb_node out_of_order_node; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci /* 2318c2ecf20Sopenharmony_ci * For writing a complete chunk, bypassing the copy. 2328c2ecf20Sopenharmony_ci */ 2338c2ecf20Sopenharmony_ci struct bio *full_bio; 2348c2ecf20Sopenharmony_ci bio_end_io_t *full_bio_end_io; 2358c2ecf20Sopenharmony_ci}; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci/* 2388c2ecf20Sopenharmony_ci * Hash table mapping origin volumes to lists of snapshots and 2398c2ecf20Sopenharmony_ci * a lock to protect it 2408c2ecf20Sopenharmony_ci */ 2418c2ecf20Sopenharmony_cistatic struct kmem_cache *exception_cache; 2428c2ecf20Sopenharmony_cistatic struct kmem_cache *pending_cache; 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_cistruct dm_snap_tracked_chunk { 2458c2ecf20Sopenharmony_ci struct hlist_node node; 2468c2ecf20Sopenharmony_ci chunk_t chunk; 2478c2ecf20Sopenharmony_ci}; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_cistatic void init_tracked_chunk(struct bio *bio) 2508c2ecf20Sopenharmony_ci{ 2518c2ecf20Sopenharmony_ci struct dm_snap_tracked_chunk *c = dm_per_bio_data(bio, sizeof(struct dm_snap_tracked_chunk)); 2528c2ecf20Sopenharmony_ci INIT_HLIST_NODE(&c->node); 2538c2ecf20Sopenharmony_ci} 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_cistatic bool is_bio_tracked(struct bio *bio) 2568c2ecf20Sopenharmony_ci{ 2578c2ecf20Sopenharmony_ci struct dm_snap_tracked_chunk *c = dm_per_bio_data(bio, sizeof(struct dm_snap_tracked_chunk)); 2588c2ecf20Sopenharmony_ci return !hlist_unhashed(&c->node); 2598c2ecf20Sopenharmony_ci} 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_cistatic void track_chunk(struct dm_snapshot *s, struct bio *bio, chunk_t chunk) 2628c2ecf20Sopenharmony_ci{ 2638c2ecf20Sopenharmony_ci struct dm_snap_tracked_chunk *c = dm_per_bio_data(bio, sizeof(struct dm_snap_tracked_chunk)); 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci c->chunk = chunk; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci spin_lock_irq(&s->tracked_chunk_lock); 2688c2ecf20Sopenharmony_ci hlist_add_head(&c->node, 2698c2ecf20Sopenharmony_ci &s->tracked_chunk_hash[DM_TRACKED_CHUNK_HASH(chunk)]); 2708c2ecf20Sopenharmony_ci spin_unlock_irq(&s->tracked_chunk_lock); 2718c2ecf20Sopenharmony_ci} 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_cistatic void stop_tracking_chunk(struct dm_snapshot *s, struct bio *bio) 2748c2ecf20Sopenharmony_ci{ 2758c2ecf20Sopenharmony_ci struct dm_snap_tracked_chunk *c = dm_per_bio_data(bio, sizeof(struct dm_snap_tracked_chunk)); 2768c2ecf20Sopenharmony_ci unsigned long flags; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci spin_lock_irqsave(&s->tracked_chunk_lock, flags); 2798c2ecf20Sopenharmony_ci hlist_del(&c->node); 2808c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&s->tracked_chunk_lock, flags); 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_cistatic int __chunk_is_tracked(struct dm_snapshot *s, chunk_t chunk) 2848c2ecf20Sopenharmony_ci{ 2858c2ecf20Sopenharmony_ci struct dm_snap_tracked_chunk *c; 2868c2ecf20Sopenharmony_ci int found = 0; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci spin_lock_irq(&s->tracked_chunk_lock); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci hlist_for_each_entry(c, 2918c2ecf20Sopenharmony_ci &s->tracked_chunk_hash[DM_TRACKED_CHUNK_HASH(chunk)], node) { 2928c2ecf20Sopenharmony_ci if (c->chunk == chunk) { 2938c2ecf20Sopenharmony_ci found = 1; 2948c2ecf20Sopenharmony_ci break; 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci } 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci spin_unlock_irq(&s->tracked_chunk_lock); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci return found; 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci/* 3048c2ecf20Sopenharmony_ci * This conflicting I/O is extremely improbable in the caller, 3058c2ecf20Sopenharmony_ci * so msleep(1) is sufficient and there is no need for a wait queue. 3068c2ecf20Sopenharmony_ci */ 3078c2ecf20Sopenharmony_cistatic void __check_for_conflicting_io(struct dm_snapshot *s, chunk_t chunk) 3088c2ecf20Sopenharmony_ci{ 3098c2ecf20Sopenharmony_ci while (__chunk_is_tracked(s, chunk)) 3108c2ecf20Sopenharmony_ci msleep(1); 3118c2ecf20Sopenharmony_ci} 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci/* 3148c2ecf20Sopenharmony_ci * One of these per registered origin, held in the snapshot_origins hash 3158c2ecf20Sopenharmony_ci */ 3168c2ecf20Sopenharmony_cistruct origin { 3178c2ecf20Sopenharmony_ci /* The origin device */ 3188c2ecf20Sopenharmony_ci struct block_device *bdev; 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci struct list_head hash_list; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci /* List of snapshots for this origin */ 3238c2ecf20Sopenharmony_ci struct list_head snapshots; 3248c2ecf20Sopenharmony_ci}; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci/* 3278c2ecf20Sopenharmony_ci * This structure is allocated for each origin target 3288c2ecf20Sopenharmony_ci */ 3298c2ecf20Sopenharmony_cistruct dm_origin { 3308c2ecf20Sopenharmony_ci struct dm_dev *dev; 3318c2ecf20Sopenharmony_ci struct dm_target *ti; 3328c2ecf20Sopenharmony_ci unsigned split_boundary; 3338c2ecf20Sopenharmony_ci struct list_head hash_list; 3348c2ecf20Sopenharmony_ci}; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci/* 3378c2ecf20Sopenharmony_ci * Size of the hash table for origin volumes. If we make this 3388c2ecf20Sopenharmony_ci * the size of the minors list then it should be nearly perfect 3398c2ecf20Sopenharmony_ci */ 3408c2ecf20Sopenharmony_ci#define ORIGIN_HASH_SIZE 256 3418c2ecf20Sopenharmony_ci#define ORIGIN_MASK 0xFF 3428c2ecf20Sopenharmony_cistatic struct list_head *_origins; 3438c2ecf20Sopenharmony_cistatic struct list_head *_dm_origins; 3448c2ecf20Sopenharmony_cistatic struct rw_semaphore _origins_lock; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_cistatic DECLARE_WAIT_QUEUE_HEAD(_pending_exceptions_done); 3478c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(_pending_exceptions_done_spinlock); 3488c2ecf20Sopenharmony_cistatic uint64_t _pending_exceptions_done_count; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_cistatic int init_origin_hash(void) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci int i; 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci _origins = kmalloc_array(ORIGIN_HASH_SIZE, sizeof(struct list_head), 3558c2ecf20Sopenharmony_ci GFP_KERNEL); 3568c2ecf20Sopenharmony_ci if (!_origins) { 3578c2ecf20Sopenharmony_ci DMERR("unable to allocate memory for _origins"); 3588c2ecf20Sopenharmony_ci return -ENOMEM; 3598c2ecf20Sopenharmony_ci } 3608c2ecf20Sopenharmony_ci for (i = 0; i < ORIGIN_HASH_SIZE; i++) 3618c2ecf20Sopenharmony_ci INIT_LIST_HEAD(_origins + i); 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci _dm_origins = kmalloc_array(ORIGIN_HASH_SIZE, 3648c2ecf20Sopenharmony_ci sizeof(struct list_head), 3658c2ecf20Sopenharmony_ci GFP_KERNEL); 3668c2ecf20Sopenharmony_ci if (!_dm_origins) { 3678c2ecf20Sopenharmony_ci DMERR("unable to allocate memory for _dm_origins"); 3688c2ecf20Sopenharmony_ci kfree(_origins); 3698c2ecf20Sopenharmony_ci return -ENOMEM; 3708c2ecf20Sopenharmony_ci } 3718c2ecf20Sopenharmony_ci for (i = 0; i < ORIGIN_HASH_SIZE; i++) 3728c2ecf20Sopenharmony_ci INIT_LIST_HEAD(_dm_origins + i); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci init_rwsem(&_origins_lock); 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci return 0; 3778c2ecf20Sopenharmony_ci} 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_cistatic void exit_origin_hash(void) 3808c2ecf20Sopenharmony_ci{ 3818c2ecf20Sopenharmony_ci kfree(_origins); 3828c2ecf20Sopenharmony_ci kfree(_dm_origins); 3838c2ecf20Sopenharmony_ci} 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_cistatic unsigned origin_hash(struct block_device *bdev) 3868c2ecf20Sopenharmony_ci{ 3878c2ecf20Sopenharmony_ci return bdev->bd_dev & ORIGIN_MASK; 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_cistatic struct origin *__lookup_origin(struct block_device *origin) 3918c2ecf20Sopenharmony_ci{ 3928c2ecf20Sopenharmony_ci struct list_head *ol; 3938c2ecf20Sopenharmony_ci struct origin *o; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci ol = &_origins[origin_hash(origin)]; 3968c2ecf20Sopenharmony_ci list_for_each_entry (o, ol, hash_list) 3978c2ecf20Sopenharmony_ci if (bdev_equal(o->bdev, origin)) 3988c2ecf20Sopenharmony_ci return o; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci return NULL; 4018c2ecf20Sopenharmony_ci} 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_cistatic void __insert_origin(struct origin *o) 4048c2ecf20Sopenharmony_ci{ 4058c2ecf20Sopenharmony_ci struct list_head *sl = &_origins[origin_hash(o->bdev)]; 4068c2ecf20Sopenharmony_ci list_add_tail(&o->hash_list, sl); 4078c2ecf20Sopenharmony_ci} 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_cistatic struct dm_origin *__lookup_dm_origin(struct block_device *origin) 4108c2ecf20Sopenharmony_ci{ 4118c2ecf20Sopenharmony_ci struct list_head *ol; 4128c2ecf20Sopenharmony_ci struct dm_origin *o; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci ol = &_dm_origins[origin_hash(origin)]; 4158c2ecf20Sopenharmony_ci list_for_each_entry (o, ol, hash_list) 4168c2ecf20Sopenharmony_ci if (bdev_equal(o->dev->bdev, origin)) 4178c2ecf20Sopenharmony_ci return o; 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci return NULL; 4208c2ecf20Sopenharmony_ci} 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_cistatic void __insert_dm_origin(struct dm_origin *o) 4238c2ecf20Sopenharmony_ci{ 4248c2ecf20Sopenharmony_ci struct list_head *sl = &_dm_origins[origin_hash(o->dev->bdev)]; 4258c2ecf20Sopenharmony_ci list_add_tail(&o->hash_list, sl); 4268c2ecf20Sopenharmony_ci} 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_cistatic void __remove_dm_origin(struct dm_origin *o) 4298c2ecf20Sopenharmony_ci{ 4308c2ecf20Sopenharmony_ci list_del(&o->hash_list); 4318c2ecf20Sopenharmony_ci} 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci/* 4348c2ecf20Sopenharmony_ci * _origins_lock must be held when calling this function. 4358c2ecf20Sopenharmony_ci * Returns number of snapshots registered using the supplied cow device, plus: 4368c2ecf20Sopenharmony_ci * snap_src - a snapshot suitable for use as a source of exception handover 4378c2ecf20Sopenharmony_ci * snap_dest - a snapshot capable of receiving exception handover. 4388c2ecf20Sopenharmony_ci * snap_merge - an existing snapshot-merge target linked to the same origin. 4398c2ecf20Sopenharmony_ci * There can be at most one snapshot-merge target. The parameter is optional. 4408c2ecf20Sopenharmony_ci * 4418c2ecf20Sopenharmony_ci * Possible return values and states of snap_src and snap_dest. 4428c2ecf20Sopenharmony_ci * 0: NULL, NULL - first new snapshot 4438c2ecf20Sopenharmony_ci * 1: snap_src, NULL - normal snapshot 4448c2ecf20Sopenharmony_ci * 2: snap_src, snap_dest - waiting for handover 4458c2ecf20Sopenharmony_ci * 2: snap_src, NULL - handed over, waiting for old to be deleted 4468c2ecf20Sopenharmony_ci * 1: NULL, snap_dest - source got destroyed without handover 4478c2ecf20Sopenharmony_ci */ 4488c2ecf20Sopenharmony_cistatic int __find_snapshots_sharing_cow(struct dm_snapshot *snap, 4498c2ecf20Sopenharmony_ci struct dm_snapshot **snap_src, 4508c2ecf20Sopenharmony_ci struct dm_snapshot **snap_dest, 4518c2ecf20Sopenharmony_ci struct dm_snapshot **snap_merge) 4528c2ecf20Sopenharmony_ci{ 4538c2ecf20Sopenharmony_ci struct dm_snapshot *s; 4548c2ecf20Sopenharmony_ci struct origin *o; 4558c2ecf20Sopenharmony_ci int count = 0; 4568c2ecf20Sopenharmony_ci int active; 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci o = __lookup_origin(snap->origin->bdev); 4598c2ecf20Sopenharmony_ci if (!o) 4608c2ecf20Sopenharmony_ci goto out; 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci list_for_each_entry(s, &o->snapshots, list) { 4638c2ecf20Sopenharmony_ci if (dm_target_is_snapshot_merge(s->ti) && snap_merge) 4648c2ecf20Sopenharmony_ci *snap_merge = s; 4658c2ecf20Sopenharmony_ci if (!bdev_equal(s->cow->bdev, snap->cow->bdev)) 4668c2ecf20Sopenharmony_ci continue; 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci down_read(&s->lock); 4698c2ecf20Sopenharmony_ci active = s->active; 4708c2ecf20Sopenharmony_ci up_read(&s->lock); 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci if (active) { 4738c2ecf20Sopenharmony_ci if (snap_src) 4748c2ecf20Sopenharmony_ci *snap_src = s; 4758c2ecf20Sopenharmony_ci } else if (snap_dest) 4768c2ecf20Sopenharmony_ci *snap_dest = s; 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci count++; 4798c2ecf20Sopenharmony_ci } 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ciout: 4828c2ecf20Sopenharmony_ci return count; 4838c2ecf20Sopenharmony_ci} 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci/* 4868c2ecf20Sopenharmony_ci * On success, returns 1 if this snapshot is a handover destination, 4878c2ecf20Sopenharmony_ci * otherwise returns 0. 4888c2ecf20Sopenharmony_ci */ 4898c2ecf20Sopenharmony_cistatic int __validate_exception_handover(struct dm_snapshot *snap) 4908c2ecf20Sopenharmony_ci{ 4918c2ecf20Sopenharmony_ci struct dm_snapshot *snap_src = NULL, *snap_dest = NULL; 4928c2ecf20Sopenharmony_ci struct dm_snapshot *snap_merge = NULL; 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci /* Does snapshot need exceptions handed over to it? */ 4958c2ecf20Sopenharmony_ci if ((__find_snapshots_sharing_cow(snap, &snap_src, &snap_dest, 4968c2ecf20Sopenharmony_ci &snap_merge) == 2) || 4978c2ecf20Sopenharmony_ci snap_dest) { 4988c2ecf20Sopenharmony_ci snap->ti->error = "Snapshot cow pairing for exception " 4998c2ecf20Sopenharmony_ci "table handover failed"; 5008c2ecf20Sopenharmony_ci return -EINVAL; 5018c2ecf20Sopenharmony_ci } 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci /* 5048c2ecf20Sopenharmony_ci * If no snap_src was found, snap cannot become a handover 5058c2ecf20Sopenharmony_ci * destination. 5068c2ecf20Sopenharmony_ci */ 5078c2ecf20Sopenharmony_ci if (!snap_src) 5088c2ecf20Sopenharmony_ci return 0; 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci /* 5118c2ecf20Sopenharmony_ci * Non-snapshot-merge handover? 5128c2ecf20Sopenharmony_ci */ 5138c2ecf20Sopenharmony_ci if (!dm_target_is_snapshot_merge(snap->ti)) 5148c2ecf20Sopenharmony_ci return 1; 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci /* 5178c2ecf20Sopenharmony_ci * Do not allow more than one merging snapshot. 5188c2ecf20Sopenharmony_ci */ 5198c2ecf20Sopenharmony_ci if (snap_merge) { 5208c2ecf20Sopenharmony_ci snap->ti->error = "A snapshot is already merging."; 5218c2ecf20Sopenharmony_ci return -EINVAL; 5228c2ecf20Sopenharmony_ci } 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci if (!snap_src->store->type->prepare_merge || 5258c2ecf20Sopenharmony_ci !snap_src->store->type->commit_merge) { 5268c2ecf20Sopenharmony_ci snap->ti->error = "Snapshot exception store does not " 5278c2ecf20Sopenharmony_ci "support snapshot-merge."; 5288c2ecf20Sopenharmony_ci return -EINVAL; 5298c2ecf20Sopenharmony_ci } 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci return 1; 5328c2ecf20Sopenharmony_ci} 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_cistatic void __insert_snapshot(struct origin *o, struct dm_snapshot *s) 5358c2ecf20Sopenharmony_ci{ 5368c2ecf20Sopenharmony_ci struct dm_snapshot *l; 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci /* Sort the list according to chunk size, largest-first smallest-last */ 5398c2ecf20Sopenharmony_ci list_for_each_entry(l, &o->snapshots, list) 5408c2ecf20Sopenharmony_ci if (l->store->chunk_size < s->store->chunk_size) 5418c2ecf20Sopenharmony_ci break; 5428c2ecf20Sopenharmony_ci list_add_tail(&s->list, &l->list); 5438c2ecf20Sopenharmony_ci} 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci/* 5468c2ecf20Sopenharmony_ci * Make a note of the snapshot and its origin so we can look it 5478c2ecf20Sopenharmony_ci * up when the origin has a write on it. 5488c2ecf20Sopenharmony_ci * 5498c2ecf20Sopenharmony_ci * Also validate snapshot exception store handovers. 5508c2ecf20Sopenharmony_ci * On success, returns 1 if this registration is a handover destination, 5518c2ecf20Sopenharmony_ci * otherwise returns 0. 5528c2ecf20Sopenharmony_ci */ 5538c2ecf20Sopenharmony_cistatic int register_snapshot(struct dm_snapshot *snap) 5548c2ecf20Sopenharmony_ci{ 5558c2ecf20Sopenharmony_ci struct origin *o, *new_o = NULL; 5568c2ecf20Sopenharmony_ci struct block_device *bdev = snap->origin->bdev; 5578c2ecf20Sopenharmony_ci int r = 0; 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci new_o = kmalloc(sizeof(*new_o), GFP_KERNEL); 5608c2ecf20Sopenharmony_ci if (!new_o) 5618c2ecf20Sopenharmony_ci return -ENOMEM; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci down_write(&_origins_lock); 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci r = __validate_exception_handover(snap); 5668c2ecf20Sopenharmony_ci if (r < 0) { 5678c2ecf20Sopenharmony_ci kfree(new_o); 5688c2ecf20Sopenharmony_ci goto out; 5698c2ecf20Sopenharmony_ci } 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci o = __lookup_origin(bdev); 5728c2ecf20Sopenharmony_ci if (o) 5738c2ecf20Sopenharmony_ci kfree(new_o); 5748c2ecf20Sopenharmony_ci else { 5758c2ecf20Sopenharmony_ci /* New origin */ 5768c2ecf20Sopenharmony_ci o = new_o; 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci /* Initialise the struct */ 5798c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&o->snapshots); 5808c2ecf20Sopenharmony_ci o->bdev = bdev; 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci __insert_origin(o); 5838c2ecf20Sopenharmony_ci } 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci __insert_snapshot(o, snap); 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ciout: 5888c2ecf20Sopenharmony_ci up_write(&_origins_lock); 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci return r; 5918c2ecf20Sopenharmony_ci} 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci/* 5948c2ecf20Sopenharmony_ci * Move snapshot to correct place in list according to chunk size. 5958c2ecf20Sopenharmony_ci */ 5968c2ecf20Sopenharmony_cistatic void reregister_snapshot(struct dm_snapshot *s) 5978c2ecf20Sopenharmony_ci{ 5988c2ecf20Sopenharmony_ci struct block_device *bdev = s->origin->bdev; 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci down_write(&_origins_lock); 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci list_del(&s->list); 6038c2ecf20Sopenharmony_ci __insert_snapshot(__lookup_origin(bdev), s); 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci up_write(&_origins_lock); 6068c2ecf20Sopenharmony_ci} 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_cistatic void unregister_snapshot(struct dm_snapshot *s) 6098c2ecf20Sopenharmony_ci{ 6108c2ecf20Sopenharmony_ci struct origin *o; 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci down_write(&_origins_lock); 6138c2ecf20Sopenharmony_ci o = __lookup_origin(s->origin->bdev); 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci list_del(&s->list); 6168c2ecf20Sopenharmony_ci if (o && list_empty(&o->snapshots)) { 6178c2ecf20Sopenharmony_ci list_del(&o->hash_list); 6188c2ecf20Sopenharmony_ci kfree(o); 6198c2ecf20Sopenharmony_ci } 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci up_write(&_origins_lock); 6228c2ecf20Sopenharmony_ci} 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci/* 6258c2ecf20Sopenharmony_ci * Implementation of the exception hash tables. 6268c2ecf20Sopenharmony_ci * The lowest hash_shift bits of the chunk number are ignored, allowing 6278c2ecf20Sopenharmony_ci * some consecutive chunks to be grouped together. 6288c2ecf20Sopenharmony_ci */ 6298c2ecf20Sopenharmony_cistatic uint32_t exception_hash(struct dm_exception_table *et, chunk_t chunk); 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci/* Lock to protect access to the completed and pending exception hash tables. */ 6328c2ecf20Sopenharmony_cistruct dm_exception_table_lock { 6338c2ecf20Sopenharmony_ci struct hlist_bl_head *complete_slot; 6348c2ecf20Sopenharmony_ci struct hlist_bl_head *pending_slot; 6358c2ecf20Sopenharmony_ci}; 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_cistatic void dm_exception_table_lock_init(struct dm_snapshot *s, chunk_t chunk, 6388c2ecf20Sopenharmony_ci struct dm_exception_table_lock *lock) 6398c2ecf20Sopenharmony_ci{ 6408c2ecf20Sopenharmony_ci struct dm_exception_table *complete = &s->complete; 6418c2ecf20Sopenharmony_ci struct dm_exception_table *pending = &s->pending; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci lock->complete_slot = &complete->table[exception_hash(complete, chunk)]; 6448c2ecf20Sopenharmony_ci lock->pending_slot = &pending->table[exception_hash(pending, chunk)]; 6458c2ecf20Sopenharmony_ci} 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_cistatic void dm_exception_table_lock(struct dm_exception_table_lock *lock) 6488c2ecf20Sopenharmony_ci{ 6498c2ecf20Sopenharmony_ci hlist_bl_lock(lock->complete_slot); 6508c2ecf20Sopenharmony_ci hlist_bl_lock(lock->pending_slot); 6518c2ecf20Sopenharmony_ci} 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_cistatic void dm_exception_table_unlock(struct dm_exception_table_lock *lock) 6548c2ecf20Sopenharmony_ci{ 6558c2ecf20Sopenharmony_ci hlist_bl_unlock(lock->pending_slot); 6568c2ecf20Sopenharmony_ci hlist_bl_unlock(lock->complete_slot); 6578c2ecf20Sopenharmony_ci} 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_cistatic int dm_exception_table_init(struct dm_exception_table *et, 6608c2ecf20Sopenharmony_ci uint32_t size, unsigned hash_shift) 6618c2ecf20Sopenharmony_ci{ 6628c2ecf20Sopenharmony_ci unsigned int i; 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci et->hash_shift = hash_shift; 6658c2ecf20Sopenharmony_ci et->hash_mask = size - 1; 6668c2ecf20Sopenharmony_ci et->table = dm_vcalloc(size, sizeof(struct hlist_bl_head)); 6678c2ecf20Sopenharmony_ci if (!et->table) 6688c2ecf20Sopenharmony_ci return -ENOMEM; 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci for (i = 0; i < size; i++) 6718c2ecf20Sopenharmony_ci INIT_HLIST_BL_HEAD(et->table + i); 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci return 0; 6748c2ecf20Sopenharmony_ci} 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_cistatic void dm_exception_table_exit(struct dm_exception_table *et, 6778c2ecf20Sopenharmony_ci struct kmem_cache *mem) 6788c2ecf20Sopenharmony_ci{ 6798c2ecf20Sopenharmony_ci struct hlist_bl_head *slot; 6808c2ecf20Sopenharmony_ci struct dm_exception *ex; 6818c2ecf20Sopenharmony_ci struct hlist_bl_node *pos, *n; 6828c2ecf20Sopenharmony_ci int i, size; 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci size = et->hash_mask + 1; 6858c2ecf20Sopenharmony_ci for (i = 0; i < size; i++) { 6868c2ecf20Sopenharmony_ci slot = et->table + i; 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci hlist_bl_for_each_entry_safe(ex, pos, n, slot, hash_list) 6898c2ecf20Sopenharmony_ci kmem_cache_free(mem, ex); 6908c2ecf20Sopenharmony_ci } 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci vfree(et->table); 6938c2ecf20Sopenharmony_ci} 6948c2ecf20Sopenharmony_ci 6958c2ecf20Sopenharmony_cistatic uint32_t exception_hash(struct dm_exception_table *et, chunk_t chunk) 6968c2ecf20Sopenharmony_ci{ 6978c2ecf20Sopenharmony_ci return (chunk >> et->hash_shift) & et->hash_mask; 6988c2ecf20Sopenharmony_ci} 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_cistatic void dm_remove_exception(struct dm_exception *e) 7018c2ecf20Sopenharmony_ci{ 7028c2ecf20Sopenharmony_ci hlist_bl_del(&e->hash_list); 7038c2ecf20Sopenharmony_ci} 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci/* 7068c2ecf20Sopenharmony_ci * Return the exception data for a sector, or NULL if not 7078c2ecf20Sopenharmony_ci * remapped. 7088c2ecf20Sopenharmony_ci */ 7098c2ecf20Sopenharmony_cistatic struct dm_exception *dm_lookup_exception(struct dm_exception_table *et, 7108c2ecf20Sopenharmony_ci chunk_t chunk) 7118c2ecf20Sopenharmony_ci{ 7128c2ecf20Sopenharmony_ci struct hlist_bl_head *slot; 7138c2ecf20Sopenharmony_ci struct hlist_bl_node *pos; 7148c2ecf20Sopenharmony_ci struct dm_exception *e; 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci slot = &et->table[exception_hash(et, chunk)]; 7178c2ecf20Sopenharmony_ci hlist_bl_for_each_entry(e, pos, slot, hash_list) 7188c2ecf20Sopenharmony_ci if (chunk >= e->old_chunk && 7198c2ecf20Sopenharmony_ci chunk <= e->old_chunk + dm_consecutive_chunk_count(e)) 7208c2ecf20Sopenharmony_ci return e; 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci return NULL; 7238c2ecf20Sopenharmony_ci} 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_cistatic struct dm_exception *alloc_completed_exception(gfp_t gfp) 7268c2ecf20Sopenharmony_ci{ 7278c2ecf20Sopenharmony_ci struct dm_exception *e; 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci e = kmem_cache_alloc(exception_cache, gfp); 7308c2ecf20Sopenharmony_ci if (!e && gfp == GFP_NOIO) 7318c2ecf20Sopenharmony_ci e = kmem_cache_alloc(exception_cache, GFP_ATOMIC); 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci return e; 7348c2ecf20Sopenharmony_ci} 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_cistatic void free_completed_exception(struct dm_exception *e) 7378c2ecf20Sopenharmony_ci{ 7388c2ecf20Sopenharmony_ci kmem_cache_free(exception_cache, e); 7398c2ecf20Sopenharmony_ci} 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_cistatic struct dm_snap_pending_exception *alloc_pending_exception(struct dm_snapshot *s) 7428c2ecf20Sopenharmony_ci{ 7438c2ecf20Sopenharmony_ci struct dm_snap_pending_exception *pe = mempool_alloc(&s->pending_pool, 7448c2ecf20Sopenharmony_ci GFP_NOIO); 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci atomic_inc(&s->pending_exceptions_count); 7478c2ecf20Sopenharmony_ci pe->snap = s; 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci return pe; 7508c2ecf20Sopenharmony_ci} 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_cistatic void free_pending_exception(struct dm_snap_pending_exception *pe) 7538c2ecf20Sopenharmony_ci{ 7548c2ecf20Sopenharmony_ci struct dm_snapshot *s = pe->snap; 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci mempool_free(pe, &s->pending_pool); 7578c2ecf20Sopenharmony_ci smp_mb__before_atomic(); 7588c2ecf20Sopenharmony_ci atomic_dec(&s->pending_exceptions_count); 7598c2ecf20Sopenharmony_ci} 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_cistatic void dm_insert_exception(struct dm_exception_table *eh, 7628c2ecf20Sopenharmony_ci struct dm_exception *new_e) 7638c2ecf20Sopenharmony_ci{ 7648c2ecf20Sopenharmony_ci struct hlist_bl_head *l; 7658c2ecf20Sopenharmony_ci struct hlist_bl_node *pos; 7668c2ecf20Sopenharmony_ci struct dm_exception *e = NULL; 7678c2ecf20Sopenharmony_ci 7688c2ecf20Sopenharmony_ci l = &eh->table[exception_hash(eh, new_e->old_chunk)]; 7698c2ecf20Sopenharmony_ci 7708c2ecf20Sopenharmony_ci /* Add immediately if this table doesn't support consecutive chunks */ 7718c2ecf20Sopenharmony_ci if (!eh->hash_shift) 7728c2ecf20Sopenharmony_ci goto out; 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci /* List is ordered by old_chunk */ 7758c2ecf20Sopenharmony_ci hlist_bl_for_each_entry(e, pos, l, hash_list) { 7768c2ecf20Sopenharmony_ci /* Insert after an existing chunk? */ 7778c2ecf20Sopenharmony_ci if (new_e->old_chunk == (e->old_chunk + 7788c2ecf20Sopenharmony_ci dm_consecutive_chunk_count(e) + 1) && 7798c2ecf20Sopenharmony_ci new_e->new_chunk == (dm_chunk_number(e->new_chunk) + 7808c2ecf20Sopenharmony_ci dm_consecutive_chunk_count(e) + 1)) { 7818c2ecf20Sopenharmony_ci dm_consecutive_chunk_count_inc(e); 7828c2ecf20Sopenharmony_ci free_completed_exception(new_e); 7838c2ecf20Sopenharmony_ci return; 7848c2ecf20Sopenharmony_ci } 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci /* Insert before an existing chunk? */ 7878c2ecf20Sopenharmony_ci if (new_e->old_chunk == (e->old_chunk - 1) && 7888c2ecf20Sopenharmony_ci new_e->new_chunk == (dm_chunk_number(e->new_chunk) - 1)) { 7898c2ecf20Sopenharmony_ci dm_consecutive_chunk_count_inc(e); 7908c2ecf20Sopenharmony_ci e->old_chunk--; 7918c2ecf20Sopenharmony_ci e->new_chunk--; 7928c2ecf20Sopenharmony_ci free_completed_exception(new_e); 7938c2ecf20Sopenharmony_ci return; 7948c2ecf20Sopenharmony_ci } 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci if (new_e->old_chunk < e->old_chunk) 7978c2ecf20Sopenharmony_ci break; 7988c2ecf20Sopenharmony_ci } 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ciout: 8018c2ecf20Sopenharmony_ci if (!e) { 8028c2ecf20Sopenharmony_ci /* 8038c2ecf20Sopenharmony_ci * Either the table doesn't support consecutive chunks or slot 8048c2ecf20Sopenharmony_ci * l is empty. 8058c2ecf20Sopenharmony_ci */ 8068c2ecf20Sopenharmony_ci hlist_bl_add_head(&new_e->hash_list, l); 8078c2ecf20Sopenharmony_ci } else if (new_e->old_chunk < e->old_chunk) { 8088c2ecf20Sopenharmony_ci /* Add before an existing exception */ 8098c2ecf20Sopenharmony_ci hlist_bl_add_before(&new_e->hash_list, &e->hash_list); 8108c2ecf20Sopenharmony_ci } else { 8118c2ecf20Sopenharmony_ci /* Add to l's tail: e is the last exception in this slot */ 8128c2ecf20Sopenharmony_ci hlist_bl_add_behind(&new_e->hash_list, &e->hash_list); 8138c2ecf20Sopenharmony_ci } 8148c2ecf20Sopenharmony_ci} 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci/* 8178c2ecf20Sopenharmony_ci * Callback used by the exception stores to load exceptions when 8188c2ecf20Sopenharmony_ci * initialising. 8198c2ecf20Sopenharmony_ci */ 8208c2ecf20Sopenharmony_cistatic int dm_add_exception(void *context, chunk_t old, chunk_t new) 8218c2ecf20Sopenharmony_ci{ 8228c2ecf20Sopenharmony_ci struct dm_exception_table_lock lock; 8238c2ecf20Sopenharmony_ci struct dm_snapshot *s = context; 8248c2ecf20Sopenharmony_ci struct dm_exception *e; 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci e = alloc_completed_exception(GFP_KERNEL); 8278c2ecf20Sopenharmony_ci if (!e) 8288c2ecf20Sopenharmony_ci return -ENOMEM; 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci e->old_chunk = old; 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci /* Consecutive_count is implicitly initialised to zero */ 8338c2ecf20Sopenharmony_ci e->new_chunk = new; 8348c2ecf20Sopenharmony_ci 8358c2ecf20Sopenharmony_ci /* 8368c2ecf20Sopenharmony_ci * Although there is no need to lock access to the exception tables 8378c2ecf20Sopenharmony_ci * here, if we don't then hlist_bl_add_head(), called by 8388c2ecf20Sopenharmony_ci * dm_insert_exception(), will complain about accessing the 8398c2ecf20Sopenharmony_ci * corresponding list without locking it first. 8408c2ecf20Sopenharmony_ci */ 8418c2ecf20Sopenharmony_ci dm_exception_table_lock_init(s, old, &lock); 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci dm_exception_table_lock(&lock); 8448c2ecf20Sopenharmony_ci dm_insert_exception(&s->complete, e); 8458c2ecf20Sopenharmony_ci dm_exception_table_unlock(&lock); 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci return 0; 8488c2ecf20Sopenharmony_ci} 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci/* 8518c2ecf20Sopenharmony_ci * Return a minimum chunk size of all snapshots that have the specified origin. 8528c2ecf20Sopenharmony_ci * Return zero if the origin has no snapshots. 8538c2ecf20Sopenharmony_ci */ 8548c2ecf20Sopenharmony_cistatic uint32_t __minimum_chunk_size(struct origin *o) 8558c2ecf20Sopenharmony_ci{ 8568c2ecf20Sopenharmony_ci struct dm_snapshot *snap; 8578c2ecf20Sopenharmony_ci unsigned chunk_size = rounddown_pow_of_two(UINT_MAX); 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci if (o) 8608c2ecf20Sopenharmony_ci list_for_each_entry(snap, &o->snapshots, list) 8618c2ecf20Sopenharmony_ci chunk_size = min_not_zero(chunk_size, 8628c2ecf20Sopenharmony_ci snap->store->chunk_size); 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci return (uint32_t) chunk_size; 8658c2ecf20Sopenharmony_ci} 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci/* 8688c2ecf20Sopenharmony_ci * Hard coded magic. 8698c2ecf20Sopenharmony_ci */ 8708c2ecf20Sopenharmony_cistatic int calc_max_buckets(void) 8718c2ecf20Sopenharmony_ci{ 8728c2ecf20Sopenharmony_ci /* use a fixed size of 2MB */ 8738c2ecf20Sopenharmony_ci unsigned long mem = 2 * 1024 * 1024; 8748c2ecf20Sopenharmony_ci mem /= sizeof(struct hlist_bl_head); 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci return mem; 8778c2ecf20Sopenharmony_ci} 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci/* 8808c2ecf20Sopenharmony_ci * Allocate room for a suitable hash table. 8818c2ecf20Sopenharmony_ci */ 8828c2ecf20Sopenharmony_cistatic int init_hash_tables(struct dm_snapshot *s) 8838c2ecf20Sopenharmony_ci{ 8848c2ecf20Sopenharmony_ci sector_t hash_size, cow_dev_size, max_buckets; 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_ci /* 8878c2ecf20Sopenharmony_ci * Calculate based on the size of the original volume or 8888c2ecf20Sopenharmony_ci * the COW volume... 8898c2ecf20Sopenharmony_ci */ 8908c2ecf20Sopenharmony_ci cow_dev_size = get_dev_size(s->cow->bdev); 8918c2ecf20Sopenharmony_ci max_buckets = calc_max_buckets(); 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci hash_size = cow_dev_size >> s->store->chunk_shift; 8948c2ecf20Sopenharmony_ci hash_size = min(hash_size, max_buckets); 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci if (hash_size < 64) 8978c2ecf20Sopenharmony_ci hash_size = 64; 8988c2ecf20Sopenharmony_ci hash_size = rounddown_pow_of_two(hash_size); 8998c2ecf20Sopenharmony_ci if (dm_exception_table_init(&s->complete, hash_size, 9008c2ecf20Sopenharmony_ci DM_CHUNK_CONSECUTIVE_BITS)) 9018c2ecf20Sopenharmony_ci return -ENOMEM; 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci /* 9048c2ecf20Sopenharmony_ci * Allocate hash table for in-flight exceptions 9058c2ecf20Sopenharmony_ci * Make this smaller than the real hash table 9068c2ecf20Sopenharmony_ci */ 9078c2ecf20Sopenharmony_ci hash_size >>= 3; 9088c2ecf20Sopenharmony_ci if (hash_size < 64) 9098c2ecf20Sopenharmony_ci hash_size = 64; 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci if (dm_exception_table_init(&s->pending, hash_size, 0)) { 9128c2ecf20Sopenharmony_ci dm_exception_table_exit(&s->complete, exception_cache); 9138c2ecf20Sopenharmony_ci return -ENOMEM; 9148c2ecf20Sopenharmony_ci } 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci return 0; 9178c2ecf20Sopenharmony_ci} 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_cistatic void merge_shutdown(struct dm_snapshot *s) 9208c2ecf20Sopenharmony_ci{ 9218c2ecf20Sopenharmony_ci clear_bit_unlock(RUNNING_MERGE, &s->state_bits); 9228c2ecf20Sopenharmony_ci smp_mb__after_atomic(); 9238c2ecf20Sopenharmony_ci wake_up_bit(&s->state_bits, RUNNING_MERGE); 9248c2ecf20Sopenharmony_ci} 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_cistatic struct bio *__release_queued_bios_after_merge(struct dm_snapshot *s) 9278c2ecf20Sopenharmony_ci{ 9288c2ecf20Sopenharmony_ci s->first_merging_chunk = 0; 9298c2ecf20Sopenharmony_ci s->num_merging_chunks = 0; 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci return bio_list_get(&s->bios_queued_during_merge); 9328c2ecf20Sopenharmony_ci} 9338c2ecf20Sopenharmony_ci 9348c2ecf20Sopenharmony_ci/* 9358c2ecf20Sopenharmony_ci * Remove one chunk from the index of completed exceptions. 9368c2ecf20Sopenharmony_ci */ 9378c2ecf20Sopenharmony_cistatic int __remove_single_exception_chunk(struct dm_snapshot *s, 9388c2ecf20Sopenharmony_ci chunk_t old_chunk) 9398c2ecf20Sopenharmony_ci{ 9408c2ecf20Sopenharmony_ci struct dm_exception *e; 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci e = dm_lookup_exception(&s->complete, old_chunk); 9438c2ecf20Sopenharmony_ci if (!e) { 9448c2ecf20Sopenharmony_ci DMERR("Corruption detected: exception for block %llu is " 9458c2ecf20Sopenharmony_ci "on disk but not in memory", 9468c2ecf20Sopenharmony_ci (unsigned long long)old_chunk); 9478c2ecf20Sopenharmony_ci return -EINVAL; 9488c2ecf20Sopenharmony_ci } 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ci /* 9518c2ecf20Sopenharmony_ci * If this is the only chunk using this exception, remove exception. 9528c2ecf20Sopenharmony_ci */ 9538c2ecf20Sopenharmony_ci if (!dm_consecutive_chunk_count(e)) { 9548c2ecf20Sopenharmony_ci dm_remove_exception(e); 9558c2ecf20Sopenharmony_ci free_completed_exception(e); 9568c2ecf20Sopenharmony_ci return 0; 9578c2ecf20Sopenharmony_ci } 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci /* 9608c2ecf20Sopenharmony_ci * The chunk may be either at the beginning or the end of a 9618c2ecf20Sopenharmony_ci * group of consecutive chunks - never in the middle. We are 9628c2ecf20Sopenharmony_ci * removing chunks in the opposite order to that in which they 9638c2ecf20Sopenharmony_ci * were added, so this should always be true. 9648c2ecf20Sopenharmony_ci * Decrement the consecutive chunk counter and adjust the 9658c2ecf20Sopenharmony_ci * starting point if necessary. 9668c2ecf20Sopenharmony_ci */ 9678c2ecf20Sopenharmony_ci if (old_chunk == e->old_chunk) { 9688c2ecf20Sopenharmony_ci e->old_chunk++; 9698c2ecf20Sopenharmony_ci e->new_chunk++; 9708c2ecf20Sopenharmony_ci } else if (old_chunk != e->old_chunk + 9718c2ecf20Sopenharmony_ci dm_consecutive_chunk_count(e)) { 9728c2ecf20Sopenharmony_ci DMERR("Attempt to merge block %llu from the " 9738c2ecf20Sopenharmony_ci "middle of a chunk range [%llu - %llu]", 9748c2ecf20Sopenharmony_ci (unsigned long long)old_chunk, 9758c2ecf20Sopenharmony_ci (unsigned long long)e->old_chunk, 9768c2ecf20Sopenharmony_ci (unsigned long long) 9778c2ecf20Sopenharmony_ci e->old_chunk + dm_consecutive_chunk_count(e)); 9788c2ecf20Sopenharmony_ci return -EINVAL; 9798c2ecf20Sopenharmony_ci } 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci dm_consecutive_chunk_count_dec(e); 9828c2ecf20Sopenharmony_ci 9838c2ecf20Sopenharmony_ci return 0; 9848c2ecf20Sopenharmony_ci} 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_cistatic void flush_bios(struct bio *bio); 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_cistatic int remove_single_exception_chunk(struct dm_snapshot *s) 9898c2ecf20Sopenharmony_ci{ 9908c2ecf20Sopenharmony_ci struct bio *b = NULL; 9918c2ecf20Sopenharmony_ci int r; 9928c2ecf20Sopenharmony_ci chunk_t old_chunk = s->first_merging_chunk + s->num_merging_chunks - 1; 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci down_write(&s->lock); 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci /* 9978c2ecf20Sopenharmony_ci * Process chunks (and associated exceptions) in reverse order 9988c2ecf20Sopenharmony_ci * so that dm_consecutive_chunk_count_dec() accounting works. 9998c2ecf20Sopenharmony_ci */ 10008c2ecf20Sopenharmony_ci do { 10018c2ecf20Sopenharmony_ci r = __remove_single_exception_chunk(s, old_chunk); 10028c2ecf20Sopenharmony_ci if (r) 10038c2ecf20Sopenharmony_ci goto out; 10048c2ecf20Sopenharmony_ci } while (old_chunk-- > s->first_merging_chunk); 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_ci b = __release_queued_bios_after_merge(s); 10078c2ecf20Sopenharmony_ci 10088c2ecf20Sopenharmony_ciout: 10098c2ecf20Sopenharmony_ci up_write(&s->lock); 10108c2ecf20Sopenharmony_ci if (b) 10118c2ecf20Sopenharmony_ci flush_bios(b); 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci return r; 10148c2ecf20Sopenharmony_ci} 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_cistatic int origin_write_extent(struct dm_snapshot *merging_snap, 10178c2ecf20Sopenharmony_ci sector_t sector, unsigned chunk_size); 10188c2ecf20Sopenharmony_ci 10198c2ecf20Sopenharmony_cistatic void merge_callback(int read_err, unsigned long write_err, 10208c2ecf20Sopenharmony_ci void *context); 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_cistatic uint64_t read_pending_exceptions_done_count(void) 10238c2ecf20Sopenharmony_ci{ 10248c2ecf20Sopenharmony_ci uint64_t pending_exceptions_done; 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci spin_lock(&_pending_exceptions_done_spinlock); 10278c2ecf20Sopenharmony_ci pending_exceptions_done = _pending_exceptions_done_count; 10288c2ecf20Sopenharmony_ci spin_unlock(&_pending_exceptions_done_spinlock); 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci return pending_exceptions_done; 10318c2ecf20Sopenharmony_ci} 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_cistatic void increment_pending_exceptions_done_count(void) 10348c2ecf20Sopenharmony_ci{ 10358c2ecf20Sopenharmony_ci spin_lock(&_pending_exceptions_done_spinlock); 10368c2ecf20Sopenharmony_ci _pending_exceptions_done_count++; 10378c2ecf20Sopenharmony_ci spin_unlock(&_pending_exceptions_done_spinlock); 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci wake_up_all(&_pending_exceptions_done); 10408c2ecf20Sopenharmony_ci} 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_cistatic void snapshot_merge_next_chunks(struct dm_snapshot *s) 10438c2ecf20Sopenharmony_ci{ 10448c2ecf20Sopenharmony_ci int i, linear_chunks; 10458c2ecf20Sopenharmony_ci chunk_t old_chunk, new_chunk; 10468c2ecf20Sopenharmony_ci struct dm_io_region src, dest; 10478c2ecf20Sopenharmony_ci sector_t io_size; 10488c2ecf20Sopenharmony_ci uint64_t previous_count; 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci BUG_ON(!test_bit(RUNNING_MERGE, &s->state_bits)); 10518c2ecf20Sopenharmony_ci if (unlikely(test_bit(SHUTDOWN_MERGE, &s->state_bits))) 10528c2ecf20Sopenharmony_ci goto shut; 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci /* 10558c2ecf20Sopenharmony_ci * valid flag never changes during merge, so no lock required. 10568c2ecf20Sopenharmony_ci */ 10578c2ecf20Sopenharmony_ci if (!s->valid) { 10588c2ecf20Sopenharmony_ci DMERR("Snapshot is invalid: can't merge"); 10598c2ecf20Sopenharmony_ci goto shut; 10608c2ecf20Sopenharmony_ci } 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_ci linear_chunks = s->store->type->prepare_merge(s->store, &old_chunk, 10638c2ecf20Sopenharmony_ci &new_chunk); 10648c2ecf20Sopenharmony_ci if (linear_chunks <= 0) { 10658c2ecf20Sopenharmony_ci if (linear_chunks < 0) { 10668c2ecf20Sopenharmony_ci DMERR("Read error in exception store: " 10678c2ecf20Sopenharmony_ci "shutting down merge"); 10688c2ecf20Sopenharmony_ci down_write(&s->lock); 10698c2ecf20Sopenharmony_ci s->merge_failed = true; 10708c2ecf20Sopenharmony_ci up_write(&s->lock); 10718c2ecf20Sopenharmony_ci } 10728c2ecf20Sopenharmony_ci goto shut; 10738c2ecf20Sopenharmony_ci } 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_ci /* Adjust old_chunk and new_chunk to reflect start of linear region */ 10768c2ecf20Sopenharmony_ci old_chunk = old_chunk + 1 - linear_chunks; 10778c2ecf20Sopenharmony_ci new_chunk = new_chunk + 1 - linear_chunks; 10788c2ecf20Sopenharmony_ci 10798c2ecf20Sopenharmony_ci /* 10808c2ecf20Sopenharmony_ci * Use one (potentially large) I/O to copy all 'linear_chunks' 10818c2ecf20Sopenharmony_ci * from the exception store to the origin 10828c2ecf20Sopenharmony_ci */ 10838c2ecf20Sopenharmony_ci io_size = linear_chunks * s->store->chunk_size; 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci dest.bdev = s->origin->bdev; 10868c2ecf20Sopenharmony_ci dest.sector = chunk_to_sector(s->store, old_chunk); 10878c2ecf20Sopenharmony_ci dest.count = min(io_size, get_dev_size(dest.bdev) - dest.sector); 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci src.bdev = s->cow->bdev; 10908c2ecf20Sopenharmony_ci src.sector = chunk_to_sector(s->store, new_chunk); 10918c2ecf20Sopenharmony_ci src.count = dest.count; 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci /* 10948c2ecf20Sopenharmony_ci * Reallocate any exceptions needed in other snapshots then 10958c2ecf20Sopenharmony_ci * wait for the pending exceptions to complete. 10968c2ecf20Sopenharmony_ci * Each time any pending exception (globally on the system) 10978c2ecf20Sopenharmony_ci * completes we are woken and repeat the process to find out 10988c2ecf20Sopenharmony_ci * if we can proceed. While this may not seem a particularly 10998c2ecf20Sopenharmony_ci * efficient algorithm, it is not expected to have any 11008c2ecf20Sopenharmony_ci * significant impact on performance. 11018c2ecf20Sopenharmony_ci */ 11028c2ecf20Sopenharmony_ci previous_count = read_pending_exceptions_done_count(); 11038c2ecf20Sopenharmony_ci while (origin_write_extent(s, dest.sector, io_size)) { 11048c2ecf20Sopenharmony_ci wait_event(_pending_exceptions_done, 11058c2ecf20Sopenharmony_ci (read_pending_exceptions_done_count() != 11068c2ecf20Sopenharmony_ci previous_count)); 11078c2ecf20Sopenharmony_ci /* Retry after the wait, until all exceptions are done. */ 11088c2ecf20Sopenharmony_ci previous_count = read_pending_exceptions_done_count(); 11098c2ecf20Sopenharmony_ci } 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci down_write(&s->lock); 11128c2ecf20Sopenharmony_ci s->first_merging_chunk = old_chunk; 11138c2ecf20Sopenharmony_ci s->num_merging_chunks = linear_chunks; 11148c2ecf20Sopenharmony_ci up_write(&s->lock); 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ci /* Wait until writes to all 'linear_chunks' drain */ 11178c2ecf20Sopenharmony_ci for (i = 0; i < linear_chunks; i++) 11188c2ecf20Sopenharmony_ci __check_for_conflicting_io(s, old_chunk + i); 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci dm_kcopyd_copy(s->kcopyd_client, &src, 1, &dest, 0, merge_callback, s); 11218c2ecf20Sopenharmony_ci return; 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_cishut: 11248c2ecf20Sopenharmony_ci merge_shutdown(s); 11258c2ecf20Sopenharmony_ci} 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_cistatic void error_bios(struct bio *bio); 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_cistatic int flush_data(struct dm_snapshot *s) 11308c2ecf20Sopenharmony_ci{ 11318c2ecf20Sopenharmony_ci struct bio *flush_bio = &s->flush_bio; 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_ci bio_reset(flush_bio); 11348c2ecf20Sopenharmony_ci bio_set_dev(flush_bio, s->origin->bdev); 11358c2ecf20Sopenharmony_ci flush_bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH; 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_ci return submit_bio_wait(flush_bio); 11388c2ecf20Sopenharmony_ci} 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_cistatic void merge_callback(int read_err, unsigned long write_err, void *context) 11418c2ecf20Sopenharmony_ci{ 11428c2ecf20Sopenharmony_ci struct dm_snapshot *s = context; 11438c2ecf20Sopenharmony_ci struct bio *b = NULL; 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci if (read_err || write_err) { 11468c2ecf20Sopenharmony_ci if (read_err) 11478c2ecf20Sopenharmony_ci DMERR("Read error: shutting down merge."); 11488c2ecf20Sopenharmony_ci else 11498c2ecf20Sopenharmony_ci DMERR("Write error: shutting down merge."); 11508c2ecf20Sopenharmony_ci goto shut; 11518c2ecf20Sopenharmony_ci } 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci if (flush_data(s) < 0) { 11548c2ecf20Sopenharmony_ci DMERR("Flush after merge failed: shutting down merge"); 11558c2ecf20Sopenharmony_ci goto shut; 11568c2ecf20Sopenharmony_ci } 11578c2ecf20Sopenharmony_ci 11588c2ecf20Sopenharmony_ci if (s->store->type->commit_merge(s->store, 11598c2ecf20Sopenharmony_ci s->num_merging_chunks) < 0) { 11608c2ecf20Sopenharmony_ci DMERR("Write error in exception store: shutting down merge"); 11618c2ecf20Sopenharmony_ci goto shut; 11628c2ecf20Sopenharmony_ci } 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_ci if (remove_single_exception_chunk(s) < 0) 11658c2ecf20Sopenharmony_ci goto shut; 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci snapshot_merge_next_chunks(s); 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_ci return; 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_cishut: 11728c2ecf20Sopenharmony_ci down_write(&s->lock); 11738c2ecf20Sopenharmony_ci s->merge_failed = true; 11748c2ecf20Sopenharmony_ci b = __release_queued_bios_after_merge(s); 11758c2ecf20Sopenharmony_ci up_write(&s->lock); 11768c2ecf20Sopenharmony_ci error_bios(b); 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ci merge_shutdown(s); 11798c2ecf20Sopenharmony_ci} 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_cistatic void start_merge(struct dm_snapshot *s) 11828c2ecf20Sopenharmony_ci{ 11838c2ecf20Sopenharmony_ci if (!test_and_set_bit(RUNNING_MERGE, &s->state_bits)) 11848c2ecf20Sopenharmony_ci snapshot_merge_next_chunks(s); 11858c2ecf20Sopenharmony_ci} 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci/* 11888c2ecf20Sopenharmony_ci * Stop the merging process and wait until it finishes. 11898c2ecf20Sopenharmony_ci */ 11908c2ecf20Sopenharmony_cistatic void stop_merge(struct dm_snapshot *s) 11918c2ecf20Sopenharmony_ci{ 11928c2ecf20Sopenharmony_ci set_bit(SHUTDOWN_MERGE, &s->state_bits); 11938c2ecf20Sopenharmony_ci wait_on_bit(&s->state_bits, RUNNING_MERGE, TASK_UNINTERRUPTIBLE); 11948c2ecf20Sopenharmony_ci clear_bit(SHUTDOWN_MERGE, &s->state_bits); 11958c2ecf20Sopenharmony_ci} 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_cistatic int parse_snapshot_features(struct dm_arg_set *as, struct dm_snapshot *s, 11988c2ecf20Sopenharmony_ci struct dm_target *ti) 11998c2ecf20Sopenharmony_ci{ 12008c2ecf20Sopenharmony_ci int r; 12018c2ecf20Sopenharmony_ci unsigned argc; 12028c2ecf20Sopenharmony_ci const char *arg_name; 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_ci static const struct dm_arg _args[] = { 12058c2ecf20Sopenharmony_ci {0, 2, "Invalid number of feature arguments"}, 12068c2ecf20Sopenharmony_ci }; 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci /* 12098c2ecf20Sopenharmony_ci * No feature arguments supplied. 12108c2ecf20Sopenharmony_ci */ 12118c2ecf20Sopenharmony_ci if (!as->argc) 12128c2ecf20Sopenharmony_ci return 0; 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci r = dm_read_arg_group(_args, as, &argc, &ti->error); 12158c2ecf20Sopenharmony_ci if (r) 12168c2ecf20Sopenharmony_ci return -EINVAL; 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_ci while (argc && !r) { 12198c2ecf20Sopenharmony_ci arg_name = dm_shift_arg(as); 12208c2ecf20Sopenharmony_ci argc--; 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_ci if (!strcasecmp(arg_name, "discard_zeroes_cow")) 12238c2ecf20Sopenharmony_ci s->discard_zeroes_cow = true; 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci else if (!strcasecmp(arg_name, "discard_passdown_origin")) 12268c2ecf20Sopenharmony_ci s->discard_passdown_origin = true; 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci else { 12298c2ecf20Sopenharmony_ci ti->error = "Unrecognised feature requested"; 12308c2ecf20Sopenharmony_ci r = -EINVAL; 12318c2ecf20Sopenharmony_ci break; 12328c2ecf20Sopenharmony_ci } 12338c2ecf20Sopenharmony_ci } 12348c2ecf20Sopenharmony_ci 12358c2ecf20Sopenharmony_ci if (!s->discard_zeroes_cow && s->discard_passdown_origin) { 12368c2ecf20Sopenharmony_ci /* 12378c2ecf20Sopenharmony_ci * TODO: really these are disjoint.. but ti->num_discard_bios 12388c2ecf20Sopenharmony_ci * and dm_bio_get_target_bio_nr() require rigid constraints. 12398c2ecf20Sopenharmony_ci */ 12408c2ecf20Sopenharmony_ci ti->error = "discard_passdown_origin feature depends on discard_zeroes_cow"; 12418c2ecf20Sopenharmony_ci r = -EINVAL; 12428c2ecf20Sopenharmony_ci } 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci return r; 12458c2ecf20Sopenharmony_ci} 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_ci/* 12488c2ecf20Sopenharmony_ci * Construct a snapshot mapping: 12498c2ecf20Sopenharmony_ci * <origin_dev> <COW-dev> <p|po|n> <chunk-size> [<# feature args> [<arg>]*] 12508c2ecf20Sopenharmony_ci */ 12518c2ecf20Sopenharmony_cistatic int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) 12528c2ecf20Sopenharmony_ci{ 12538c2ecf20Sopenharmony_ci struct dm_snapshot *s; 12548c2ecf20Sopenharmony_ci struct dm_arg_set as; 12558c2ecf20Sopenharmony_ci int i; 12568c2ecf20Sopenharmony_ci int r = -EINVAL; 12578c2ecf20Sopenharmony_ci char *origin_path, *cow_path; 12588c2ecf20Sopenharmony_ci dev_t origin_dev, cow_dev; 12598c2ecf20Sopenharmony_ci unsigned args_used, num_flush_bios = 1; 12608c2ecf20Sopenharmony_ci fmode_t origin_mode = FMODE_READ; 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_ci if (argc < 4) { 12638c2ecf20Sopenharmony_ci ti->error = "requires 4 or more arguments"; 12648c2ecf20Sopenharmony_ci r = -EINVAL; 12658c2ecf20Sopenharmony_ci goto bad; 12668c2ecf20Sopenharmony_ci } 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci if (dm_target_is_snapshot_merge(ti)) { 12698c2ecf20Sopenharmony_ci num_flush_bios = 2; 12708c2ecf20Sopenharmony_ci origin_mode = FMODE_WRITE; 12718c2ecf20Sopenharmony_ci } 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci s = kzalloc(sizeof(*s), GFP_KERNEL); 12748c2ecf20Sopenharmony_ci if (!s) { 12758c2ecf20Sopenharmony_ci ti->error = "Cannot allocate private snapshot structure"; 12768c2ecf20Sopenharmony_ci r = -ENOMEM; 12778c2ecf20Sopenharmony_ci goto bad; 12788c2ecf20Sopenharmony_ci } 12798c2ecf20Sopenharmony_ci 12808c2ecf20Sopenharmony_ci as.argc = argc; 12818c2ecf20Sopenharmony_ci as.argv = argv; 12828c2ecf20Sopenharmony_ci dm_consume_args(&as, 4); 12838c2ecf20Sopenharmony_ci r = parse_snapshot_features(&as, s, ti); 12848c2ecf20Sopenharmony_ci if (r) 12858c2ecf20Sopenharmony_ci goto bad_features; 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_ci origin_path = argv[0]; 12888c2ecf20Sopenharmony_ci argv++; 12898c2ecf20Sopenharmony_ci argc--; 12908c2ecf20Sopenharmony_ci 12918c2ecf20Sopenharmony_ci r = dm_get_device(ti, origin_path, origin_mode, &s->origin); 12928c2ecf20Sopenharmony_ci if (r) { 12938c2ecf20Sopenharmony_ci ti->error = "Cannot get origin device"; 12948c2ecf20Sopenharmony_ci goto bad_origin; 12958c2ecf20Sopenharmony_ci } 12968c2ecf20Sopenharmony_ci origin_dev = s->origin->bdev->bd_dev; 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_ci cow_path = argv[0]; 12998c2ecf20Sopenharmony_ci argv++; 13008c2ecf20Sopenharmony_ci argc--; 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci cow_dev = dm_get_dev_t(cow_path); 13038c2ecf20Sopenharmony_ci if (cow_dev && cow_dev == origin_dev) { 13048c2ecf20Sopenharmony_ci ti->error = "COW device cannot be the same as origin device"; 13058c2ecf20Sopenharmony_ci r = -EINVAL; 13068c2ecf20Sopenharmony_ci goto bad_cow; 13078c2ecf20Sopenharmony_ci } 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_ci r = dm_get_device(ti, cow_path, dm_table_get_mode(ti->table), &s->cow); 13108c2ecf20Sopenharmony_ci if (r) { 13118c2ecf20Sopenharmony_ci ti->error = "Cannot get COW device"; 13128c2ecf20Sopenharmony_ci goto bad_cow; 13138c2ecf20Sopenharmony_ci } 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci r = dm_exception_store_create(ti, argc, argv, s, &args_used, &s->store); 13168c2ecf20Sopenharmony_ci if (r) { 13178c2ecf20Sopenharmony_ci ti->error = "Couldn't create exception store"; 13188c2ecf20Sopenharmony_ci r = -EINVAL; 13198c2ecf20Sopenharmony_ci goto bad_store; 13208c2ecf20Sopenharmony_ci } 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_ci argv += args_used; 13238c2ecf20Sopenharmony_ci argc -= args_used; 13248c2ecf20Sopenharmony_ci 13258c2ecf20Sopenharmony_ci s->ti = ti; 13268c2ecf20Sopenharmony_ci s->valid = 1; 13278c2ecf20Sopenharmony_ci s->snapshot_overflowed = 0; 13288c2ecf20Sopenharmony_ci s->active = 0; 13298c2ecf20Sopenharmony_ci atomic_set(&s->pending_exceptions_count, 0); 13308c2ecf20Sopenharmony_ci spin_lock_init(&s->pe_allocation_lock); 13318c2ecf20Sopenharmony_ci s->exception_start_sequence = 0; 13328c2ecf20Sopenharmony_ci s->exception_complete_sequence = 0; 13338c2ecf20Sopenharmony_ci s->out_of_order_tree = RB_ROOT; 13348c2ecf20Sopenharmony_ci init_rwsem(&s->lock); 13358c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&s->list); 13368c2ecf20Sopenharmony_ci spin_lock_init(&s->pe_lock); 13378c2ecf20Sopenharmony_ci s->state_bits = 0; 13388c2ecf20Sopenharmony_ci s->merge_failed = false; 13398c2ecf20Sopenharmony_ci s->first_merging_chunk = 0; 13408c2ecf20Sopenharmony_ci s->num_merging_chunks = 0; 13418c2ecf20Sopenharmony_ci bio_list_init(&s->bios_queued_during_merge); 13428c2ecf20Sopenharmony_ci bio_init(&s->flush_bio, NULL, 0); 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_ci /* Allocate hash table for COW data */ 13458c2ecf20Sopenharmony_ci if (init_hash_tables(s)) { 13468c2ecf20Sopenharmony_ci ti->error = "Unable to allocate hash table space"; 13478c2ecf20Sopenharmony_ci r = -ENOMEM; 13488c2ecf20Sopenharmony_ci goto bad_hash_tables; 13498c2ecf20Sopenharmony_ci } 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci init_waitqueue_head(&s->in_progress_wait); 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci s->kcopyd_client = dm_kcopyd_client_create(&dm_kcopyd_throttle); 13548c2ecf20Sopenharmony_ci if (IS_ERR(s->kcopyd_client)) { 13558c2ecf20Sopenharmony_ci r = PTR_ERR(s->kcopyd_client); 13568c2ecf20Sopenharmony_ci ti->error = "Could not create kcopyd client"; 13578c2ecf20Sopenharmony_ci goto bad_kcopyd; 13588c2ecf20Sopenharmony_ci } 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_ci r = mempool_init_slab_pool(&s->pending_pool, MIN_IOS, pending_cache); 13618c2ecf20Sopenharmony_ci if (r) { 13628c2ecf20Sopenharmony_ci ti->error = "Could not allocate mempool for pending exceptions"; 13638c2ecf20Sopenharmony_ci goto bad_pending_pool; 13648c2ecf20Sopenharmony_ci } 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_ci for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++) 13678c2ecf20Sopenharmony_ci INIT_HLIST_HEAD(&s->tracked_chunk_hash[i]); 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_ci spin_lock_init(&s->tracked_chunk_lock); 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci ti->private = s; 13728c2ecf20Sopenharmony_ci ti->num_flush_bios = num_flush_bios; 13738c2ecf20Sopenharmony_ci if (s->discard_zeroes_cow) 13748c2ecf20Sopenharmony_ci ti->num_discard_bios = (s->discard_passdown_origin ? 2 : 1); 13758c2ecf20Sopenharmony_ci ti->per_io_data_size = sizeof(struct dm_snap_tracked_chunk); 13768c2ecf20Sopenharmony_ci 13778c2ecf20Sopenharmony_ci /* Add snapshot to the list of snapshots for this origin */ 13788c2ecf20Sopenharmony_ci /* Exceptions aren't triggered till snapshot_resume() is called */ 13798c2ecf20Sopenharmony_ci r = register_snapshot(s); 13808c2ecf20Sopenharmony_ci if (r == -ENOMEM) { 13818c2ecf20Sopenharmony_ci ti->error = "Snapshot origin struct allocation failed"; 13828c2ecf20Sopenharmony_ci goto bad_load_and_register; 13838c2ecf20Sopenharmony_ci } else if (r < 0) { 13848c2ecf20Sopenharmony_ci /* invalid handover, register_snapshot has set ti->error */ 13858c2ecf20Sopenharmony_ci goto bad_load_and_register; 13868c2ecf20Sopenharmony_ci } 13878c2ecf20Sopenharmony_ci 13888c2ecf20Sopenharmony_ci /* 13898c2ecf20Sopenharmony_ci * Metadata must only be loaded into one table at once, so skip this 13908c2ecf20Sopenharmony_ci * if metadata will be handed over during resume. 13918c2ecf20Sopenharmony_ci * Chunk size will be set during the handover - set it to zero to 13928c2ecf20Sopenharmony_ci * ensure it's ignored. 13938c2ecf20Sopenharmony_ci */ 13948c2ecf20Sopenharmony_ci if (r > 0) { 13958c2ecf20Sopenharmony_ci s->store->chunk_size = 0; 13968c2ecf20Sopenharmony_ci return 0; 13978c2ecf20Sopenharmony_ci } 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci r = s->store->type->read_metadata(s->store, dm_add_exception, 14008c2ecf20Sopenharmony_ci (void *)s); 14018c2ecf20Sopenharmony_ci if (r < 0) { 14028c2ecf20Sopenharmony_ci ti->error = "Failed to read snapshot metadata"; 14038c2ecf20Sopenharmony_ci goto bad_read_metadata; 14048c2ecf20Sopenharmony_ci } else if (r > 0) { 14058c2ecf20Sopenharmony_ci s->valid = 0; 14068c2ecf20Sopenharmony_ci DMWARN("Snapshot is marked invalid."); 14078c2ecf20Sopenharmony_ci } 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci if (!s->store->chunk_size) { 14108c2ecf20Sopenharmony_ci ti->error = "Chunk size not set"; 14118c2ecf20Sopenharmony_ci r = -EINVAL; 14128c2ecf20Sopenharmony_ci goto bad_read_metadata; 14138c2ecf20Sopenharmony_ci } 14148c2ecf20Sopenharmony_ci 14158c2ecf20Sopenharmony_ci r = dm_set_target_max_io_len(ti, s->store->chunk_size); 14168c2ecf20Sopenharmony_ci if (r) 14178c2ecf20Sopenharmony_ci goto bad_read_metadata; 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_ci return 0; 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_cibad_read_metadata: 14228c2ecf20Sopenharmony_ci unregister_snapshot(s); 14238c2ecf20Sopenharmony_cibad_load_and_register: 14248c2ecf20Sopenharmony_ci mempool_exit(&s->pending_pool); 14258c2ecf20Sopenharmony_cibad_pending_pool: 14268c2ecf20Sopenharmony_ci dm_kcopyd_client_destroy(s->kcopyd_client); 14278c2ecf20Sopenharmony_cibad_kcopyd: 14288c2ecf20Sopenharmony_ci dm_exception_table_exit(&s->pending, pending_cache); 14298c2ecf20Sopenharmony_ci dm_exception_table_exit(&s->complete, exception_cache); 14308c2ecf20Sopenharmony_cibad_hash_tables: 14318c2ecf20Sopenharmony_ci dm_exception_store_destroy(s->store); 14328c2ecf20Sopenharmony_cibad_store: 14338c2ecf20Sopenharmony_ci dm_put_device(ti, s->cow); 14348c2ecf20Sopenharmony_cibad_cow: 14358c2ecf20Sopenharmony_ci dm_put_device(ti, s->origin); 14368c2ecf20Sopenharmony_cibad_origin: 14378c2ecf20Sopenharmony_cibad_features: 14388c2ecf20Sopenharmony_ci kfree(s); 14398c2ecf20Sopenharmony_cibad: 14408c2ecf20Sopenharmony_ci return r; 14418c2ecf20Sopenharmony_ci} 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_cistatic void __free_exceptions(struct dm_snapshot *s) 14448c2ecf20Sopenharmony_ci{ 14458c2ecf20Sopenharmony_ci dm_kcopyd_client_destroy(s->kcopyd_client); 14468c2ecf20Sopenharmony_ci s->kcopyd_client = NULL; 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_ci dm_exception_table_exit(&s->pending, pending_cache); 14498c2ecf20Sopenharmony_ci dm_exception_table_exit(&s->complete, exception_cache); 14508c2ecf20Sopenharmony_ci} 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_cistatic void __handover_exceptions(struct dm_snapshot *snap_src, 14538c2ecf20Sopenharmony_ci struct dm_snapshot *snap_dest) 14548c2ecf20Sopenharmony_ci{ 14558c2ecf20Sopenharmony_ci union { 14568c2ecf20Sopenharmony_ci struct dm_exception_table table_swap; 14578c2ecf20Sopenharmony_ci struct dm_exception_store *store_swap; 14588c2ecf20Sopenharmony_ci } u; 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_ci /* 14618c2ecf20Sopenharmony_ci * Swap all snapshot context information between the two instances. 14628c2ecf20Sopenharmony_ci */ 14638c2ecf20Sopenharmony_ci u.table_swap = snap_dest->complete; 14648c2ecf20Sopenharmony_ci snap_dest->complete = snap_src->complete; 14658c2ecf20Sopenharmony_ci snap_src->complete = u.table_swap; 14668c2ecf20Sopenharmony_ci 14678c2ecf20Sopenharmony_ci u.store_swap = snap_dest->store; 14688c2ecf20Sopenharmony_ci snap_dest->store = snap_src->store; 14698c2ecf20Sopenharmony_ci snap_dest->store->userspace_supports_overflow = u.store_swap->userspace_supports_overflow; 14708c2ecf20Sopenharmony_ci snap_src->store = u.store_swap; 14718c2ecf20Sopenharmony_ci 14728c2ecf20Sopenharmony_ci snap_dest->store->snap = snap_dest; 14738c2ecf20Sopenharmony_ci snap_src->store->snap = snap_src; 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_ci snap_dest->ti->max_io_len = snap_dest->store->chunk_size; 14768c2ecf20Sopenharmony_ci snap_dest->valid = snap_src->valid; 14778c2ecf20Sopenharmony_ci snap_dest->snapshot_overflowed = snap_src->snapshot_overflowed; 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_ci /* 14808c2ecf20Sopenharmony_ci * Set source invalid to ensure it receives no further I/O. 14818c2ecf20Sopenharmony_ci */ 14828c2ecf20Sopenharmony_ci snap_src->valid = 0; 14838c2ecf20Sopenharmony_ci} 14848c2ecf20Sopenharmony_ci 14858c2ecf20Sopenharmony_cistatic void snapshot_dtr(struct dm_target *ti) 14868c2ecf20Sopenharmony_ci{ 14878c2ecf20Sopenharmony_ci#ifdef CONFIG_DM_DEBUG 14888c2ecf20Sopenharmony_ci int i; 14898c2ecf20Sopenharmony_ci#endif 14908c2ecf20Sopenharmony_ci struct dm_snapshot *s = ti->private; 14918c2ecf20Sopenharmony_ci struct dm_snapshot *snap_src = NULL, *snap_dest = NULL; 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_ci down_read(&_origins_lock); 14948c2ecf20Sopenharmony_ci /* Check whether exception handover must be cancelled */ 14958c2ecf20Sopenharmony_ci (void) __find_snapshots_sharing_cow(s, &snap_src, &snap_dest, NULL); 14968c2ecf20Sopenharmony_ci if (snap_src && snap_dest && (s == snap_src)) { 14978c2ecf20Sopenharmony_ci down_write(&snap_dest->lock); 14988c2ecf20Sopenharmony_ci snap_dest->valid = 0; 14998c2ecf20Sopenharmony_ci up_write(&snap_dest->lock); 15008c2ecf20Sopenharmony_ci DMERR("Cancelling snapshot handover."); 15018c2ecf20Sopenharmony_ci } 15028c2ecf20Sopenharmony_ci up_read(&_origins_lock); 15038c2ecf20Sopenharmony_ci 15048c2ecf20Sopenharmony_ci if (dm_target_is_snapshot_merge(ti)) 15058c2ecf20Sopenharmony_ci stop_merge(s); 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci /* Prevent further origin writes from using this snapshot. */ 15088c2ecf20Sopenharmony_ci /* After this returns there can be no new kcopyd jobs. */ 15098c2ecf20Sopenharmony_ci unregister_snapshot(s); 15108c2ecf20Sopenharmony_ci 15118c2ecf20Sopenharmony_ci while (atomic_read(&s->pending_exceptions_count)) 15128c2ecf20Sopenharmony_ci msleep(1); 15138c2ecf20Sopenharmony_ci /* 15148c2ecf20Sopenharmony_ci * Ensure instructions in mempool_exit aren't reordered 15158c2ecf20Sopenharmony_ci * before atomic_read. 15168c2ecf20Sopenharmony_ci */ 15178c2ecf20Sopenharmony_ci smp_mb(); 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_ci#ifdef CONFIG_DM_DEBUG 15208c2ecf20Sopenharmony_ci for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++) 15218c2ecf20Sopenharmony_ci BUG_ON(!hlist_empty(&s->tracked_chunk_hash[i])); 15228c2ecf20Sopenharmony_ci#endif 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_ci __free_exceptions(s); 15258c2ecf20Sopenharmony_ci 15268c2ecf20Sopenharmony_ci mempool_exit(&s->pending_pool); 15278c2ecf20Sopenharmony_ci 15288c2ecf20Sopenharmony_ci dm_exception_store_destroy(s->store); 15298c2ecf20Sopenharmony_ci 15308c2ecf20Sopenharmony_ci bio_uninit(&s->flush_bio); 15318c2ecf20Sopenharmony_ci 15328c2ecf20Sopenharmony_ci dm_put_device(ti, s->cow); 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_ci dm_put_device(ti, s->origin); 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_ci WARN_ON(s->in_progress); 15378c2ecf20Sopenharmony_ci 15388c2ecf20Sopenharmony_ci kfree(s); 15398c2ecf20Sopenharmony_ci} 15408c2ecf20Sopenharmony_ci 15418c2ecf20Sopenharmony_cistatic void account_start_copy(struct dm_snapshot *s) 15428c2ecf20Sopenharmony_ci{ 15438c2ecf20Sopenharmony_ci spin_lock(&s->in_progress_wait.lock); 15448c2ecf20Sopenharmony_ci s->in_progress++; 15458c2ecf20Sopenharmony_ci spin_unlock(&s->in_progress_wait.lock); 15468c2ecf20Sopenharmony_ci} 15478c2ecf20Sopenharmony_ci 15488c2ecf20Sopenharmony_cistatic void account_end_copy(struct dm_snapshot *s) 15498c2ecf20Sopenharmony_ci{ 15508c2ecf20Sopenharmony_ci spin_lock(&s->in_progress_wait.lock); 15518c2ecf20Sopenharmony_ci BUG_ON(!s->in_progress); 15528c2ecf20Sopenharmony_ci s->in_progress--; 15538c2ecf20Sopenharmony_ci if (likely(s->in_progress <= cow_threshold) && 15548c2ecf20Sopenharmony_ci unlikely(waitqueue_active(&s->in_progress_wait))) 15558c2ecf20Sopenharmony_ci wake_up_locked(&s->in_progress_wait); 15568c2ecf20Sopenharmony_ci spin_unlock(&s->in_progress_wait.lock); 15578c2ecf20Sopenharmony_ci} 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_cistatic bool wait_for_in_progress(struct dm_snapshot *s, bool unlock_origins) 15608c2ecf20Sopenharmony_ci{ 15618c2ecf20Sopenharmony_ci if (unlikely(s->in_progress > cow_threshold)) { 15628c2ecf20Sopenharmony_ci spin_lock(&s->in_progress_wait.lock); 15638c2ecf20Sopenharmony_ci if (likely(s->in_progress > cow_threshold)) { 15648c2ecf20Sopenharmony_ci /* 15658c2ecf20Sopenharmony_ci * NOTE: this throttle doesn't account for whether 15668c2ecf20Sopenharmony_ci * the caller is servicing an IO that will trigger a COW 15678c2ecf20Sopenharmony_ci * so excess throttling may result for chunks not required 15688c2ecf20Sopenharmony_ci * to be COW'd. But if cow_threshold was reached, extra 15698c2ecf20Sopenharmony_ci * throttling is unlikely to negatively impact performance. 15708c2ecf20Sopenharmony_ci */ 15718c2ecf20Sopenharmony_ci DECLARE_WAITQUEUE(wait, current); 15728c2ecf20Sopenharmony_ci __add_wait_queue(&s->in_progress_wait, &wait); 15738c2ecf20Sopenharmony_ci __set_current_state(TASK_UNINTERRUPTIBLE); 15748c2ecf20Sopenharmony_ci spin_unlock(&s->in_progress_wait.lock); 15758c2ecf20Sopenharmony_ci if (unlock_origins) 15768c2ecf20Sopenharmony_ci up_read(&_origins_lock); 15778c2ecf20Sopenharmony_ci io_schedule(); 15788c2ecf20Sopenharmony_ci remove_wait_queue(&s->in_progress_wait, &wait); 15798c2ecf20Sopenharmony_ci return false; 15808c2ecf20Sopenharmony_ci } 15818c2ecf20Sopenharmony_ci spin_unlock(&s->in_progress_wait.lock); 15828c2ecf20Sopenharmony_ci } 15838c2ecf20Sopenharmony_ci return true; 15848c2ecf20Sopenharmony_ci} 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_ci/* 15878c2ecf20Sopenharmony_ci * Flush a list of buffers. 15888c2ecf20Sopenharmony_ci */ 15898c2ecf20Sopenharmony_cistatic void flush_bios(struct bio *bio) 15908c2ecf20Sopenharmony_ci{ 15918c2ecf20Sopenharmony_ci struct bio *n; 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_ci while (bio) { 15948c2ecf20Sopenharmony_ci n = bio->bi_next; 15958c2ecf20Sopenharmony_ci bio->bi_next = NULL; 15968c2ecf20Sopenharmony_ci submit_bio_noacct(bio); 15978c2ecf20Sopenharmony_ci bio = n; 15988c2ecf20Sopenharmony_ci } 15998c2ecf20Sopenharmony_ci} 16008c2ecf20Sopenharmony_ci 16018c2ecf20Sopenharmony_cistatic int do_origin(struct dm_dev *origin, struct bio *bio, bool limit); 16028c2ecf20Sopenharmony_ci 16038c2ecf20Sopenharmony_ci/* 16048c2ecf20Sopenharmony_ci * Flush a list of buffers. 16058c2ecf20Sopenharmony_ci */ 16068c2ecf20Sopenharmony_cistatic void retry_origin_bios(struct dm_snapshot *s, struct bio *bio) 16078c2ecf20Sopenharmony_ci{ 16088c2ecf20Sopenharmony_ci struct bio *n; 16098c2ecf20Sopenharmony_ci int r; 16108c2ecf20Sopenharmony_ci 16118c2ecf20Sopenharmony_ci while (bio) { 16128c2ecf20Sopenharmony_ci n = bio->bi_next; 16138c2ecf20Sopenharmony_ci bio->bi_next = NULL; 16148c2ecf20Sopenharmony_ci r = do_origin(s->origin, bio, false); 16158c2ecf20Sopenharmony_ci if (r == DM_MAPIO_REMAPPED) 16168c2ecf20Sopenharmony_ci submit_bio_noacct(bio); 16178c2ecf20Sopenharmony_ci bio = n; 16188c2ecf20Sopenharmony_ci } 16198c2ecf20Sopenharmony_ci} 16208c2ecf20Sopenharmony_ci 16218c2ecf20Sopenharmony_ci/* 16228c2ecf20Sopenharmony_ci * Error a list of buffers. 16238c2ecf20Sopenharmony_ci */ 16248c2ecf20Sopenharmony_cistatic void error_bios(struct bio *bio) 16258c2ecf20Sopenharmony_ci{ 16268c2ecf20Sopenharmony_ci struct bio *n; 16278c2ecf20Sopenharmony_ci 16288c2ecf20Sopenharmony_ci while (bio) { 16298c2ecf20Sopenharmony_ci n = bio->bi_next; 16308c2ecf20Sopenharmony_ci bio->bi_next = NULL; 16318c2ecf20Sopenharmony_ci bio_io_error(bio); 16328c2ecf20Sopenharmony_ci bio = n; 16338c2ecf20Sopenharmony_ci } 16348c2ecf20Sopenharmony_ci} 16358c2ecf20Sopenharmony_ci 16368c2ecf20Sopenharmony_cistatic void __invalidate_snapshot(struct dm_snapshot *s, int err) 16378c2ecf20Sopenharmony_ci{ 16388c2ecf20Sopenharmony_ci if (!s->valid) 16398c2ecf20Sopenharmony_ci return; 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_ci if (err == -EIO) 16428c2ecf20Sopenharmony_ci DMERR("Invalidating snapshot: Error reading/writing."); 16438c2ecf20Sopenharmony_ci else if (err == -ENOMEM) 16448c2ecf20Sopenharmony_ci DMERR("Invalidating snapshot: Unable to allocate exception."); 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci if (s->store->type->drop_snapshot) 16478c2ecf20Sopenharmony_ci s->store->type->drop_snapshot(s->store); 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_ci s->valid = 0; 16508c2ecf20Sopenharmony_ci 16518c2ecf20Sopenharmony_ci dm_table_event(s->ti->table); 16528c2ecf20Sopenharmony_ci} 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_cistatic void invalidate_snapshot(struct dm_snapshot *s, int err) 16558c2ecf20Sopenharmony_ci{ 16568c2ecf20Sopenharmony_ci down_write(&s->lock); 16578c2ecf20Sopenharmony_ci __invalidate_snapshot(s, err); 16588c2ecf20Sopenharmony_ci up_write(&s->lock); 16598c2ecf20Sopenharmony_ci} 16608c2ecf20Sopenharmony_ci 16618c2ecf20Sopenharmony_cistatic void pending_complete(void *context, int success) 16628c2ecf20Sopenharmony_ci{ 16638c2ecf20Sopenharmony_ci struct dm_snap_pending_exception *pe = context; 16648c2ecf20Sopenharmony_ci struct dm_exception *e; 16658c2ecf20Sopenharmony_ci struct dm_snapshot *s = pe->snap; 16668c2ecf20Sopenharmony_ci struct bio *origin_bios = NULL; 16678c2ecf20Sopenharmony_ci struct bio *snapshot_bios = NULL; 16688c2ecf20Sopenharmony_ci struct bio *full_bio = NULL; 16698c2ecf20Sopenharmony_ci struct dm_exception_table_lock lock; 16708c2ecf20Sopenharmony_ci int error = 0; 16718c2ecf20Sopenharmony_ci 16728c2ecf20Sopenharmony_ci dm_exception_table_lock_init(s, pe->e.old_chunk, &lock); 16738c2ecf20Sopenharmony_ci 16748c2ecf20Sopenharmony_ci if (!success) { 16758c2ecf20Sopenharmony_ci /* Read/write error - snapshot is unusable */ 16768c2ecf20Sopenharmony_ci invalidate_snapshot(s, -EIO); 16778c2ecf20Sopenharmony_ci error = 1; 16788c2ecf20Sopenharmony_ci 16798c2ecf20Sopenharmony_ci dm_exception_table_lock(&lock); 16808c2ecf20Sopenharmony_ci goto out; 16818c2ecf20Sopenharmony_ci } 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_ci e = alloc_completed_exception(GFP_NOIO); 16848c2ecf20Sopenharmony_ci if (!e) { 16858c2ecf20Sopenharmony_ci invalidate_snapshot(s, -ENOMEM); 16868c2ecf20Sopenharmony_ci error = 1; 16878c2ecf20Sopenharmony_ci 16888c2ecf20Sopenharmony_ci dm_exception_table_lock(&lock); 16898c2ecf20Sopenharmony_ci goto out; 16908c2ecf20Sopenharmony_ci } 16918c2ecf20Sopenharmony_ci *e = pe->e; 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci down_read(&s->lock); 16948c2ecf20Sopenharmony_ci dm_exception_table_lock(&lock); 16958c2ecf20Sopenharmony_ci if (!s->valid) { 16968c2ecf20Sopenharmony_ci up_read(&s->lock); 16978c2ecf20Sopenharmony_ci free_completed_exception(e); 16988c2ecf20Sopenharmony_ci error = 1; 16998c2ecf20Sopenharmony_ci 17008c2ecf20Sopenharmony_ci goto out; 17018c2ecf20Sopenharmony_ci } 17028c2ecf20Sopenharmony_ci 17038c2ecf20Sopenharmony_ci /* 17048c2ecf20Sopenharmony_ci * Add a proper exception. After inserting the completed exception all 17058c2ecf20Sopenharmony_ci * subsequent snapshot reads to this chunk will be redirected to the 17068c2ecf20Sopenharmony_ci * COW device. This ensures that we do not starve. Moreover, as long 17078c2ecf20Sopenharmony_ci * as the pending exception exists, neither origin writes nor snapshot 17088c2ecf20Sopenharmony_ci * merging can overwrite the chunk in origin. 17098c2ecf20Sopenharmony_ci */ 17108c2ecf20Sopenharmony_ci dm_insert_exception(&s->complete, e); 17118c2ecf20Sopenharmony_ci up_read(&s->lock); 17128c2ecf20Sopenharmony_ci 17138c2ecf20Sopenharmony_ci /* Wait for conflicting reads to drain */ 17148c2ecf20Sopenharmony_ci if (__chunk_is_tracked(s, pe->e.old_chunk)) { 17158c2ecf20Sopenharmony_ci dm_exception_table_unlock(&lock); 17168c2ecf20Sopenharmony_ci __check_for_conflicting_io(s, pe->e.old_chunk); 17178c2ecf20Sopenharmony_ci dm_exception_table_lock(&lock); 17188c2ecf20Sopenharmony_ci } 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_ciout: 17218c2ecf20Sopenharmony_ci /* Remove the in-flight exception from the list */ 17228c2ecf20Sopenharmony_ci dm_remove_exception(&pe->e); 17238c2ecf20Sopenharmony_ci 17248c2ecf20Sopenharmony_ci dm_exception_table_unlock(&lock); 17258c2ecf20Sopenharmony_ci 17268c2ecf20Sopenharmony_ci snapshot_bios = bio_list_get(&pe->snapshot_bios); 17278c2ecf20Sopenharmony_ci origin_bios = bio_list_get(&pe->origin_bios); 17288c2ecf20Sopenharmony_ci full_bio = pe->full_bio; 17298c2ecf20Sopenharmony_ci if (full_bio) 17308c2ecf20Sopenharmony_ci full_bio->bi_end_io = pe->full_bio_end_io; 17318c2ecf20Sopenharmony_ci increment_pending_exceptions_done_count(); 17328c2ecf20Sopenharmony_ci 17338c2ecf20Sopenharmony_ci /* Submit any pending write bios */ 17348c2ecf20Sopenharmony_ci if (error) { 17358c2ecf20Sopenharmony_ci if (full_bio) 17368c2ecf20Sopenharmony_ci bio_io_error(full_bio); 17378c2ecf20Sopenharmony_ci error_bios(snapshot_bios); 17388c2ecf20Sopenharmony_ci } else { 17398c2ecf20Sopenharmony_ci if (full_bio) 17408c2ecf20Sopenharmony_ci bio_endio(full_bio); 17418c2ecf20Sopenharmony_ci flush_bios(snapshot_bios); 17428c2ecf20Sopenharmony_ci } 17438c2ecf20Sopenharmony_ci 17448c2ecf20Sopenharmony_ci retry_origin_bios(s, origin_bios); 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_ci free_pending_exception(pe); 17478c2ecf20Sopenharmony_ci} 17488c2ecf20Sopenharmony_ci 17498c2ecf20Sopenharmony_cistatic void complete_exception(struct dm_snap_pending_exception *pe) 17508c2ecf20Sopenharmony_ci{ 17518c2ecf20Sopenharmony_ci struct dm_snapshot *s = pe->snap; 17528c2ecf20Sopenharmony_ci 17538c2ecf20Sopenharmony_ci /* Update the metadata if we are persistent */ 17548c2ecf20Sopenharmony_ci s->store->type->commit_exception(s->store, &pe->e, !pe->copy_error, 17558c2ecf20Sopenharmony_ci pending_complete, pe); 17568c2ecf20Sopenharmony_ci} 17578c2ecf20Sopenharmony_ci 17588c2ecf20Sopenharmony_ci/* 17598c2ecf20Sopenharmony_ci * Called when the copy I/O has finished. kcopyd actually runs 17608c2ecf20Sopenharmony_ci * this code so don't block. 17618c2ecf20Sopenharmony_ci */ 17628c2ecf20Sopenharmony_cistatic void copy_callback(int read_err, unsigned long write_err, void *context) 17638c2ecf20Sopenharmony_ci{ 17648c2ecf20Sopenharmony_ci struct dm_snap_pending_exception *pe = context; 17658c2ecf20Sopenharmony_ci struct dm_snapshot *s = pe->snap; 17668c2ecf20Sopenharmony_ci 17678c2ecf20Sopenharmony_ci pe->copy_error = read_err || write_err; 17688c2ecf20Sopenharmony_ci 17698c2ecf20Sopenharmony_ci if (pe->exception_sequence == s->exception_complete_sequence) { 17708c2ecf20Sopenharmony_ci struct rb_node *next; 17718c2ecf20Sopenharmony_ci 17728c2ecf20Sopenharmony_ci s->exception_complete_sequence++; 17738c2ecf20Sopenharmony_ci complete_exception(pe); 17748c2ecf20Sopenharmony_ci 17758c2ecf20Sopenharmony_ci next = rb_first(&s->out_of_order_tree); 17768c2ecf20Sopenharmony_ci while (next) { 17778c2ecf20Sopenharmony_ci pe = rb_entry(next, struct dm_snap_pending_exception, 17788c2ecf20Sopenharmony_ci out_of_order_node); 17798c2ecf20Sopenharmony_ci if (pe->exception_sequence != s->exception_complete_sequence) 17808c2ecf20Sopenharmony_ci break; 17818c2ecf20Sopenharmony_ci next = rb_next(next); 17828c2ecf20Sopenharmony_ci s->exception_complete_sequence++; 17838c2ecf20Sopenharmony_ci rb_erase(&pe->out_of_order_node, &s->out_of_order_tree); 17848c2ecf20Sopenharmony_ci complete_exception(pe); 17858c2ecf20Sopenharmony_ci cond_resched(); 17868c2ecf20Sopenharmony_ci } 17878c2ecf20Sopenharmony_ci } else { 17888c2ecf20Sopenharmony_ci struct rb_node *parent = NULL; 17898c2ecf20Sopenharmony_ci struct rb_node **p = &s->out_of_order_tree.rb_node; 17908c2ecf20Sopenharmony_ci struct dm_snap_pending_exception *pe2; 17918c2ecf20Sopenharmony_ci 17928c2ecf20Sopenharmony_ci while (*p) { 17938c2ecf20Sopenharmony_ci pe2 = rb_entry(*p, struct dm_snap_pending_exception, out_of_order_node); 17948c2ecf20Sopenharmony_ci parent = *p; 17958c2ecf20Sopenharmony_ci 17968c2ecf20Sopenharmony_ci BUG_ON(pe->exception_sequence == pe2->exception_sequence); 17978c2ecf20Sopenharmony_ci if (pe->exception_sequence < pe2->exception_sequence) 17988c2ecf20Sopenharmony_ci p = &((*p)->rb_left); 17998c2ecf20Sopenharmony_ci else 18008c2ecf20Sopenharmony_ci p = &((*p)->rb_right); 18018c2ecf20Sopenharmony_ci } 18028c2ecf20Sopenharmony_ci 18038c2ecf20Sopenharmony_ci rb_link_node(&pe->out_of_order_node, parent, p); 18048c2ecf20Sopenharmony_ci rb_insert_color(&pe->out_of_order_node, &s->out_of_order_tree); 18058c2ecf20Sopenharmony_ci } 18068c2ecf20Sopenharmony_ci account_end_copy(s); 18078c2ecf20Sopenharmony_ci} 18088c2ecf20Sopenharmony_ci 18098c2ecf20Sopenharmony_ci/* 18108c2ecf20Sopenharmony_ci * Dispatches the copy operation to kcopyd. 18118c2ecf20Sopenharmony_ci */ 18128c2ecf20Sopenharmony_cistatic void start_copy(struct dm_snap_pending_exception *pe) 18138c2ecf20Sopenharmony_ci{ 18148c2ecf20Sopenharmony_ci struct dm_snapshot *s = pe->snap; 18158c2ecf20Sopenharmony_ci struct dm_io_region src, dest; 18168c2ecf20Sopenharmony_ci struct block_device *bdev = s->origin->bdev; 18178c2ecf20Sopenharmony_ci sector_t dev_size; 18188c2ecf20Sopenharmony_ci 18198c2ecf20Sopenharmony_ci dev_size = get_dev_size(bdev); 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_ci src.bdev = bdev; 18228c2ecf20Sopenharmony_ci src.sector = chunk_to_sector(s->store, pe->e.old_chunk); 18238c2ecf20Sopenharmony_ci src.count = min((sector_t)s->store->chunk_size, dev_size - src.sector); 18248c2ecf20Sopenharmony_ci 18258c2ecf20Sopenharmony_ci dest.bdev = s->cow->bdev; 18268c2ecf20Sopenharmony_ci dest.sector = chunk_to_sector(s->store, pe->e.new_chunk); 18278c2ecf20Sopenharmony_ci dest.count = src.count; 18288c2ecf20Sopenharmony_ci 18298c2ecf20Sopenharmony_ci /* Hand over to kcopyd */ 18308c2ecf20Sopenharmony_ci account_start_copy(s); 18318c2ecf20Sopenharmony_ci dm_kcopyd_copy(s->kcopyd_client, &src, 1, &dest, 0, copy_callback, pe); 18328c2ecf20Sopenharmony_ci} 18338c2ecf20Sopenharmony_ci 18348c2ecf20Sopenharmony_cistatic void full_bio_end_io(struct bio *bio) 18358c2ecf20Sopenharmony_ci{ 18368c2ecf20Sopenharmony_ci void *callback_data = bio->bi_private; 18378c2ecf20Sopenharmony_ci 18388c2ecf20Sopenharmony_ci dm_kcopyd_do_callback(callback_data, 0, bio->bi_status ? 1 : 0); 18398c2ecf20Sopenharmony_ci} 18408c2ecf20Sopenharmony_ci 18418c2ecf20Sopenharmony_cistatic void start_full_bio(struct dm_snap_pending_exception *pe, 18428c2ecf20Sopenharmony_ci struct bio *bio) 18438c2ecf20Sopenharmony_ci{ 18448c2ecf20Sopenharmony_ci struct dm_snapshot *s = pe->snap; 18458c2ecf20Sopenharmony_ci void *callback_data; 18468c2ecf20Sopenharmony_ci 18478c2ecf20Sopenharmony_ci pe->full_bio = bio; 18488c2ecf20Sopenharmony_ci pe->full_bio_end_io = bio->bi_end_io; 18498c2ecf20Sopenharmony_ci 18508c2ecf20Sopenharmony_ci account_start_copy(s); 18518c2ecf20Sopenharmony_ci callback_data = dm_kcopyd_prepare_callback(s->kcopyd_client, 18528c2ecf20Sopenharmony_ci copy_callback, pe); 18538c2ecf20Sopenharmony_ci 18548c2ecf20Sopenharmony_ci bio->bi_end_io = full_bio_end_io; 18558c2ecf20Sopenharmony_ci bio->bi_private = callback_data; 18568c2ecf20Sopenharmony_ci 18578c2ecf20Sopenharmony_ci submit_bio_noacct(bio); 18588c2ecf20Sopenharmony_ci} 18598c2ecf20Sopenharmony_ci 18608c2ecf20Sopenharmony_cistatic struct dm_snap_pending_exception * 18618c2ecf20Sopenharmony_ci__lookup_pending_exception(struct dm_snapshot *s, chunk_t chunk) 18628c2ecf20Sopenharmony_ci{ 18638c2ecf20Sopenharmony_ci struct dm_exception *e = dm_lookup_exception(&s->pending, chunk); 18648c2ecf20Sopenharmony_ci 18658c2ecf20Sopenharmony_ci if (!e) 18668c2ecf20Sopenharmony_ci return NULL; 18678c2ecf20Sopenharmony_ci 18688c2ecf20Sopenharmony_ci return container_of(e, struct dm_snap_pending_exception, e); 18698c2ecf20Sopenharmony_ci} 18708c2ecf20Sopenharmony_ci 18718c2ecf20Sopenharmony_ci/* 18728c2ecf20Sopenharmony_ci * Inserts a pending exception into the pending table. 18738c2ecf20Sopenharmony_ci * 18748c2ecf20Sopenharmony_ci * NOTE: a write lock must be held on the chunk's pending exception table slot 18758c2ecf20Sopenharmony_ci * before calling this. 18768c2ecf20Sopenharmony_ci */ 18778c2ecf20Sopenharmony_cistatic struct dm_snap_pending_exception * 18788c2ecf20Sopenharmony_ci__insert_pending_exception(struct dm_snapshot *s, 18798c2ecf20Sopenharmony_ci struct dm_snap_pending_exception *pe, chunk_t chunk) 18808c2ecf20Sopenharmony_ci{ 18818c2ecf20Sopenharmony_ci pe->e.old_chunk = chunk; 18828c2ecf20Sopenharmony_ci bio_list_init(&pe->origin_bios); 18838c2ecf20Sopenharmony_ci bio_list_init(&pe->snapshot_bios); 18848c2ecf20Sopenharmony_ci pe->started = 0; 18858c2ecf20Sopenharmony_ci pe->full_bio = NULL; 18868c2ecf20Sopenharmony_ci 18878c2ecf20Sopenharmony_ci spin_lock(&s->pe_allocation_lock); 18888c2ecf20Sopenharmony_ci if (s->store->type->prepare_exception(s->store, &pe->e)) { 18898c2ecf20Sopenharmony_ci spin_unlock(&s->pe_allocation_lock); 18908c2ecf20Sopenharmony_ci free_pending_exception(pe); 18918c2ecf20Sopenharmony_ci return NULL; 18928c2ecf20Sopenharmony_ci } 18938c2ecf20Sopenharmony_ci 18948c2ecf20Sopenharmony_ci pe->exception_sequence = s->exception_start_sequence++; 18958c2ecf20Sopenharmony_ci spin_unlock(&s->pe_allocation_lock); 18968c2ecf20Sopenharmony_ci 18978c2ecf20Sopenharmony_ci dm_insert_exception(&s->pending, &pe->e); 18988c2ecf20Sopenharmony_ci 18998c2ecf20Sopenharmony_ci return pe; 19008c2ecf20Sopenharmony_ci} 19018c2ecf20Sopenharmony_ci 19028c2ecf20Sopenharmony_ci/* 19038c2ecf20Sopenharmony_ci * Looks to see if this snapshot already has a pending exception 19048c2ecf20Sopenharmony_ci * for this chunk, otherwise it allocates a new one and inserts 19058c2ecf20Sopenharmony_ci * it into the pending table. 19068c2ecf20Sopenharmony_ci * 19078c2ecf20Sopenharmony_ci * NOTE: a write lock must be held on the chunk's pending exception table slot 19088c2ecf20Sopenharmony_ci * before calling this. 19098c2ecf20Sopenharmony_ci */ 19108c2ecf20Sopenharmony_cistatic struct dm_snap_pending_exception * 19118c2ecf20Sopenharmony_ci__find_pending_exception(struct dm_snapshot *s, 19128c2ecf20Sopenharmony_ci struct dm_snap_pending_exception *pe, chunk_t chunk) 19138c2ecf20Sopenharmony_ci{ 19148c2ecf20Sopenharmony_ci struct dm_snap_pending_exception *pe2; 19158c2ecf20Sopenharmony_ci 19168c2ecf20Sopenharmony_ci pe2 = __lookup_pending_exception(s, chunk); 19178c2ecf20Sopenharmony_ci if (pe2) { 19188c2ecf20Sopenharmony_ci free_pending_exception(pe); 19198c2ecf20Sopenharmony_ci return pe2; 19208c2ecf20Sopenharmony_ci } 19218c2ecf20Sopenharmony_ci 19228c2ecf20Sopenharmony_ci return __insert_pending_exception(s, pe, chunk); 19238c2ecf20Sopenharmony_ci} 19248c2ecf20Sopenharmony_ci 19258c2ecf20Sopenharmony_cistatic void remap_exception(struct dm_snapshot *s, struct dm_exception *e, 19268c2ecf20Sopenharmony_ci struct bio *bio, chunk_t chunk) 19278c2ecf20Sopenharmony_ci{ 19288c2ecf20Sopenharmony_ci bio_set_dev(bio, s->cow->bdev); 19298c2ecf20Sopenharmony_ci bio->bi_iter.bi_sector = 19308c2ecf20Sopenharmony_ci chunk_to_sector(s->store, dm_chunk_number(e->new_chunk) + 19318c2ecf20Sopenharmony_ci (chunk - e->old_chunk)) + 19328c2ecf20Sopenharmony_ci (bio->bi_iter.bi_sector & s->store->chunk_mask); 19338c2ecf20Sopenharmony_ci} 19348c2ecf20Sopenharmony_ci 19358c2ecf20Sopenharmony_cistatic void zero_callback(int read_err, unsigned long write_err, void *context) 19368c2ecf20Sopenharmony_ci{ 19378c2ecf20Sopenharmony_ci struct bio *bio = context; 19388c2ecf20Sopenharmony_ci struct dm_snapshot *s = bio->bi_private; 19398c2ecf20Sopenharmony_ci 19408c2ecf20Sopenharmony_ci account_end_copy(s); 19418c2ecf20Sopenharmony_ci bio->bi_status = write_err ? BLK_STS_IOERR : 0; 19428c2ecf20Sopenharmony_ci bio_endio(bio); 19438c2ecf20Sopenharmony_ci} 19448c2ecf20Sopenharmony_ci 19458c2ecf20Sopenharmony_cistatic void zero_exception(struct dm_snapshot *s, struct dm_exception *e, 19468c2ecf20Sopenharmony_ci struct bio *bio, chunk_t chunk) 19478c2ecf20Sopenharmony_ci{ 19488c2ecf20Sopenharmony_ci struct dm_io_region dest; 19498c2ecf20Sopenharmony_ci 19508c2ecf20Sopenharmony_ci dest.bdev = s->cow->bdev; 19518c2ecf20Sopenharmony_ci dest.sector = bio->bi_iter.bi_sector; 19528c2ecf20Sopenharmony_ci dest.count = s->store->chunk_size; 19538c2ecf20Sopenharmony_ci 19548c2ecf20Sopenharmony_ci account_start_copy(s); 19558c2ecf20Sopenharmony_ci WARN_ON_ONCE(bio->bi_private); 19568c2ecf20Sopenharmony_ci bio->bi_private = s; 19578c2ecf20Sopenharmony_ci dm_kcopyd_zero(s->kcopyd_client, 1, &dest, 0, zero_callback, bio); 19588c2ecf20Sopenharmony_ci} 19598c2ecf20Sopenharmony_ci 19608c2ecf20Sopenharmony_cistatic bool io_overlaps_chunk(struct dm_snapshot *s, struct bio *bio) 19618c2ecf20Sopenharmony_ci{ 19628c2ecf20Sopenharmony_ci return bio->bi_iter.bi_size == 19638c2ecf20Sopenharmony_ci (s->store->chunk_size << SECTOR_SHIFT); 19648c2ecf20Sopenharmony_ci} 19658c2ecf20Sopenharmony_ci 19668c2ecf20Sopenharmony_cistatic int snapshot_map(struct dm_target *ti, struct bio *bio) 19678c2ecf20Sopenharmony_ci{ 19688c2ecf20Sopenharmony_ci struct dm_exception *e; 19698c2ecf20Sopenharmony_ci struct dm_snapshot *s = ti->private; 19708c2ecf20Sopenharmony_ci int r = DM_MAPIO_REMAPPED; 19718c2ecf20Sopenharmony_ci chunk_t chunk; 19728c2ecf20Sopenharmony_ci struct dm_snap_pending_exception *pe = NULL; 19738c2ecf20Sopenharmony_ci struct dm_exception_table_lock lock; 19748c2ecf20Sopenharmony_ci 19758c2ecf20Sopenharmony_ci init_tracked_chunk(bio); 19768c2ecf20Sopenharmony_ci 19778c2ecf20Sopenharmony_ci if (bio->bi_opf & REQ_PREFLUSH) { 19788c2ecf20Sopenharmony_ci bio_set_dev(bio, s->cow->bdev); 19798c2ecf20Sopenharmony_ci return DM_MAPIO_REMAPPED; 19808c2ecf20Sopenharmony_ci } 19818c2ecf20Sopenharmony_ci 19828c2ecf20Sopenharmony_ci chunk = sector_to_chunk(s->store, bio->bi_iter.bi_sector); 19838c2ecf20Sopenharmony_ci dm_exception_table_lock_init(s, chunk, &lock); 19848c2ecf20Sopenharmony_ci 19858c2ecf20Sopenharmony_ci /* Full snapshots are not usable */ 19868c2ecf20Sopenharmony_ci /* To get here the table must be live so s->active is always set. */ 19878c2ecf20Sopenharmony_ci if (!s->valid) 19888c2ecf20Sopenharmony_ci return DM_MAPIO_KILL; 19898c2ecf20Sopenharmony_ci 19908c2ecf20Sopenharmony_ci if (bio_data_dir(bio) == WRITE) { 19918c2ecf20Sopenharmony_ci while (unlikely(!wait_for_in_progress(s, false))) 19928c2ecf20Sopenharmony_ci ; /* wait_for_in_progress() has slept */ 19938c2ecf20Sopenharmony_ci } 19948c2ecf20Sopenharmony_ci 19958c2ecf20Sopenharmony_ci down_read(&s->lock); 19968c2ecf20Sopenharmony_ci dm_exception_table_lock(&lock); 19978c2ecf20Sopenharmony_ci 19988c2ecf20Sopenharmony_ci if (!s->valid || (unlikely(s->snapshot_overflowed) && 19998c2ecf20Sopenharmony_ci bio_data_dir(bio) == WRITE)) { 20008c2ecf20Sopenharmony_ci r = DM_MAPIO_KILL; 20018c2ecf20Sopenharmony_ci goto out_unlock; 20028c2ecf20Sopenharmony_ci } 20038c2ecf20Sopenharmony_ci 20048c2ecf20Sopenharmony_ci if (unlikely(bio_op(bio) == REQ_OP_DISCARD)) { 20058c2ecf20Sopenharmony_ci if (s->discard_passdown_origin && dm_bio_get_target_bio_nr(bio)) { 20068c2ecf20Sopenharmony_ci /* 20078c2ecf20Sopenharmony_ci * passdown discard to origin (without triggering 20088c2ecf20Sopenharmony_ci * snapshot exceptions via do_origin; doing so would 20098c2ecf20Sopenharmony_ci * defeat the goal of freeing space in origin that is 20108c2ecf20Sopenharmony_ci * implied by the "discard_passdown_origin" feature) 20118c2ecf20Sopenharmony_ci */ 20128c2ecf20Sopenharmony_ci bio_set_dev(bio, s->origin->bdev); 20138c2ecf20Sopenharmony_ci track_chunk(s, bio, chunk); 20148c2ecf20Sopenharmony_ci goto out_unlock; 20158c2ecf20Sopenharmony_ci } 20168c2ecf20Sopenharmony_ci /* discard to snapshot (target_bio_nr == 0) zeroes exceptions */ 20178c2ecf20Sopenharmony_ci } 20188c2ecf20Sopenharmony_ci 20198c2ecf20Sopenharmony_ci /* If the block is already remapped - use that, else remap it */ 20208c2ecf20Sopenharmony_ci e = dm_lookup_exception(&s->complete, chunk); 20218c2ecf20Sopenharmony_ci if (e) { 20228c2ecf20Sopenharmony_ci remap_exception(s, e, bio, chunk); 20238c2ecf20Sopenharmony_ci if (unlikely(bio_op(bio) == REQ_OP_DISCARD) && 20248c2ecf20Sopenharmony_ci io_overlaps_chunk(s, bio)) { 20258c2ecf20Sopenharmony_ci dm_exception_table_unlock(&lock); 20268c2ecf20Sopenharmony_ci up_read(&s->lock); 20278c2ecf20Sopenharmony_ci zero_exception(s, e, bio, chunk); 20288c2ecf20Sopenharmony_ci r = DM_MAPIO_SUBMITTED; /* discard is not issued */ 20298c2ecf20Sopenharmony_ci goto out; 20308c2ecf20Sopenharmony_ci } 20318c2ecf20Sopenharmony_ci goto out_unlock; 20328c2ecf20Sopenharmony_ci } 20338c2ecf20Sopenharmony_ci 20348c2ecf20Sopenharmony_ci if (unlikely(bio_op(bio) == REQ_OP_DISCARD)) { 20358c2ecf20Sopenharmony_ci /* 20368c2ecf20Sopenharmony_ci * If no exception exists, complete discard immediately 20378c2ecf20Sopenharmony_ci * otherwise it'll trigger copy-out. 20388c2ecf20Sopenharmony_ci */ 20398c2ecf20Sopenharmony_ci bio_endio(bio); 20408c2ecf20Sopenharmony_ci r = DM_MAPIO_SUBMITTED; 20418c2ecf20Sopenharmony_ci goto out_unlock; 20428c2ecf20Sopenharmony_ci } 20438c2ecf20Sopenharmony_ci 20448c2ecf20Sopenharmony_ci /* 20458c2ecf20Sopenharmony_ci * Write to snapshot - higher level takes care of RW/RO 20468c2ecf20Sopenharmony_ci * flags so we should only get this if we are 20478c2ecf20Sopenharmony_ci * writeable. 20488c2ecf20Sopenharmony_ci */ 20498c2ecf20Sopenharmony_ci if (bio_data_dir(bio) == WRITE) { 20508c2ecf20Sopenharmony_ci pe = __lookup_pending_exception(s, chunk); 20518c2ecf20Sopenharmony_ci if (!pe) { 20528c2ecf20Sopenharmony_ci dm_exception_table_unlock(&lock); 20538c2ecf20Sopenharmony_ci pe = alloc_pending_exception(s); 20548c2ecf20Sopenharmony_ci dm_exception_table_lock(&lock); 20558c2ecf20Sopenharmony_ci 20568c2ecf20Sopenharmony_ci e = dm_lookup_exception(&s->complete, chunk); 20578c2ecf20Sopenharmony_ci if (e) { 20588c2ecf20Sopenharmony_ci free_pending_exception(pe); 20598c2ecf20Sopenharmony_ci remap_exception(s, e, bio, chunk); 20608c2ecf20Sopenharmony_ci goto out_unlock; 20618c2ecf20Sopenharmony_ci } 20628c2ecf20Sopenharmony_ci 20638c2ecf20Sopenharmony_ci pe = __find_pending_exception(s, pe, chunk); 20648c2ecf20Sopenharmony_ci if (!pe) { 20658c2ecf20Sopenharmony_ci dm_exception_table_unlock(&lock); 20668c2ecf20Sopenharmony_ci up_read(&s->lock); 20678c2ecf20Sopenharmony_ci 20688c2ecf20Sopenharmony_ci down_write(&s->lock); 20698c2ecf20Sopenharmony_ci 20708c2ecf20Sopenharmony_ci if (s->store->userspace_supports_overflow) { 20718c2ecf20Sopenharmony_ci if (s->valid && !s->snapshot_overflowed) { 20728c2ecf20Sopenharmony_ci s->snapshot_overflowed = 1; 20738c2ecf20Sopenharmony_ci DMERR("Snapshot overflowed: Unable to allocate exception."); 20748c2ecf20Sopenharmony_ci } 20758c2ecf20Sopenharmony_ci } else 20768c2ecf20Sopenharmony_ci __invalidate_snapshot(s, -ENOMEM); 20778c2ecf20Sopenharmony_ci up_write(&s->lock); 20788c2ecf20Sopenharmony_ci 20798c2ecf20Sopenharmony_ci r = DM_MAPIO_KILL; 20808c2ecf20Sopenharmony_ci goto out; 20818c2ecf20Sopenharmony_ci } 20828c2ecf20Sopenharmony_ci } 20838c2ecf20Sopenharmony_ci 20848c2ecf20Sopenharmony_ci remap_exception(s, &pe->e, bio, chunk); 20858c2ecf20Sopenharmony_ci 20868c2ecf20Sopenharmony_ci r = DM_MAPIO_SUBMITTED; 20878c2ecf20Sopenharmony_ci 20888c2ecf20Sopenharmony_ci if (!pe->started && io_overlaps_chunk(s, bio)) { 20898c2ecf20Sopenharmony_ci pe->started = 1; 20908c2ecf20Sopenharmony_ci 20918c2ecf20Sopenharmony_ci dm_exception_table_unlock(&lock); 20928c2ecf20Sopenharmony_ci up_read(&s->lock); 20938c2ecf20Sopenharmony_ci 20948c2ecf20Sopenharmony_ci start_full_bio(pe, bio); 20958c2ecf20Sopenharmony_ci goto out; 20968c2ecf20Sopenharmony_ci } 20978c2ecf20Sopenharmony_ci 20988c2ecf20Sopenharmony_ci bio_list_add(&pe->snapshot_bios, bio); 20998c2ecf20Sopenharmony_ci 21008c2ecf20Sopenharmony_ci if (!pe->started) { 21018c2ecf20Sopenharmony_ci /* this is protected by the exception table lock */ 21028c2ecf20Sopenharmony_ci pe->started = 1; 21038c2ecf20Sopenharmony_ci 21048c2ecf20Sopenharmony_ci dm_exception_table_unlock(&lock); 21058c2ecf20Sopenharmony_ci up_read(&s->lock); 21068c2ecf20Sopenharmony_ci 21078c2ecf20Sopenharmony_ci start_copy(pe); 21088c2ecf20Sopenharmony_ci goto out; 21098c2ecf20Sopenharmony_ci } 21108c2ecf20Sopenharmony_ci } else { 21118c2ecf20Sopenharmony_ci bio_set_dev(bio, s->origin->bdev); 21128c2ecf20Sopenharmony_ci track_chunk(s, bio, chunk); 21138c2ecf20Sopenharmony_ci } 21148c2ecf20Sopenharmony_ci 21158c2ecf20Sopenharmony_ciout_unlock: 21168c2ecf20Sopenharmony_ci dm_exception_table_unlock(&lock); 21178c2ecf20Sopenharmony_ci up_read(&s->lock); 21188c2ecf20Sopenharmony_ciout: 21198c2ecf20Sopenharmony_ci return r; 21208c2ecf20Sopenharmony_ci} 21218c2ecf20Sopenharmony_ci 21228c2ecf20Sopenharmony_ci/* 21238c2ecf20Sopenharmony_ci * A snapshot-merge target behaves like a combination of a snapshot 21248c2ecf20Sopenharmony_ci * target and a snapshot-origin target. It only generates new 21258c2ecf20Sopenharmony_ci * exceptions in other snapshots and not in the one that is being 21268c2ecf20Sopenharmony_ci * merged. 21278c2ecf20Sopenharmony_ci * 21288c2ecf20Sopenharmony_ci * For each chunk, if there is an existing exception, it is used to 21298c2ecf20Sopenharmony_ci * redirect I/O to the cow device. Otherwise I/O is sent to the origin, 21308c2ecf20Sopenharmony_ci * which in turn might generate exceptions in other snapshots. 21318c2ecf20Sopenharmony_ci * If merging is currently taking place on the chunk in question, the 21328c2ecf20Sopenharmony_ci * I/O is deferred by adding it to s->bios_queued_during_merge. 21338c2ecf20Sopenharmony_ci */ 21348c2ecf20Sopenharmony_cistatic int snapshot_merge_map(struct dm_target *ti, struct bio *bio) 21358c2ecf20Sopenharmony_ci{ 21368c2ecf20Sopenharmony_ci struct dm_exception *e; 21378c2ecf20Sopenharmony_ci struct dm_snapshot *s = ti->private; 21388c2ecf20Sopenharmony_ci int r = DM_MAPIO_REMAPPED; 21398c2ecf20Sopenharmony_ci chunk_t chunk; 21408c2ecf20Sopenharmony_ci 21418c2ecf20Sopenharmony_ci init_tracked_chunk(bio); 21428c2ecf20Sopenharmony_ci 21438c2ecf20Sopenharmony_ci if (bio->bi_opf & REQ_PREFLUSH) { 21448c2ecf20Sopenharmony_ci if (!dm_bio_get_target_bio_nr(bio)) 21458c2ecf20Sopenharmony_ci bio_set_dev(bio, s->origin->bdev); 21468c2ecf20Sopenharmony_ci else 21478c2ecf20Sopenharmony_ci bio_set_dev(bio, s->cow->bdev); 21488c2ecf20Sopenharmony_ci return DM_MAPIO_REMAPPED; 21498c2ecf20Sopenharmony_ci } 21508c2ecf20Sopenharmony_ci 21518c2ecf20Sopenharmony_ci if (unlikely(bio_op(bio) == REQ_OP_DISCARD)) { 21528c2ecf20Sopenharmony_ci /* Once merging, discards no longer effect change */ 21538c2ecf20Sopenharmony_ci bio_endio(bio); 21548c2ecf20Sopenharmony_ci return DM_MAPIO_SUBMITTED; 21558c2ecf20Sopenharmony_ci } 21568c2ecf20Sopenharmony_ci 21578c2ecf20Sopenharmony_ci chunk = sector_to_chunk(s->store, bio->bi_iter.bi_sector); 21588c2ecf20Sopenharmony_ci 21598c2ecf20Sopenharmony_ci down_write(&s->lock); 21608c2ecf20Sopenharmony_ci 21618c2ecf20Sopenharmony_ci /* Full merging snapshots are redirected to the origin */ 21628c2ecf20Sopenharmony_ci if (!s->valid) 21638c2ecf20Sopenharmony_ci goto redirect_to_origin; 21648c2ecf20Sopenharmony_ci 21658c2ecf20Sopenharmony_ci /* If the block is already remapped - use that */ 21668c2ecf20Sopenharmony_ci e = dm_lookup_exception(&s->complete, chunk); 21678c2ecf20Sopenharmony_ci if (e) { 21688c2ecf20Sopenharmony_ci /* Queue writes overlapping with chunks being merged */ 21698c2ecf20Sopenharmony_ci if (bio_data_dir(bio) == WRITE && 21708c2ecf20Sopenharmony_ci chunk >= s->first_merging_chunk && 21718c2ecf20Sopenharmony_ci chunk < (s->first_merging_chunk + 21728c2ecf20Sopenharmony_ci s->num_merging_chunks)) { 21738c2ecf20Sopenharmony_ci bio_set_dev(bio, s->origin->bdev); 21748c2ecf20Sopenharmony_ci bio_list_add(&s->bios_queued_during_merge, bio); 21758c2ecf20Sopenharmony_ci r = DM_MAPIO_SUBMITTED; 21768c2ecf20Sopenharmony_ci goto out_unlock; 21778c2ecf20Sopenharmony_ci } 21788c2ecf20Sopenharmony_ci 21798c2ecf20Sopenharmony_ci remap_exception(s, e, bio, chunk); 21808c2ecf20Sopenharmony_ci 21818c2ecf20Sopenharmony_ci if (bio_data_dir(bio) == WRITE) 21828c2ecf20Sopenharmony_ci track_chunk(s, bio, chunk); 21838c2ecf20Sopenharmony_ci goto out_unlock; 21848c2ecf20Sopenharmony_ci } 21858c2ecf20Sopenharmony_ci 21868c2ecf20Sopenharmony_ciredirect_to_origin: 21878c2ecf20Sopenharmony_ci bio_set_dev(bio, s->origin->bdev); 21888c2ecf20Sopenharmony_ci 21898c2ecf20Sopenharmony_ci if (bio_data_dir(bio) == WRITE) { 21908c2ecf20Sopenharmony_ci up_write(&s->lock); 21918c2ecf20Sopenharmony_ci return do_origin(s->origin, bio, false); 21928c2ecf20Sopenharmony_ci } 21938c2ecf20Sopenharmony_ci 21948c2ecf20Sopenharmony_ciout_unlock: 21958c2ecf20Sopenharmony_ci up_write(&s->lock); 21968c2ecf20Sopenharmony_ci 21978c2ecf20Sopenharmony_ci return r; 21988c2ecf20Sopenharmony_ci} 21998c2ecf20Sopenharmony_ci 22008c2ecf20Sopenharmony_cistatic int snapshot_end_io(struct dm_target *ti, struct bio *bio, 22018c2ecf20Sopenharmony_ci blk_status_t *error) 22028c2ecf20Sopenharmony_ci{ 22038c2ecf20Sopenharmony_ci struct dm_snapshot *s = ti->private; 22048c2ecf20Sopenharmony_ci 22058c2ecf20Sopenharmony_ci if (is_bio_tracked(bio)) 22068c2ecf20Sopenharmony_ci stop_tracking_chunk(s, bio); 22078c2ecf20Sopenharmony_ci 22088c2ecf20Sopenharmony_ci return DM_ENDIO_DONE; 22098c2ecf20Sopenharmony_ci} 22108c2ecf20Sopenharmony_ci 22118c2ecf20Sopenharmony_cistatic void snapshot_merge_presuspend(struct dm_target *ti) 22128c2ecf20Sopenharmony_ci{ 22138c2ecf20Sopenharmony_ci struct dm_snapshot *s = ti->private; 22148c2ecf20Sopenharmony_ci 22158c2ecf20Sopenharmony_ci stop_merge(s); 22168c2ecf20Sopenharmony_ci} 22178c2ecf20Sopenharmony_ci 22188c2ecf20Sopenharmony_cistatic int snapshot_preresume(struct dm_target *ti) 22198c2ecf20Sopenharmony_ci{ 22208c2ecf20Sopenharmony_ci int r = 0; 22218c2ecf20Sopenharmony_ci struct dm_snapshot *s = ti->private; 22228c2ecf20Sopenharmony_ci struct dm_snapshot *snap_src = NULL, *snap_dest = NULL; 22238c2ecf20Sopenharmony_ci 22248c2ecf20Sopenharmony_ci down_read(&_origins_lock); 22258c2ecf20Sopenharmony_ci (void) __find_snapshots_sharing_cow(s, &snap_src, &snap_dest, NULL); 22268c2ecf20Sopenharmony_ci if (snap_src && snap_dest) { 22278c2ecf20Sopenharmony_ci down_read(&snap_src->lock); 22288c2ecf20Sopenharmony_ci if (s == snap_src) { 22298c2ecf20Sopenharmony_ci DMERR("Unable to resume snapshot source until " 22308c2ecf20Sopenharmony_ci "handover completes."); 22318c2ecf20Sopenharmony_ci r = -EINVAL; 22328c2ecf20Sopenharmony_ci } else if (!dm_suspended(snap_src->ti)) { 22338c2ecf20Sopenharmony_ci DMERR("Unable to perform snapshot handover until " 22348c2ecf20Sopenharmony_ci "source is suspended."); 22358c2ecf20Sopenharmony_ci r = -EINVAL; 22368c2ecf20Sopenharmony_ci } 22378c2ecf20Sopenharmony_ci up_read(&snap_src->lock); 22388c2ecf20Sopenharmony_ci } 22398c2ecf20Sopenharmony_ci up_read(&_origins_lock); 22408c2ecf20Sopenharmony_ci 22418c2ecf20Sopenharmony_ci return r; 22428c2ecf20Sopenharmony_ci} 22438c2ecf20Sopenharmony_ci 22448c2ecf20Sopenharmony_cistatic void snapshot_resume(struct dm_target *ti) 22458c2ecf20Sopenharmony_ci{ 22468c2ecf20Sopenharmony_ci struct dm_snapshot *s = ti->private; 22478c2ecf20Sopenharmony_ci struct dm_snapshot *snap_src = NULL, *snap_dest = NULL, *snap_merging = NULL; 22488c2ecf20Sopenharmony_ci struct dm_origin *o; 22498c2ecf20Sopenharmony_ci struct mapped_device *origin_md = NULL; 22508c2ecf20Sopenharmony_ci bool must_restart_merging = false; 22518c2ecf20Sopenharmony_ci 22528c2ecf20Sopenharmony_ci down_read(&_origins_lock); 22538c2ecf20Sopenharmony_ci 22548c2ecf20Sopenharmony_ci o = __lookup_dm_origin(s->origin->bdev); 22558c2ecf20Sopenharmony_ci if (o) 22568c2ecf20Sopenharmony_ci origin_md = dm_table_get_md(o->ti->table); 22578c2ecf20Sopenharmony_ci if (!origin_md) { 22588c2ecf20Sopenharmony_ci (void) __find_snapshots_sharing_cow(s, NULL, NULL, &snap_merging); 22598c2ecf20Sopenharmony_ci if (snap_merging) 22608c2ecf20Sopenharmony_ci origin_md = dm_table_get_md(snap_merging->ti->table); 22618c2ecf20Sopenharmony_ci } 22628c2ecf20Sopenharmony_ci if (origin_md == dm_table_get_md(ti->table)) 22638c2ecf20Sopenharmony_ci origin_md = NULL; 22648c2ecf20Sopenharmony_ci if (origin_md) { 22658c2ecf20Sopenharmony_ci if (dm_hold(origin_md)) 22668c2ecf20Sopenharmony_ci origin_md = NULL; 22678c2ecf20Sopenharmony_ci } 22688c2ecf20Sopenharmony_ci 22698c2ecf20Sopenharmony_ci up_read(&_origins_lock); 22708c2ecf20Sopenharmony_ci 22718c2ecf20Sopenharmony_ci if (origin_md) { 22728c2ecf20Sopenharmony_ci dm_internal_suspend_fast(origin_md); 22738c2ecf20Sopenharmony_ci if (snap_merging && test_bit(RUNNING_MERGE, &snap_merging->state_bits)) { 22748c2ecf20Sopenharmony_ci must_restart_merging = true; 22758c2ecf20Sopenharmony_ci stop_merge(snap_merging); 22768c2ecf20Sopenharmony_ci } 22778c2ecf20Sopenharmony_ci } 22788c2ecf20Sopenharmony_ci 22798c2ecf20Sopenharmony_ci down_read(&_origins_lock); 22808c2ecf20Sopenharmony_ci 22818c2ecf20Sopenharmony_ci (void) __find_snapshots_sharing_cow(s, &snap_src, &snap_dest, NULL); 22828c2ecf20Sopenharmony_ci if (snap_src && snap_dest) { 22838c2ecf20Sopenharmony_ci down_write(&snap_src->lock); 22848c2ecf20Sopenharmony_ci down_write_nested(&snap_dest->lock, SINGLE_DEPTH_NESTING); 22858c2ecf20Sopenharmony_ci __handover_exceptions(snap_src, snap_dest); 22868c2ecf20Sopenharmony_ci up_write(&snap_dest->lock); 22878c2ecf20Sopenharmony_ci up_write(&snap_src->lock); 22888c2ecf20Sopenharmony_ci } 22898c2ecf20Sopenharmony_ci 22908c2ecf20Sopenharmony_ci up_read(&_origins_lock); 22918c2ecf20Sopenharmony_ci 22928c2ecf20Sopenharmony_ci if (origin_md) { 22938c2ecf20Sopenharmony_ci if (must_restart_merging) 22948c2ecf20Sopenharmony_ci start_merge(snap_merging); 22958c2ecf20Sopenharmony_ci dm_internal_resume_fast(origin_md); 22968c2ecf20Sopenharmony_ci dm_put(origin_md); 22978c2ecf20Sopenharmony_ci } 22988c2ecf20Sopenharmony_ci 22998c2ecf20Sopenharmony_ci /* Now we have correct chunk size, reregister */ 23008c2ecf20Sopenharmony_ci reregister_snapshot(s); 23018c2ecf20Sopenharmony_ci 23028c2ecf20Sopenharmony_ci down_write(&s->lock); 23038c2ecf20Sopenharmony_ci s->active = 1; 23048c2ecf20Sopenharmony_ci up_write(&s->lock); 23058c2ecf20Sopenharmony_ci} 23068c2ecf20Sopenharmony_ci 23078c2ecf20Sopenharmony_cistatic uint32_t get_origin_minimum_chunksize(struct block_device *bdev) 23088c2ecf20Sopenharmony_ci{ 23098c2ecf20Sopenharmony_ci uint32_t min_chunksize; 23108c2ecf20Sopenharmony_ci 23118c2ecf20Sopenharmony_ci down_read(&_origins_lock); 23128c2ecf20Sopenharmony_ci min_chunksize = __minimum_chunk_size(__lookup_origin(bdev)); 23138c2ecf20Sopenharmony_ci up_read(&_origins_lock); 23148c2ecf20Sopenharmony_ci 23158c2ecf20Sopenharmony_ci return min_chunksize; 23168c2ecf20Sopenharmony_ci} 23178c2ecf20Sopenharmony_ci 23188c2ecf20Sopenharmony_cistatic void snapshot_merge_resume(struct dm_target *ti) 23198c2ecf20Sopenharmony_ci{ 23208c2ecf20Sopenharmony_ci struct dm_snapshot *s = ti->private; 23218c2ecf20Sopenharmony_ci 23228c2ecf20Sopenharmony_ci /* 23238c2ecf20Sopenharmony_ci * Handover exceptions from existing snapshot. 23248c2ecf20Sopenharmony_ci */ 23258c2ecf20Sopenharmony_ci snapshot_resume(ti); 23268c2ecf20Sopenharmony_ci 23278c2ecf20Sopenharmony_ci /* 23288c2ecf20Sopenharmony_ci * snapshot-merge acts as an origin, so set ti->max_io_len 23298c2ecf20Sopenharmony_ci */ 23308c2ecf20Sopenharmony_ci ti->max_io_len = get_origin_minimum_chunksize(s->origin->bdev); 23318c2ecf20Sopenharmony_ci 23328c2ecf20Sopenharmony_ci start_merge(s); 23338c2ecf20Sopenharmony_ci} 23348c2ecf20Sopenharmony_ci 23358c2ecf20Sopenharmony_cistatic void snapshot_status(struct dm_target *ti, status_type_t type, 23368c2ecf20Sopenharmony_ci unsigned status_flags, char *result, unsigned maxlen) 23378c2ecf20Sopenharmony_ci{ 23388c2ecf20Sopenharmony_ci unsigned sz = 0; 23398c2ecf20Sopenharmony_ci struct dm_snapshot *snap = ti->private; 23408c2ecf20Sopenharmony_ci unsigned num_features; 23418c2ecf20Sopenharmony_ci 23428c2ecf20Sopenharmony_ci switch (type) { 23438c2ecf20Sopenharmony_ci case STATUSTYPE_INFO: 23448c2ecf20Sopenharmony_ci 23458c2ecf20Sopenharmony_ci down_write(&snap->lock); 23468c2ecf20Sopenharmony_ci 23478c2ecf20Sopenharmony_ci if (!snap->valid) 23488c2ecf20Sopenharmony_ci DMEMIT("Invalid"); 23498c2ecf20Sopenharmony_ci else if (snap->merge_failed) 23508c2ecf20Sopenharmony_ci DMEMIT("Merge failed"); 23518c2ecf20Sopenharmony_ci else if (snap->snapshot_overflowed) 23528c2ecf20Sopenharmony_ci DMEMIT("Overflow"); 23538c2ecf20Sopenharmony_ci else { 23548c2ecf20Sopenharmony_ci if (snap->store->type->usage) { 23558c2ecf20Sopenharmony_ci sector_t total_sectors, sectors_allocated, 23568c2ecf20Sopenharmony_ci metadata_sectors; 23578c2ecf20Sopenharmony_ci snap->store->type->usage(snap->store, 23588c2ecf20Sopenharmony_ci &total_sectors, 23598c2ecf20Sopenharmony_ci §ors_allocated, 23608c2ecf20Sopenharmony_ci &metadata_sectors); 23618c2ecf20Sopenharmony_ci DMEMIT("%llu/%llu %llu", 23628c2ecf20Sopenharmony_ci (unsigned long long)sectors_allocated, 23638c2ecf20Sopenharmony_ci (unsigned long long)total_sectors, 23648c2ecf20Sopenharmony_ci (unsigned long long)metadata_sectors); 23658c2ecf20Sopenharmony_ci } 23668c2ecf20Sopenharmony_ci else 23678c2ecf20Sopenharmony_ci DMEMIT("Unknown"); 23688c2ecf20Sopenharmony_ci } 23698c2ecf20Sopenharmony_ci 23708c2ecf20Sopenharmony_ci up_write(&snap->lock); 23718c2ecf20Sopenharmony_ci 23728c2ecf20Sopenharmony_ci break; 23738c2ecf20Sopenharmony_ci 23748c2ecf20Sopenharmony_ci case STATUSTYPE_TABLE: 23758c2ecf20Sopenharmony_ci /* 23768c2ecf20Sopenharmony_ci * kdevname returns a static pointer so we need 23778c2ecf20Sopenharmony_ci * to make private copies if the output is to 23788c2ecf20Sopenharmony_ci * make sense. 23798c2ecf20Sopenharmony_ci */ 23808c2ecf20Sopenharmony_ci DMEMIT("%s %s", snap->origin->name, snap->cow->name); 23818c2ecf20Sopenharmony_ci sz += snap->store->type->status(snap->store, type, result + sz, 23828c2ecf20Sopenharmony_ci maxlen - sz); 23838c2ecf20Sopenharmony_ci num_features = snap->discard_zeroes_cow + snap->discard_passdown_origin; 23848c2ecf20Sopenharmony_ci if (num_features) { 23858c2ecf20Sopenharmony_ci DMEMIT(" %u", num_features); 23868c2ecf20Sopenharmony_ci if (snap->discard_zeroes_cow) 23878c2ecf20Sopenharmony_ci DMEMIT(" discard_zeroes_cow"); 23888c2ecf20Sopenharmony_ci if (snap->discard_passdown_origin) 23898c2ecf20Sopenharmony_ci DMEMIT(" discard_passdown_origin"); 23908c2ecf20Sopenharmony_ci } 23918c2ecf20Sopenharmony_ci break; 23928c2ecf20Sopenharmony_ci } 23938c2ecf20Sopenharmony_ci} 23948c2ecf20Sopenharmony_ci 23958c2ecf20Sopenharmony_cistatic int snapshot_iterate_devices(struct dm_target *ti, 23968c2ecf20Sopenharmony_ci iterate_devices_callout_fn fn, void *data) 23978c2ecf20Sopenharmony_ci{ 23988c2ecf20Sopenharmony_ci struct dm_snapshot *snap = ti->private; 23998c2ecf20Sopenharmony_ci int r; 24008c2ecf20Sopenharmony_ci 24018c2ecf20Sopenharmony_ci r = fn(ti, snap->origin, 0, ti->len, data); 24028c2ecf20Sopenharmony_ci 24038c2ecf20Sopenharmony_ci if (!r) 24048c2ecf20Sopenharmony_ci r = fn(ti, snap->cow, 0, get_dev_size(snap->cow->bdev), data); 24058c2ecf20Sopenharmony_ci 24068c2ecf20Sopenharmony_ci return r; 24078c2ecf20Sopenharmony_ci} 24088c2ecf20Sopenharmony_ci 24098c2ecf20Sopenharmony_cistatic void snapshot_io_hints(struct dm_target *ti, struct queue_limits *limits) 24108c2ecf20Sopenharmony_ci{ 24118c2ecf20Sopenharmony_ci struct dm_snapshot *snap = ti->private; 24128c2ecf20Sopenharmony_ci 24138c2ecf20Sopenharmony_ci if (snap->discard_zeroes_cow) { 24148c2ecf20Sopenharmony_ci struct dm_snapshot *snap_src = NULL, *snap_dest = NULL; 24158c2ecf20Sopenharmony_ci 24168c2ecf20Sopenharmony_ci down_read(&_origins_lock); 24178c2ecf20Sopenharmony_ci 24188c2ecf20Sopenharmony_ci (void) __find_snapshots_sharing_cow(snap, &snap_src, &snap_dest, NULL); 24198c2ecf20Sopenharmony_ci if (snap_src && snap_dest) 24208c2ecf20Sopenharmony_ci snap = snap_src; 24218c2ecf20Sopenharmony_ci 24228c2ecf20Sopenharmony_ci /* All discards are split on chunk_size boundary */ 24238c2ecf20Sopenharmony_ci limits->discard_granularity = snap->store->chunk_size; 24248c2ecf20Sopenharmony_ci limits->max_discard_sectors = snap->store->chunk_size; 24258c2ecf20Sopenharmony_ci 24268c2ecf20Sopenharmony_ci up_read(&_origins_lock); 24278c2ecf20Sopenharmony_ci } 24288c2ecf20Sopenharmony_ci} 24298c2ecf20Sopenharmony_ci 24308c2ecf20Sopenharmony_ci/*----------------------------------------------------------------- 24318c2ecf20Sopenharmony_ci * Origin methods 24328c2ecf20Sopenharmony_ci *---------------------------------------------------------------*/ 24338c2ecf20Sopenharmony_ci 24348c2ecf20Sopenharmony_ci/* 24358c2ecf20Sopenharmony_ci * If no exceptions need creating, DM_MAPIO_REMAPPED is returned and any 24368c2ecf20Sopenharmony_ci * supplied bio was ignored. The caller may submit it immediately. 24378c2ecf20Sopenharmony_ci * (No remapping actually occurs as the origin is always a direct linear 24388c2ecf20Sopenharmony_ci * map.) 24398c2ecf20Sopenharmony_ci * 24408c2ecf20Sopenharmony_ci * If further exceptions are required, DM_MAPIO_SUBMITTED is returned 24418c2ecf20Sopenharmony_ci * and any supplied bio is added to a list to be submitted once all 24428c2ecf20Sopenharmony_ci * the necessary exceptions exist. 24438c2ecf20Sopenharmony_ci */ 24448c2ecf20Sopenharmony_cistatic int __origin_write(struct list_head *snapshots, sector_t sector, 24458c2ecf20Sopenharmony_ci struct bio *bio) 24468c2ecf20Sopenharmony_ci{ 24478c2ecf20Sopenharmony_ci int r = DM_MAPIO_REMAPPED; 24488c2ecf20Sopenharmony_ci struct dm_snapshot *snap; 24498c2ecf20Sopenharmony_ci struct dm_exception *e; 24508c2ecf20Sopenharmony_ci struct dm_snap_pending_exception *pe, *pe2; 24518c2ecf20Sopenharmony_ci struct dm_snap_pending_exception *pe_to_start_now = NULL; 24528c2ecf20Sopenharmony_ci struct dm_snap_pending_exception *pe_to_start_last = NULL; 24538c2ecf20Sopenharmony_ci struct dm_exception_table_lock lock; 24548c2ecf20Sopenharmony_ci chunk_t chunk; 24558c2ecf20Sopenharmony_ci 24568c2ecf20Sopenharmony_ci /* Do all the snapshots on this origin */ 24578c2ecf20Sopenharmony_ci list_for_each_entry (snap, snapshots, list) { 24588c2ecf20Sopenharmony_ci /* 24598c2ecf20Sopenharmony_ci * Don't make new exceptions in a merging snapshot 24608c2ecf20Sopenharmony_ci * because it has effectively been deleted 24618c2ecf20Sopenharmony_ci */ 24628c2ecf20Sopenharmony_ci if (dm_target_is_snapshot_merge(snap->ti)) 24638c2ecf20Sopenharmony_ci continue; 24648c2ecf20Sopenharmony_ci 24658c2ecf20Sopenharmony_ci /* Nothing to do if writing beyond end of snapshot */ 24668c2ecf20Sopenharmony_ci if (sector >= dm_table_get_size(snap->ti->table)) 24678c2ecf20Sopenharmony_ci continue; 24688c2ecf20Sopenharmony_ci 24698c2ecf20Sopenharmony_ci /* 24708c2ecf20Sopenharmony_ci * Remember, different snapshots can have 24718c2ecf20Sopenharmony_ci * different chunk sizes. 24728c2ecf20Sopenharmony_ci */ 24738c2ecf20Sopenharmony_ci chunk = sector_to_chunk(snap->store, sector); 24748c2ecf20Sopenharmony_ci dm_exception_table_lock_init(snap, chunk, &lock); 24758c2ecf20Sopenharmony_ci 24768c2ecf20Sopenharmony_ci down_read(&snap->lock); 24778c2ecf20Sopenharmony_ci dm_exception_table_lock(&lock); 24788c2ecf20Sopenharmony_ci 24798c2ecf20Sopenharmony_ci /* Only deal with valid and active snapshots */ 24808c2ecf20Sopenharmony_ci if (!snap->valid || !snap->active) 24818c2ecf20Sopenharmony_ci goto next_snapshot; 24828c2ecf20Sopenharmony_ci 24838c2ecf20Sopenharmony_ci pe = __lookup_pending_exception(snap, chunk); 24848c2ecf20Sopenharmony_ci if (!pe) { 24858c2ecf20Sopenharmony_ci /* 24868c2ecf20Sopenharmony_ci * Check exception table to see if block is already 24878c2ecf20Sopenharmony_ci * remapped in this snapshot and trigger an exception 24888c2ecf20Sopenharmony_ci * if not. 24898c2ecf20Sopenharmony_ci */ 24908c2ecf20Sopenharmony_ci e = dm_lookup_exception(&snap->complete, chunk); 24918c2ecf20Sopenharmony_ci if (e) 24928c2ecf20Sopenharmony_ci goto next_snapshot; 24938c2ecf20Sopenharmony_ci 24948c2ecf20Sopenharmony_ci dm_exception_table_unlock(&lock); 24958c2ecf20Sopenharmony_ci pe = alloc_pending_exception(snap); 24968c2ecf20Sopenharmony_ci dm_exception_table_lock(&lock); 24978c2ecf20Sopenharmony_ci 24988c2ecf20Sopenharmony_ci pe2 = __lookup_pending_exception(snap, chunk); 24998c2ecf20Sopenharmony_ci 25008c2ecf20Sopenharmony_ci if (!pe2) { 25018c2ecf20Sopenharmony_ci e = dm_lookup_exception(&snap->complete, chunk); 25028c2ecf20Sopenharmony_ci if (e) { 25038c2ecf20Sopenharmony_ci free_pending_exception(pe); 25048c2ecf20Sopenharmony_ci goto next_snapshot; 25058c2ecf20Sopenharmony_ci } 25068c2ecf20Sopenharmony_ci 25078c2ecf20Sopenharmony_ci pe = __insert_pending_exception(snap, pe, chunk); 25088c2ecf20Sopenharmony_ci if (!pe) { 25098c2ecf20Sopenharmony_ci dm_exception_table_unlock(&lock); 25108c2ecf20Sopenharmony_ci up_read(&snap->lock); 25118c2ecf20Sopenharmony_ci 25128c2ecf20Sopenharmony_ci invalidate_snapshot(snap, -ENOMEM); 25138c2ecf20Sopenharmony_ci continue; 25148c2ecf20Sopenharmony_ci } 25158c2ecf20Sopenharmony_ci } else { 25168c2ecf20Sopenharmony_ci free_pending_exception(pe); 25178c2ecf20Sopenharmony_ci pe = pe2; 25188c2ecf20Sopenharmony_ci } 25198c2ecf20Sopenharmony_ci } 25208c2ecf20Sopenharmony_ci 25218c2ecf20Sopenharmony_ci r = DM_MAPIO_SUBMITTED; 25228c2ecf20Sopenharmony_ci 25238c2ecf20Sopenharmony_ci /* 25248c2ecf20Sopenharmony_ci * If an origin bio was supplied, queue it to wait for the 25258c2ecf20Sopenharmony_ci * completion of this exception, and start this one last, 25268c2ecf20Sopenharmony_ci * at the end of the function. 25278c2ecf20Sopenharmony_ci */ 25288c2ecf20Sopenharmony_ci if (bio) { 25298c2ecf20Sopenharmony_ci bio_list_add(&pe->origin_bios, bio); 25308c2ecf20Sopenharmony_ci bio = NULL; 25318c2ecf20Sopenharmony_ci 25328c2ecf20Sopenharmony_ci if (!pe->started) { 25338c2ecf20Sopenharmony_ci pe->started = 1; 25348c2ecf20Sopenharmony_ci pe_to_start_last = pe; 25358c2ecf20Sopenharmony_ci } 25368c2ecf20Sopenharmony_ci } 25378c2ecf20Sopenharmony_ci 25388c2ecf20Sopenharmony_ci if (!pe->started) { 25398c2ecf20Sopenharmony_ci pe->started = 1; 25408c2ecf20Sopenharmony_ci pe_to_start_now = pe; 25418c2ecf20Sopenharmony_ci } 25428c2ecf20Sopenharmony_ci 25438c2ecf20Sopenharmony_cinext_snapshot: 25448c2ecf20Sopenharmony_ci dm_exception_table_unlock(&lock); 25458c2ecf20Sopenharmony_ci up_read(&snap->lock); 25468c2ecf20Sopenharmony_ci 25478c2ecf20Sopenharmony_ci if (pe_to_start_now) { 25488c2ecf20Sopenharmony_ci start_copy(pe_to_start_now); 25498c2ecf20Sopenharmony_ci pe_to_start_now = NULL; 25508c2ecf20Sopenharmony_ci } 25518c2ecf20Sopenharmony_ci } 25528c2ecf20Sopenharmony_ci 25538c2ecf20Sopenharmony_ci /* 25548c2ecf20Sopenharmony_ci * Submit the exception against which the bio is queued last, 25558c2ecf20Sopenharmony_ci * to give the other exceptions a head start. 25568c2ecf20Sopenharmony_ci */ 25578c2ecf20Sopenharmony_ci if (pe_to_start_last) 25588c2ecf20Sopenharmony_ci start_copy(pe_to_start_last); 25598c2ecf20Sopenharmony_ci 25608c2ecf20Sopenharmony_ci return r; 25618c2ecf20Sopenharmony_ci} 25628c2ecf20Sopenharmony_ci 25638c2ecf20Sopenharmony_ci/* 25648c2ecf20Sopenharmony_ci * Called on a write from the origin driver. 25658c2ecf20Sopenharmony_ci */ 25668c2ecf20Sopenharmony_cistatic int do_origin(struct dm_dev *origin, struct bio *bio, bool limit) 25678c2ecf20Sopenharmony_ci{ 25688c2ecf20Sopenharmony_ci struct origin *o; 25698c2ecf20Sopenharmony_ci int r = DM_MAPIO_REMAPPED; 25708c2ecf20Sopenharmony_ci 25718c2ecf20Sopenharmony_ciagain: 25728c2ecf20Sopenharmony_ci down_read(&_origins_lock); 25738c2ecf20Sopenharmony_ci o = __lookup_origin(origin->bdev); 25748c2ecf20Sopenharmony_ci if (o) { 25758c2ecf20Sopenharmony_ci if (limit) { 25768c2ecf20Sopenharmony_ci struct dm_snapshot *s; 25778c2ecf20Sopenharmony_ci list_for_each_entry(s, &o->snapshots, list) 25788c2ecf20Sopenharmony_ci if (unlikely(!wait_for_in_progress(s, true))) 25798c2ecf20Sopenharmony_ci goto again; 25808c2ecf20Sopenharmony_ci } 25818c2ecf20Sopenharmony_ci 25828c2ecf20Sopenharmony_ci r = __origin_write(&o->snapshots, bio->bi_iter.bi_sector, bio); 25838c2ecf20Sopenharmony_ci } 25848c2ecf20Sopenharmony_ci up_read(&_origins_lock); 25858c2ecf20Sopenharmony_ci 25868c2ecf20Sopenharmony_ci return r; 25878c2ecf20Sopenharmony_ci} 25888c2ecf20Sopenharmony_ci 25898c2ecf20Sopenharmony_ci/* 25908c2ecf20Sopenharmony_ci * Trigger exceptions in all non-merging snapshots. 25918c2ecf20Sopenharmony_ci * 25928c2ecf20Sopenharmony_ci * The chunk size of the merging snapshot may be larger than the chunk 25938c2ecf20Sopenharmony_ci * size of some other snapshot so we may need to reallocate multiple 25948c2ecf20Sopenharmony_ci * chunks in other snapshots. 25958c2ecf20Sopenharmony_ci * 25968c2ecf20Sopenharmony_ci * We scan all the overlapping exceptions in the other snapshots. 25978c2ecf20Sopenharmony_ci * Returns 1 if anything was reallocated and must be waited for, 25988c2ecf20Sopenharmony_ci * otherwise returns 0. 25998c2ecf20Sopenharmony_ci * 26008c2ecf20Sopenharmony_ci * size must be a multiple of merging_snap's chunk_size. 26018c2ecf20Sopenharmony_ci */ 26028c2ecf20Sopenharmony_cistatic int origin_write_extent(struct dm_snapshot *merging_snap, 26038c2ecf20Sopenharmony_ci sector_t sector, unsigned size) 26048c2ecf20Sopenharmony_ci{ 26058c2ecf20Sopenharmony_ci int must_wait = 0; 26068c2ecf20Sopenharmony_ci sector_t n; 26078c2ecf20Sopenharmony_ci struct origin *o; 26088c2ecf20Sopenharmony_ci 26098c2ecf20Sopenharmony_ci /* 26108c2ecf20Sopenharmony_ci * The origin's __minimum_chunk_size() got stored in max_io_len 26118c2ecf20Sopenharmony_ci * by snapshot_merge_resume(). 26128c2ecf20Sopenharmony_ci */ 26138c2ecf20Sopenharmony_ci down_read(&_origins_lock); 26148c2ecf20Sopenharmony_ci o = __lookup_origin(merging_snap->origin->bdev); 26158c2ecf20Sopenharmony_ci for (n = 0; n < size; n += merging_snap->ti->max_io_len) 26168c2ecf20Sopenharmony_ci if (__origin_write(&o->snapshots, sector + n, NULL) == 26178c2ecf20Sopenharmony_ci DM_MAPIO_SUBMITTED) 26188c2ecf20Sopenharmony_ci must_wait = 1; 26198c2ecf20Sopenharmony_ci up_read(&_origins_lock); 26208c2ecf20Sopenharmony_ci 26218c2ecf20Sopenharmony_ci return must_wait; 26228c2ecf20Sopenharmony_ci} 26238c2ecf20Sopenharmony_ci 26248c2ecf20Sopenharmony_ci/* 26258c2ecf20Sopenharmony_ci * Origin: maps a linear range of a device, with hooks for snapshotting. 26268c2ecf20Sopenharmony_ci */ 26278c2ecf20Sopenharmony_ci 26288c2ecf20Sopenharmony_ci/* 26298c2ecf20Sopenharmony_ci * Construct an origin mapping: <dev_path> 26308c2ecf20Sopenharmony_ci * The context for an origin is merely a 'struct dm_dev *' 26318c2ecf20Sopenharmony_ci * pointing to the real device. 26328c2ecf20Sopenharmony_ci */ 26338c2ecf20Sopenharmony_cistatic int origin_ctr(struct dm_target *ti, unsigned int argc, char **argv) 26348c2ecf20Sopenharmony_ci{ 26358c2ecf20Sopenharmony_ci int r; 26368c2ecf20Sopenharmony_ci struct dm_origin *o; 26378c2ecf20Sopenharmony_ci 26388c2ecf20Sopenharmony_ci if (argc != 1) { 26398c2ecf20Sopenharmony_ci ti->error = "origin: incorrect number of arguments"; 26408c2ecf20Sopenharmony_ci return -EINVAL; 26418c2ecf20Sopenharmony_ci } 26428c2ecf20Sopenharmony_ci 26438c2ecf20Sopenharmony_ci o = kmalloc(sizeof(struct dm_origin), GFP_KERNEL); 26448c2ecf20Sopenharmony_ci if (!o) { 26458c2ecf20Sopenharmony_ci ti->error = "Cannot allocate private origin structure"; 26468c2ecf20Sopenharmony_ci r = -ENOMEM; 26478c2ecf20Sopenharmony_ci goto bad_alloc; 26488c2ecf20Sopenharmony_ci } 26498c2ecf20Sopenharmony_ci 26508c2ecf20Sopenharmony_ci r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &o->dev); 26518c2ecf20Sopenharmony_ci if (r) { 26528c2ecf20Sopenharmony_ci ti->error = "Cannot get target device"; 26538c2ecf20Sopenharmony_ci goto bad_open; 26548c2ecf20Sopenharmony_ci } 26558c2ecf20Sopenharmony_ci 26568c2ecf20Sopenharmony_ci o->ti = ti; 26578c2ecf20Sopenharmony_ci ti->private = o; 26588c2ecf20Sopenharmony_ci ti->num_flush_bios = 1; 26598c2ecf20Sopenharmony_ci 26608c2ecf20Sopenharmony_ci return 0; 26618c2ecf20Sopenharmony_ci 26628c2ecf20Sopenharmony_cibad_open: 26638c2ecf20Sopenharmony_ci kfree(o); 26648c2ecf20Sopenharmony_cibad_alloc: 26658c2ecf20Sopenharmony_ci return r; 26668c2ecf20Sopenharmony_ci} 26678c2ecf20Sopenharmony_ci 26688c2ecf20Sopenharmony_cistatic void origin_dtr(struct dm_target *ti) 26698c2ecf20Sopenharmony_ci{ 26708c2ecf20Sopenharmony_ci struct dm_origin *o = ti->private; 26718c2ecf20Sopenharmony_ci 26728c2ecf20Sopenharmony_ci dm_put_device(ti, o->dev); 26738c2ecf20Sopenharmony_ci kfree(o); 26748c2ecf20Sopenharmony_ci} 26758c2ecf20Sopenharmony_ci 26768c2ecf20Sopenharmony_cistatic int origin_map(struct dm_target *ti, struct bio *bio) 26778c2ecf20Sopenharmony_ci{ 26788c2ecf20Sopenharmony_ci struct dm_origin *o = ti->private; 26798c2ecf20Sopenharmony_ci unsigned available_sectors; 26808c2ecf20Sopenharmony_ci 26818c2ecf20Sopenharmony_ci bio_set_dev(bio, o->dev->bdev); 26828c2ecf20Sopenharmony_ci 26838c2ecf20Sopenharmony_ci if (unlikely(bio->bi_opf & REQ_PREFLUSH)) 26848c2ecf20Sopenharmony_ci return DM_MAPIO_REMAPPED; 26858c2ecf20Sopenharmony_ci 26868c2ecf20Sopenharmony_ci if (bio_data_dir(bio) != WRITE) 26878c2ecf20Sopenharmony_ci return DM_MAPIO_REMAPPED; 26888c2ecf20Sopenharmony_ci 26898c2ecf20Sopenharmony_ci available_sectors = o->split_boundary - 26908c2ecf20Sopenharmony_ci ((unsigned)bio->bi_iter.bi_sector & (o->split_boundary - 1)); 26918c2ecf20Sopenharmony_ci 26928c2ecf20Sopenharmony_ci if (bio_sectors(bio) > available_sectors) 26938c2ecf20Sopenharmony_ci dm_accept_partial_bio(bio, available_sectors); 26948c2ecf20Sopenharmony_ci 26958c2ecf20Sopenharmony_ci /* Only tell snapshots if this is a write */ 26968c2ecf20Sopenharmony_ci return do_origin(o->dev, bio, true); 26978c2ecf20Sopenharmony_ci} 26988c2ecf20Sopenharmony_ci 26998c2ecf20Sopenharmony_ci/* 27008c2ecf20Sopenharmony_ci * Set the target "max_io_len" field to the minimum of all the snapshots' 27018c2ecf20Sopenharmony_ci * chunk sizes. 27028c2ecf20Sopenharmony_ci */ 27038c2ecf20Sopenharmony_cistatic void origin_resume(struct dm_target *ti) 27048c2ecf20Sopenharmony_ci{ 27058c2ecf20Sopenharmony_ci struct dm_origin *o = ti->private; 27068c2ecf20Sopenharmony_ci 27078c2ecf20Sopenharmony_ci o->split_boundary = get_origin_minimum_chunksize(o->dev->bdev); 27088c2ecf20Sopenharmony_ci 27098c2ecf20Sopenharmony_ci down_write(&_origins_lock); 27108c2ecf20Sopenharmony_ci __insert_dm_origin(o); 27118c2ecf20Sopenharmony_ci up_write(&_origins_lock); 27128c2ecf20Sopenharmony_ci} 27138c2ecf20Sopenharmony_ci 27148c2ecf20Sopenharmony_cistatic void origin_postsuspend(struct dm_target *ti) 27158c2ecf20Sopenharmony_ci{ 27168c2ecf20Sopenharmony_ci struct dm_origin *o = ti->private; 27178c2ecf20Sopenharmony_ci 27188c2ecf20Sopenharmony_ci down_write(&_origins_lock); 27198c2ecf20Sopenharmony_ci __remove_dm_origin(o); 27208c2ecf20Sopenharmony_ci up_write(&_origins_lock); 27218c2ecf20Sopenharmony_ci} 27228c2ecf20Sopenharmony_ci 27238c2ecf20Sopenharmony_cistatic void origin_status(struct dm_target *ti, status_type_t type, 27248c2ecf20Sopenharmony_ci unsigned status_flags, char *result, unsigned maxlen) 27258c2ecf20Sopenharmony_ci{ 27268c2ecf20Sopenharmony_ci struct dm_origin *o = ti->private; 27278c2ecf20Sopenharmony_ci 27288c2ecf20Sopenharmony_ci switch (type) { 27298c2ecf20Sopenharmony_ci case STATUSTYPE_INFO: 27308c2ecf20Sopenharmony_ci result[0] = '\0'; 27318c2ecf20Sopenharmony_ci break; 27328c2ecf20Sopenharmony_ci 27338c2ecf20Sopenharmony_ci case STATUSTYPE_TABLE: 27348c2ecf20Sopenharmony_ci snprintf(result, maxlen, "%s", o->dev->name); 27358c2ecf20Sopenharmony_ci break; 27368c2ecf20Sopenharmony_ci } 27378c2ecf20Sopenharmony_ci} 27388c2ecf20Sopenharmony_ci 27398c2ecf20Sopenharmony_cistatic int origin_iterate_devices(struct dm_target *ti, 27408c2ecf20Sopenharmony_ci iterate_devices_callout_fn fn, void *data) 27418c2ecf20Sopenharmony_ci{ 27428c2ecf20Sopenharmony_ci struct dm_origin *o = ti->private; 27438c2ecf20Sopenharmony_ci 27448c2ecf20Sopenharmony_ci return fn(ti, o->dev, 0, ti->len, data); 27458c2ecf20Sopenharmony_ci} 27468c2ecf20Sopenharmony_ci 27478c2ecf20Sopenharmony_cistatic struct target_type origin_target = { 27488c2ecf20Sopenharmony_ci .name = "snapshot-origin", 27498c2ecf20Sopenharmony_ci .version = {1, 9, 0}, 27508c2ecf20Sopenharmony_ci .module = THIS_MODULE, 27518c2ecf20Sopenharmony_ci .ctr = origin_ctr, 27528c2ecf20Sopenharmony_ci .dtr = origin_dtr, 27538c2ecf20Sopenharmony_ci .map = origin_map, 27548c2ecf20Sopenharmony_ci .resume = origin_resume, 27558c2ecf20Sopenharmony_ci .postsuspend = origin_postsuspend, 27568c2ecf20Sopenharmony_ci .status = origin_status, 27578c2ecf20Sopenharmony_ci .iterate_devices = origin_iterate_devices, 27588c2ecf20Sopenharmony_ci}; 27598c2ecf20Sopenharmony_ci 27608c2ecf20Sopenharmony_cistatic struct target_type snapshot_target = { 27618c2ecf20Sopenharmony_ci .name = "snapshot", 27628c2ecf20Sopenharmony_ci .version = {1, 16, 0}, 27638c2ecf20Sopenharmony_ci .module = THIS_MODULE, 27648c2ecf20Sopenharmony_ci .ctr = snapshot_ctr, 27658c2ecf20Sopenharmony_ci .dtr = snapshot_dtr, 27668c2ecf20Sopenharmony_ci .map = snapshot_map, 27678c2ecf20Sopenharmony_ci .end_io = snapshot_end_io, 27688c2ecf20Sopenharmony_ci .preresume = snapshot_preresume, 27698c2ecf20Sopenharmony_ci .resume = snapshot_resume, 27708c2ecf20Sopenharmony_ci .status = snapshot_status, 27718c2ecf20Sopenharmony_ci .iterate_devices = snapshot_iterate_devices, 27728c2ecf20Sopenharmony_ci .io_hints = snapshot_io_hints, 27738c2ecf20Sopenharmony_ci}; 27748c2ecf20Sopenharmony_ci 27758c2ecf20Sopenharmony_cistatic struct target_type merge_target = { 27768c2ecf20Sopenharmony_ci .name = dm_snapshot_merge_target_name, 27778c2ecf20Sopenharmony_ci .version = {1, 5, 0}, 27788c2ecf20Sopenharmony_ci .module = THIS_MODULE, 27798c2ecf20Sopenharmony_ci .ctr = snapshot_ctr, 27808c2ecf20Sopenharmony_ci .dtr = snapshot_dtr, 27818c2ecf20Sopenharmony_ci .map = snapshot_merge_map, 27828c2ecf20Sopenharmony_ci .end_io = snapshot_end_io, 27838c2ecf20Sopenharmony_ci .presuspend = snapshot_merge_presuspend, 27848c2ecf20Sopenharmony_ci .preresume = snapshot_preresume, 27858c2ecf20Sopenharmony_ci .resume = snapshot_merge_resume, 27868c2ecf20Sopenharmony_ci .status = snapshot_status, 27878c2ecf20Sopenharmony_ci .iterate_devices = snapshot_iterate_devices, 27888c2ecf20Sopenharmony_ci .io_hints = snapshot_io_hints, 27898c2ecf20Sopenharmony_ci}; 27908c2ecf20Sopenharmony_ci 27918c2ecf20Sopenharmony_cistatic int __init dm_snapshot_init(void) 27928c2ecf20Sopenharmony_ci{ 27938c2ecf20Sopenharmony_ci int r; 27948c2ecf20Sopenharmony_ci 27958c2ecf20Sopenharmony_ci r = dm_exception_store_init(); 27968c2ecf20Sopenharmony_ci if (r) { 27978c2ecf20Sopenharmony_ci DMERR("Failed to initialize exception stores"); 27988c2ecf20Sopenharmony_ci return r; 27998c2ecf20Sopenharmony_ci } 28008c2ecf20Sopenharmony_ci 28018c2ecf20Sopenharmony_ci r = init_origin_hash(); 28028c2ecf20Sopenharmony_ci if (r) { 28038c2ecf20Sopenharmony_ci DMERR("init_origin_hash failed."); 28048c2ecf20Sopenharmony_ci goto bad_origin_hash; 28058c2ecf20Sopenharmony_ci } 28068c2ecf20Sopenharmony_ci 28078c2ecf20Sopenharmony_ci exception_cache = KMEM_CACHE(dm_exception, 0); 28088c2ecf20Sopenharmony_ci if (!exception_cache) { 28098c2ecf20Sopenharmony_ci DMERR("Couldn't create exception cache."); 28108c2ecf20Sopenharmony_ci r = -ENOMEM; 28118c2ecf20Sopenharmony_ci goto bad_exception_cache; 28128c2ecf20Sopenharmony_ci } 28138c2ecf20Sopenharmony_ci 28148c2ecf20Sopenharmony_ci pending_cache = KMEM_CACHE(dm_snap_pending_exception, 0); 28158c2ecf20Sopenharmony_ci if (!pending_cache) { 28168c2ecf20Sopenharmony_ci DMERR("Couldn't create pending cache."); 28178c2ecf20Sopenharmony_ci r = -ENOMEM; 28188c2ecf20Sopenharmony_ci goto bad_pending_cache; 28198c2ecf20Sopenharmony_ci } 28208c2ecf20Sopenharmony_ci 28218c2ecf20Sopenharmony_ci r = dm_register_target(&snapshot_target); 28228c2ecf20Sopenharmony_ci if (r < 0) { 28238c2ecf20Sopenharmony_ci DMERR("snapshot target register failed %d", r); 28248c2ecf20Sopenharmony_ci goto bad_register_snapshot_target; 28258c2ecf20Sopenharmony_ci } 28268c2ecf20Sopenharmony_ci 28278c2ecf20Sopenharmony_ci r = dm_register_target(&origin_target); 28288c2ecf20Sopenharmony_ci if (r < 0) { 28298c2ecf20Sopenharmony_ci DMERR("Origin target register failed %d", r); 28308c2ecf20Sopenharmony_ci goto bad_register_origin_target; 28318c2ecf20Sopenharmony_ci } 28328c2ecf20Sopenharmony_ci 28338c2ecf20Sopenharmony_ci r = dm_register_target(&merge_target); 28348c2ecf20Sopenharmony_ci if (r < 0) { 28358c2ecf20Sopenharmony_ci DMERR("Merge target register failed %d", r); 28368c2ecf20Sopenharmony_ci goto bad_register_merge_target; 28378c2ecf20Sopenharmony_ci } 28388c2ecf20Sopenharmony_ci 28398c2ecf20Sopenharmony_ci return 0; 28408c2ecf20Sopenharmony_ci 28418c2ecf20Sopenharmony_cibad_register_merge_target: 28428c2ecf20Sopenharmony_ci dm_unregister_target(&origin_target); 28438c2ecf20Sopenharmony_cibad_register_origin_target: 28448c2ecf20Sopenharmony_ci dm_unregister_target(&snapshot_target); 28458c2ecf20Sopenharmony_cibad_register_snapshot_target: 28468c2ecf20Sopenharmony_ci kmem_cache_destroy(pending_cache); 28478c2ecf20Sopenharmony_cibad_pending_cache: 28488c2ecf20Sopenharmony_ci kmem_cache_destroy(exception_cache); 28498c2ecf20Sopenharmony_cibad_exception_cache: 28508c2ecf20Sopenharmony_ci exit_origin_hash(); 28518c2ecf20Sopenharmony_cibad_origin_hash: 28528c2ecf20Sopenharmony_ci dm_exception_store_exit(); 28538c2ecf20Sopenharmony_ci 28548c2ecf20Sopenharmony_ci return r; 28558c2ecf20Sopenharmony_ci} 28568c2ecf20Sopenharmony_ci 28578c2ecf20Sopenharmony_cistatic void __exit dm_snapshot_exit(void) 28588c2ecf20Sopenharmony_ci{ 28598c2ecf20Sopenharmony_ci dm_unregister_target(&snapshot_target); 28608c2ecf20Sopenharmony_ci dm_unregister_target(&origin_target); 28618c2ecf20Sopenharmony_ci dm_unregister_target(&merge_target); 28628c2ecf20Sopenharmony_ci 28638c2ecf20Sopenharmony_ci exit_origin_hash(); 28648c2ecf20Sopenharmony_ci kmem_cache_destroy(pending_cache); 28658c2ecf20Sopenharmony_ci kmem_cache_destroy(exception_cache); 28668c2ecf20Sopenharmony_ci 28678c2ecf20Sopenharmony_ci dm_exception_store_exit(); 28688c2ecf20Sopenharmony_ci} 28698c2ecf20Sopenharmony_ci 28708c2ecf20Sopenharmony_ci/* Module hooks */ 28718c2ecf20Sopenharmony_cimodule_init(dm_snapshot_init); 28728c2ecf20Sopenharmony_cimodule_exit(dm_snapshot_exit); 28738c2ecf20Sopenharmony_ci 28748c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(DM_NAME " snapshot target"); 28758c2ecf20Sopenharmony_ciMODULE_AUTHOR("Joe Thornber"); 28768c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 28778c2ecf20Sopenharmony_ciMODULE_ALIAS("dm-snapshot-origin"); 28788c2ecf20Sopenharmony_ciMODULE_ALIAS("dm-snapshot-merge"); 2879