Adding Error Logging Calls into the Code

Typically, you define a routine in the device driver that can be called by other device driver routines when a loggable error is encountered.

The errsave kernel service allows the kernel and kernel extensions to write to the error log. This function takes the data passed to it, puts it into the proper structure and calls the errsave kernel service. The syntax for the errsave kernel service is:

#include <sys/errids.h>
void errsave(buf, cnt)
char *buf;
unsigned int cnt;

where:

Item Description
buf Specifies a pointer to a buffer that contains an error record as described in the sys/errids.h header file.
cnt Specifies a number of bytes in the error record contained in the buffer pointed to by the buf parameter.
The following sample code is an example of a device driver error logging routine. This routine takes data passed to it from some part of the main body of the device driver. This code simply fills in the structure with the pertinent information, then passes it on using the errsave kernel service.

void
errsv_ex (int err_id, unsigned int port_num,
            int line, char *file, uint data1, uint data2)
{
    dderr   log;
    char      errbuf[255];
    ddex_dds  *p_dds;
   
    p_dds = dds_dir[port_num];
    log.err.error_id = err_id;
   
    if (port_num = BAD_STATE) {
            sprintf(log.err.resource_name, "%s :%d",
              p_dds->dds_vpd.adpt_name, data1);
            data1 = 0;
    }
   
   
 else
                sprintf(log.err.resource_name,"%s",p_dds->dds_vpd.devname);
    
        sprintf(errbuf, "line: %d file: %s", line, file);
        strncpy(log.file, errbuf, (size_t)sizeof(log.file));
     
        log.data1 = data1;
        log.data2 = data2;
    
        errsave(&log, (uint)sizeof(dderr));   /* run actual logging  */
}  /* end errlog_ex */
The data to be passed to the errsave kernel service is defined in the dderr structure, which is defined in a local header file, dderr.h. The definition for dderr is:

typedef struct dderr {
        struct  err_rec0 err;
        int  data1;     /* use data1 and data2 to show detail  */
        int  data2;     /* data in the errlog report. Define   */
                        /* these fields in the errlog template */
                        /* These fields may not be used in all */
                        /* cases.                              */
} dderr;

The first field of the dderr.h header file is comprised of the err_rec0 structure, which is defined in the sys/err_rec.h header file. This structure contains the ID (or label) and a field for the resource name. The two data fields hold the detail data for the error log report. As an alternative, you could simply list the fields within the function.

You can also log a message into the error log from the command line. To do this, use the errlogger command.

Errors can be logged from applications using the errlog subroutine.
Note: Care must be taken when logging a data structure, because error logging does not support padding done by the compiler.
Consider the following data structure:

struct {
       struct err_rec0 err;
       long data;
} myerr;

Because err_rec0 is 20 bytes in length, 0x14 bytes, the compiler normally inserts 4 bytes of padding before data, when compiling in 64-bit mode. The structure then looks like the following:


struct {
       struct err_rec0 err;
       int padding;
       long data;       /* 64 bits of data, 64-bit aligned */
} myerr;

Thus the Detail_Data item in the template begins formatting at the padding data item rather than at data.

This can be overcome, if you use the Xlc compiler as follows:

#pragma options align=packed
struct {
       struct err_rec0 err;
       long data;
} myerr;
#pragma options align=reset
After you add the templates using the errupdate command, compile the device driver code along with the new header file. Simulate the error and verify that it was written to the error log correctly. Some details to check for include:
  • Is the error demon running? This can be verified by running the ps -ef command and checking for /usr/lib/errdemon as part of the output.
  • Is the error part of the error template repository? Verify this by running the errpt -at command.
  • Was the new header file, which was created by the errupdate command and which contains the error label and unique error identification number, included in the device driver code when it was compiled?