dm-exception-store.c 6.5 KB

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