root/drivers/md/persistent-data/dm-btree-spine.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. node_prepare_for_write
  2. node_check
  3. bn_read_lock
  4. bn_shadow
  5. new_block
  6. unlock_block
  7. init_ro_spine
  8. exit_ro_spine
  9. ro_step
  10. ro_pop
  11. ro_node
  12. init_shadow_spine
  13. exit_shadow_spine
  14. shadow_step
  15. shadow_current
  16. shadow_parent
  17. shadow_has_parent
  18. shadow_root
  19. le64_inc
  20. le64_dec
  21. le64_equal
  22. init_le64_type

   1 /*
   2  * Copyright (C) 2011 Red Hat, Inc.
   3  *
   4  * This file is released under the GPL.
   5  */
   6 
   7 #include "dm-btree-internal.h"
   8 #include "dm-transaction-manager.h"
   9 
  10 #include <linux/device-mapper.h>
  11 
  12 #define DM_MSG_PREFIX "btree spine"
  13 
  14 /*----------------------------------------------------------------*/
  15 
  16 #define BTREE_CSUM_XOR 121107
  17 
  18 static int node_check(struct dm_block_validator *v,
  19                       struct dm_block *b,
  20                       size_t block_size);
  21 
  22 static void node_prepare_for_write(struct dm_block_validator *v,
  23                                    struct dm_block *b,
  24                                    size_t block_size)
  25 {
  26         struct btree_node *n = dm_block_data(b);
  27         struct node_header *h = &n->header;
  28 
  29         h->blocknr = cpu_to_le64(dm_block_location(b));
  30         h->csum = cpu_to_le32(dm_bm_checksum(&h->flags,
  31                                              block_size - sizeof(__le32),
  32                                              BTREE_CSUM_XOR));
  33 
  34         BUG_ON(node_check(v, b, 4096));
  35 }
  36 
  37 static int node_check(struct dm_block_validator *v,
  38                       struct dm_block *b,
  39                       size_t block_size)
  40 {
  41         struct btree_node *n = dm_block_data(b);
  42         struct node_header *h = &n->header;
  43         size_t value_size;
  44         __le32 csum_disk;
  45         uint32_t flags;
  46 
  47         if (dm_block_location(b) != le64_to_cpu(h->blocknr)) {
  48                 DMERR_LIMIT("node_check failed: blocknr %llu != wanted %llu",
  49                             le64_to_cpu(h->blocknr), dm_block_location(b));
  50                 return -ENOTBLK;
  51         }
  52 
  53         csum_disk = cpu_to_le32(dm_bm_checksum(&h->flags,
  54                                                block_size - sizeof(__le32),
  55                                                BTREE_CSUM_XOR));
  56         if (csum_disk != h->csum) {
  57                 DMERR_LIMIT("node_check failed: csum %u != wanted %u",
  58                             le32_to_cpu(csum_disk), le32_to_cpu(h->csum));
  59                 return -EILSEQ;
  60         }
  61 
  62         value_size = le32_to_cpu(h->value_size);
  63 
  64         if (sizeof(struct node_header) +
  65             (sizeof(__le64) + value_size) * le32_to_cpu(h->max_entries) > block_size) {
  66                 DMERR_LIMIT("node_check failed: max_entries too large");
  67                 return -EILSEQ;
  68         }
  69 
  70         if (le32_to_cpu(h->nr_entries) > le32_to_cpu(h->max_entries)) {
  71                 DMERR_LIMIT("node_check failed: too many entries");
  72                 return -EILSEQ;
  73         }
  74 
  75         /*
  76          * The node must be either INTERNAL or LEAF.
  77          */
  78         flags = le32_to_cpu(h->flags);
  79         if (!(flags & INTERNAL_NODE) && !(flags & LEAF_NODE)) {
  80                 DMERR_LIMIT("node_check failed: node is neither INTERNAL or LEAF");
  81                 return -EILSEQ;
  82         }
  83 
  84         return 0;
  85 }
  86 
  87 struct dm_block_validator btree_node_validator = {
  88         .name = "btree_node",
  89         .prepare_for_write = node_prepare_for_write,
  90         .check = node_check
  91 };
  92 
  93 /*----------------------------------------------------------------*/
  94 
  95 int bn_read_lock(struct dm_btree_info *info, dm_block_t b,
  96                  struct dm_block **result)
  97 {
  98         return dm_tm_read_lock(info->tm, b, &btree_node_validator, result);
  99 }
 100 
 101 static int bn_shadow(struct dm_btree_info *info, dm_block_t orig,
 102               struct dm_btree_value_type *vt,
 103               struct dm_block **result)
 104 {
 105         int r, inc;
 106 
 107         r = dm_tm_shadow_block(info->tm, orig, &btree_node_validator,
 108                                result, &inc);
 109         if (!r && inc)
 110                 inc_children(info->tm, dm_block_data(*result), vt);
 111 
 112         return r;
 113 }
 114 
 115 int new_block(struct dm_btree_info *info, struct dm_block **result)
 116 {
 117         return dm_tm_new_block(info->tm, &btree_node_validator, result);
 118 }
 119 
 120 void unlock_block(struct dm_btree_info *info, struct dm_block *b)
 121 {
 122         dm_tm_unlock(info->tm, b);
 123 }
 124 
 125 /*----------------------------------------------------------------*/
 126 
 127 void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info)
 128 {
 129         s->info = info;
 130         s->count = 0;
 131         s->nodes[0] = NULL;
 132         s->nodes[1] = NULL;
 133 }
 134 
 135 int exit_ro_spine(struct ro_spine *s)
 136 {
 137         int r = 0, i;
 138 
 139         for (i = 0; i < s->count; i++) {
 140                 unlock_block(s->info, s->nodes[i]);
 141         }
 142 
 143         return r;
 144 }
 145 
 146 int ro_step(struct ro_spine *s, dm_block_t new_child)
 147 {
 148         int r;
 149 
 150         if (s->count == 2) {
 151                 unlock_block(s->info, s->nodes[0]);
 152                 s->nodes[0] = s->nodes[1];
 153                 s->count--;
 154         }
 155 
 156         r = bn_read_lock(s->info, new_child, s->nodes + s->count);
 157         if (!r)
 158                 s->count++;
 159 
 160         return r;
 161 }
 162 
 163 void ro_pop(struct ro_spine *s)
 164 {
 165         BUG_ON(!s->count);
 166         --s->count;
 167         unlock_block(s->info, s->nodes[s->count]);
 168 }
 169 
 170 struct btree_node *ro_node(struct ro_spine *s)
 171 {
 172         struct dm_block *block;
 173 
 174         BUG_ON(!s->count);
 175         block = s->nodes[s->count - 1];
 176 
 177         return dm_block_data(block);
 178 }
 179 
 180 /*----------------------------------------------------------------*/
 181 
 182 void init_shadow_spine(struct shadow_spine *s, struct dm_btree_info *info)
 183 {
 184         s->info = info;
 185         s->count = 0;
 186 }
 187 
 188 int exit_shadow_spine(struct shadow_spine *s)
 189 {
 190         int r = 0, i;
 191 
 192         for (i = 0; i < s->count; i++) {
 193                 unlock_block(s->info, s->nodes[i]);
 194         }
 195 
 196         return r;
 197 }
 198 
 199 int shadow_step(struct shadow_spine *s, dm_block_t b,
 200                 struct dm_btree_value_type *vt)
 201 {
 202         int r;
 203 
 204         if (s->count == 2) {
 205                 unlock_block(s->info, s->nodes[0]);
 206                 s->nodes[0] = s->nodes[1];
 207                 s->count--;
 208         }
 209 
 210         r = bn_shadow(s->info, b, vt, s->nodes + s->count);
 211         if (!r) {
 212                 if (!s->count)
 213                         s->root = dm_block_location(s->nodes[0]);
 214 
 215                 s->count++;
 216         }
 217 
 218         return r;
 219 }
 220 
 221 struct dm_block *shadow_current(struct shadow_spine *s)
 222 {
 223         BUG_ON(!s->count);
 224 
 225         return s->nodes[s->count - 1];
 226 }
 227 
 228 struct dm_block *shadow_parent(struct shadow_spine *s)
 229 {
 230         BUG_ON(s->count != 2);
 231 
 232         return s->count == 2 ? s->nodes[0] : NULL;
 233 }
 234 
 235 int shadow_has_parent(struct shadow_spine *s)
 236 {
 237         return s->count >= 2;
 238 }
 239 
 240 int shadow_root(struct shadow_spine *s)
 241 {
 242         return s->root;
 243 }
 244 
 245 static void le64_inc(void *context, const void *value_le)
 246 {
 247         struct dm_transaction_manager *tm = context;
 248         __le64 v_le;
 249 
 250         memcpy(&v_le, value_le, sizeof(v_le));
 251         dm_tm_inc(tm, le64_to_cpu(v_le));
 252 }
 253 
 254 static void le64_dec(void *context, const void *value_le)
 255 {
 256         struct dm_transaction_manager *tm = context;
 257         __le64 v_le;
 258 
 259         memcpy(&v_le, value_le, sizeof(v_le));
 260         dm_tm_dec(tm, le64_to_cpu(v_le));
 261 }
 262 
 263 static int le64_equal(void *context, const void *value1_le, const void *value2_le)
 264 {
 265         __le64 v1_le, v2_le;
 266 
 267         memcpy(&v1_le, value1_le, sizeof(v1_le));
 268         memcpy(&v2_le, value2_le, sizeof(v2_le));
 269         return v1_le == v2_le;
 270 }
 271 
 272 void init_le64_type(struct dm_transaction_manager *tm,
 273                     struct dm_btree_value_type *vt)
 274 {
 275         vt->context = tm;
 276         vt->size = sizeof(__le64);
 277         vt->inc = le64_inc;
 278         vt->dec = le64_dec;
 279         vt->equal = le64_equal;
 280 }

/* [<][>][^][v][top][bottom][index][help] */