---
name: "edac"
section: "3"
platform: "linux"
package: "libedac-dev"
version: "0.18+git16-g8fdc1d4-2"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/edac"
---

# edac(3)

EDAC error reporting library

## NAME

libedac - EDAC error reporting library

## SYNOPSIS

```
#include <edac.h>

cc ... -ledac

edac_handle * edac_handle_create (void);

void edac_handle_destroy (edac_handle *edac);

int edac_handle_init (edac_handle *edac);

unsigned int edac_mc_count (edac_handle *edac);

int edac_handle_reset (edac_handle *edac);

int edac_error_totals (edac_handle *edac, struct edac_totals *totals);

edac_mc * edac_next_mc (edac_handle *edac);

int edac_mc_get_info (edac_mc *mc, struct edac_mc_info *info);
```

**edac\_mc \*edac\_next\_mc\_info (edac\_handle \****edac***,**                             **struct edac\_mc\_info \****info***);**

**int edac\_mc\_reset (struct edac\_mc \****mc***);**

**edac\_csrow \* edac\_next\_csrow (struct edac\_mc \****mc***);**

**int edac\_csrow\_get\_info (edac\_csrow \****csrow***,**                          **struct edac\_csrow\_info \****info***);**

**edac\_csrow \* edac\_next\_csrow\_info (edac\_mc \****mc***,**                                    **struct edac\_csrow\_info \****info***);**

**const char \* edac\_strerror (edac\_handle \****edac***);**

**edac\_for\_each\_mc\_info (edac\_handle \****edac***, edac\_mc \****mc***,**                        **struct edac\_csrow\_info \****info***)    { ... }**

**edac\_for\_each\_csrow\_info (edac\_mc \****mc***, edac\_csrow \****csrow***,**                            **struct edac\_csrow\_info \****info***) { ... }**

## DESCRIPTION

The *libedac* library offers a very simple programming interface to the information exported from in-kernel EDAC (Error Detection and Correction) drivers in sysfs. The *edac-util*(8) utility uses *libedac* to report errors in a user-friendly manner from the command line.

EDAC errors for most systems are recorded in sysfs on a per  memory controller (MC) basis. Memory controllers are further subdivided by csrow and channel. The *libedac* library provides a method to loop through multiple MCs, and their corresponding csrows, obtaining information about each component from sysfs along the way. There is also a simple  single call to retrieve the total error counts for a given machine.

In order to use *libedac* an **edac\_handle** must first be opened via the call **edac\_handle\_create**(). Once the handle is created, sysfs data can be loaded into the handle with **edac\_handle\_init**(). A final call to **edac\_handle\_destroy**()  will free all memory and open files associated with the edac handle.

**edac\_handle\_create**() will return **NULL** on failure to allocate memory.

The **edac\_strerror** function will return a descriptive string  representation of the last error for the *libedac* handle *edac*.

The **edac\_error\_totals**() function will return the total counts of memory and pci errors in the *totals* structure passed to the function. The *totals* structure is of type *edac\_totals* which has the form:

```
struct edac_totals {
   unsigned int  ce_total;         /* Total corrected errors   */
   unsigned int  ue_total;         /* Total uncorrected errors */
   unsigned int  pci_parity_total; /* Total PCI Parity errors  */
};
```

## MEMORY CONTROLLER INFORMATION

Systems may have one or more memory controllers (MCs) with EDAC information. The number of MCs detected by EDAC drivers may be queried with the **edac\_mc\_count**() function, while the **edac\_next\_mc** function will return a handle to the next memory controller in the *libedac* handle´s internal list. This memory controller is represented by the opaque **edac\_mc** type.

**edac\_next\_mc** will return **NULL** when there are no further memory controllers to return. Thus the following example code is another method to count all EDAC MCs (assuming the EDAC library handle *edac* has already been initialized):

```
int i = 0;
edac_mc *mc;
while ((mc = edac_next_mc (edac)))
    i++;
return (i);
```

To query information about an **edac\_mc**, use the **edac\_mc\_get\_info** function. This function fills in the given **info** structure, which is of type **edac\_mc\_info**:

```
struct edac_mc_info {
    char           id[];           /* Id of memory controller */
    char           mc_name[];      /* Name of MC              */
    unsigned int   size_mb;        /* Amount of RAM in MB     */
    unsigned int   ce_count;       /* Corrected error count   */
    unsigned int   ce_noinfo_count;/* noinfo Corrected errors */
    unsigned int   ue_count;       /* Uncorrected error count */
    unsigned int   ue_noinfo_count;/* noinfo Uncorrected errors*/
};
```

The function **edac\_next\_mc\_info**() can be used to  loop through all EDAC memory controllers and obtain MC information in a single call. It is a combined **edac\_next\_mc**() and  **edac\_mc\_get\_info**().

The function **edac\_handle\_reset**() will reset the internal memory controller iterator in the *libedac* handle. A subsequent call to **edac\_next\_mc**() would thus return the first EDAC MC.

A convenience macro, **edac\_for\_each\_mc\_info**(), is provided which defines a for loop that iterates through all memory controller\
  objects for a given EDAC handle, returning the MC information in the *info* structure on each iteration. For example (assuming initialized *libedac* handle *edac*):

```
edac_mc *mc;
struct edac_mc_info info;
int count = 0;
edac_for_each_mc_info (edac, mc, info) {
    count++;
    printf ("MC info: id=%s name=%s\n", info.id, info.mc_name);
}
```

## CSROW INFORMATION

Each EDAC memory controller may have one or more *csrow*s  associated with it. Similar to the MC iterator functions described above, the **edac\_next\_csrow**() function allows *libedac* users to loop through all csrows within a given MC. Once the last csrow is reached, the function will return **NULL**.

The **edac\_csrow\_get\_info**() function returns information about **edac\_csrow in the edac\_csrow\_info** structure, which has the contents:

```
struct edac_csrow_info {
    char          id[];      /* CSROW Identity (e.g. csrow0)  */
    unsigned int  size_mb;   /* CSROW size in MB              */
    unsigned int  ce_count;  /* Total corrected errors        */
    unsigned int  ue_count;  /* Total uncorrected errors      */
    struct edac_channel channel[EDAC_MAX_CHANNELS];
};
struct edac_channel {
    int           valid;            /* Is this channel valid */
    unsigned int  ce_count;         /* Corrected error count */
    int           dimm_label_valid; /* Is DIMM label valid?  */
    char          dimm_label[];     /* DIMM name             */
};
```

The **edac\_next\_csrow\_info**() function is a combined version of **edac\_next\_csrow**() and **edac\_csrow\_get\_info**() for  convenience.

The **edac\_mc\_reset**() function is provided to reset the **edac\_mc** internal csrow iterator.

A convenience macro, **edac\_for\_each\_csrow\_info**(), is provided which defines a for loop that iterates through all csrow objects in an EDAC memory controller, returning the csrow information in the *info* structure on each iteration.

## EXAMPLES

Initialize *libedac* handle:

```
edac_handle *edac;
if (!(edac = edac_handle_create ())) {
    fprintf (stderr, "edac_handle_create: Out of memory!\n");
    exit (1);
}
if (edac_handle_init (edac) < 0) {
   fprintf (stderr, "Unable to get EDAC data: %s\n",
                    edac_strerror (edac));
   exit (1);
}
printf ("EDAC initialized with %d MCs\n", edac_mc_count (edac));
edac_handle_destroy (edac);
```

Report all DIMM labels for MC:csrow:channel combinations

```
edac_mc *mc;
edac_csrow *csrow;
struct edac_mc_info mci;
struct edac_csrow_info csi;
edac_for_each_mc_info (ctx->edac, mc, mci) {
    edac_for_each_csrow_info (mc, csrow, csi) {
        char *label[2] = { "unset", "unset" };
        if (csi.channel[0].dimm_label_valid)
            label[0] = csi.channel[0].dimm_label;
        if (csi.channel[1].dimm_label_valid)
            label[1] = csi.channel[1].dimm_label;
        printf ("%s:%s:ch0 = %s\n", mci.id, csi.id, label[0]);
        printf ("%s:%s:ch1 = %s\n", mci.id, csi.id, label[1]);
    }
}
```

## SEE ALSO

**edac-util**(8), [**edac-ctl**(8)](/edac-ctl/8.md)
