values[1] = Int64GetDatum(fctx->record[i].page_num);
nulls[1] = false;
- values[2] = Int32GetDatum(fctx->record[i].numa_node);
- nulls[2] = false;
+ /* status is valid node number */
+ if (fctx->record[i].numa_node >= 0)
+ {
+ values[2] = Int32GetDatum(fctx->record[i].numa_node);
+ nulls[2] = false;
+ } else {
+ /* some kind of error (e.g. pages moved to swap) */
+ values[2] = (Datum) 0;
+ nulls[2] = true;
+ }
/* Build and return the tuple. */
tuple = heap_form_tuple(fctx->tupdesc, values, nulls);
InitMaterializedSRF(fcinfo, 0);
max_nodes = pg_numa_get_max_node();
- nodes = palloc(sizeof(Size) * (max_nodes + 1));
+ nodes = palloc(sizeof(Size) * (max_nodes + 2));
/*
* Shared memory allocations can vary in size and may not align with OS
hash_seq_init(&hstat, ShmemIndex);
/* output all allocated entries */
- memset(nulls, 0, sizeof(nulls));
while ((ent = (ShmemIndexEnt *) hash_seq_search(&hstat)) != NULL)
{
int i;
elog(ERROR, "failed NUMA pages inquiry status: %m");
/* Count number of NUMA nodes used for this shared memory entry */
- memset(nodes, 0, sizeof(Size) * (max_nodes + 1));
+ memset(nodes, 0, sizeof(Size) * (max_nodes + 2));
for (i = 0; i < shm_ent_page_count; i++)
{
int s = pages_status[i];
/* Ensure we are adding only valid index to the array */
- if (s < 0 || s > max_nodes)
+ if (s >= 0 && s <= max_nodes)
+ {
+ /* valid NUMA node */
+ nodes[s]++;
+ continue;
+ }
+ else if (s == -2)
{
- elog(ERROR, "invalid NUMA node id outside of allowed range "
- "[0, " UINT64_FORMAT "]: %d", max_nodes, s);
+ /* -2 means ENOENT (e.g. page was moved to swap) */
+ nodes[max_nodes + 1]++;
+ continue;
}
- nodes[s]++;
+ elog(ERROR, "invalid NUMA node id outside of allowed range "
+ "[0, " UINT64_FORMAT "]: %d", max_nodes, s);
}
+ /* no NULLs for regular nodes */
+ memset(nulls, 0, sizeof(nulls));
+
/*
* Add one entry for each NUMA node, including those without allocated
* memory for this segment.
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
values, nulls);
}
+
+ /* The last entry is used for pages without a NUMA node. */
+ nulls[1] = true;
+ values[0] = CStringGetTextDatum(ent->key);
+ values[2] = Int64GetDatum(nodes[max_nodes + 1] * os_page_size);
+
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
+ values, nulls);
}
LWLockRelease(ShmemIndexLock);