a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * CDDL HEADER START
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * The contents of this file are subject to the terms of the
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Common Development and Distribution License (the "License").
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * You may not use this file except in compliance with the License.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * or http://www.opensolaris.org/os/licensing.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * See the License for the specific language governing permissions
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * and limitations under the License.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * When distributing Covered Code, include this CDDL HEADER in each
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * If applicable, add the following below this CDDL HEADER, with the
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * fields enclosed by brackets "[]" replaced with your own identifying
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * information: Portions Copyright [yyyy] [name of copyright owner]
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * CDDL HEADER END
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Use is subject to license terms.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/types.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/cmn_err.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/param.h> /* for NULL */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/sbd_ioctl.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/dr_util.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/varargs.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/sysmacros.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/systm.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/* sbd_etab[] and sbd_etab_len provided by sbdgenerr.pl */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuextern sbd_etab_t sbd_etab[];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuextern int sbd_etab_len;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liusbd_error_t *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liusbd_err_new(int e_code, char *fmt, va_list args)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_error_t *new;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu new = GETSTRUCT(sbd_error_t, 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu new->e_code = e_code;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (fmt)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void) vsnprintf(new->e_rsc, sizeof (new->e_rsc), fmt, args);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (new);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid
a31148363f598def767ac48c5d82e1572e44b935Gerry Liusbd_err_log(sbd_error_t *ep, int ce)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char buf[32];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *fmt;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *txt;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int i;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_etab_t *tp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!ep)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ep->e_rsc[0] == '\0')
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu fmt = "%s";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu else
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu fmt = "%s: %s";
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (tp = sbd_etab, i = 0; i < sbd_etab_len; i++, tp++)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ep->e_code >= tp->t_base && ep->e_code <= tp->t_bnd)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (i < sbd_etab_len)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu txt = tp->t_text[ep->e_code - tp->t_base];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void) snprintf(buf, sizeof (buf), "error %d", ep->e_code);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu txt = buf;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(ce, fmt, txt, ep->e_rsc);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid
a31148363f598def767ac48c5d82e1572e44b935Gerry Liusbd_err_clear(sbd_error_t **ep)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu FREESTRUCT(*ep, sbd_error_t, 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *ep = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid
a31148363f598def767ac48c5d82e1572e44b935Gerry Liusbd_err_set_c(sbd_error_t **ep, int ce, int e_code, char *fmt, ...)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_error_t *tmp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu va_list args;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu va_start(args, fmt);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu tmp = sbd_err_new(e_code, fmt, args);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_err_log(tmp, ce);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (*ep == NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *ep = tmp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu else
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_err_clear(&tmp);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu va_end(args);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid
a31148363f598def767ac48c5d82e1572e44b935Gerry Liusbd_err_set(sbd_error_t **ep, int ce, int e_code, char *fmt, ...)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_error_t *tmp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu va_list args;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu va_start(args, fmt);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu tmp = sbd_err_new(e_code, fmt, args);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_err_log(tmp, ce);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *ep = tmp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu va_end(args);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liusbd_error_t *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudrerr_new_v(int e_code, char *fmt, va_list args)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (sbd_err_new(e_code, fmt, args));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liusbd_error_t *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudrerr_new(int log, int e_code, char *fmt, ...)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_error_t *ep;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu va_list args;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu va_start(args, fmt);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ep = sbd_err_new(e_code, fmt, args);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu va_end(args);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (log)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_err_log(ep, CE_WARN);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (ep);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudrerr_set_c(int log, sbd_error_t **ep, int e_code, char *fmt, ...)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_error_t *err;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu va_list args;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu va_start(args, fmt);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu err = sbd_err_new(e_code, fmt, args);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu va_end(args);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (log)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_err_log(err, CE_WARN);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (*ep == NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *ep = err;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu else
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu sbd_err_clear(&err);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Memlist support.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_memlist_delete(struct memlist *mlist)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu register struct memlist *ml;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (ml = mlist; ml; ml = mlist) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mlist = ml->ml_next;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu FREESTRUCT(ml, struct memlist, 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuint
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_memlist_intersect(struct memlist *al, struct memlist *bl)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint64_t astart, aend, bstart, bend;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((al == NULL) || (bl == NULL))
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu aend = al->ml_address + al->ml_size;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu bstart = bl->ml_address;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu bend = bl->ml_address + bl->ml_size;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu while (al && bl) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu while (al && (aend <= bstart))
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((al = al->ml_next) != NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu aend = al->ml_address + al->ml_size;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (al == NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((astart = al->ml_address) <= bstart)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu while (bl && (bend <= astart))
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((bl = bl->ml_next) != NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu bend = bl->ml_address + bl->ml_size;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (bl == NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((bstart = bl->ml_address) <= astart)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (0);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_memlist_coalesce(struct memlist *mlist)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint64_t end, nend;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((mlist == NULL) || (mlist->ml_next == NULL))
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu while (mlist->ml_next) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu end = mlist->ml_address + mlist->ml_size;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mlist->ml_next->ml_address <= end) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct memlist *nl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nend = mlist->ml_next->ml_address +
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mlist->ml_next->ml_size;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (nend > end)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mlist->ml_size += (nend - end);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl = mlist->ml_next;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mlist->ml_next = mlist->ml_next->ml_next;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (nl) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu FREESTRUCT(nl, struct memlist, 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mlist->ml_next)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mlist->ml_next->ml_prev = mlist;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mlist = mlist->ml_next;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#ifdef DEBUG
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuvoid
a31148363f598def767ac48c5d82e1572e44b935Gerry Liumemlist_dump(struct memlist *mlist)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu register struct memlist *ml;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mlist == NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu printf("memlist> EMPTY\n");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu else for (ml = mlist; ml; ml = ml->ml_next)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu printf("memlist> 0x%" PRIx64 ", 0x%" PRIx64 "\n",
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ml->ml_address, ml->ml_size);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#endif
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustruct memlist *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_memlist_dup(struct memlist *mlist)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct memlist *hl = NULL, *tl, **mlp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mlist == NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mlp = &hl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu tl = *mlp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (; mlist; mlist = mlist->ml_next) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *mlp = GETSTRUCT(struct memlist, 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (*mlp)->ml_address = mlist->ml_address;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (*mlp)->ml_size = mlist->ml_size;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (*mlp)->ml_prev = tl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu tl = *mlp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mlp = &((*mlp)->ml_next);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *mlp = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (hl);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustruct memlist *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_memlist_add_span(struct memlist *mlist, uint64_t base, uint64_t len)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct memlist *ml, *tl, *nl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (len == 0ull)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mlist == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mlist = GETSTRUCT(struct memlist, 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mlist->ml_address = base;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mlist->ml_size = len;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mlist->ml_next = mlist->ml_prev = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (mlist);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (tl = ml = mlist; ml; tl = ml, ml = ml->ml_next) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (base < ml->ml_address) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((base + len) < ml->ml_address) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl = GETSTRUCT(struct memlist, 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl->ml_address = base;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl->ml_size = len;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl->ml_next = ml;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((nl->ml_prev = ml->ml_prev) != NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl->ml_prev->ml_next = nl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ml->ml_prev = nl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mlist == ml)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mlist = nl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ml->ml_size = MAX((base + len),
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (ml->ml_address + ml->ml_size)) - base;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ml->ml_address = base;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else if (base <= (ml->ml_address + ml->ml_size)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ml->ml_size = MAX((base + len),
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (ml->ml_address + ml->ml_size)) -
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu MIN(ml->ml_address, base);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ml->ml_address = MIN(ml->ml_address, base);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ml == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl = GETSTRUCT(struct memlist, 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl->ml_address = base;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl->ml_size = len;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl->ml_next = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl->ml_prev = tl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu tl->ml_next = nl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu dr_memlist_coalesce(mlist);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (mlist);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustruct memlist *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_memlist_del_span(struct memlist *mlist, uint64_t base, uint64_t len)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint64_t end;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct memlist *ml, *tl, *nlp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mlist == NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu end = base + len;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((end <= mlist->ml_address) || (base == end))
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (mlist);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (tl = ml = mlist; ml; tl = ml, ml = nlp) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu uint64_t mend;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nlp = ml->ml_next;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (end <= ml->ml_address)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mend = ml->ml_address + ml->ml_size;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (base < mend) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (base <= ml->ml_address) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ml->ml_address = end;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (end >= mend)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ml->ml_size = 0ull;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu else
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ml->ml_size = mend - ml->ml_address;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ml->ml_size = base - ml->ml_address;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (end < mend) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct memlist *nl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * splitting an memlist entry.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl = GETSTRUCT(struct memlist, 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl->ml_address = end;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl->ml_size = mend - nl->ml_address;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((nl->ml_next = nlp) != NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nlp->ml_prev = nl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl->ml_prev = ml;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ml->ml_next = nl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nlp = nl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ml->ml_size == 0ull) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ml == mlist) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((mlist = nlp) != NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nlp->ml_prev = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu FREESTRUCT(ml, struct memlist, 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mlist == NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ml = nlp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((tl->ml_next = nlp) != NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nlp->ml_prev = tl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu FREESTRUCT(ml, struct memlist, 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ml = tl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (mlist);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * add span without merging
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liustruct memlist *
a31148363f598def767ac48c5d82e1572e44b935Gerry Liudr_memlist_cat_span(struct memlist *mlist, uint64_t base, uint64_t len)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu struct memlist *ml, *tl, *nl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (len == 0ull)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mlist == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mlist = GETSTRUCT(struct memlist, 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mlist->ml_address = base;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mlist->ml_size = len;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mlist->ml_next = mlist->ml_prev = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (mlist);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu for (tl = ml = mlist; ml; tl = ml, ml = ml->ml_next) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (base < ml->ml_address) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl = GETSTRUCT(struct memlist, 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl->ml_address = base;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl->ml_size = len;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl->ml_next = ml;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((nl->ml_prev = ml->ml_prev) != NULL)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl->ml_prev->ml_next = nl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ml->ml_prev = nl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (mlist == ml)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mlist = nl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ml == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl = GETSTRUCT(struct memlist, 1);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl->ml_address = base;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl->ml_size = len;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl->ml_next = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu nl->ml_prev = tl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu tl->ml_next = nl;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (mlist);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}