How to map ataX.0 identifiers in kern.log error messages to actual /dev/sdY devices?

You can find the corresponding /dev/sdY device via traversing the /sys tree:

$ find /sys/devices | grep '/ata[0-9]\+/.*/block/s[^/]\+$' \
    | sed 's@^.\+/\(ata[0-9]\+\)/.\+/block/\(.\+\)$@\1 => /dev/\2@'

With a more efficient /sys traversal (cf. lsata.sh):

$ echo /sys/class/ata_port/ata*/../../host*/target*/*/block/s* | tr ' ' '\n' \
    | awk -F/ '{printf("%s => /dev/%s\n", $5, $NF)}'

Example output from a 2 disk system:

ata1 => /dev/sda
ata2 => /dev/sdb

Then, for reliably identifying the actual hardware you need to map /dev/sdY to the serial number, e.g.:

$ ls /dev/disk/by-id -l | grep 'ata.*sd[a-zA-Z]$'

lssci

The lssci utility can also be used to derive the mapping:

$ lsscsi | sed 's@^\[\([^:]\+\).\+\(/dev/.\+\)$@\1,\2@' \
    | awk -F, '{ printf("ata%d => %s\n", $1+1, $2) }'

Note that the relevant lsscsi enumeration starts from 0 while the ata enumeration starts from 0.

Syslog

If nothing else works one can look at the syslog/journal to derive the mapping.

The /dev/sdY devices are created in the same order as the ataX identifiers are enumerated in the kern.log while ignoring non-disk devices (ATAPI) and not-connected links.

Thus, following command displays the mapping:

$ grep '^May 28 2'  /var/log/kern.log.0  | \
   grep 'ata[0-9]\+.[0-9][0-9]: ATA-' | \
   sed 's/^.*\] ata//' | \
   sort -n | sed 's/:.*//' | \
   awk ' { a="ata" $1; printf("%10s is /dev/sd%c\n", a, 96+NR); }'
ata1.00 is /dev/sda
ata3.00 is /dev/sdb
ata5.00 is /dev/sdc
ata7.00 is /dev/sdd
ata8.00 is /dev/sde
ata10.00 is /dev/sdf

(Note that ata4 is not displayed because the above log messages are from another system.)

I am using /var/log/kern.log.0 and not /var/log/kern.log because the boot messages are already rotated. I grep for May 28 2 because this was the last boot time and I want to ignore previous messages.

To verify the mapping you can do some checks via looking at the output of:

$ grep '^May 28 2'  /var/log/kern.log.0  | \
grep 'ata[0-9]\+.[0-9][0-9]: ATA-'
May 28 20:43:26 hn kernel: [    1.260488] ata1.00: ATA-7: SAMSUNG SV0802N, max UDMA/100
May 28 20:43:26 hn kernel: [    1.676400] ata5.00: ATA-5: ST380021A, 3.19, max UDMA/10
[..]

And you can compare this output with hdparm output, e.g.:

$ hdparm -i /dev/sda

/dev/sda:

Model=SAMSUNG SV0802N [..]

(using Kernel 2.6.32-31)


Here's my version, modified from above. Since I don't know the exact date the system was booted (for testing this it was 27 days ago), and I don't know which kern.log contains the data I need (some may be gzipped on my system), I use uptime and date to calculate an approximate system boot date (to the day, anyway), then use zgrep to search through all available kern.log files.

I also slightly modified the second grep statement, since it will now also show an ATAPI CD/DVD drive as well as ATA-* drives.

It could still use refinement (i.e. if system uptime is greater than a year), but should work OK for now.

#!/bin/bash

uptime=$(uptime | awk -F' '  '{ print $3" "$4 }' | sed s/,//)
date=$(date -d "$uptime ago" | awk '{print $2" "$3 }')
zgrep "$date"  /var/log/kern.log*  | \
grep 'ata[0-9]\+.[0-9][0-9]: ATA'  | \
sed 's/^.*\] ata//' | \
sort -n | sed 's/:.*//' | \
awk ' { a="ata" $1; printf("%10s is /dev/sd%c\n", a, 96+NR); }'

Tags:

Linux

Sata