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 2010 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->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->ml_address + al->ml_size; 194 bstart = bl->ml_address; 195 bend = bl->ml_address + bl->ml_size; 196 197 while (al && bl) { 198 while (al && (aend <= bstart)) 199 if ((al = al->ml_next) != NULL) 200 aend = al->ml_address + al->ml_size; 201 if (al == NULL) 202 return (0); 203 204 if ((astart = al->ml_address) <= bstart) 205 return (1); 206 207 while (bl && (bend <= astart)) 208 if ((bl = bl->ml_next) != NULL) 209 bend = bl->ml_address + bl->ml_size; 210 if (bl == NULL) 211 return (0); 212 213 if ((bstart = bl->ml_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->ml_next == NULL)) 226 return; 227 228 while (mlist->ml_next) { 229 end = mlist->ml_address + mlist->ml_size; 230 if (mlist->ml_next->ml_address <= end) { 231 struct memlist *nl; 232 233 nend = mlist->ml_next->ml_address + 234 mlist->ml_next->ml_size; 235 if (nend > end) 236 mlist->ml_size += (nend - end); 237 nl = mlist->ml_next; 238 mlist->ml_next = mlist->ml_next->ml_next; 239 if (nl) { 240 FREESTRUCT(nl, struct memlist, 1); 241 } 242 if (mlist->ml_next) 243 mlist->ml_next->ml_prev = mlist; 244 } else { 245 mlist = mlist->ml_next; 246 } 247 } 248 } 249 250 #ifdef DEBUG 251 void 252 memlist_dump(struct memlist *mlist) 253 { 254 register struct memlist *ml; 255 256 if (mlist == NULL) 257 printf("memlist> EMPTY\n"); 258 else for (ml = mlist; ml; ml = ml->ml_next) 259 printf("memlist> 0x%lx, 0x%lx\n", ml->ml_address, ml->ml_size); 260 } 261 #endif 262 263 struct memlist * 264 dr_memlist_dup(struct memlist *mlist) 265 { 266 struct memlist *hl = NULL, *tl, **mlp; 267 268 if (mlist == NULL) 269 return (NULL); 270 271 mlp = &hl; 272 tl = *mlp; 273 for (; mlist; mlist = mlist->ml_next) { 274 *mlp = GETSTRUCT(struct memlist, 1); 275 (*mlp)->ml_address = mlist->ml_address; 276 (*mlp)->ml_size = mlist->ml_size; 277 (*mlp)->ml_prev = tl; 278 tl = *mlp; 279 mlp = &((*mlp)->ml_next); 280 } 281 *mlp = NULL; 282 283 return (hl); 284 } 285 286 struct memlist * 287 dr_memlist_add_span(struct memlist *mlist, uint64_t base, uint64_t len) 288 { 289 struct memlist *ml, *tl, *nl; 290 291 if (len == 0ull) 292 return (NULL); 293 294 if (mlist == NULL) { 295 mlist = GETSTRUCT(struct memlist, 1); 296 mlist->ml_address = base; 297 mlist->ml_size = len; 298 mlist->ml_next = mlist->ml_prev = NULL; 299 300 return (mlist); 301 } 302 303 for (tl = ml = mlist; ml; tl = ml, ml = ml->ml_next) { 304 if (base < ml->ml_address) { 305 if ((base + len) < ml->ml_address) { 306 nl = GETSTRUCT(struct memlist, 1); 307 nl->ml_address = base; 308 nl->ml_size = len; 309 nl->ml_next = ml; 310 if ((nl->ml_prev = ml->ml_prev) != NULL) 311 nl->ml_prev->ml_next = nl; 312 ml->ml_prev = nl; 313 if (mlist == ml) 314 mlist = nl; 315 } else { 316 ml->ml_size = MAX((base + len), 317 (ml->ml_address + ml->ml_size)) - base; 318 ml->ml_address = base; 319 } 320 break; 321 322 } else if (base <= (ml->ml_address + ml->ml_size)) { 323 ml->ml_size = MAX((base + len), 324 (ml->ml_address + ml->ml_size)) - 325 MIN(ml->ml_address, base); 326 ml->ml_address = MIN(ml->ml_address, base); 327 break; 328 } 329 } 330 if (ml == NULL) { 331 nl = GETSTRUCT(struct memlist, 1); 332 nl->ml_address = base; 333 nl->ml_size = len; 334 nl->ml_next = NULL; 335 nl->ml_prev = tl; 336 tl->ml_next = nl; 337 } 338 339 dr_memlist_coalesce(mlist); 340 341 return (mlist); 342 } 343 344 struct memlist * 345 dr_memlist_del_span(struct memlist *mlist, uint64_t base, uint64_t len) 346 { 347 uint64_t end; 348 struct memlist *ml, *tl, *nlp; 349 350 if (mlist == NULL) 351 return (NULL); 352 353 end = base + len; 354 if ((end <= mlist->ml_address) || (base == end)) 355 return (mlist); 356 357 for (tl = ml = mlist; ml; tl = ml, ml = nlp) { 358 uint64_t mend; 359 360 nlp = ml->ml_next; 361 362 if (end <= ml->ml_address) 363 break; 364 365 mend = ml->ml_address + ml->ml_size; 366 if (base < mend) { 367 if (base <= ml->ml_address) { 368 ml->ml_address = end; 369 if (end >= mend) 370 ml->ml_size = 0ull; 371 else 372 ml->ml_size = mend - ml->ml_address; 373 } else { 374 ml->ml_size = base - ml->ml_address; 375 if (end < mend) { 376 struct memlist *nl; 377 /* 378 * splitting an memlist entry. 379 */ 380 nl = GETSTRUCT(struct memlist, 1); 381 nl->ml_address = end; 382 nl->ml_size = mend - nl->ml_address; 383 if ((nl->ml_next = nlp) != NULL) 384 nlp->ml_prev = nl; 385 nl->ml_prev = ml; 386 ml->ml_next = nl; 387 nlp = nl; 388 } 389 } 390 if (ml->ml_size == 0ull) { 391 if (ml == mlist) { 392 if ((mlist = nlp) != NULL) 393 nlp->ml_prev = NULL; 394 FREESTRUCT(ml, struct memlist, 1); 395 if (mlist == NULL) 396 break; 397 ml = nlp; 398 } else { 399 if ((tl->ml_next = nlp) != NULL) 400 nlp->ml_prev = tl; 401 FREESTRUCT(ml, struct memlist, 1); 402 ml = tl; 403 } 404 } 405 } 406 } 407 408 return (mlist); 409 } 410 411 /* 412 * add span without merging 413 */ 414 struct memlist * 415 dr_memlist_cat_span(struct memlist *mlist, uint64_t base, uint64_t len) 416 { 417 struct memlist *ml, *tl, *nl; 418 419 if (len == 0ull) 420 return (NULL); 421 422 if (mlist == NULL) { 423 mlist = GETSTRUCT(struct memlist, 1); 424 mlist->ml_address = base; 425 mlist->ml_size = len; 426 mlist->ml_next = mlist->ml_prev = NULL; 427 428 return (mlist); 429 } 430 431 for (tl = ml = mlist; ml; tl = ml, ml = ml->ml_next) { 432 if (base < ml->ml_address) { 433 nl = GETSTRUCT(struct memlist, 1); 434 nl->ml_address = base; 435 nl->ml_size = len; 436 nl->ml_next = ml; 437 if ((nl->ml_prev = ml->ml_prev) != NULL) 438 nl->ml_prev->ml_next = nl; 439 ml->ml_prev = nl; 440 if (mlist == ml) 441 mlist = nl; 442 break; 443 } 444 } 445 446 if (ml == NULL) { 447 nl = GETSTRUCT(struct memlist, 1); 448 nl->ml_address = base; 449 nl->ml_size = len; 450 nl->ml_next = NULL; 451 nl->ml_prev = tl; 452 tl->ml_next = nl; 453 } 454 455 return (mlist); 456 } 457