1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/cmn_err.h> 29 #include <sys/param.h> /* for NULL */ 30 #include <sys/sbd_ioctl.h> 31 #include <sys/dr_util.h> 32 #include <sys/varargs.h> 33 #include <sys/sysmacros.h> 34 #include <sys/systm.h> 35 36 /* sbd_etab[] and sbd_etab_len provided by sbdgenerr.pl */ 37 extern sbd_etab_t sbd_etab[]; 38 extern int sbd_etab_len; 39 40 sbd_error_t * 41 sbd_err_new(int e_code, char *fmt, va_list args) 42 { 43 sbd_error_t *new; 44 45 new = GETSTRUCT(sbd_error_t, 1); 46 new->e_code = e_code; 47 48 if (fmt) 49 (void) vsnprintf(new->e_rsc, sizeof (new->e_rsc), fmt, args); 50 51 return (new); 52 } 53 54 void 55 sbd_err_log(sbd_error_t *ep, int ce) 56 { 57 char buf[32]; 58 char *fmt; 59 char *txt; 60 int i; 61 sbd_etab_t *tp; 62 63 if (!ep) 64 return; 65 66 if (ep->e_rsc[0] == '\0') 67 fmt = "%s"; 68 else 69 fmt = "%s: %s"; 70 71 for (tp = sbd_etab, i = 0; i < sbd_etab_len; i++, tp++) 72 if (ep->e_code >= tp->t_base && ep->e_code <= tp->t_bnd) 73 break; 74 75 if (i < sbd_etab_len) 76 txt = tp->t_text[ep->e_code - tp->t_base]; 77 else { 78 (void) snprintf(buf, sizeof (buf), "error %d", ep->e_code); 79 txt = buf; 80 } 81 82 cmn_err(ce, fmt, txt, ep->e_rsc); 83 } 84 85 void 86 sbd_err_clear(sbd_error_t **ep) 87 { 88 FREESTRUCT(*ep, sbd_error_t, 1); 89 *ep = NULL; 90 } 91 92 void 93 sbd_err_set_c(sbd_error_t **ep, int ce, int e_code, char *fmt, ...) 94 { 95 sbd_error_t *tmp; 96 va_list args; 97 98 va_start(args, fmt); 99 100 tmp = sbd_err_new(e_code, fmt, args); 101 102 sbd_err_log(tmp, ce); 103 104 if (*ep == NULL) 105 *ep = tmp; 106 else 107 sbd_err_clear(&tmp); 108 109 va_end(args); 110 } 111 112 void 113 sbd_err_set(sbd_error_t **ep, int ce, int e_code, char *fmt, ...) 114 { 115 sbd_error_t *tmp; 116 va_list args; 117 118 va_start(args, fmt); 119 120 tmp = sbd_err_new(e_code, fmt, args); 121 122 sbd_err_log(tmp, ce); 123 124 *ep = tmp; 125 126 va_end(args); 127 } 128 129 sbd_error_t * 130 drerr_new_v(int e_code, char *fmt, va_list args) 131 { 132 return (sbd_err_new(e_code, fmt, args)); 133 } 134 135 sbd_error_t * 136 drerr_new(int log, int e_code, char *fmt, ...) 137 { 138 sbd_error_t *ep; 139 va_list args; 140 141 va_start(args, fmt); 142 ep = sbd_err_new(e_code, fmt, args); 143 va_end(args); 144 145 if (log) 146 sbd_err_log(ep, CE_WARN); 147 148 return (ep); 149 } 150 151 void 152 drerr_set_c(int log, sbd_error_t **ep, int e_code, char *fmt, ...) 153 { 154 sbd_error_t *err; 155 va_list args; 156 157 va_start(args, fmt); 158 err = sbd_err_new(e_code, fmt, args); 159 va_end(args); 160 161 if (log) 162 sbd_err_log(err, CE_WARN); 163 164 if (*ep == NULL) 165 *ep = err; 166 else 167 sbd_err_clear(&err); 168 } 169 170 171 /* 172 * Memlist support. 173 */ 174 void 175 dr_memlist_delete(struct memlist *mlist) 176 { 177 register struct memlist *ml; 178 179 for (ml = mlist; ml; ml = mlist) { 180 mlist = ml->next; 181 FREESTRUCT(ml, struct memlist, 1); 182 } 183 } 184 185 int 186 dr_memlist_intersect(struct memlist *al, struct memlist *bl) 187 { 188 uint64_t astart, aend, bstart, bend; 189 190 if ((al == NULL) || (bl == NULL)) 191 return (0); 192 193 aend = al->address + al->size; 194 bstart = bl->address; 195 bend = bl->address + bl->size; 196 197 while (al && bl) { 198 while (al && (aend <= bstart)) 199 if ((al = al->next) != NULL) 200 aend = al->address + al->size; 201 if (al == NULL) 202 return (0); 203 204 if ((astart = al->address) <= bstart) 205 return (1); 206 207 while (bl && (bend <= astart)) 208 if ((bl = bl->next) != NULL) 209 bend = bl->address + bl->size; 210 if (bl == NULL) 211 return (0); 212 213 if ((bstart = bl->address) <= astart) 214 return (1); 215 } 216 217 return (0); 218 } 219 220 void 221 dr_memlist_coalesce(struct memlist *mlist) 222 { 223 uint64_t end, nend; 224 225 if ((mlist == NULL) || (mlist->next == NULL)) 226 return; 227 228 while (mlist->next) { 229 end = mlist->address + mlist->size; 230 if (mlist->next->address <= end) { 231 struct memlist *nl; 232 233 nend = mlist->next->address + mlist->next->size; 234 if (nend > end) 235 mlist->size += (nend - end); 236 nl = mlist->next; 237 mlist->next = mlist->next->next; 238 if (nl) { 239 FREESTRUCT(nl, struct memlist, 1); 240 } 241 if (mlist->next) 242 mlist->next->prev = mlist; 243 } else { 244 mlist = mlist->next; 245 } 246 } 247 } 248 249 #ifdef DEBUG 250 void 251 memlist_dump(struct memlist *mlist) 252 { 253 register struct memlist *ml; 254 255 if (mlist == NULL) 256 printf("memlist> EMPTY\n"); 257 else for (ml = mlist; ml; ml = ml->next) 258 printf("memlist> 0x%lx, 0x%lx\n", ml->address, ml->size); 259 } 260 #endif 261 262 struct memlist * 263 dr_memlist_dup(struct memlist *mlist) 264 { 265 struct memlist *hl = NULL, *tl, **mlp; 266 267 if (mlist == NULL) 268 return (NULL); 269 270 mlp = &hl; 271 tl = *mlp; 272 for (; mlist; mlist = mlist->next) { 273 *mlp = GETSTRUCT(struct memlist, 1); 274 (*mlp)->address = mlist->address; 275 (*mlp)->size = mlist->size; 276 (*mlp)->prev = tl; 277 tl = *mlp; 278 mlp = &((*mlp)->next); 279 } 280 *mlp = NULL; 281 282 return (hl); 283 } 284 285 struct memlist * 286 dr_memlist_add_span(struct memlist *mlist, uint64_t base, uint64_t len) 287 { 288 struct memlist *ml, *tl, *nl; 289 290 if (len == 0ull) 291 return (NULL); 292 293 if (mlist == NULL) { 294 mlist = GETSTRUCT(struct memlist, 1); 295 mlist->address = base; 296 mlist->size = len; 297 mlist->next = mlist->prev = NULL; 298 299 return (mlist); 300 } 301 302 for (tl = ml = mlist; ml; tl = ml, ml = ml->next) { 303 if (base < ml->address) { 304 if ((base + len) < ml->address) { 305 nl = GETSTRUCT(struct memlist, 1); 306 nl->address = base; 307 nl->size = len; 308 nl->next = ml; 309 if ((nl->prev = ml->prev) != NULL) 310 nl->prev->next = nl; 311 ml->prev = nl; 312 if (mlist == ml) 313 mlist = nl; 314 } else { 315 ml->size = MAX((base + len), 316 (ml->address + ml->size)) - base; 317 ml->address = base; 318 } 319 break; 320 321 } else if (base <= (ml->address + ml->size)) { 322 ml->size = MAX((base + len), 323 (ml->address + ml->size)) - 324 MIN(ml->address, base); 325 ml->address = MIN(ml->address, base); 326 break; 327 } 328 } 329 if (ml == NULL) { 330 nl = GETSTRUCT(struct memlist, 1); 331 nl->address = base; 332 nl->size = len; 333 nl->next = NULL; 334 nl->prev = tl; 335 tl->next = nl; 336 } 337 338 dr_memlist_coalesce(mlist); 339 340 return (mlist); 341 } 342 343 struct memlist * 344 dr_memlist_del_span(struct memlist *mlist, uint64_t base, uint64_t len) 345 { 346 uint64_t end; 347 struct memlist *ml, *tl, *nlp; 348 349 if (mlist == NULL) 350 return (NULL); 351 352 end = base + len; 353 if ((end <= mlist->address) || (base == end)) 354 return (mlist); 355 356 for (tl = ml = mlist; ml; tl = ml, ml = nlp) { 357 uint64_t mend; 358 359 nlp = ml->next; 360 361 if (end <= ml->address) 362 break; 363 364 mend = ml->address + ml->size; 365 if (base < mend) { 366 if (base <= ml->address) { 367 ml->address = end; 368 if (end >= mend) 369 ml->size = 0ull; 370 else 371 ml->size = mend - ml->address; 372 } else { 373 ml->size = base - ml->address; 374 if (end < mend) { 375 struct memlist *nl; 376 /* 377 * splitting an memlist entry. 378 */ 379 nl = GETSTRUCT(struct memlist, 1); 380 nl->address = end; 381 nl->size = mend - nl->address; 382 if ((nl->next = nlp) != NULL) 383 nlp->prev = nl; 384 nl->prev = ml; 385 ml->next = nl; 386 nlp = nl; 387 } 388 } 389 if (ml->size == 0ull) { 390 if (ml == mlist) { 391 if ((mlist = nlp) != NULL) 392 nlp->prev = NULL; 393 FREESTRUCT(ml, struct memlist, 1); 394 if (mlist == NULL) 395 break; 396 ml = nlp; 397 } else { 398 if ((tl->next = nlp) != NULL) 399 nlp->prev = tl; 400 FREESTRUCT(ml, struct memlist, 1); 401 ml = tl; 402 } 403 } 404 } 405 } 406 407 return (mlist); 408 } 409 410 /* 411 * add span without merging 412 */ 413 struct memlist * 414 dr_memlist_cat_span(struct memlist *mlist, uint64_t base, uint64_t len) 415 { 416 struct memlist *ml, *tl, *nl; 417 418 if (len == 0ull) 419 return (NULL); 420 421 if (mlist == NULL) { 422 mlist = GETSTRUCT(struct memlist, 1); 423 mlist->address = base; 424 mlist->size = len; 425 mlist->next = mlist->prev = NULL; 426 427 return (mlist); 428 } 429 430 for (tl = ml = mlist; ml; tl = ml, ml = ml->next) { 431 if (base < ml->address) { 432 nl = GETSTRUCT(struct memlist, 1); 433 nl->address = base; 434 nl->size = len; 435 nl->next = ml; 436 if ((nl->prev = ml->prev) != NULL) 437 nl->prev->next = nl; 438 ml->prev = nl; 439 if (mlist == ml) 440 mlist = nl; 441 break; 442 } 443 } 444 445 if (ml == NULL) { 446 nl = GETSTRUCT(struct memlist, 1); 447 nl->address = base; 448 nl->size = len; 449 nl->next = NULL; 450 nl->prev = tl; 451 tl->next = nl; 452 } 453 454 return (mlist); 455 } 456