Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | /* * Copyright (C) 2011 Red Hat, Inc. * * This file is released under the GPL. */ #ifndef DM_SPACE_MAP_COMMON_H #define DM_SPACE_MAP_COMMON_H #include "dm-btree.h" /*----------------------------------------------------------------*/ /* * Low level disk format * * Bitmap btree * ------------ * * Each value stored in the btree is an index_entry. This points to a * block that is used as a bitmap. Within the bitmap hold 2 bits per * entry, which represent UNUSED = 0, REF_COUNT = 1, REF_COUNT = 2 and * REF_COUNT = many. * * Refcount btree * -------------- * * Any entry that has a ref count higher than 2 gets entered in the ref * count tree. The leaf values for this tree is the 32-bit ref count. */ struct disk_index_entry { __le64 blocknr; __le32 nr_free; __le32 none_free_before; } __attribute__ ((packed, aligned(8))); #define MAX_METADATA_BITMAPS 255 struct disk_metadata_index { __le32 csum; __le32 padding; __le64 blocknr; struct disk_index_entry index[MAX_METADATA_BITMAPS]; } __attribute__ ((packed, aligned(8))); struct ll_disk; typedef int (*load_ie_fn)(struct ll_disk *ll, dm_block_t index, struct disk_index_entry *result); typedef int (*save_ie_fn)(struct ll_disk *ll, dm_block_t index, struct disk_index_entry *ie); typedef int (*init_index_fn)(struct ll_disk *ll); typedef int (*open_index_fn)(struct ll_disk *ll); typedef dm_block_t (*max_index_entries_fn)(struct ll_disk *ll); typedef int (*commit_fn)(struct ll_disk *ll); /* * A lot of time can be wasted reading and writing the same * index entry. So we cache a few entries. */ #define IE_CACHE_SIZE 64 #define IE_CACHE_MASK (IE_CACHE_SIZE - 1) struct ie_cache { bool valid; bool dirty; dm_block_t index; struct disk_index_entry ie; }; struct ll_disk { struct dm_transaction_manager *tm; struct dm_btree_info bitmap_info; struct dm_btree_info ref_count_info; uint32_t block_size; uint32_t entries_per_block; dm_block_t nr_blocks; dm_block_t nr_allocated; /* * bitmap_root may be a btree root or a simple index. */ dm_block_t bitmap_root; dm_block_t ref_count_root; struct disk_metadata_index mi_le; load_ie_fn load_ie; save_ie_fn save_ie; init_index_fn init_index; open_index_fn open_index; max_index_entries_fn max_entries; commit_fn commit; bool bitmap_index_changed:1; struct ie_cache ie_cache[IE_CACHE_SIZE]; }; struct disk_sm_root { __le64 nr_blocks; __le64 nr_allocated; __le64 bitmap_root; __le64 ref_count_root; } __attribute__ ((packed, aligned(8))); #define ENTRIES_PER_BYTE 4 struct disk_bitmap_header { __le32 csum; __le32 not_used; __le64 blocknr; } __attribute__ ((packed, aligned(8))); /*----------------------------------------------------------------*/ int sm_ll_extend(struct ll_disk *ll, dm_block_t extra_blocks); int sm_ll_lookup_bitmap(struct ll_disk *ll, dm_block_t b, uint32_t *result); int sm_ll_lookup(struct ll_disk *ll, dm_block_t b, uint32_t *result); int sm_ll_find_free_block(struct ll_disk *ll, dm_block_t begin, dm_block_t end, dm_block_t *result); int sm_ll_find_common_free_block(struct ll_disk *old_ll, struct ll_disk *new_ll, dm_block_t begin, dm_block_t end, dm_block_t *result); /* * The next three functions return (via nr_allocations) the net number of * allocations that were made. This number may be negative if there were * more frees than allocs. */ int sm_ll_insert(struct ll_disk *ll, dm_block_t b, uint32_t ref_count, int32_t *nr_allocations); int sm_ll_inc(struct ll_disk *ll, dm_block_t b, dm_block_t e, int32_t *nr_allocations); int sm_ll_dec(struct ll_disk *ll, dm_block_t b, dm_block_t e, int32_t *nr_allocations); int sm_ll_commit(struct ll_disk *ll); int sm_ll_new_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm); int sm_ll_open_metadata(struct ll_disk *ll, struct dm_transaction_manager *tm, void *root_le, size_t len); int sm_ll_new_disk(struct ll_disk *ll, struct dm_transaction_manager *tm); int sm_ll_open_disk(struct ll_disk *ll, struct dm_transaction_manager *tm, void *root_le, size_t len); /*----------------------------------------------------------------*/ #endif /* DM_SPACE_MAP_COMMON_H */ |