dm-exception-store.c revision c24110450650f17f7d3ba4fbe01f01ac5a115456
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 Brassowstatic int set_chunk_size(struct dm_exception_store *store, 142fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow const char *chunk_size_arg, char **error) 143fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow{ 144fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow unsigned long chunk_size_ulong; 145fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow char *value; 146fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 147fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow chunk_size_ulong = simple_strtoul(chunk_size_arg, &value, 10); 148df96eee679ba28c98cf722fa7c9f4286ee1ed0bdMikulas Patocka if (*chunk_size_arg == '\0' || *value != '\0' || 149df96eee679ba28c98cf722fa7c9f4286ee1ed0bdMikulas Patocka chunk_size_ulong > UINT_MAX) { 150fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow *error = "Invalid chunk size"; 151fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return -EINVAL; 152fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 153fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 154fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow if (!chunk_size_ulong) { 155fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow store->chunk_size = store->chunk_mask = store->chunk_shift = 0; 156fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return 0; 157fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 158fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 159df96eee679ba28c98cf722fa7c9f4286ee1ed0bdMikulas Patocka return dm_exception_store_set_chunk_size(store, 160df96eee679ba28c98cf722fa7c9f4286ee1ed0bdMikulas Patocka (unsigned) chunk_size_ulong, 1612defcc3fb4661e7351cb2ac48d843efc4c64db13Mikulas Patocka error); 1622defcc3fb4661e7351cb2ac48d843efc4c64db13Mikulas Patocka} 1632defcc3fb4661e7351cb2ac48d843efc4c64db13Mikulas Patocka 1642defcc3fb4661e7351cb2ac48d843efc4c64db13Mikulas Patockaint dm_exception_store_set_chunk_size(struct dm_exception_store *store, 165df96eee679ba28c98cf722fa7c9f4286ee1ed0bdMikulas Patocka unsigned chunk_size, 1662defcc3fb4661e7351cb2ac48d843efc4c64db13Mikulas Patocka char **error) 1672defcc3fb4661e7351cb2ac48d843efc4c64db13Mikulas Patocka{ 168fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow /* Check chunk_size is a power of 2 */ 169df96eee679ba28c98cf722fa7c9f4286ee1ed0bdMikulas Patocka if (!is_power_of_2(chunk_size)) { 170fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow *error = "Chunk size is not a power of 2"; 171fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return -EINVAL; 172fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 173fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 174fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow /* Validate the chunk size against the device block size */ 175fc56f6fbcca3672c63c93c65f45105faacfc13cbMike Snitzer if (chunk_size % 176c24110450650f17f7d3ba4fbe01f01ac5a115456Mikulas Patocka (bdev_logical_block_size(dm_snap_cow(store->snap)->bdev) >> 9) || 177c24110450650f17f7d3ba4fbe01f01ac5a115456Mikulas Patocka chunk_size % 178c24110450650f17f7d3ba4fbe01f01ac5a115456Mikulas Patocka (bdev_logical_block_size(dm_snap_origin(store->snap)->bdev) >> 9)) { 179fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow *error = "Chunk size is not a multiple of device blocksize"; 180fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return -EINVAL; 181fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 182fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 183df96eee679ba28c98cf722fa7c9f4286ee1ed0bdMikulas Patocka if (chunk_size > INT_MAX >> SECTOR_SHIFT) { 184ae0b7448e91353ea5f821601a055aca6b58042cdMikulas Patocka *error = "Chunk size is too high"; 185ae0b7448e91353ea5f821601a055aca6b58042cdMikulas Patocka return -EINVAL; 186ae0b7448e91353ea5f821601a055aca6b58042cdMikulas Patocka } 187ae0b7448e91353ea5f821601a055aca6b58042cdMikulas Patocka 188df96eee679ba28c98cf722fa7c9f4286ee1ed0bdMikulas Patocka store->chunk_size = chunk_size; 189df96eee679ba28c98cf722fa7c9f4286ee1ed0bdMikulas Patocka store->chunk_mask = chunk_size - 1; 190df96eee679ba28c98cf722fa7c9f4286ee1ed0bdMikulas Patocka store->chunk_shift = ffs(chunk_size) - 1; 191fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 192fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return 0; 193fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow} 194fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 195fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassowint dm_exception_store_create(struct dm_target *ti, int argc, char **argv, 196fc56f6fbcca3672c63c93c65f45105faacfc13cbMike Snitzer struct dm_snapshot *snap, 197fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow unsigned *args_used, 198493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow struct dm_exception_store **store) 199493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{ 200493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow int r = 0; 201874d2f61d31e596c36af7732dc1b3aa2dc233824Milan Broz struct dm_exception_store_type *type = NULL; 202493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow struct dm_exception_store *tmp_store; 203fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow char persistent; 204fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 205fc56f6fbcca3672c63c93c65f45105faacfc13cbMike Snitzer if (argc < 2) { 206fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow ti->error = "Insufficient exception store arguments"; 207fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return -EINVAL; 208fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 209493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 210493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow tmp_store = kmalloc(sizeof(*tmp_store), GFP_KERNEL); 211fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow if (!tmp_store) { 212fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow ti->error = "Exception store allocation failed"; 213493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return -ENOMEM; 214fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 215493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 216fc56f6fbcca3672c63c93c65f45105faacfc13cbMike Snitzer persistent = toupper(*argv[0]); 217874d2f61d31e596c36af7732dc1b3aa2dc233824Milan Broz if (persistent == 'P') 218874d2f61d31e596c36af7732dc1b3aa2dc233824Milan Broz type = get_type("P"); 219874d2f61d31e596c36af7732dc1b3aa2dc233824Milan Broz else if (persistent == 'N') 220874d2f61d31e596c36af7732dc1b3aa2dc233824Milan Broz type = get_type("N"); 221874d2f61d31e596c36af7732dc1b3aa2dc233824Milan Broz else { 222fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow ti->error = "Persistent flag is not P or N"; 223613978f8711c7fd4d0aa856872375d2abd7c92ffJulia Lawall r = -EINVAL; 224613978f8711c7fd4d0aa856872375d2abd7c92ffJulia Lawall goto bad_type; 225493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow } 226493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 227fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow if (!type) { 228fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow ti->error = "Exception store type not recognised"; 229fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow r = -EINVAL; 230fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow goto bad_type; 231fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow } 232fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 233493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow tmp_store->type = type; 234fc56f6fbcca3672c63c93c65f45105faacfc13cbMike Snitzer tmp_store->snap = snap; 235493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 236fc56f6fbcca3672c63c93c65f45105faacfc13cbMike Snitzer r = set_chunk_size(tmp_store, argv[1], &ti->error); 237fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow if (r) 238fc56f6fbcca3672c63c93c65f45105faacfc13cbMike Snitzer goto bad; 23949beb2b87a972a994ff77633234ca3bf0d30a1d8Jonathan Brassow 240493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow r = type->ctr(tmp_store, 0, NULL); 241493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow if (r) { 242fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow ti->error = "Exception store type constructor failed"; 243fc56f6fbcca3672c63c93c65f45105faacfc13cbMike Snitzer goto bad; 244493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow } 245493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 246fc56f6fbcca3672c63c93c65f45105faacfc13cbMike Snitzer *args_used = 2; 247493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow *store = tmp_store; 248493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow return 0; 249fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow 250fc56f6fbcca3672c63c93c65f45105faacfc13cbMike Snitzerbad: 251fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow put_type(type); 252fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassowbad_type: 253fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow kfree(tmp_store); 254fee1998e9c690f9920671e1e0ef187a48cfbbde4Jonathan Brassow return r; 255493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow} 256493df71c6420b211a68ae82b889c1e8a5fe701beJonathan BrassowEXPORT_SYMBOL(dm_exception_store_create); 257493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 258493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowvoid dm_exception_store_destroy(struct dm_exception_store *store) 259493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{ 260493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow store->type->dtr(store); 261493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow put_type(store->type); 262493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow kfree(store); 263493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow} 264493df71c6420b211a68ae82b889c1e8a5fe701beJonathan BrassowEXPORT_SYMBOL(dm_exception_store_destroy); 265493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow 2664db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergonint dm_exception_store_init(void) 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int r; 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2704db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon r = dm_transient_snapshot_init(); 2714db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon if (r) { 2724db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon DMERR("Unable to register transient exception store type."); 2734db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon goto transient_fail; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2764db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon r = dm_persistent_snapshot_init(); 2774db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon if (r) { 2784db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon DMERR("Unable to register persistent exception store type"); 2794db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon goto persistent_fail; 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2844db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergonpersistent_fail: 2854db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon dm_persistent_snapshot_exit(); 2864db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergontransient_fail: 2874db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon return r; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2904db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergonvoid dm_exception_store_exit(void) 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2924db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon dm_persistent_snapshot_exit(); 2934db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon dm_transient_snapshot_exit(); 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 295