163 right_over = (ss->ss_end != end);
164
165 if (left_over && right_over) {
166 newseg = kmem_alloc(sizeof (*newseg), KM_SLEEP);
167 newseg->ss_start = end;
168 newseg->ss_end = ss->ss_end;
169 ss->ss_end = start;
170 avl_insert_here(&sm->sm_root, newseg, ss, AVL_AFTER);
171 } else if (left_over) {
172 ss->ss_end = start;
173 } else if (right_over) {
174 ss->ss_start = end;
175 } else {
176 avl_remove(&sm->sm_root, ss);
177 kmem_free(ss, sizeof (*ss));
178 }
179
180 sm->sm_space -= size;
181 }
182
183 int
184 space_map_contains(space_map_t *sm, uint64_t start, uint64_t size)
185 {
186 avl_index_t where;
187 space_seg_t ssearch, *ss;
188 uint64_t end = start + size;
189
190 ASSERT(MUTEX_HELD(sm->sm_lock));
191 VERIFY(size != 0);
192 VERIFY(P2PHASE(start, 1ULL << sm->sm_shift) == 0);
193 VERIFY(P2PHASE(size, 1ULL << sm->sm_shift) == 0);
194
195 ssearch.ss_start = start;
196 ssearch.ss_end = end;
197 ss = avl_find(&sm->sm_root, &ssearch, &where);
198
199 return (ss != NULL && ss->ss_start <= start && ss->ss_end >= end);
200 }
201
202 void
203 space_map_vacate(space_map_t *sm, space_map_func_t *func, space_map_t *mdest)
328 mutex_enter(sm->sm_lock);
329
330 for (offset = 0; offset < end; offset += bufsize) {
331 size = MIN(end - offset, bufsize);
332 VERIFY(P2PHASE(size, sizeof (uint64_t)) == 0);
333 VERIFY(size != 0);
334
335 dprintf("object=%llu offset=%llx size=%llx\n",
336 smo->smo_object, offset, size);
337
338 mutex_exit(sm->sm_lock);
339 error = dmu_read(os, smo->smo_object, offset, size, entry_map);
340 mutex_enter(sm->sm_lock);
341 if (error != 0)
342 break;
343
344 entry_map_end = entry_map + (size / sizeof (uint64_t));
345 for (entry = entry_map; entry < entry_map_end; entry++) {
346 uint64_t e = *entry;
347
348 if (SM_DEBUG_DECODE(e)) /* Skip debug entries */
349 continue;
350
351 (SM_TYPE_DECODE(e) == maptype ?
352 space_map_add : space_map_remove)(sm,
353 (SM_OFFSET_DECODE(e) << sm->sm_shift) + mapstart,
354 SM_RUN_DECODE(e) << sm->sm_shift);
355 }
356 }
357
358 if (error == 0) {
359 VERIFY3U(sm->sm_space, ==, space);
360
361 sm->sm_loaded = B_TRUE;
362 sm->sm_ops = ops;
363 if (ops != NULL)
364 ops->smop_load(sm);
365 } else {
366 space_map_vacate(sm, NULL, NULL);
367 }
368
369 zio_buf_free(entry_map, bufsize);
370
|
163 right_over = (ss->ss_end != end);
164
165 if (left_over && right_over) {
166 newseg = kmem_alloc(sizeof (*newseg), KM_SLEEP);
167 newseg->ss_start = end;
168 newseg->ss_end = ss->ss_end;
169 ss->ss_end = start;
170 avl_insert_here(&sm->sm_root, newseg, ss, AVL_AFTER);
171 } else if (left_over) {
172 ss->ss_end = start;
173 } else if (right_over) {
174 ss->ss_start = end;
175 } else {
176 avl_remove(&sm->sm_root, ss);
177 kmem_free(ss, sizeof (*ss));
178 }
179
180 sm->sm_space -= size;
181 }
182
183
184
185 int
186 space_map_fold(space_map_t *sm, uint8_t oldwidth, uint8_t newwidth)
187 {
188 space_seg_t *ss;
189 uint64_t d, r;
190
191 ASSERT(MUTEX_HELD(sm->sm_lock));
192
193 for (ss = avl_first(&sm->sm_root); ss != NULL;
194 ss = AVL_NEXT(&sm->sm_root, ss)) {
195 d = ss->ss_start / oldwidth;
196 r = ss->ss_start % oldwidth;
197 ss->ss_start = d * newwidth + r;
198
199 d = ss->ss_end / oldwidth;
200 r = ss->ss_end % oldwidth;
201 ss->ss_end = d * newwidth + r;
202 }
203 }
204
205 int
206 space_map_contains(space_map_t *sm, uint64_t start, uint64_t size)
207 {
208 avl_index_t where;
209 space_seg_t ssearch, *ss;
210 uint64_t end = start + size;
211
212 ASSERT(MUTEX_HELD(sm->sm_lock));
213 VERIFY(size != 0);
214 VERIFY(P2PHASE(start, 1ULL << sm->sm_shift) == 0);
215 VERIFY(P2PHASE(size, 1ULL << sm->sm_shift) == 0);
216
217 ssearch.ss_start = start;
218 ssearch.ss_end = end;
219 ss = avl_find(&sm->sm_root, &ssearch, &where);
220
221 return (ss != NULL && ss->ss_start <= start && ss->ss_end >= end);
222 }
223
224 void
225 space_map_vacate(space_map_t *sm, space_map_func_t *func, space_map_t *mdest)
350 mutex_enter(sm->sm_lock);
351
352 for (offset = 0; offset < end; offset += bufsize) {
353 size = MIN(end - offset, bufsize);
354 VERIFY(P2PHASE(size, sizeof (uint64_t)) == 0);
355 VERIFY(size != 0);
356
357 dprintf("object=%llu offset=%llx size=%llx\n",
358 smo->smo_object, offset, size);
359
360 mutex_exit(sm->sm_lock);
361 error = dmu_read(os, smo->smo_object, offset, size, entry_map);
362 mutex_enter(sm->sm_lock);
363 if (error != 0)
364 break;
365
366 entry_map_end = entry_map + (size / sizeof (uint64_t));
367 for (entry = entry_map; entry < entry_map_end; entry++) {
368 uint64_t e = *entry;
369
370 if (SM_IS_DEBUG(e)) /* Skip debug entries */
371 continue;
372
373 if (SM_IS_SPECIAL(e)) {
374 uint8_t oldwidth, newwidth;
375 ASSERT(SM_SPECIAL_ACTION_DECODE(e) == SM_FOLD);
376 oldwidth = BF64_ENCODE(e, 0, 8);
377 newwidth = BF64_ENCODE(e, 8, 8);
378 space_map_fold(sm, oldwidth, newwidth);
379 continue;
380 }
381
382 (SM_TYPE_DECODE(e) == maptype ?
383 space_map_add : space_map_remove)(sm,
384 (SM_OFFSET_DECODE(e) << sm->sm_shift) + mapstart,
385 SM_RUN_DECODE(e) << sm->sm_shift);
386 }
387 }
388
389 if (error == 0) {
390 VERIFY3U(sm->sm_space, ==, space);
391
392 sm->sm_loaded = B_TRUE;
393 sm->sm_ops = ops;
394 if (ops != NULL)
395 ops->smop_load(sm);
396 } else {
397 space_map_vacate(sm, NULL, NULL);
398 }
399
400 zio_buf_free(entry_map, bufsize);
401
|