diff options
Diffstat (limited to 'drivers/md/persistent-data/dm-array.h')
| -rw-r--r-- | drivers/md/persistent-data/dm-array.h | 166 | 
1 files changed, 166 insertions, 0 deletions
diff --git a/drivers/md/persistent-data/dm-array.h b/drivers/md/persistent-data/dm-array.h new file mode 100644 index 00000000000..ea177d6fa58 --- /dev/null +++ b/drivers/md/persistent-data/dm-array.h @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2012 Red Hat, Inc. + * + * This file is released under the GPL. + */ +#ifndef _LINUX_DM_ARRAY_H +#define _LINUX_DM_ARRAY_H + +#include "dm-btree.h" + +/*----------------------------------------------------------------*/ + +/* + * The dm-array is a persistent version of an array.  It packs the data + * more efficiently than a btree which will result in less disk space use, + * and a performance boost.  The element get and set operations are still + * O(ln(n)), but with a much smaller constant. + * + * The value type structure is reused from the btree type to support proper + * reference counting of values. + * + * The arrays implicitly know their length, and bounds are checked for + * lookups and updated.  It doesn't store this in an accessible place + * because it would waste a whole metadata block.  Make sure you store the + * size along with the array root in your encompassing data. + * + * Array entries are indexed via an unsigned integer starting from zero. + * Arrays are not sparse; if you resize an array to have 'n' entries then + * 'n - 1' will be the last valid index. + * + * Typical use: + * + * a) initialise a dm_array_info structure.  This describes the array + *    values and ties it into a specific transaction manager.  It holds no + *    instance data; the same info can be used for many similar arrays if + *    you wish. + * + * b) Get yourself a root.  The root is the index of a block of data on the + *    disk that holds a particular instance of an array.  You may have a + *    pre existing root in your metadata that you wish to use, or you may + *    want to create a brand new, empty array with dm_array_empty(). + * + * Like the other data structures in this library, dm_array objects are + * immutable between transactions.  Update functions will return you the + * root for a _new_ array.  If you've incremented the old root, via + * dm_tm_inc(), before calling the update function you may continue to use + * it in parallel with the new root. + * + * c) resize an array with dm_array_resize(). + * + * d) Get a value from the array with dm_array_get_value(). + * + * e) Set a value in the array with dm_array_set_value(). + * + * f) Walk an array of values in index order with dm_array_walk().  More + *    efficient than making many calls to dm_array_get_value(). + * + * g) Destroy the array with dm_array_del().  This tells the transaction + *    manager that you're no longer using this data structure so it can + *    recycle it's blocks.  (dm_array_dec() would be a better name for it, + *    but del is in keeping with dm_btree_del()). + */ + +/* + * Describes an array.  Don't initialise this structure yourself, use the + * init function below. + */ +struct dm_array_info { +	struct dm_transaction_manager *tm; +	struct dm_btree_value_type value_type; +	struct dm_btree_info btree_info; +}; + +/* + * Sets up a dm_array_info structure.  You don't need to do anything with + * this structure when you finish using it. + * + * info - the structure being filled in. + * tm   - the transaction manager that should supervise this structure. + * vt   - describes the leaf values. + */ +void dm_array_info_init(struct dm_array_info *info, +			struct dm_transaction_manager *tm, +			struct dm_btree_value_type *vt); + +/* + * Create an empty, zero length array. + * + * info - describes the array + * root - on success this will be filled out with the root block + */ +int dm_array_empty(struct dm_array_info *info, dm_block_t *root); + +/* + * Resizes the array. + * + * info - describes the array + * root - the root block of the array on disk + * old_size - the caller is responsible for remembering the size of + *            the array + * new_size - can be bigger or smaller than old_size + * value - if we're growing the array the new entries will have this value + * new_root - on success, points to the new root block + * + * If growing the inc function for 'value' will be called the appropriate + * number of times.  So if the caller is holding a reference they may want + * to drop it. + */ +int dm_array_resize(struct dm_array_info *info, dm_block_t root, +		    uint32_t old_size, uint32_t new_size, +		    const void *value, dm_block_t *new_root) +	__dm_written_to_disk(value); + +/* + * Frees a whole array.  The value_type's decrement operation will be called + * for all values in the array + */ +int dm_array_del(struct dm_array_info *info, dm_block_t root); + +/* + * Lookup a value in the array + * + * info - describes the array + * root - root block of the array + * index - array index + * value - the value to be read.  Will be in on-disk format of course. + * + * -ENODATA will be returned if the index is out of bounds. + */ +int dm_array_get_value(struct dm_array_info *info, dm_block_t root, +		       uint32_t index, void *value); + +/* + * Set an entry in the array. + * + * info - describes the array + * root - root block of the array + * index - array index + * value - value to be written to disk.  Make sure you confirm the value is + *         in on-disk format with__dm_bless_for_disk() before calling. + * new_root - the new root block + * + * The old value being overwritten will be decremented, the new value + * incremented. + * + * -ENODATA will be returned if the index is out of bounds. + */ +int dm_array_set_value(struct dm_array_info *info, dm_block_t root, +		       uint32_t index, const void *value, dm_block_t *new_root) +	__dm_written_to_disk(value); + +/* + * Walk through all the entries in an array. + * + * info - describes the array + * root - root block of the array + * fn - called back for every element + * context - passed to the callback + */ +int dm_array_walk(struct dm_array_info *info, dm_block_t root, +		  int (*fn)(void *context, uint64_t key, void *leaf), +		  void *context); + +/*----------------------------------------------------------------*/ + +#endif	/* _LINUX_DM_ARRAY_H */  |