Example #1
0
File: sm_jm.c Project: 01org/opa-fm
Status_t
sm_jm_free_job(JmEntry_t *job)
{
	if (job->ports != NULL) vs_pool_free(&sm_pool, job->ports);
	if (job->jobSwToTopoSwMap != NULL) vs_pool_free(&sm_pool, job->jobSwToTopoSwMap);
	if (job->useMatrix.elements != NULL) vs_pool_free(&sm_pool, job->useMatrix.elements);
	vs_pool_free(&sm_pool, job);

	return VSTATUS_OK;
}
Example #2
0
static void
sa_cntxt_retire( sa_cntxt_t* lcl_cntxt )
{
	IB_ENTER( "sa_cntxt_retire", lcl_cntxt, 0, 0, 0 );

	// release getMulti request buffer if allocated
	if( lcl_cntxt->reqData ) {
		vs_pool_free( &sm_pool, lcl_cntxt->reqData );
	}
	// If data was privately allocated, free it
	if (lcl_cntxt->freeDataFunc) {
		(void)lcl_cntxt->freeDataFunc(lcl_cntxt);
	}

	// Reset all fields
	lcl_cntxt->ref = 0 ;
    lcl_cntxt->isDS = 0;
    lcl_cntxt->reqDataLen = 0;
	lcl_cntxt->reqData = NULL ;
	lcl_cntxt->data = NULL ;
	lcl_cntxt->len = 0 ;
	lcl_cntxt->lid = 0 ;
	lcl_cntxt->tid = 0 ;
	lcl_cntxt->hashed = 0 ;
	lcl_cntxt->cache = NULL;
	lcl_cntxt->freeDataFunc = NULL;

	sa_cntxt_insert_head( sa_cntxt_free_list, lcl_cntxt );
	INCR_SA_CNTXT_NFREE();
    DECR_SA_CNTXT_NALLOC();

	IB_EXIT( "sa_cntxt_retire", 0 );
}
Example #3
0
int bitset_resize(bitset_t *bitset, size_t n) {
    Status_t	status;
	size_t orig_nbits = bitset->nbits_m;
	size_t orig_nset = bitset->nset_m;
	size_t orig_nwords = bitset->nwords_m;
	uint32_t *orig_bits = bitset->bits_m;

	if (n == bitset->nbits_m) return 1;

	bitset->bits_m = NULL;

	if (!bitset_init(bitset->pool_m, bitset, n)) {
		bitset->nbits_m = orig_nbits;
		bitset->nset_m = orig_nset;
		bitset->nwords_m = orig_nwords;
		bitset->bits_m = orig_bits;
		return 0;
	}

	if (!orig_bits) return 1;

	if (n > orig_nbits) {
		memcpy(bitset->bits_m, orig_bits, orig_nwords*sizeof(uint32_t));
		bitset->nset_m = orig_nset;
	} else {
		memcpy(bitset->bits_m, orig_bits, bitset->nwords_m*sizeof(uint32_t));
		bitset->nset_m = count_nset(bitset);
	}

	if ((status = vs_pool_free(bitset->pool_m, orig_bits)) != VSTATUS_OK) {
		IB_LOG_ERRORRC("can't free allocated space for bitset, rc:", status);
	}
	return 1;
}
Example #4
0
Status_t
sm_routing_alloc_cost_matrix(Topology_t *topop)
{
	Status_t status;
	size_t   bytesCost;

	/* Allocate space for the cost array. */
	bytesCost = topop->max_sws * topop->max_sws * sizeof(uint16_t);
	if (bytesCost > topop->bytes) {
		topop->bytes = 0;

		if (topop->cost != NULL) {
			(void)vs_pool_free(&sm_pool, (void *)topop->cost);
			topop->cost = NULL;
		}

		status = vs_pool_alloc(&sm_pool, bytesCost, (void *)&topop->cost);
		if (status != VSTATUS_OK) {
			IB_LOG_ERRORRC("can't malloc cost array rc:", status);
			IB_EXIT(__func__, status);
			return status;
		}

		topop->bytes = bytesCost;
	}

	return VSTATUS_OK;
}
Example #5
0
void
freeFeXmlParserMemory(void *address, uint32_t size, char* info) {

#ifdef XML_MEMORY
	printf("called freeFeXmlParserMemory() size (%u) (%s) from fe_main.c\n", size, info);
#endif
	vs_pool_free(&fe_xml_pool, address);
}
Example #6
0
void bitset_free(bitset_t *bitset) {
    Status_t	status;

	if (bitset->bits_m) {
		if ((status = vs_pool_free(bitset->pool_m, bitset->bits_m)) != VSTATUS_OK) {
			IB_LOG_ERRORRC("can't free allocated space for bitset, rc:", status);
		}
	}
    memset(bitset, 0, sizeof(bitset_t));
}
Example #7
0
// "free" function for SA Contexts that contain allocated (non-cached) data
//
static Status_t
sa_cntxt_free_data(sa_cntxt_t *cntxt)
{
	IB_ENTER( "sa_cntxt_retire", cntxt, 0, 0, 0 );
	
	if (cntxt->data)
		vs_pool_free(&sm_pool, cntxt->data);
	
	IB_EXIT( "sa_cntxt_retire", VSTATUS_OK);
	return VSTATUS_OK;
}
Example #8
0
Status_t
sm_routing_freeModule(RoutingModule_t ** module, Topology_t * topop)
{
	if (module == NULL || *module == NULL)
		return VSTATUS_ILLPARM;

	if (topop != NULL&& (*module)->funcs.destroy != NULL) {
		(*module)->funcs.destroy(topop);
	}

	if ((*module)->release != NULL)
		(*module)->release(*module);

	vs_pool_free(&sm_pool, *module);
	*module = NULL;

	return VSTATUS_OK;
}
Example #9
0
static Status_t
activate_switch_via_portstateinfo(Topology_t * topop, Node_t * nodep, Port_t * port0p, pActivationRetry_t retry)
{
	Status_t status = VSTATUS_OK;
	int i;

	IB_ENTER(__func__, topop, nodep, retry, 0);

	STL_PORT_STATE_INFO * psi = NULL;
	status = sm_set_node_port_states(topop, nodep, port0p, NULL, IB_PORT_ARMED, IB_PORT_ACTIVE, &psi);
	if (status != VSTATUS_OK) {
		IB_LOG_WARN_FMT(__func__,
			"Failed Set(PortStateInfo) for node %s nodeGuid "FMT_U64": status=%u",
			sm_nodeDescString(nodep), nodep->nodeInfo.NodeGUID, status);

		// if Set failed, see if we can Get and take advantage of any ports
		// that succeeded
		status = sm_get_node_port_states(topop, nodep, port0p, NULL, &psi);
		if (status != VSTATUS_OK) {
			IB_LOG_WARN_FMT(__func__,
				"Failed Get(PortStateInfo) for node %s nodeGuid "FMT_U64": status=%u",
				sm_nodeDescString(nodep), nodep->nodeInfo.NodeGUID, status);

			// last resort... hit each port individually
			status = activate_switch_via_portinfo(topop, nodep, retry);
			IB_EXIT(__func__, status);
			return status;
		}
	}

	if (!psi) {
		// success and no buffer?  nothing needed to be done
		IB_EXIT(__func__, VSTATUS_OK);
		return VSTATUS_OK;
	}

	// we have a buffer: either Set succeeded, or it failed and we did a Get
	for(i = 0; i <= nodep->nodeInfo.NumPorts; i++) {
		Port_t * portp = sm_get_port(nodep, i);
		if (!sm_valid_port(portp) || portp->state < IB_PORT_ARMED) continue;

		portp->portData->portInfo.PortStates = psi[i].PortStates;
		portp->state = psi[i].PortStates.s.PortState;

		switch (psi[i].PortStates.s.PortState) {
			case IB_PORT_ACTIVE:
				// success
				portp->portData->numFailedActivate = 0;
				break;
			case IB_PORT_ARMED:
				// still armed or never got processed
				if (!psi[i].PortStates.s.IsSMConfigurationStarted) {
					handle_activate_bounce(nodep, portp);
				} else if (i > 0 && !psi[i].PortStates.s.NeighborNormal) {
					handle_activate_retry(nodep, portp, retry);
				} else {
					// looks okay; most likely that the Set(PortStateInfo) failed
					// before reaching this port, or that NeighborNormal propagated
					// between the set and get.  attempt directly via Set(PortInfo)
					status = sm_activate_port(topop, nodep, portp, FALSE, retry);
					if (status != VSTATUS_OK) {
						IB_LOG_WARN_FMT(__func__,
							"Failed to activate node %s nodeGuid "FMT_U64" port 0: status=%u",
							sm_nodeDescString(nodep), nodep->nodeInfo.NodeGUID, status);
					}
				}
				break;
			default:
				// state < ARMED: port bounce
				handle_activate_bounce(nodep, portp);
				break;
		}
	}

	vs_pool_free(&sm_pool, psi);

	IB_EXIT(__func__, VSTATUS_OK);
	return VSTATUS_OK;
}
Example #10
0
uint32_t fe_unsolicited(FE_ConnList *clist, uint32_t *conn_state) { 
    uint32_t i, rc = FE_SUCCESS; 
    uint32_t found = 0, count = 0; 
    int32_t len = 0;
    STL_NOTICE connStateTrap; 
    STL_NOTICE *noticep;
    FE_ConnList *tlist; 
    FE_Trap_t traps, *curr; 
#ifndef IB_STACK_OPENIB
    FE_Trap_t *temp;
#endif
    uint64_t tid; 
    ManagerInfo_t *mi; 
    SA_MAD *noticeMad; 
    OOBPacket *packet; 
    
    IB_ENTER(__func__, conn_state, 0, 0, 0); 
    tlist = clist; 
    
#ifdef IB_STACK_OPENIB
    // early sanity check on OFED to avoid locking the trap thread
    if (!fe_trap_thread_get_trapcount()
        && *conn_state != CONN_LOST && *conn_state != CONN_ESTABLISH) {
        IB_EXIT(__func__, rc); 
        return (rc);
    }
    
    // stop the trap thread and grab the traps.  due to the non-OFED semantics
    // of this function, we store the first trap on the stack
    {
        FE_Trap_t *ptraps; 
        fe_trap_thread_pause(); 
        fe_trap_thread_get_traplist(&ptraps, &found); 
        if (found) {
            memcpy(&traps, ptraps, sizeof(FE_Trap_t));
        }
    }
#else
    (void)fe_if3_get_traps(&traps, &found); 
#endif
    
    if (*conn_state == CONN_LOST) {
        count++;
    }
    
    if (*conn_state == CONN_ESTABLISH) {
        count++;
    }
    
    if (rc == FE_SUCCESS) {
        count = count + found;
    }
    
    if (count == 0) {
        /* no Notices to send */
#ifdef IB_STACK_OPENIB
        fe_trap_thread_resume(); 
#endif
        IB_EXIT(__func__, rc); 
        return (rc);
    }
    

    // find the handle stuff
    if ((rc = if3_mngr_locate_minfo(fdsa, &mi))) {
        IB_EXIT(__func__, rc); 
        return rc;
    }

    // allocate a tid
    ; 
    if ((rc = mai_alloc_tid(mi->fds, mi->mclass, &tid))) {
        IB_LOG_ERRORRC("unable to allocate tid rc:", rc);
        IB_EXIT(__func__, rc); 
        return rc;
    }
    
    //    
    // process the traps
    if (found) {
        curr = &traps;
        
        for (i = 0; i < found; i++, tid = mai_increment_tid(tid)) {
#ifndef IB_STACK_OPENIB
            temp = curr; 
#endif
            
            // build the out of band packet and copy the response into it.
            // there's no need to bswap the data, as that will be done by
            // the FEC on the other side
            packet = (OOBPacket *)g_fe_oob_send_buf; 
            memset(packet, 0, sizeof(OOBPacket)); 
            noticeMad = (SA_MAD *)&(packet->MadData); 
            
            // initialize SA MAD header fields    
            SA_MAD_SET_HEADER(noticeMad, SM_KEY, 0);             
            // initialize the commom mad header fields
            packet->Header.HeaderVersion = STL_BASE_VERSION; 
            MAD_SET_VERSION_INFO(noticeMad, STL_BASE_VERSION, MCLASS_SUBN_ADM, STL_SA_CLASS_VERSION); 
            MAD_SET_METHOD_TYPE(noticeMad, MAD_CM_REPORT); 
            MAD_SET_ATTRIB_ID(noticeMad, SA_NOTICE); 
            MAD_SET_TRANSACTION_ID(noticeMad, tid);             
            // initialize RMPP fields
            noticeMad->RmppHdr.RmppVersion = 1;
                         
            // copy the notice data into our packet and convert to network byte order.
            // Byte swapping to network byte order for the rest of the packet, will
            // be done by the fe_send_packet() routine.  
            (void)BSWAPCOPY_STL_NOTICE(&curr->notice, (STL_NOTICE *)noticeMad->Data);
            
            len = sizeof(OOBHeader) + IBA_SUBN_ADM_HDRSIZE + sizeof(STL_NOTICE);

            // send the notice to all FECs
            while (tlist) {
                if ((rc = fe_send_packet(tlist->conn, g_fe_oob_send_buf, len))) {
                    IB_LOG_ERROR("fe_send_packet fail in fe_unsolicited rc:", rc);
                }

                // the fe_send_packet() routine byte swaps the headers of the
                // OOB packet, so convert them back to host byte order before
                // sending packet again.
                BSWAP_OOB_PACKET(packet);
                
                tlist = tlist->next;
            }
            
            curr = curr->next;             
            // relegate memory management to trap thread functions on OFED
#ifndef IB_STACK_OPENIB
            if (i > 0) {
                vs_pool_free(&fe_pool, (void *)temp);
            }
#endif
        }
    }

    switch (*conn_state) {
    case CONN_LOST:
    case CONN_ESTABLISH:
        tlist = clist;
         
        // use 64/65 trap to notify the FEC that the connection to the SM/SA
        // has gone down/reestablished
        tid = mai_increment_tid(tid);

        // build the out of band packet and copy the response into it.
        // there's no need to bswap the data, as that will be done by
        // the FEC on the other side
        memset(&connStateTrap, 0, sizeof(connStateTrap));
        packet = (OOBPacket *)g_fe_oob_send_buf; 
        memset(packet, 0, sizeof(OOBPacket)); 
        noticeMad = (SA_MAD *)&(packet->MadData); 

        // initialize SA MAD header fields    
        SA_MAD_SET_HEADER(noticeMad, SM_KEY, 0);
                     
        // initialize the commom mad header fields
        packet->Header.HeaderVersion = STL_BASE_VERSION; 
        MAD_SET_VERSION_INFO(noticeMad, STL_BASE_VERSION, MCLASS_SUBN_ADM, STL_SA_CLASS_VERSION); 
        MAD_SET_METHOD_TYPE(noticeMad, MAD_CM_REPORT); 
        MAD_SET_ATTRIB_ID(noticeMad, SA_NOTICE); 
        MAD_SET_TRANSACTION_ID(noticeMad, tid);             
        // initialize RMPP fields
        noticeMad->RmppHdr.RmppVersion = 1;

        // initialize the notice fields
        connStateTrap.Attributes.Generic.u.s.IsGeneric = 1;
        connStateTrap.Attributes.Generic.u.s.Type = NOTICE_TYPE_INFO;
        connStateTrap.Attributes.Generic.u.s.ProducerType = NOTICE_PRODUCERTYPE_CLASSMANAGER;
        connStateTrap.Attributes.Generic.TrapNumber = (*conn_state == CONN_LOST) ? MAD_SMT_PORT_DOWN: MAD_SMT_PORT_UP;
        connStateTrap.IssuerLID	= mi->saLid;
        connStateTrap.Stats.s.Toggle = 0;
        connStateTrap.Stats.s.Count = 0;

        // copy the notice data into our packet and convert to network byte order.
        // Byte swapping to network byte order for the rest of the packet, will
        // be done by the fe_send_packet() routine.  
        (void)BSWAPCOPY_STL_NOTICE(&connStateTrap, (STL_NOTICE *)noticeMad->Data);

        // Now construct IssurerGID
        // 
        // Note, we don't copy the GIDs till after we bswap the rest of the notice.
        // This is done in order to remain consistant with the unique handling of
        // GIDs throughout the FM (GIDs are stored in network byte order).
        noticep = (STL_NOTICE *)noticeMad->Data;
		(void) memcpy((void *) &noticep->IssuerGID.Raw[0], (void *) &mi->gidPrefix, 8);
		(void) memcpy((void *) &noticep->IssuerGID.Raw[8], (void *) &mi->guid, 8);
		*(uint64_t *) &noticep->IssuerGID.Raw[0] = ntoh64(*(uint64_t *) &noticep->IssuerGID.Raw[0]);
		*(uint64_t *) &noticep->IssuerGID.Raw[8] = ntoh64(*(uint64_t *) &noticep->IssuerGID.Raw[8]);

        len = sizeof(OOBHeader) + IBA_SUBN_ADM_HDRSIZE + sizeof(STL_NOTICE);

        // send the notice to all FECs
        while (tlist) {
            if ((rc = fe_send_packet(tlist->conn, g_fe_oob_send_buf, len))) {
                IB_LOG_ERROR("fe_send_packet fail in fe_unsolicited rc:", rc);
            }
            // the fe_send_packet() routine byte swaps the headers of the
            // OOB packet, so convert them back to host byte order before
            // sending packet again.
            BSWAP_OOB_PACKET(packet);

            tlist = tlist->next;
        }
        break;

    default:
        break;
    }
    
    PCHK(rc, FAILED, "fe_unsolicited"); 
    
    *conn_state = CONN_UNCHANGED; 
    
#ifdef IB_STACK_OPENIB
    fe_trap_thread_free_traps(); 
    fe_trap_thread_resume(); 
#endif
    
    IB_EXIT(__func__, rc); 
    return (rc);
}
Example #11
0
hsm_com_errno_t 
pm_conf_callback(hsm_com_datagram_t *data)
{
	fm_config_datagram_t *msg;
	char * tmpData = NULL;
	int length = 0;

	printf("pm_conf_callback: LEN: %d, BUFLEN: %d \n",
		   data->data_len,data->buf_size);

	if(data->data_len >= sizeof(msg->header)){
		msg = (fm_config_datagram_t*)data->buf;

		switch (msg->header.data_id) {
		case FM_DT_COMMON:
			if (msg->header.data_len != sizeof(fm_config_common_t)) {
				msg->header.ret_code = FM_RET_BAD_LEN;
			} else {
				msg->header.ret_code = pm_conf_fill_common(msg->header.action,(fm_config_common_t*)&msg->data[0]);
			}
			break;
		case FM_DT_PM_CFG:
			if (msg->header.data_len != sizeof(pm_config_t)) {
				msg->header.ret_code = FM_RET_BAD_LEN;
			} else {
				msg->header.ret_code = pm_conf_fill_pm_conf(msg->header.action,(pm_config_t*)&msg->data[0]);
			}
			break;

		case FM_DT_PM_RESTORE_PRIORITY:
		case FM_DT_LOG_LEVEL:
		case FM_DT_LOG_MODE:
		case FM_DT_LOG_MASK:
			msg->header.ret_code = FM_RET_UNKNOWN_DT;
			break;

		case FM_DT_DEBUG_TOGGLE:
			if (pmDebugGet()) {
				pmDebugOff();
				IB_LOG_INFINI_INFO0("Turning OFF Debug for PM");
			} else {
				pmDebugOn();
				IB_LOG_INFINI_INFO0("Turning ON Debug for PM");
			}
			msg->header.ret_code = FM_RET_OK;
			break;

		case FM_DT_RMPP_DEBUG_TOGGLE:
			if (if3RmppDebugGet()) {
				IB_LOG_INFINI_INFO0("turning rmpp debug off for PM");
				if3RmppDebugOff();
			} else {
				IB_LOG_INFINI_INFO0("turning rmpp debug on for PM");
				if3RmppDebugOn();
			}
			msg->header.ret_code = FM_RET_OK;
			break;

		case FM_DT_PM_GET_COUNTERS:
			tmpData = pm_print_counters_to_buf();

			printf("%s\n", tmpData);
			if (tmpData != NULL) {
				length = strlen(tmpData) + 1;

				memcpy(&msg->data[0], tmpData, MIN(msg->header.data_len, length));
				msg->data[msg->header.data_len - 1] = '\0';
				/* PR 116307 - buffer returned from pm_print_counters_to_buf() is from
				 * sm_pool, so free the buffer from smpool.
				 */
				vs_pool_free(&sm_pool, tmpData);
			}
			msg->header.ret_code = FM_RET_OK;
			break;

		case FM_DT_PM_RESET_COUNTERS:
			pm_reset_counters();
			msg->header.ret_code = FM_RET_OK;
			break;

		default:
			msg->header.ret_code = FM_RET_UNKNOWN_DT;
			break;
		}

		return HSM_COM_OK;
	}



	return HSM_COM_ERR_LEN;
}
Example #12
0
File: sm_jm.c Project: 01org/opa-fm
void
sm_jm_free_cost(uint16_t *cost)
{
	(void)vs_pool_free(&sm_pool, cost);
}
Example #13
0
File: sm_jm.c Project: 01org/opa-fm
// outCount wil be set to the number of ports actually found and valid in the
// topology
//
Status_t
sm_jm_fill_ports
	( Topology_t *topop
	, JmMsgReqCreate_t *input
	, JmEntry_t *job
	, uint16_t *outCount
	)
{
	Status_t s;
	int i;
	Node_t *nodep;
	Port_t *portp;
	int count = 0, nextIdx = 0;
	uint16_t *topoSwToJobSwMap;

	s = vs_pool_alloc(&sm_pool, input->guids.count * sizeof(JmPort_t),
		(void *)&job->ports);
	if (s != VSTATUS_OK) {
		IB_LOG_ERROR_FMT(__func__,
			"Failed to allocate space for PortGuid list (status %d)", s);
		goto fail1;
	}

	s = vs_pool_alloc(&sm_pool, input->guids.count * sizeof(uint16_t),
		(void *)&job->jobSwToTopoSwMap);
	if (s != VSTATUS_OK) {
		IB_LOG_ERROR_FMT(__func__,
			"Failed to allocate space for switch translation map (status %d)", s);
		goto fail2;
	}

	s = vs_pool_alloc(&sm_pool, topop->max_sws * sizeof(uint16_t),
		(void *)&topoSwToJobSwMap);
	if (s != VSTATUS_OK) {
		IB_LOG_ERROR_FMT(__func__,
			"Failed to allocate space for switch translation map (status %d)", s);
		goto fail3;
	}
	memset(topoSwToJobSwMap, 0xff, topop->max_sws * sizeof(uint16_t));

	// for each portguid: find the port/switch in the topology
	for (i = 0; i < input->guids.count; ++i) {
		job->ports[i].guid = input->guids.entries[i];
		portp = sm_find_port_guid(topop, input->guids.entries[i]);
		if (  !sm_valid_port(portp)
		   || portp->state < IB_PORT_INIT
		   || portp->portData->nodePtr->nodeInfo.NodeType == NI_TYPE_SWITCH) {
			// port not found; clear port in job
			job->ports[i].portp = NULL;
			job->ports[i].jobSwIdx = 0xffff;
		} else {
			// port found; find neighbor switch
			job->ports[i].portp = portp;
			nodep = sm_find_node(topop, portp->nodeno);
			if (nodep == NULL) {
				// switch not found; clear port in job
				job->ports[i].jobSwIdx = 0xffff;
			} else {
				// switch found; determine job-specific switch index
				if (topoSwToJobSwMap[nodep->swIdx] != 0xffff) {
					// index already created; use it
					job->ports[i].jobSwIdx = topoSwToJobSwMap[nodep->swIdx];
				} else {
					// index not created; use next available
					job->ports[i].jobSwIdx = topoSwToJobSwMap[nodep->swIdx] = nextIdx;
					job->jobSwToTopoSwMap[nextIdx] = nodep->swIdx;
					++nextIdx;
				}
				++count;
			}
		}
	}

	(void)vs_pool_free(&sm_pool, topoSwToJobSwMap);

	job->portCount = input->guids.count;
	job->switchCount = nextIdx;
	*outCount = count;

	return VSTATUS_OK;

fail3:
	(void)vs_pool_free(&sm_pool, job->jobSwToTopoSwMap);
fail2:
	(void)vs_pool_free(&sm_pool, job->ports);
fail1:
	return VSTATUS_BAD;
}
Example #14
0
//
//  This uses log level INFINI_INFO and should probably only
//  be called under debug mode.
//
void bitset_info_log(bitset_t* bitset, char* prelude) {
	char*	string = NULL;
	int		first = 1;
	int		range = 0;
	int		range_start = -1;
	int		prev = -1;
	int		bit = -1;
	size_t	max_str_len = bitset->nset_m*5+1;
	size_t	pos = 0;
	int		res = 0;
    Status_t	status;
	
	if (!bitset) return;

	if (bitset->bits_m == NULL) {
		IB_LOG_INFINI_INFO_FMT( __func__, "NOBITS");
		return;
	}

	if (bitset->nset_m == 0) {
		if (prelude) {
			IB_LOG_INFINI_INFO_FMT(__func__, "%s <nil>", prelude);
		} else {
			IB_LOG_INFINI_INFO_FMT(__func__, "<nil>");
		}
		return;

	} else if (!bitset->pool_m || (bitset->nset_m>500)) {
		if (prelude) {
			IB_LOG_INFINI_INFO_FMT(__func__, "%s, nset= %d", prelude, (int)bitset->nset_m);
		} else {
			IB_LOG_INFINI_INFO_FMT(__func__, "nset= %d", (int)bitset->nset_m);
		}
		return;
	}

	status = vs_pool_alloc(bitset->pool_m, max_str_len, (void *)&string);
	if (status != VSTATUS_OK) {
		if (prelude) {
			IB_LOG_INFINI_INFO_FMT(__func__, "%s, nset= %d", prelude, (int)bitset->nset_m);
		} else {
			IB_LOG_INFINI_INFO_FMT(__func__, "nset= %d", (int)bitset->nset_m);
		}
		return;
	}
	string[0] = '\0';

	bit = bitset_find_first_one(bitset);

	while (bit != -1) {
		if (first) {
			res = snprintf(string + pos, max_str_len - pos, "%d", bit);
			if (res > 0){
				pos += res;
			} else {
				if (res == 0)
					break;
				else
					goto bail;
			}
			first = 0;
		} else {
			if (range && (prev != bit-1)) {
				range = 0;
				if ((prev - range_start) > 1) {
					res = snprintf(string + pos, max_str_len - pos, "-%d,%d", prev, bit);
				} else {
					res = snprintf(string + pos, max_str_len - pos, ",%d,%d", prev, bit);
				}
				if (res > 0){
					pos += res;
				} else {
					if (res == 0)
						break;
					else
						goto bail;
				}
				prev = -1;
				range_start = -1;
			} else if (!range && (prev == bit-1)) {
				range_start = prev;
				range = 1;
			} else if (!range) {
				res = snprintf(string + pos, max_str_len - pos, ",%d", bit);
				if (res > 0){
					pos += res;
				} else {
					if (res == 0)
						break;
					else
						goto bail;
				}
			}
		}
		prev = bit;
		bit = bitset_find_next_one(bitset, bit+1);
	}

	if (range && (prev != -1)) {
		if ((prev - range_start) > 1) {
			res = snprintf(string + pos, max_str_len - pos, "-%d", prev);
		} else {
			res = snprintf(string + pos, max_str_len - pos, ",%d", prev);
		}
		if (res > 0){
			pos += res;
		}
	}

bail:  
	if (prelude) {
		IB_LOG_INFINI_INFO_FMT(__func__, "%s %s", prelude, string);
	} else {
		IB_LOG_INFINI_INFO_FMT(__func__, "%s", string);
	}

	if ((status = vs_pool_free(bitset->pool_m, string)) != VSTATUS_OK) {
		IB_LOG_ERRORRC("can't free allocated space for bitset log, rc:", status);
	}
}