Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (C) 2006-2008 Red Hat GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * This file is released under the GPL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include "dm-exception-store.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/pagemap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/vmalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #define DM_MSG_PREFIX "snapshot exception stores"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) static LIST_HEAD(_exception_store_types);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) static DEFINE_SPINLOCK(_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) static struct dm_exception_store_type *__find_exception_store_type(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	struct dm_exception_store_type *type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	list_for_each_entry(type, &_exception_store_types, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 		if (!strcmp(name, type->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 			return type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) static struct dm_exception_store_type *_get_exception_store_type(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	struct dm_exception_store_type *type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	spin_lock(&_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	type = __find_exception_store_type(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	if (type && !try_module_get(type->module))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		type = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	spin_unlock(&_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	return type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  * get_type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)  * @type_name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  * Attempt to retrieve the dm_exception_store_type by name.  If not already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  * available, attempt to load the appropriate module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56)  * Exstore modules are named "dm-exstore-" followed by the 'type_name'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57)  * Modules may contain multiple types.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58)  * This function will first try the module "dm-exstore-<type_name>",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  * then truncate 'type_name' on the last '-' and try again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  * For example, if type_name was "clustered-shared", it would search
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  * 'dm-exstore-clustered-shared' then 'dm-exstore-clustered'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)  * 'dm-exception-store-<type_name>' is too long of a name in my
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)  * opinion, which is why I've chosen to have the files
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  * containing exception store implementations be 'dm-exstore-<type_name>'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  * If you want your module to be autoloaded, you will follow this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)  * naming convention.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  * Returns: dm_exception_store_type* on success, NULL on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) static struct dm_exception_store_type *get_type(const char *type_name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	char *p, *type_name_dup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	struct dm_exception_store_type *type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	type = _get_exception_store_type(type_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	if (type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		return type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	type_name_dup = kstrdup(type_name, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	if (!type_name_dup) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 		DMERR("No memory left to attempt load for \"%s\"", type_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	while (request_module("dm-exstore-%s", type_name_dup) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	       !(type = _get_exception_store_type(type_name))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 		p = strrchr(type_name_dup, '-');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 		if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 		p[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	if (!type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		DMWARN("Module for exstore type \"%s\" not found.", type_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	kfree(type_name_dup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	return type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static void put_type(struct dm_exception_store_type *type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	spin_lock(&_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	module_put(type->module);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	spin_unlock(&_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) int dm_exception_store_type_register(struct dm_exception_store_type *type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	int r = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	spin_lock(&_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	if (!__find_exception_store_type(type->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		list_add(&type->list, &_exception_store_types);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		r = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	spin_unlock(&_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) EXPORT_SYMBOL(dm_exception_store_type_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) int dm_exception_store_type_unregister(struct dm_exception_store_type *type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	spin_lock(&_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	if (!__find_exception_store_type(type->name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		spin_unlock(&_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	list_del(&type->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	spin_unlock(&_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) EXPORT_SYMBOL(dm_exception_store_type_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static int set_chunk_size(struct dm_exception_store *store,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 			  const char *chunk_size_arg, char **error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	unsigned chunk_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	if (kstrtouint(chunk_size_arg, 10, &chunk_size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 		*error = "Invalid chunk size";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	if (!chunk_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		store->chunk_size = store->chunk_mask = store->chunk_shift = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	return dm_exception_store_set_chunk_size(store, chunk_size, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 				      unsigned chunk_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 				      char **error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	/* Check chunk_size is a power of 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	if (!is_power_of_2(chunk_size)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		*error = "Chunk size is not a power of 2";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	/* Validate the chunk size against the device block size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	if (chunk_size %
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	    (bdev_logical_block_size(dm_snap_cow(store->snap)->bdev) >> 9) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	    chunk_size %
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	    (bdev_logical_block_size(dm_snap_origin(store->snap)->bdev) >> 9)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		*error = "Chunk size is not a multiple of device blocksize";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	if (chunk_size > INT_MAX >> SECTOR_SHIFT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		*error = "Chunk size is too high";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 	store->chunk_size = chunk_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	store->chunk_mask = chunk_size - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	store->chunk_shift = __ffs(chunk_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 			      struct dm_snapshot *snap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 			      unsigned *args_used,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 			      struct dm_exception_store **store)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	int r = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	struct dm_exception_store_type *type = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	struct dm_exception_store *tmp_store;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	char persistent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	if (argc < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 		ti->error = "Insufficient exception store arguments";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	tmp_store = kzalloc(sizeof(*tmp_store), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	if (!tmp_store) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		ti->error = "Exception store allocation failed";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	persistent = toupper(*argv[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	if (persistent == 'P')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		type = get_type("P");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 	else if (persistent == 'N')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 		type = get_type("N");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 		ti->error = "Exception store type is not P or N";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 		r = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 		goto bad_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 	if (!type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 		ti->error = "Exception store type not recognised";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 		r = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 		goto bad_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	tmp_store->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	tmp_store->snap = snap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	r = set_chunk_size(tmp_store, argv[1], &ti->error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	if (r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	r = type->ctr(tmp_store, (strlen(argv[0]) > 1 ? &argv[0][1] : NULL));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	if (r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		ti->error = "Exception store type constructor failed";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		goto bad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	*args_used = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	*store = tmp_store;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) bad:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	put_type(type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) bad_type:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	kfree(tmp_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) EXPORT_SYMBOL(dm_exception_store_create);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) void dm_exception_store_destroy(struct dm_exception_store *store)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	store->type->dtr(store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	put_type(store->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	kfree(store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) EXPORT_SYMBOL(dm_exception_store_destroy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) int dm_exception_store_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 	r = dm_transient_snapshot_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	if (r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		DMERR("Unable to register transient exception store type.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		goto transient_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 	r = dm_persistent_snapshot_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	if (r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		DMERR("Unable to register persistent exception store type");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		goto persistent_fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) persistent_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	dm_transient_snapshot_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) transient_fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	return r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) void dm_exception_store_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	dm_persistent_snapshot_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	dm_transient_snapshot_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }