cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dm-array.h (7448B)


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