11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001-2002 Sistina Software (UK) Limited. 34db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon * Copyright (C) 2006-2008 Red Hat GmbH 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file is released under the GPL. 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8aea53d92f70eeb00ae480e399a997dd55fd5055dJonathan Brassow#include "dm-exception-store.h" 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow#include <linux/ctype.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h> 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pagemap.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vmalloc.h> 14056075c76417b112b4924e7b6386fdc6dfc9ac03Paul Gortmaker#include <linux/module.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 174db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon#define DM_MSG_PREFIX "snapshot exception stores" 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 19493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowstatic LIST_HEAD(_exception_store_types); 20493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowstatic DEFINE_SPINLOCK(_lock); 21493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 22493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowstatic struct dm_exception_store_type *__find_exception_store_type(const char *name) 23493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{ 24493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow struct dm_exception_store_type *type; 25493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 26493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow list_for_each_entry(type, &_exception_store_types, list) 27493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow if (!strcmp(name, type->name)) 28493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return type; 29493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 30493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return NULL; 31493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow} 32493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 33493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowstatic struct dm_exception_store_type *_get_exception_store_type(const char *name) 34493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{ 35493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow struct dm_exception_store_type *type; 36493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 37493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow spin_lock(&_lock); 38493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 39493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow type = __find_exception_store_type(name); 40493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 41493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow if (type && !try_module_get(type->module)) 42493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow type = NULL; 43493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 44493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow spin_unlock(&_lock); 45493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 46493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return type; 47493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow} 48493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 49493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow/* 50493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * get_type 51493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * @type_name 52493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * 53493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * Attempt to retrieve the dm_exception_store_type by name. If not already 54493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * available, attempt to load the appropriate module. 55493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * 56493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * Exstore modules are named "dm-exstore-" followed by the 'type_name'. 57493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * Modules may contain multiple types. 58493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * This function will first try the module "dm-exstore-<type_name>", 59493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * then truncate 'type_name' on the last '-' and try again. 60493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * 61493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * For example, if type_name was "clustered-shared", it would search 62493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * 'dm-exstore-clustered-shared' then 'dm-exstore-clustered'. 63493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * 64493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * 'dm-exception-store-<type_name>' is too long of a name in my 65493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * opinion, which is why I've chosen to have the files 66493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * containing exception store implementations be 'dm-exstore-<type_name>'. 67493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * If you want your module to be autoloaded, you will follow this 68493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * naming convention. 69493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * 70493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * Returns: dm_exception_store_type* on success, NULL on failure 71493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow */ 72493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowstatic struct dm_exception_store_type *get_type(const char *type_name) 73493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{ 74493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow char *p, *type_name_dup; 75493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow struct dm_exception_store_type *type; 76493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 77493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow type = _get_exception_store_type(type_name); 78493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow if (type) 79493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return type; 80493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 81493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow type_name_dup = kstrdup(type_name, GFP_KERNEL); 82493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow if (!type_name_dup) { 83493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow DMERR("No memory left to attempt load for \"%s\"", type_name); 84493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return NULL; 85493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow } 86493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 87493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow while (request_module("dm-exstore-%s", type_name_dup) || 88493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow !(type = _get_exception_store_type(type_name))) { 89493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow p = strrchr(type_name_dup, '-'); 90493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow if (!p) 91493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow break; 92493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow p[0] = '\0'; 93493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow } 94493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 95493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow if (!type) 96493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow DMWARN("Module for exstore type \"%s\" not found.", type_name); 97493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 98493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow kfree(type_name_dup); 99493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 100493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return type; 101493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow} 102493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 103493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowstatic void put_type(struct dm_exception_store_type *type) 104493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{ 105493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow spin_lock(&_lock); 106493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow module_put(type->module); 107493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow spin_unlock(&_lock); 108493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow} 109493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 110493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowint dm_exception_store_type_register(struct dm_exception_store_type *type) 111493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{ 112493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow int r = 0; 113493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 114493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow spin_lock(&_lock); 115493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow if (!__find_exception_store_type(type->name)) 116493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow list_add(&type->list, &_exception_store_types); 117493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow else 118493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow r = -EEXIST; 119493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow spin_unlock(&_lock); 120493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 121493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return r; 122493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow} 123493df71c6420b211a68ae82b889c1e8a5fe701beJonathan BrassowEXPORT_SYMBOL(dm_exception_store_type_register); 124493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 125493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowint dm_exception_store_type_unregister(struct dm_exception_store_type *type) 126493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{ 127493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow spin_lock(&_lock); 128493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 129493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow if (!__find_exception_store_type(type->name)) { 130493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow spin_unlock(&_lock); 131493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return -EINVAL; 132493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow } 133493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 134493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow list_del(&type->list); 135493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 136493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow spin_unlock(&_lock); 137493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 138493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return 0; 139493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow} 140493df71c6420b211a68ae82b889c1e8a5fe701beJonathan BrassowEXPORT_SYMBOL(dm_exception_store_type_unregister); 141493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 142fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassowstatic int set_chunk_size(struct dm_exception_store *store, 143fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow const char *chunk_size_arg, char **error) 144fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow{ 1451a66a08ae82b16eb40705ad112ff28873981af92majianpeng unsigned chunk_size; 146fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 1471a66a08ae82b16eb40705ad112ff28873981af92majianpeng if (kstrtouint(chunk_size_arg, 10, &chunk_size)) { 148fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow *error = "Invalid chunk size"; 149fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return -EINVAL; 150fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 151fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 1521a66a08ae82b16eb40705ad112ff28873981af92majianpeng if (!chunk_size) { 153fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow store->chunk_size = store->chunk_mask = store->chunk_shift = 0; 154fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return 0; 155fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 156fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 1571a66a08ae82b16eb40705ad112ff28873981af92majianpeng return dm_exception_store_set_chunk_size(store, chunk_size, error); 1582defcc3fb4661e7351cb2ac48d843efc4c64db13Mikulas Patocka} 1592defcc3fb4661e7351cb2ac48d843efc4c64db13Mikulas Patocka 1602defcc3fb4661e7351cb2ac48d843efc4c64db13Mikulas Patockaint dm_exception_store_set_chunk_size(struct dm_exception_store *store, 161df96eee679ba28c98cf722fa7c9f4286ee1ed0bdMikulas Patocka unsigned chunk_size, 1622defcc3fb4661e7351cb2ac48d843efc4c64db13Mikulas Patocka char **error) 1632defcc3fb4661e7351cb2ac48d843efc4c64db13Mikulas Patocka{ 164fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow /* Check chunk_size is a power of 2 */ 165df96eee679ba28c98cf722fa7c9f4286ee1ed0bdMikulas Patocka if (!is_power_of_2(chunk_size)) { 166fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow *error = "Chunk size is not a power of 2"; 167fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return -EINVAL; 168fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 169fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 170fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow /* Validate the chunk size against the device block size */ 171fc56f6fbcca3672c63c93c65f45105faacfc13cbMike Snitzer if (chunk_size % 172c24110450650f17f7d3ba4fbe01f01ac5a115456Mikulas Patocka (bdev_logical_block_size(dm_snap_cow(store->snap)->bdev) >> 9) || 173c24110450650f17f7d3ba4fbe01f01ac5a115456Mikulas Patocka chunk_size % 174c24110450650f17f7d3ba4fbe01f01ac5a115456Mikulas Patocka (bdev_logical_block_size(dm_snap_origin(store->snap)->bdev) >> 9)) { 175fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow *error = "Chunk size is not a multiple of device blocksize"; 176fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return -EINVAL; 177fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 178fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 179df96eee679ba28c98cf722fa7c9f4286ee1ed0bdMikulas Patocka if (chunk_size > INT_MAX >> SECTOR_SHIFT) { 180ae0b7448e91353ea5f821601a055aca6b58042cdMikulas Patocka *error = "Chunk size is too high"; 181ae0b7448e91353ea5f821601a055aca6b58042cdMikulas Patocka return -EINVAL; 182ae0b7448e91353ea5f821601a055aca6b58042cdMikulas Patocka } 183ae0b7448e91353ea5f821601a055aca6b58042cdMikulas Patocka 184df96eee679ba28c98cf722fa7c9f4286ee1ed0bdMikulas Patocka store->chunk_size = chunk_size; 185df96eee679ba28c98cf722fa7c9f4286ee1ed0bdMikulas Patocka store->chunk_mask = chunk_size - 1; 186df96eee679ba28c98cf722fa7c9f4286ee1ed0bdMikulas Patocka store->chunk_shift = ffs(chunk_size) - 1; 187fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 188fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return 0; 189fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow} 190fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 191fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassowint dm_exception_store_create(struct dm_target *ti, int argc, char **argv, 192fc56f6fbcca3672c63c93c65f45105faacfc13cbMike Snitzer struct dm_snapshot *snap, 193fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow unsigned *args_used, 194493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow struct dm_exception_store **store) 195493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{ 196493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow int r = 0; 197874d2f61d31e596c36af7732dc1b3aa2dc233824Milan Broz struct dm_exception_store_type *type = NULL; 198493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow struct dm_exception_store *tmp_store; 199fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow char persistent; 200fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 201fc56f6fbcca3672c63c93c65f45105faacfc13cbMike Snitzer if (argc < 2) { 202fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow ti->error = "Insufficient exception store arguments"; 203fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return -EINVAL; 204fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 205493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 206493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow tmp_store = kmalloc(sizeof(*tmp_store), GFP_KERNEL); 207fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow if (!tmp_store) { 208fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow ti->error = "Exception store allocation failed"; 209493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return -ENOMEM; 210fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 211493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 212fc56f6fbcca3672c63c93c65f45105faacfc13cbMike Snitzer persistent = toupper(*argv[0]); 213874d2f61d31e596c36af7732dc1b3aa2dc233824Milan Broz if (persistent == 'P') 214874d2f61d31e596c36af7732dc1b3aa2dc233824Milan Broz type = get_type("P"); 215874d2f61d31e596c36af7732dc1b3aa2dc233824Milan Broz else if (persistent == 'N') 216874d2f61d31e596c36af7732dc1b3aa2dc233824Milan Broz type = get_type("N"); 217874d2f61d31e596c36af7732dc1b3aa2dc233824Milan Broz else { 218fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow ti->error = "Persistent flag is not P or N"; 219613978f8711c7fd4d0aa856872375d2abd7c92ffJulia Lawall r = -EINVAL; 220613978f8711c7fd4d0aa856872375d2abd7c92ffJulia Lawall goto bad_type; 221493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow } 222493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 223fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow if (!type) { 224fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow ti->error = "Exception store type not recognised"; 225fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow r = -EINVAL; 226fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow goto bad_type; 227fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 228fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 229493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow tmp_store->type = type; 230fc56f6fbcca3672c63c93c65f45105faacfc13cbMike Snitzer tmp_store->snap = snap; 231493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 232fc56f6fbcca3672c63c93c65f45105faacfc13cbMike Snitzer r = set_chunk_size(tmp_store, argv[1], &ti->error); 233fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow if (r) 234fc56f6fbcca3672c63c93c65f45105faacfc13cbMike Snitzer goto bad; 23549beb2b87a972a994ff77633234ca3bf0d30a1d8Jonathan Brassow 236493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow r = type->ctr(tmp_store, 0, NULL); 237493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow if (r) { 238fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow ti->error = "Exception store type constructor failed"; 239fc56f6fbcca3672c63c93c65f45105faacfc13cbMike Snitzer goto bad; 240493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow } 241493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 242fc56f6fbcca3672c63c93c65f45105faacfc13cbMike Snitzer *args_used = 2; 243493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow *store = tmp_store; 244493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return 0; 245fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 246fc56f6fbcca3672c63c93c65f45105faacfc13cbMike Snitzerbad: 247fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow put_type(type); 248fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassowbad_type: 249fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow kfree(tmp_store); 250fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return r; 251493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow} 252493df71c6420b211a68ae82b889c1e8a5fe701beJonathan BrassowEXPORT_SYMBOL(dm_exception_store_create); 253493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 254493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowvoid dm_exception_store_destroy(struct dm_exception_store *store) 255493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{ 256493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow store->type->dtr(store); 257493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow put_type(store->type); 258493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow kfree(store); 259493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow} 260493df71c6420b211a68ae82b889c1e8a5fe701beJonathan BrassowEXPORT_SYMBOL(dm_exception_store_destroy); 261493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 2624db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergonint dm_exception_store_init(void) 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int r; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2664db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon r = dm_transient_snapshot_init(); 2674db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon if (r) { 2684db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon DMERR("Unable to register transient exception store type."); 2694db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon goto transient_fail; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2724db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon r = dm_persistent_snapshot_init(); 2734db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon if (r) { 2744db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon DMERR("Unable to register persistent exception store type"); 2754db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon goto persistent_fail; 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2804db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergonpersistent_fail: 281aadbe266f2f89ccc68b52f4effc7b3a8b29521efAndrei Warkentin dm_transient_snapshot_exit(); 2824db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergontransient_fail: 2834db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon return r; 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2864db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergonvoid dm_exception_store_exit(void) 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2884db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon dm_persistent_snapshot_exit(); 2894db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon dm_transient_snapshot_exit(); 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 291