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%" PRIx64 ", 0x%" PRIx64 "\n", 260 ml->ml_address, ml->ml_size); 261 } 262 #endif 263 264 struct memlist * 265 dr_memlist_dup(struct memlist *mlist) 266 { 267 struct memlist *hl = NULL, *tl, **mlp; 268 269 if (mlist == NULL) 270 return (NULL); 271 272 mlp = &hl; 273 tl = *mlp; 274 for (; mlist; mlist = mlist->ml_next) { 275 *mlp = GETSTRUCT(struct memlist, 1); 276 (*mlp)->ml_address = mlist->ml_address; 277 (*mlp)->ml_size = mlist->ml_size; 278 (*mlp)->ml_prev = tl; 279 tl = *mlp; 280 mlp = &((*mlp)->ml_next); 281 } 282 *mlp = NULL; 283 284 return (hl); 285 } 286 287 struct memlist * 288 dr_memlist_add_span(struct memlist *mlist, uint64_t base, uint64_t len) 289 { 290 struct memlist *ml, *tl, *nl; 291 292 if (len == 0ull) 293 return (NULL); 294 295 if (mlist == NULL) { 296 mlist = GETSTRUCT(struct memlist, 1); 297 mlist->ml_address = base; 298 mlist->ml_size = len; 299 mlist->ml_next = mlist->ml_prev = NULL; 300 301 return (mlist); 302 } 303 304 for (tl = ml = mlist; ml; tl = ml, ml = ml->ml_next) { 305 if (base < ml->ml_address) { 306 if ((base + len) < ml->ml_address) { 307 nl = GETSTRUCT(struct memlist, 1); 308 nl->ml_address = base; 309 nl->ml_size = len; 310 nl->ml_next = ml; 311 if ((nl->ml_prev = ml->ml_prev) != NULL) 312 nl->ml_prev->ml_next = nl; 313 ml->ml_prev = nl; 314 if (mlist == ml) 315 mlist = nl; 316 } else { 317 ml->ml_size = MAX((base + len), 318 (ml->ml_address + ml->ml_size)) - base; 319 ml->ml_address = base; 320 } 321 break; 322 323 } else if (base <= (ml->ml_address + ml->ml_size)) { 324 ml->ml_size = MAX((base + len), 325 (ml->ml_address + ml->ml_size)) - 326 MIN(ml->ml_address, base); 327 ml->ml_address = MIN(ml->ml_address, base); 328 break; 329 } 330 } 331 if (ml == NULL) { 332 nl = GETSTRUCT(struct memlist, 1); 333 nl->ml_address = base; 334 nl->ml_size = len; 335 nl->ml_next = NULL; 336 nl->ml_prev = tl; 337 tl->ml_next = nl; 338 } 339 340 dr_memlist_coalesce(mlist); 341 342 return (mlist); 343 } 344 345 struct memlist * 346 dr_memlist_del_span(struct memlist *mlist, uint64_t base, uint64_t len) 347 { 348 uint64_t end; 349 struct memlist *ml, *tl, *nlp; 350 351 if (mlist == NULL) 352 return (NULL); 353 354 end = base + len; 355 if ((end <= mlist->ml_address) || (base == end)) 356 return (mlist); 357 358 for (tl = ml = mlist; ml; tl = ml, ml = nlp) { 359 uint64_t mend; 360 361 nlp = ml->ml_next; 362 363 if (end <= ml->ml_address) 364 break; 365 366 mend = ml->ml_address + ml->ml_size; 367 if (base < mend) { 368 if (base <= ml->ml_address) { 369 ml->ml_address = end; 370 if (end >= mend) 371 ml->ml_size = 0ull; 372 else 373 ml->ml_size = mend - ml->ml_address; 374 } else { 375 ml->ml_size = base - ml->ml_address; 376 if (end < mend) { 377 struct memlist *nl; 378 /* 379 * splitting an memlist entry. 380 */ 381 nl = GETSTRUCT(struct memlist, 1); 382 nl->ml_address = end; 383 nl->ml_size = mend - nl->ml_address; 384 if ((nl->ml_next = nlp) != NULL) 385 nlp->ml_prev = nl; 386 nl->ml_prev = ml; 387 ml->ml_next = nl; 388 nlp = nl; 389 } 390 } 391 if (ml->ml_size == 0ull) { 392 if (ml == mlist) { 393 if ((mlist = nlp) != NULL) 394 nlp->ml_prev = NULL; 395 FREESTRUCT(ml, struct memlist, 1); 396 if (mlist == NULL) 397 break; 398 ml = nlp; 399 } else { 400 if ((tl->ml_next = nlp) != NULL) 401 nlp->ml_prev = tl; 402 FREESTRUCT(ml, struct memlist, 1); 403 ml = tl; 404 } 405 } 406 } 407 } 408 409 return (mlist); 410 } 411 412 /* 413 * add span without merging 414 */ 415 struct memlist * 416 dr_memlist_cat_span(struct memlist *mlist, uint64_t base, uint64_t len) 417 { 418 struct memlist *ml, *tl, *nl; 419 420 if (len == 0ull) 421 return (NULL); 422 423 if (mlist == NULL) { 424 mlist = GETSTRUCT(struct memlist, 1); 425 mlist->ml_address = base; 426 mlist->ml_size = len; 427 mlist->ml_next = mlist->ml_prev = NULL; 428 429 return (mlist); 430 } 431 432 for (tl = ml = mlist; ml; tl = ml, ml = ml->ml_next) { 433 if (base < ml->ml_address) { 434 nl = GETSTRUCT(struct memlist, 1); 435 nl->ml_address = base; 436 nl->ml_size = len; 437 nl->ml_next = ml; 438 if ((nl->ml_prev = ml->ml_prev) != NULL) 439 nl->ml_prev->ml_next = nl; 440 ml->ml_prev = nl; 441 if (mlist == ml) 442 mlist = nl; 443 break; 444 } 445 } 446 447 if (ml == NULL) { 448 nl = GETSTRUCT(struct memlist, 1); 449 nl->ml_address = base; 450 nl->ml_size = len; 451 nl->ml_next = NULL; 452 nl->ml_prev = tl; 453 tl->ml_next = nl; 454 } 455 456 return (mlist); 457 } 458