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