dm-bitset.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  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)
  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. return 0;
  65. }
  66. EXPORT_SYMBOL_GPL(dm_bitset_flush);
  67. static int read_bits(struct dm_disk_bitset *info, dm_block_t root,
  68. uint32_t array_index)
  69. {
  70. int r;
  71. __le64 value;
  72. r = dm_array_get_value(&info->array_info, root, array_index, &value);
  73. if (r)
  74. return r;
  75. info->current_bits = le64_to_cpu(value);
  76. info->current_index_set = true;
  77. info->current_index = array_index;
  78. return 0;
  79. }
  80. static int get_array_entry(struct dm_disk_bitset *info, dm_block_t root,
  81. uint32_t index, dm_block_t *new_root)
  82. {
  83. int r;
  84. unsigned array_index = index / BITS_PER_ARRAY_ENTRY;
  85. if (info->current_index_set) {
  86. if (info->current_index == array_index)
  87. return 0;
  88. r = dm_bitset_flush(info, root, new_root);
  89. if (r)
  90. return r;
  91. }
  92. return read_bits(info, root, array_index);
  93. }
  94. int dm_bitset_set_bit(struct dm_disk_bitset *info, dm_block_t root,
  95. uint32_t index, dm_block_t *new_root)
  96. {
  97. int r;
  98. unsigned b = index % BITS_PER_ARRAY_ENTRY;
  99. r = get_array_entry(info, root, index, new_root);
  100. if (r)
  101. return r;
  102. set_bit(b, (unsigned long *) &info->current_bits);
  103. return 0;
  104. }
  105. EXPORT_SYMBOL_GPL(dm_bitset_set_bit);
  106. int dm_bitset_clear_bit(struct dm_disk_bitset *info, dm_block_t root,
  107. uint32_t index, dm_block_t *new_root)
  108. {
  109. int r;
  110. unsigned b = index % BITS_PER_ARRAY_ENTRY;
  111. r = get_array_entry(info, root, index, new_root);
  112. if (r)
  113. return r;
  114. clear_bit(b, (unsigned long *) &info->current_bits);
  115. return 0;
  116. }
  117. EXPORT_SYMBOL_GPL(dm_bitset_clear_bit);
  118. int dm_bitset_test_bit(struct dm_disk_bitset *info, dm_block_t root,
  119. uint32_t index, dm_block_t *new_root, bool *result)
  120. {
  121. int r;
  122. unsigned b = index % BITS_PER_ARRAY_ENTRY;
  123. r = get_array_entry(info, root, index, new_root);
  124. if (r)
  125. return r;
  126. *result = test_bit(b, (unsigned long *) &info->current_bits);
  127. return 0;
  128. }
  129. EXPORT_SYMBOL_GPL(dm_bitset_test_bit);
  130. /*----------------------------------------------------------------*/