int get_bmap_ext( xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_agblock_t maxbno, xfs_extlen_t *blen) { int *statep; unsigned long key; statep = btree_find(ag_bmap[agno], agbno, &key); if (!statep) return -1; if (key == agbno) { if (blen) { if (!btree_peek_next(ag_bmap[agno], &key)) return -1; *blen = MIN(maxbno, key) - agbno; } return *statep; } statep = btree_peek_prev(ag_bmap[agno], NULL); if (!statep) return -1; if (blen) *blen = MIN(maxbno, key) - agbno; return *statep; }
int search_dup_extent( xfs_agnumber_t agno, xfs_agblock_t start_agbno, xfs_agblock_t end_agbno) { unsigned long bno; int ret; pthread_mutex_lock(&dup_extent_tree_locks[agno]); if (!btree_find(dup_extent_trees[agno], start_agbno, &bno)) { ret = 0; goto out; /* this really shouldn't happen */ } if (bno < end_agbno) { ret = 1; goto out; } ret = (uintptr_t)btree_peek_prev(dup_extent_trees[agno], NULL) > start_agbno; out: pthread_mutex_unlock(&dup_extent_tree_locks[agno]); return ret; }
static void update_bmap( struct btree_root *bmap, unsigned long offset, xfs_extlen_t blen, void *new_state) { unsigned long end = offset + blen; int *cur_state; unsigned long cur_key; int *next_state; unsigned long next_key; int *prev_state; cur_state = btree_find(bmap, offset, &cur_key); if (!cur_state) return; if (offset == cur_key) { /* if the start is the same as the "item" extent */ if (cur_state == new_state) return; /* * Note: this may be NULL if we are updating the map for * the superblock. */ prev_state = btree_peek_prev(bmap, NULL); next_state = btree_peek_next(bmap, &next_key); if (next_key > end) { /* different end */ if (new_state == prev_state) { /* #1: prev has same state, move offset up */ btree_update_key(bmap, offset, end); return; } /* #4: insert new extent after, update current value */ btree_update_value(bmap, offset, new_state); btree_insert(bmap, end, cur_state); return; } /* same end (and same start) */ if (new_state == next_state) { /* next has same state */ if (new_state == prev_state) { /* #3: merge prev & next */ btree_delete(bmap, offset); btree_delete(bmap, end); return; } /* #8: merge next */ btree_update_value(bmap, offset, new_state); btree_delete(bmap, end); return; } /* same start, same end, next has different state */ if (new_state == prev_state) { /* #5: prev has same state */ btree_delete(bmap, offset); return; } /* #6: update value only */ btree_update_value(bmap, offset, new_state); return; } /* different start, offset is in the middle of "cur" */ prev_state = btree_peek_prev(bmap, NULL); ASSERT(prev_state != NULL); if (prev_state == new_state) return; if (end == cur_key) { /* end is at the same point as the current extent */ if (new_state == cur_state) { /* #7: move next extent down */ btree_update_key(bmap, end, offset); return; } /* #9: different start, same end, add new extent */ btree_insert(bmap, offset, new_state); return; } /* #2: insert an extent into the middle of another extent */ btree_insert(bmap, offset, new_state); btree_insert(bmap, end, prev_state); }