dm-array.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright (C) 2012 Red Hat, Inc.
  4. *
  5. * This file is released under the GPL.
  6. */
  7. #ifndef _LINUX_DM_ARRAY_H
  8. #define _LINUX_DM_ARRAY_H
  9. #include "dm-btree.h"
  10. /*----------------------------------------------------------------*/
  11. /*
  12. * The dm-array is a persistent version of an array. It packs the data
  13. * more efficiently than a btree which will result in less disk space use,
  14. * and a performance boost. The element get and set operations are still
  15. * O(ln(n)), but with a much smaller constant.
  16. *
  17. * The value type structure is reused from the btree type to support proper
  18. * reference counting of values.
  19. *
  20. * The arrays implicitly know their length, and bounds are checked for
  21. * lookups and updated. It doesn't store this in an accessible place
  22. * because it would waste a whole metadata block. Make sure you store the
  23. * size along with the array root in your encompassing data.
  24. *
  25. * Array entries are indexed via an unsigned integer starting from zero.
  26. * Arrays are not sparse; if you resize an array to have 'n' entries then
  27. * 'n - 1' will be the last valid index.
  28. *
  29. * Typical use:
  30. *
  31. * a) initialise a dm_array_info structure. This describes the array
  32. * values and ties it into a specific transaction manager. It holds no
  33. * instance data; the same info can be used for many similar arrays if
  34. * you wish.
  35. *
  36. * b) Get yourself a root. The root is the index of a block of data on the
  37. * disk that holds a particular instance of an array. You may have a
  38. * pre existing root in your metadata that you wish to use, or you may
  39. * want to create a brand new, empty array with dm_array_empty().
  40. *
  41. * Like the other data structures in this library, dm_array objects are
  42. * immutable between transactions. Update functions will return you the
  43. * root for a _new_ array. If you've incremented the old root, via
  44. * dm_tm_inc(), before calling the update function you may continue to use
  45. * it in parallel with the new root.
  46. *
  47. * c) resize an array with dm_array_resize().
  48. *
  49. * d) Get a value from the array with dm_array_get_value().
  50. *
  51. * e) Set a value in the array with dm_array_set_value().
  52. *
  53. * f) Walk an array of values in index order with dm_array_walk(). More
  54. * efficient than making many calls to dm_array_get_value().
  55. *
  56. * g) Destroy the array with dm_array_del(). This tells the transaction
  57. * manager that you're no longer using this data structure so it can
  58. * recycle it's blocks. (dm_array_dec() would be a better name for it,
  59. * but del is in keeping with dm_btree_del()).
  60. */
  61. /*
  62. * Describes an array. Don't initialise this structure yourself, use the
  63. * init function below.
  64. */
  65. struct dm_array_info {
  66. struct dm_transaction_manager *tm;
  67. struct dm_btree_value_type value_type;
  68. struct dm_btree_info btree_info;
  69. };
  70. /*
  71. * Sets up a dm_array_info structure. You don't need to do anything with
  72. * this structure when you finish using it.
  73. *
  74. * info - the structure being filled in.
  75. * tm - the transaction manager that should supervise this structure.
  76. * vt - describes the leaf values.
  77. */
  78. void dm_array_info_init(struct dm_array_info *info,
  79. struct dm_transaction_manager *tm,
  80. struct dm_btree_value_type *vt);
  81. /*
  82. * Create an empty, zero length array.
  83. *
  84. * info - describes the array
  85. * root - on success this will be filled out with the root block
  86. */
  87. int dm_array_empty(struct dm_array_info *info, dm_block_t *root);
  88. /*
  89. * Resizes the array.
  90. *
  91. * info - describes the array
  92. * root - the root block of the array on disk
  93. * old_size - the caller is responsible for remembering the size of
  94. * the array
  95. * new_size - can be bigger or smaller than old_size
  96. * value - if we're growing the array the new entries will have this value
  97. * new_root - on success, points to the new root block
  98. *
  99. * If growing the inc function for 'value' will be called the appropriate
  100. * number of times. So if the caller is holding a reference they may want
  101. * to drop it.
  102. */
  103. int dm_array_resize(struct dm_array_info *info, dm_block_t root,
  104. uint32_t old_size, uint32_t new_size,
  105. const void *value, dm_block_t *new_root)
  106. __dm_written_to_disk(value);
  107. /*
  108. * Creates a new array populated with values provided by a callback
  109. * function. This is more efficient than creating an empty array,
  110. * resizing, and then setting values since that process incurs a lot of
  111. * copying.
  112. *
  113. * Assumes 32bit values for now since it's only used by the cache hint
  114. * array.
  115. *
  116. * info - describes the array
  117. * root - the root block of the array on disk
  118. * size - the number of entries in the array
  119. * fn - the callback
  120. * context - passed to the callback
  121. */
  122. typedef int (*value_fn)(uint32_t index, void *value_le, void *context);
  123. int dm_array_new(struct dm_array_info *info, dm_block_t *root,
  124. uint32_t size, value_fn fn, void *context);
  125. /*
  126. * Frees a whole array. The value_type's decrement operation will be called
  127. * for all values in the array
  128. */
  129. int dm_array_del(struct dm_array_info *info, dm_block_t root);
  130. /*
  131. * Lookup a value in the array
  132. *
  133. * info - describes the array
  134. * root - root block of the array
  135. * index - array index
  136. * value - the value to be read. Will be in on-disk format of course.
  137. *
  138. * -ENODATA will be returned if the index is out of bounds.
  139. */
  140. int dm_array_get_value(struct dm_array_info *info, dm_block_t root,
  141. uint32_t index, void *value);
  142. /*
  143. * Set an entry in the array.
  144. *
  145. * info - describes the array
  146. * root - root block of the array
  147. * index - array index
  148. * value - value to be written to disk. Make sure you confirm the value is
  149. * in on-disk format with__dm_bless_for_disk() before calling.
  150. * new_root - the new root block
  151. *
  152. * The old value being overwritten will be decremented, the new value
  153. * incremented.
  154. *
  155. * -ENODATA will be returned if the index is out of bounds.
  156. */
  157. int dm_array_set_value(struct dm_array_info *info, dm_block_t root,
  158. uint32_t index, const void *value, dm_block_t *new_root)
  159. __dm_written_to_disk(value);
  160. /*
  161. * Walk through all the entries in an array.
  162. *
  163. * info - describes the array
  164. * root - root block of the array
  165. * fn - called back for every element
  166. * context - passed to the callback
  167. */
  168. int dm_array_walk(struct dm_array_info *info, dm_block_t root,
  169. int (*fn)(void *context, uint64_t key, void *leaf),
  170. void *context);
  171. /*----------------------------------------------------------------*/
  172. /*
  173. * Cursor api.
  174. *
  175. * This lets you iterate through all the entries in an array efficiently
  176. * (it will preload metadata).
  177. *
  178. * I'm using a cursor, rather than a walk function with a callback because
  179. * the cache target needs to iterate both the mapping and hint arrays in
  180. * unison.
  181. */
  182. struct dm_array_cursor {
  183. struct dm_array_info *info;
  184. struct dm_btree_cursor cursor;
  185. struct dm_block *block;
  186. struct array_block *ab;
  187. unsigned int index;
  188. };
  189. int dm_array_cursor_begin(struct dm_array_info *info,
  190. dm_block_t root, struct dm_array_cursor *c);
  191. void dm_array_cursor_end(struct dm_array_cursor *c);
  192. uint32_t dm_array_cursor_index(struct dm_array_cursor *c);
  193. int dm_array_cursor_next(struct dm_array_cursor *c);
  194. int dm_array_cursor_skip(struct dm_array_cursor *c, uint32_t count);
  195. /*
  196. * value_le is only valid while the cursor points at the current value.
  197. */
  198. void dm_array_cursor_get_value(struct dm_array_cursor *c, void **value_le);
  199. /*----------------------------------------------------------------*/
  200. #endif /* _LINUX_DM_ARRAY_H */