static void trim_map_segment_remove(trim_map_t *tm, trim_seg_t *ts, uint64_t start, uint64_t end) { trim_seg_t *nts; boolean_t left_over, right_over; ASSERT(MUTEX_HELD(&tm->tm_lock)); left_over = (ts->ts_start < start); right_over = (ts->ts_end > end); TRIM_MAP_SDEC(tm, end - start); if (left_over && right_over) { nts = kmem_alloc(sizeof (*nts), KM_SLEEP); nts->ts_start = end; nts->ts_end = ts->ts_end; nts->ts_txg = ts->ts_txg; nts->ts_time = ts->ts_time; ts->ts_end = start; avl_insert_here(&tm->tm_queued_frees, nts, ts, AVL_AFTER); list_insert_after(&tm->tm_head, ts, nts); TRIM_MAP_QINC(tm); } else if (left_over) { ts->ts_end = start; } else if (right_over) { ts->ts_start = end; } else { avl_remove(&tm->tm_queued_frees, ts); list_remove(&tm->tm_head, ts); TRIM_MAP_QDEC(tm); kmem_free(ts, sizeof (*ts)); } }
void range_tree_remove(void *arg, uint64_t start, uint64_t size) { range_tree_t *rt = arg; avl_index_t where; range_seg_t rsearch, *rs, *newseg; uint64_t end = start + size; boolean_t left_over, right_over; ASSERT(MUTEX_HELD(rt->rt_lock)); VERIFY3U(size, !=, 0); VERIFY3U(size, <=, rt->rt_space); rsearch.rs_start = start; rsearch.rs_end = end; rs = avl_find(&rt->rt_root, &rsearch, &where); /* Make sure we completely overlap with someone */ if (rs == NULL) { zfs_panic_recover("zfs: freeing free segment " "(offset=%llu size=%llu)", (longlong_t)start, (longlong_t)size); return; } VERIFY3U(rs->rs_start, <=, start); VERIFY3U(rs->rs_end, >=, end); left_over = (rs->rs_start != start); right_over = (rs->rs_end != end); range_tree_stat_decr(rt, rs); if (rt->rt_ops != NULL) rt->rt_ops->rtop_remove(rt, rs, rt->rt_arg); if (left_over && right_over) { newseg = kmem_cache_alloc(range_seg_cache, KM_SLEEP); newseg->rs_start = end; newseg->rs_end = rs->rs_end; range_tree_stat_incr(rt, newseg); rs->rs_end = start; avl_insert_here(&rt->rt_root, newseg, rs, AVL_AFTER); if (rt->rt_ops != NULL) rt->rt_ops->rtop_add(rt, newseg, rt->rt_arg); } else if (left_over) { rs->rs_end = start; } else if (right_over) { rs->rs_start = end; } else { avl_remove(&rt->rt_root, rs); kmem_cache_free(range_seg_cache, rs); rs = NULL; } if (rs != NULL) { range_tree_stat_incr(rt, rs); if (rt->rt_ops != NULL) rt->rt_ops->rtop_add(rt, rs, rt->rt_arg); } rt->rt_space -= size; }
static void parse_contents(void) { int cnt; pkgentry_t *ent, *e2; avl_index_t where; int num = 0; struct stat stb; ptrdiff_t off; char *p, *q, *map; pkgentry_t *lastentry = NULL; int d; int cntserrs = 0; cnt = open(CONTENTS, O_RDONLY); cind = 0; if (cnt == -1) { if (errno == ENOENT) return; exit(99); } if (fstat(cnt, &stb) != 0) { (void) close(cnt); exit(99); } if (stb.st_size == 0) { (void) close(cnt); return; } map = mmap(0, stb.st_size, PROT_READ, MAP_PRIVATE, cnt, 0); (void) close(cnt); if (map == (char *)-1) return; (void) madvise(map, stb.st_size, MADV_WILLNEED); for (off = 0; off < stb.st_size; off += q - p) { p = map + off; q = memchr(p, '\n', stb.st_size - off); if (q == NULL) break; q++; num++; if (p[0] == '#' || p[0] == '\n') { handle_comments(p, q - p); continue; } ent = parse_line(p, q - p - 1, B_TRUE); if (ent == NULL) { cntserrs++; continue; } /* * We save time by assuming the database is sorted; by * using avl_insert_here(), building the tree is nearly free. * lastentry always contains the last entry in the AVL tree. */ if (lastentry == NULL) { avl_add(list, ent); lastentry = ent; } else if ((d = avlcmp(ent, lastentry)) == 1) { avl_insert_here(list, ent, lastentry, AVL_AFTER); lastentry = ent; } else if (d == 0 || (e2 = avl_find(list, ent, &where)) != NULL) { /* * This can only happen if the contents file is bad; * this can, e.g., happen with the old SQL contents DB, * it didn't sort properly. Assume the first one * is the correct one, but who knows? */ if (d == 0) e2 = lastentry; if (strcmp(ent->line, e2->line) != 0) { progerr(gettext("two entries for %.*s"), ent->pathlen, ent->line); cntserrs++; } freeentry(ent); } else { /* Out of order: not an error for us, really. */ progerr(gettext("bad read of contents file")); logerr(gettext("pathname: Unknown")); logerr(gettext( "problem: unable to read pathname field")); if (one_shot) exit(2); avl_insert(list, ent, where); } } cind = 0; (void) munmap(map, stb.st_size); /* By default, we ignore bad lines, keep them in a copy. */ if (cntserrs > 0 && stb.st_nlink == 1) { char bcf[sizeof (BADCONTENTS)]; (void) strcpy(bcf, BADCONTENTS); if (mktemp(bcf) != NULL) { (void) link(CONTENTS, bcf); syslog(LOG_WARNING, "A bad contents file was saved: %s", bcf); } } }