Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (C) 2012 Red Hat, Inc.
0003  *
0004  * This file is released under the GPL.
0005  */
0006 #ifndef _LINUX_DM_ARRAY_H
0007 #define _LINUX_DM_ARRAY_H
0008 
0009 #include "dm-btree.h"
0010 
0011 /*----------------------------------------------------------------*/
0012 
0013 /*
0014  * The dm-array is a persistent version of an array.  It packs the data
0015  * more efficiently than a btree which will result in less disk space use,
0016  * and a performance boost.  The element get and set operations are still
0017  * O(ln(n)), but with a much smaller constant.
0018  *
0019  * The value type structure is reused from the btree type to support proper
0020  * reference counting of values.
0021  *
0022  * The arrays implicitly know their length, and bounds are checked for
0023  * lookups and updated.  It doesn't store this in an accessible place
0024  * because it would waste a whole metadata block.  Make sure you store the
0025  * size along with the array root in your encompassing data.
0026  *
0027  * Array entries are indexed via an unsigned integer starting from zero.
0028  * Arrays are not sparse; if you resize an array to have 'n' entries then
0029  * 'n - 1' will be the last valid index.
0030  *
0031  * Typical use:
0032  *
0033  * a) initialise a dm_array_info structure.  This describes the array
0034  *    values and ties it into a specific transaction manager.  It holds no
0035  *    instance data; the same info can be used for many similar arrays if
0036  *    you wish.
0037  *
0038  * b) Get yourself a root.  The root is the index of a block of data on the
0039  *    disk that holds a particular instance of an array.  You may have a
0040  *    pre existing root in your metadata that you wish to use, or you may
0041  *    want to create a brand new, empty array with dm_array_empty().
0042  *
0043  * Like the other data structures in this library, dm_array objects are
0044  * immutable between transactions.  Update functions will return you the
0045  * root for a _new_ array.  If you've incremented the old root, via
0046  * dm_tm_inc(), before calling the update function you may continue to use
0047  * it in parallel with the new root.
0048  *
0049  * c) resize an array with dm_array_resize().
0050  *
0051  * d) Get a value from the array with dm_array_get_value().
0052  *
0053  * e) Set a value in the array with dm_array_set_value().
0054  *
0055  * f) Walk an array of values in index order with dm_array_walk().  More
0056  *    efficient than making many calls to dm_array_get_value().
0057  *
0058  * g) Destroy the array with dm_array_del().  This tells the transaction
0059  *    manager that you're no longer using this data structure so it can
0060  *    recycle it's blocks.  (dm_array_dec() would be a better name for it,
0061  *    but del is in keeping with dm_btree_del()).
0062  */
0063 
0064 /*
0065  * Describes an array.  Don't initialise this structure yourself, use the
0066  * init function below.
0067  */
0068 struct dm_array_info {
0069     struct dm_transaction_manager *tm;
0070     struct dm_btree_value_type value_type;
0071     struct dm_btree_info btree_info;
0072 };
0073 
0074 /*
0075  * Sets up a dm_array_info structure.  You don't need to do anything with
0076  * this structure when you finish using it.
0077  *
0078  * info - the structure being filled in.
0079  * tm   - the transaction manager that should supervise this structure.
0080  * vt   - describes the leaf values.
0081  */
0082 void dm_array_info_init(struct dm_array_info *info,
0083             struct dm_transaction_manager *tm,
0084             struct dm_btree_value_type *vt);
0085 
0086 /*
0087  * Create an empty, zero length array.
0088  *
0089  * info - describes the array
0090  * root - on success this will be filled out with the root block
0091  */
0092 int dm_array_empty(struct dm_array_info *info, dm_block_t *root);
0093 
0094 /*
0095  * Resizes the array.
0096  *
0097  * info - describes the array
0098  * root - the root block of the array on disk
0099  * old_size - the caller is responsible for remembering the size of
0100  *            the array
0101  * new_size - can be bigger or smaller than old_size
0102  * value - if we're growing the array the new entries will have this value
0103  * new_root - on success, points to the new root block
0104  *
0105  * If growing the inc function for 'value' will be called the appropriate
0106  * number of times.  So if the caller is holding a reference they may want
0107  * to drop it.
0108  */
0109 int dm_array_resize(struct dm_array_info *info, dm_block_t root,
0110             uint32_t old_size, uint32_t new_size,
0111             const void *value, dm_block_t *new_root)
0112     __dm_written_to_disk(value);
0113 
0114 /*
0115  * Creates a new array populated with values provided by a callback
0116  * function.  This is more efficient than creating an empty array,
0117  * resizing, and then setting values since that process incurs a lot of
0118  * copying.
0119  *
0120  * Assumes 32bit values for now since it's only used by the cache hint
0121  * array.
0122  *
0123  * info - describes the array
0124  * root - the root block of the array on disk
0125  * size - the number of entries in the array
0126  * fn - the callback
0127  * context - passed to the callback
0128  */
0129 typedef int (*value_fn)(uint32_t index, void *value_le, void *context);
0130 int dm_array_new(struct dm_array_info *info, dm_block_t *root,
0131          uint32_t size, value_fn fn, void *context);
0132 
0133 /*
0134  * Frees a whole array.  The value_type's decrement operation will be called
0135  * for all values in the array
0136  */
0137 int dm_array_del(struct dm_array_info *info, dm_block_t root);
0138 
0139 /*
0140  * Lookup a value in the array
0141  *
0142  * info - describes the array
0143  * root - root block of the array
0144  * index - array index
0145  * value - the value to be read.  Will be in on-disk format of course.
0146  *
0147  * -ENODATA will be returned if the index is out of bounds.
0148  */
0149 int dm_array_get_value(struct dm_array_info *info, dm_block_t root,
0150                uint32_t index, void *value);
0151 
0152 /*
0153  * Set an entry in the array.
0154  *
0155  * info - describes the array
0156  * root - root block of the array
0157  * index - array index
0158  * value - value to be written to disk.  Make sure you confirm the value is
0159  *         in on-disk format with__dm_bless_for_disk() before calling.
0160  * new_root - the new root block
0161  *
0162  * The old value being overwritten will be decremented, the new value
0163  * incremented.
0164  *
0165  * -ENODATA will be returned if the index is out of bounds.
0166  */
0167 int dm_array_set_value(struct dm_array_info *info, dm_block_t root,
0168                uint32_t index, const void *value, dm_block_t *new_root)
0169     __dm_written_to_disk(value);
0170 
0171 /*
0172  * Walk through all the entries in an array.
0173  *
0174  * info - describes the array
0175  * root - root block of the array
0176  * fn - called back for every element
0177  * context - passed to the callback
0178  */
0179 int dm_array_walk(struct dm_array_info *info, dm_block_t root,
0180           int (*fn)(void *context, uint64_t key, void *leaf),
0181           void *context);
0182 
0183 /*----------------------------------------------------------------*/
0184 
0185 /*
0186  * Cursor api.
0187  *
0188  * This lets you iterate through all the entries in an array efficiently
0189  * (it will preload metadata).
0190  *
0191  * I'm using a cursor, rather than a walk function with a callback because
0192  * the cache target needs to iterate both the mapping and hint arrays in
0193  * unison.
0194  */
0195 struct dm_array_cursor {
0196     struct dm_array_info *info;
0197     struct dm_btree_cursor cursor;
0198 
0199     struct dm_block *block;
0200     struct array_block *ab;
0201     unsigned index;
0202 };
0203 
0204 int dm_array_cursor_begin(struct dm_array_info *info,
0205               dm_block_t root, struct dm_array_cursor *c);
0206 void dm_array_cursor_end(struct dm_array_cursor *c);
0207 
0208 uint32_t dm_array_cursor_index(struct dm_array_cursor *c);
0209 int dm_array_cursor_next(struct dm_array_cursor *c);
0210 int dm_array_cursor_skip(struct dm_array_cursor *c, uint32_t count);
0211 
0212 /*
0213  * value_le is only valid while the cursor points at the current value.
0214  */
0215 void dm_array_cursor_get_value(struct dm_array_cursor *c, void **value_le);
0216 
0217 /*----------------------------------------------------------------*/
0218 
0219 #endif  /* _LINUX_DM_ARRAY_H */