| Commit | Line | Data |
|---|---|---|
| f03c9cf4 MD |
1 | /* |
| 2 | * Copyright (c) 2008 The DragonFly Project. All rights reserved. | |
| 3 | * | |
| 4 | * This code is derived from software contributed to The DragonFly Project | |
| 5 | * by Matthew Dillon <dillon@backplane.com> | |
| 6 | * | |
| 7 | * Redistribution and use in source and binary forms, with or without | |
| 8 | * modification, are permitted provided that the following conditions | |
| 9 | * are met: | |
| 10 | * | |
| 11 | * 1. Redistributions of source code must retain the above copyright | |
| 12 | * notice, this list of conditions and the following disclaimer. | |
| 13 | * 2. Redistributions in binary form must reproduce the above copyright | |
| 14 | * notice, this list of conditions and the following disclaimer in | |
| 15 | * the documentation and/or other materials provided with the | |
| 16 | * distribution. | |
| 17 | * 3. Neither the name of The DragonFly Project nor the names of its | |
| 18 | * contributors may be used to endorse or promote products derived | |
| 19 | * from this software without specific, prior written permission. | |
| 20 | * | |
| 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
| 24 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
| 25 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
| 26 | * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
| 27 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
| 28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
| 29 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
| 30 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |
| 31 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 32 | * SUCH DAMAGE. | |
| 33 | * | |
| 68e079b8 | 34 | * $DragonFly: src/sbin/hammer/blockmap.c,v 1.2 2008/06/17 04:03:38 dillon Exp $ |
| f03c9cf4 MD |
35 | */ |
| 36 | ||
| 37 | #include "hammer.h" | |
| 38 | ||
| 39 | hammer_off_t | |
| 68e079b8 | 40 | blockmap_lookup(hammer_off_t zone_offset, |
| f03c9cf4 | 41 | struct hammer_blockmap_layer1 *save_layer1, |
| 6ed4c886 MD |
42 | struct hammer_blockmap_layer2 *save_layer2, |
| 43 | int *errorp) | |
| f03c9cf4 | 44 | { |
| b9107f58 | 45 | struct volume_info *root_volume = NULL; |
| 68e079b8 MD |
46 | hammer_blockmap_t blockmap; |
| 47 | hammer_blockmap_t freemap; | |
| f03c9cf4 MD |
48 | struct hammer_blockmap_layer1 *layer1; |
| 49 | struct hammer_blockmap_layer2 *layer2; | |
| 50 | struct buffer_info *buffer = NULL; | |
| 51 | hammer_off_t layer1_offset; | |
| 52 | hammer_off_t layer2_offset; | |
| 53 | hammer_off_t result_offset; | |
| 54 | int zone; | |
| 68e079b8 | 55 | int i; |
| b9107f58 | 56 | int error = 0; |
| f03c9cf4 | 57 | |
| e0410f23 MD |
58 | if (save_layer1) |
| 59 | *save_layer1 = NULL; | |
| 60 | if (save_layer2) | |
| 61 | *save_layer2 = NULL; | |
| 62 | ||
| 68e079b8 MD |
63 | zone = HAMMER_ZONE_DECODE(zone_offset); |
| 64 | ||
| b9107f58 MD |
65 | if (AssertOnFailure) { |
| 66 | assert(zone > HAMMER_ZONE_RAW_VOLUME_INDEX); | |
| 67 | assert(zone < HAMMER_MAX_ZONES); | |
| 68 | assert(RootVolNo >= 0); | |
| 69 | } else { | |
| 70 | if (zone <= HAMMER_ZONE_RAW_VOLUME_INDEX) | |
| 71 | error = EDOM; | |
| 72 | if (zone >= HAMMER_MAX_ZONES) | |
| 73 | error = EDOM; | |
| 74 | if (RootVolNo < 0) | |
| 75 | error = EDOM; | |
| 76 | if (error) { | |
| 77 | result_offset = HAMMER_OFF_BAD; | |
| 78 | goto done; | |
| 79 | } | |
| 80 | } | |
| 81 | ||
| f03c9cf4 | 82 | root_volume = get_volume(RootVolNo); |
| 68e079b8 | 83 | blockmap = &root_volume->ondisk->vol0_blockmap[zone]; |
| f03c9cf4 | 84 | |
| 68e079b8 MD |
85 | if (zone == HAMMER_ZONE_RAW_BUFFER_INDEX) { |
| 86 | result_offset = zone_offset; | |
| 87 | } else if (zone == HAMMER_ZONE_UNDO_INDEX) { | |
| 88 | i = (zone_offset & HAMMER_OFF_SHORT_MASK) / | |
| 89 | HAMMER_LARGEBLOCK_SIZE; | |
| b9107f58 MD |
90 | if (AssertOnFailure) { |
| 91 | assert(zone_offset < blockmap->alloc_offset); | |
| 92 | } else { | |
| 93 | if (zone_offset >= blockmap->alloc_offset) { | |
| 94 | error = EDOM; | |
| 95 | result_offset = HAMMER_OFF_BAD; | |
| 96 | goto done; | |
| 97 | } | |
| 98 | } | |
| 68e079b8 MD |
99 | result_offset = root_volume->ondisk->vol0_undo_array[i] + |
| 100 | (zone_offset & HAMMER_LARGEBLOCK_MASK64); | |
| 101 | } else { | |
| 102 | result_offset = (zone_offset & ~HAMMER_OFF_ZONE_MASK) | | |
| 103 | HAMMER_ZONE_RAW_BUFFER; | |
| f03c9cf4 MD |
104 | } |
| 105 | ||
| b9107f58 MD |
106 | /* |
| 107 | * The blockmap should match the requested zone (else the volume | |
| 108 | * header is mashed). | |
| e0410f23 MD |
109 | * |
| 110 | * Note that a valid offset can still be returned if AssertOnFailure | |
| 111 | * is zero. | |
| b9107f58 MD |
112 | */ |
| 113 | if (AssertOnFailure) { | |
| 114 | assert(HAMMER_ZONE_DECODE(blockmap->alloc_offset) == zone); | |
| 115 | } else { | |
| 116 | if (HAMMER_ZONE_DECODE(blockmap->alloc_offset) != zone) { | |
| 117 | error = EDOM; | |
| 118 | goto done; | |
| 119 | } | |
| 120 | } | |
| 68e079b8 MD |
121 | |
| 122 | /* | |
| 123 | * Validate that the big-block is assigned to the zone. Also | |
| 124 | * assign save_layer{1,2}. | |
| 125 | */ | |
| 126 | ||
| 127 | freemap = &root_volume->ondisk->vol0_blockmap[HAMMER_ZONE_FREEMAP_INDEX]; | |
| f03c9cf4 MD |
128 | /* |
| 129 | * Dive layer 1. | |
| 130 | */ | |
| 68e079b8 | 131 | layer1_offset = freemap->phys_offset + |
| 6aec797f | 132 | HAMMER_BLOCKMAP_LAYER1_OFFSET(result_offset); |
| f03c9cf4 | 133 | layer1 = get_buffer_data(layer1_offset, &buffer, 0); |
| b9107f58 | 134 | if (AssertOnFailure) { |
| e0410f23 | 135 | assert(layer1); |
| b9107f58 MD |
136 | assert(layer1->phys_offset != HAMMER_BLOCKMAP_UNAVAIL); |
| 137 | } else { | |
| e0410f23 MD |
138 | if (layer1 == NULL) { |
| 139 | error = EDOM; | |
| 140 | goto done; | |
| 141 | } | |
| b9107f58 MD |
142 | if (layer1->phys_offset == HAMMER_BLOCKMAP_UNAVAIL) { |
| 143 | error = EDOM; | |
| 144 | goto done; | |
| 145 | } | |
| 146 | } | |
| f03c9cf4 MD |
147 | if (save_layer1) |
| 148 | *save_layer1 = *layer1; | |
| 149 | ||
| 150 | /* | |
| 151 | * Dive layer 2, each entry represents a large-block. | |
| 152 | */ | |
| 153 | layer2_offset = layer1->phys_offset + | |
| 6aec797f | 154 | HAMMER_BLOCKMAP_LAYER2_OFFSET(result_offset); |
| f03c9cf4 | 155 | layer2 = get_buffer_data(layer2_offset, &buffer, 0); |
| f03c9cf4 | 156 | |
| b9107f58 | 157 | if (AssertOnFailure) { |
| e0410f23 | 158 | assert(layer2); |
| 6ed4c886 | 159 | assert(layer2->zone == zone); |
| b9107f58 | 160 | } else { |
| e0410f23 | 161 | if (layer2 == NULL) { |
| b9107f58 | 162 | error = EDOM; |
| e0410f23 MD |
163 | goto done; |
| 164 | } | |
| 165 | if (layer2->zone != zone) { | |
| 166 | error = EDOM; | |
| 167 | goto done; | |
| 168 | } | |
| 6ed4c886 | 169 | } |
| e0410f23 MD |
170 | if (save_layer2) |
| 171 | *save_layer2 = *layer2; | |
| f03c9cf4 | 172 | |
| b9107f58 | 173 | done: |
| f03c9cf4 MD |
174 | if (buffer) |
| 175 | rel_buffer(buffer); | |
| b9107f58 MD |
176 | if (root_volume) |
| 177 | rel_volume(root_volume); | |
| 178 | ||
| 179 | if (errorp) | |
| 180 | *errorp = error; | |
| 181 | ||
| f03c9cf4 MD |
182 | return(result_offset); |
| 183 | } | |
| 184 |