dm-exception-store.c revision 2defcc3fb4661e7351cb2ac48d843efc4c64db13
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> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 164db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon#define DM_MSG_PREFIX "snapshot exception stores" 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowstatic LIST_HEAD(_exception_store_types); 19493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowstatic DEFINE_SPINLOCK(_lock); 20493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 21493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowstatic struct dm_exception_store_type *__find_exception_store_type(const char *name) 22493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{ 23493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow struct dm_exception_store_type *type; 24493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 25493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow list_for_each_entry(type, &_exception_store_types, list) 26493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow if (!strcmp(name, type->name)) 27493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return type; 28493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 29493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return NULL; 30493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow} 31493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 32493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowstatic struct dm_exception_store_type *_get_exception_store_type(const char *name) 33493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{ 34493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow struct dm_exception_store_type *type; 35493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 36493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow spin_lock(&_lock); 37493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 38493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow type = __find_exception_store_type(name); 39493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 40493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow if (type && !try_module_get(type->module)) 41493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow type = NULL; 42493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 43493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow spin_unlock(&_lock); 44493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 45493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return type; 46493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow} 47493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 48493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow/* 49493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * get_type 50493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * @type_name 51493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * 52493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * Attempt to retrieve the dm_exception_store_type by name. If not already 53493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * available, attempt to load the appropriate module. 54493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * 55493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * Exstore modules are named "dm-exstore-" followed by the 'type_name'. 56493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * Modules may contain multiple types. 57493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * This function will first try the module "dm-exstore-<type_name>", 58493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * then truncate 'type_name' on the last '-' and try again. 59493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * 60493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * For example, if type_name was "clustered-shared", it would search 61493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * 'dm-exstore-clustered-shared' then 'dm-exstore-clustered'. 62493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * 63493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * 'dm-exception-store-<type_name>' is too long of a name in my 64493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * opinion, which is why I've chosen to have the files 65493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * containing exception store implementations be 'dm-exstore-<type_name>'. 66493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * If you want your module to be autoloaded, you will follow this 67493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * naming convention. 68493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * 69493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * Returns: dm_exception_store_type* on success, NULL on failure 70493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow */ 71493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowstatic struct dm_exception_store_type *get_type(const char *type_name) 72493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{ 73493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow char *p, *type_name_dup; 74493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow struct dm_exception_store_type *type; 75493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 76493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow type = _get_exception_store_type(type_name); 77493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow if (type) 78493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return type; 79493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 80493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow type_name_dup = kstrdup(type_name, GFP_KERNEL); 81493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow if (!type_name_dup) { 82493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow DMERR("No memory left to attempt load for \"%s\"", type_name); 83493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return NULL; 84493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow } 85493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 86493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow while (request_module("dm-exstore-%s", type_name_dup) || 87493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow !(type = _get_exception_store_type(type_name))) { 88493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow p = strrchr(type_name_dup, '-'); 89493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow if (!p) 90493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow break; 91493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow p[0] = '\0'; 92493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow } 93493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 94493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow if (!type) 95493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow DMWARN("Module for exstore type \"%s\" not found.", type_name); 96493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 97493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow kfree(type_name_dup); 98493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 99493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return type; 100493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow} 101493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 102493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowstatic void put_type(struct dm_exception_store_type *type) 103493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{ 104493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow spin_lock(&_lock); 105493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow module_put(type->module); 106493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow spin_unlock(&_lock); 107493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow} 108493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 109493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowint dm_exception_store_type_register(struct dm_exception_store_type *type) 110493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{ 111493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow int r = 0; 112493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 113493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow spin_lock(&_lock); 114493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow if (!__find_exception_store_type(type->name)) 115493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow list_add(&type->list, &_exception_store_types); 116493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow else 117493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow r = -EEXIST; 118493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow spin_unlock(&_lock); 119493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 120493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return r; 121493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow} 122493df71c6420b211a68ae82b889c1e8a5fe701beJonathan BrassowEXPORT_SYMBOL(dm_exception_store_type_register); 123493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 124493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowint dm_exception_store_type_unregister(struct dm_exception_store_type *type) 125493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{ 126493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow spin_lock(&_lock); 127493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 128493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow if (!__find_exception_store_type(type->name)) { 129493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow spin_unlock(&_lock); 130493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return -EINVAL; 131493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow } 132493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 133493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow list_del(&type->list); 134493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 135493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow spin_unlock(&_lock); 136493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 137493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return 0; 138493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow} 139493df71c6420b211a68ae82b889c1e8a5fe701beJonathan BrassowEXPORT_SYMBOL(dm_exception_store_type_unregister); 140493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 141fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow/* 142fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow * Round a number up to the nearest 'size' boundary. size must 143fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow * be a power of 2. 144fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow */ 145fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassowstatic ulong round_up(ulong n, ulong size) 146fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow{ 147fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow size--; 148fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return (n + size) & ~size; 149fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow} 150fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 151fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassowstatic int set_chunk_size(struct dm_exception_store *store, 152fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow const char *chunk_size_arg, char **error) 153fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow{ 154fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow unsigned long chunk_size_ulong; 155fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow char *value; 156fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 157fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow chunk_size_ulong = simple_strtoul(chunk_size_arg, &value, 10); 158fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow if (*chunk_size_arg == '\0' || *value != '\0') { 159fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow *error = "Invalid chunk size"; 160fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return -EINVAL; 161fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 162fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 163fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow if (!chunk_size_ulong) { 164fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow store->chunk_size = store->chunk_mask = store->chunk_shift = 0; 165fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return 0; 166fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 167fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 168fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow /* 169fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow * Chunk size must be multiple of page size. Silently 170fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow * round up if it's not. 171fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow */ 172fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow chunk_size_ulong = round_up(chunk_size_ulong, PAGE_SIZE >> 9); 173fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 1742defcc3fb4661e7351cb2ac48d843efc4c64db13Mikulas Patocka return dm_exception_store_set_chunk_size(store, chunk_size_ulong, 1752defcc3fb4661e7351cb2ac48d843efc4c64db13Mikulas Patocka error); 1762defcc3fb4661e7351cb2ac48d843efc4c64db13Mikulas Patocka} 1772defcc3fb4661e7351cb2ac48d843efc4c64db13Mikulas Patocka 1782defcc3fb4661e7351cb2ac48d843efc4c64db13Mikulas Patockaint dm_exception_store_set_chunk_size(struct dm_exception_store *store, 1792defcc3fb4661e7351cb2ac48d843efc4c64db13Mikulas Patocka unsigned long chunk_size_ulong, 1802defcc3fb4661e7351cb2ac48d843efc4c64db13Mikulas Patocka char **error) 1812defcc3fb4661e7351cb2ac48d843efc4c64db13Mikulas Patocka{ 182fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow /* Check chunk_size is a power of 2 */ 183fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow if (!is_power_of_2(chunk_size_ulong)) { 184fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow *error = "Chunk size is not a power of 2"; 185fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return -EINVAL; 186fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 187fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 188fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow /* Validate the chunk size against the device block size */ 189e1defc4ff0cf57aca6c5e3ff99fa503f5943c1f1Martin K. Petersen if (chunk_size_ulong % (bdev_logical_block_size(store->cow->bdev) >> 9)) { 190fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow *error = "Chunk size is not a multiple of device blocksize"; 191fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return -EINVAL; 192fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 193fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 194fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow store->chunk_size = chunk_size_ulong; 195fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow store->chunk_mask = chunk_size_ulong - 1; 196fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow store->chunk_shift = ffs(chunk_size_ulong) - 1; 197fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 198fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return 0; 199fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow} 200fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 201fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassowint dm_exception_store_create(struct dm_target *ti, int argc, char **argv, 202fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow unsigned *args_used, 203493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow struct dm_exception_store **store) 204493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{ 205493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow int r = 0; 206874d2f61d31e596c36af7732dc1b3aa2dc233824Milan Broz struct dm_exception_store_type *type = NULL; 207493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow struct dm_exception_store *tmp_store; 208fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow char persistent; 209fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 210fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow if (argc < 3) { 211fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow ti->error = "Insufficient exception store arguments"; 212fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return -EINVAL; 213fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 214493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 215493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow tmp_store = kmalloc(sizeof(*tmp_store), GFP_KERNEL); 216fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow if (!tmp_store) { 217fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow ti->error = "Exception store allocation failed"; 218493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return -ENOMEM; 219fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 220493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 221fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow persistent = toupper(*argv[1]); 222874d2f61d31e596c36af7732dc1b3aa2dc233824Milan Broz if (persistent == 'P') 223874d2f61d31e596c36af7732dc1b3aa2dc233824Milan Broz type = get_type("P"); 224874d2f61d31e596c36af7732dc1b3aa2dc233824Milan Broz else if (persistent == 'N') 225874d2f61d31e596c36af7732dc1b3aa2dc233824Milan Broz type = get_type("N"); 226874d2f61d31e596c36af7732dc1b3aa2dc233824Milan Broz else { 227fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow ti->error = "Persistent flag is not P or N"; 228493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return -EINVAL; 229493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow } 230493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 231fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow if (!type) { 232fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow ti->error = "Exception store type not recognised"; 233fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow r = -EINVAL; 234fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow goto bad_type; 235fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 236fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 237493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow tmp_store->type = type; 2380cea9c78270cdf1d2ad74ce0e083d5555a0842e8Jonathan Brassow tmp_store->ti = ti; 239493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 240fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow r = dm_get_device(ti, argv[0], 0, 0, 241fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow FMODE_READ | FMODE_WRITE, &tmp_store->cow); 242fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow if (r) { 243fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow ti->error = "Cannot get COW device"; 244fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow goto bad_cow; 245fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 246d0216849519bec8dc96301a3cd80316e71243839Jonathan Brassow 247fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow r = set_chunk_size(tmp_store, argv[2], &ti->error); 248fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow if (r) 249fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow goto bad_cow; 25049beb2b87a972a994ff77633234ca3bf0d30a1d8Jonathan Brassow 251493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow r = type->ctr(tmp_store, 0, NULL); 252493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow if (r) { 253fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow ti->error = "Exception store type constructor failed"; 254fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow goto bad_ctr; 255493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow } 256493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 257fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow *args_used = 3; 258493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow *store = tmp_store; 259493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return 0; 260fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 261fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassowbad_ctr: 262fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow dm_put_device(ti, tmp_store->cow); 263fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassowbad_cow: 264fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow put_type(type); 265fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassowbad_type: 266fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow kfree(tmp_store); 267fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return r; 268493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow} 269493df71c6420b211a68ae82b889c1e8a5fe701beJonathan BrassowEXPORT_SYMBOL(dm_exception_store_create); 270493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 271493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowvoid dm_exception_store_destroy(struct dm_exception_store *store) 272493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{ 273493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow store->type->dtr(store); 274fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow dm_put_device(store->ti, store->cow); 275493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow put_type(store->type); 276493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow kfree(store); 277493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow} 278493df71c6420b211a68ae82b889c1e8a5fe701beJonathan BrassowEXPORT_SYMBOL(dm_exception_store_destroy); 279493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 2804db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergonint dm_exception_store_init(void) 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int r; 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2844db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon r = dm_transient_snapshot_init(); 2854db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon if (r) { 2864db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon DMERR("Unable to register transient exception store type."); 2874db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon goto transient_fail; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2904db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon r = dm_persistent_snapshot_init(); 2914db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon if (r) { 2924db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon DMERR("Unable to register persistent exception store type"); 2934db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon goto persistent_fail; 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2984db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergonpersistent_fail: 2994db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon dm_persistent_snapshot_exit(); 3004db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergontransient_fail: 3014db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon return r; 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3044db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergonvoid dm_exception_store_exit(void) 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3064db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon dm_persistent_snapshot_exit(); 3074db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon dm_transient_snapshot_exit(); 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 309