dm-bitset.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /*
  2. * Copyright (C) 2012 Red Hat, Inc.
  3. *
  4. * This file is released under the GPL.
  5. */
  6. #include "dm-bitset.h"
  7. #include "dm-transaction-manager.h"
  8. #include <linux/export.h>
  9. #include <linux/device-mapper.h>
  10. #define DM_MSG_PREFIX "bitset"
  11. #define BITS_PER_ARRAY_ENTRY 64
  12. /*----------------------------------------------------------------*/
  13. static struct dm_btree_value_type bitset_bvt = {
  14. .context = NULL,
  15. .size = sizeof(__le64),
  16. .inc = NULL,
  17. .dec = NULL,
  18. .equal = NULL,
  19. };
  20. /*----------------------------------------------------------------*/
  21. void dm_disk_bitset_init(struct dm_transaction_manager *tm,
  22. struct dm_disk_bitset *info)
  23. {
  24. dm_array_info_init(&info->array_info, tm, &bitset_bvt);
  25. info->current_index_set = false;
  26. }
  27. EXPORT_SYMBOL_GPL(dm_disk_bitset_init);
  28. int dm_bitset_empty(struct dm_disk_bitset *info, dm_block_t *root)
  29. {
  30. return dm_array_empty(&info->array_info, root);
  31. }
  32. EXPORT_SYMBOL_GPL(dm_bitset_empty);
  33. int dm_bitset_resize(struct dm_disk_bitset *info, dm_block_t root,
  34. uint32_t old_nr_entries, uint32_t new_nr_entries,
  35. bool default_value, dm_block_t *new_root)
  36. {
  37. uint32_t old_blocks = dm_div_up(old_nr_entries, BITS_PER_ARRAY_ENTRY);
  38. uint32_t new_blocks = dm_div_up(new_nr_entries, BITS_PER_ARRAY_ENTRY);
  39. __le64 value = default_value ? cpu_to_le64(~0) : cpu_to_le64(0);
  40. __dm_bless_for_disk(&value);
  41. return dm_array_resize(&info->array_info, root, old_blocks, new_blocks,
  42. &value, new_root);
  43. }
  44. EXPORT_SYMBOL_GPL(dm_bitset_resize);
  45. int dm_bitset_del(struct dm_disk_bitset *info, dm_block_t root)
  46. {
  47. return dm_array_del(&info->array_info, root);
  48. }
  49. EXPORT_SYMBOL_GPL(dm_bitset_del);
  50. int dm_bitset_flush(struct dm_disk_bitset *info, dm_block_t root,
  51. dm_block_t *new_root)
  52. {
  53. int r;
  54. __le64 value;
  55. if (!info->current_index_set || !info->dirty)
  56. return 0;
  57. value = cpu_to_le64(info->current_bits);
  58. __dm_bless_for_disk(&value);
  59. r = dm_array_set_value(&info->array_info, root, info->current_index,
  60. &value, new_root);
  61. if (r)
  62. return r;
  63. info->current_index_set = false;
  64. info->dirty = false;
  65. return 0;
  66. }
  67. EXPORT_SYMBOL_GPL(dm_bitset_flush);
  68. static int read_bits(struct dm_disk_bitset *info, dm_block_t root,
  69. uint32_t array_index)
  70. {
  71. int r;
  72. __le64 value;
  73. r = dm_array_get_value(&info->array_info, root, array_index, &value);
  74. if (r)
  75. return r;
  76. info->current_bits = le64_to_cpu(value);
  77. info->current_index_set = true;
  78. info->current_index = array_index;
  79. info->dirty = false;
  80. return 0;
  81. }
  82. static int get_array_entry(struct dm_disk_bitset *info, dm_block_t root,
  83. uint32_t index, dm_block_t *new_root)
  84. {
  85. int r;
  86. unsigned array_index = index / BITS_PER_ARRAY_ENTRY;
  87. if (info->current_index_set) {
  88. if (info->current_index == array_index)
  89. return 0;
  90. r = dm_bitset_flush(info, root, new_root);
  91. if (r)
  92. return r;
  93. }
  94. return read_bits(info, root, array_index);
  95. }
  96. int dm_bitset_set_bit(struct dm_disk_bitset *info, dm_block_t root,
  97. uint32_t index, dm_block_t *new_root)
  98. {
  99. int r;
  100. unsigned b = index % BITS_PER_ARRAY_ENTRY;
  101. r = get_array_entry(info, root, index, new_root);
  102. if (r)
  103. return r;
  104. set_bit(b, (unsigned long *) &info->current_bits);
  105. info->dirty = true;
  106. return 0;
  107. }
  108. EXPORT_SYMBOL_GPL(dm_bitset_set_bit);
  109. int dm_bitset_clear_bit(struct dm_disk_bitset *info, dm_block_t root,
  110. uint32_t index, dm_block_t *new_root)
  111. {
  112. int r;
  113. unsigned b = index % BITS_PER_ARRAY_ENTRY;
  114. r = get_array_entry(info, root, index, new_root);
  115. if (r)
  116. return r;
  117. clear_bit(b, (unsigned long *) &info->current_bits);
  118. info->dirty = true;
  119. return 0;
  120. }
  121. EXPORT_SYMBOL_GPL(dm_bitset_clear_bit);
  122. int dm_bitset_test_bit(struct dm_disk_bitset *info, dm_block_t root,
  123. uint32_t index, dm_block_t *new_root, bool *result)
  124. {
  125. int r;
  126. unsigned b = index % BITS_PER_ARRAY_ENTRY;
  127. r = get_array_entry(info, root, index, new_root);
  128. if (r)
  129. return r;
  130. *result = test_bit(b, (unsigned long *) &info->current_bits);
  131. return 0;
  132. }
  133. EXPORT_SYMBOL_GPL(dm_bitset_test_bit);
  134. /*----------------------------------------------------------------*/