Wednesday, September 14, 2011

run MegaCli under Linux kernel 3.0 with LD_PRELOAD a fake uname


the MegaCli tool seems doesn't recognize the kernel 3.0; even the latest 8.02.16_MegaCLI
http://www.lsi.com/products/storagecomponents/Pages/MegaRAIDSAS9240-8i.aspx#misc

Since lsi only provides its binary, we cannot know what is lsi internally doing, what we can do is only to strace it,

Gentoo-11 tmp # env -i strace -v -e execve,open,ioctl,uname ./opt/MegaRAID/MegaCli/MegaCli64 -adpCount
execve("./opt/MegaRAID/MegaCli/MegaCli64", ["./opt/MegaRAID/MegaCli/MegaCli64", "-adpCount"], []) = 0
open("/etc/ld.so.cache", O_RDONLY)      = 3
open("/lib64/libpthread.so.0", O_RDONLY) = 3
open("/lib64/libncurses.so.5", O_RDONLY) = 3
open("/lib64/libdl.so.2", O_RDONLY)     = 3
open("/usr/lib/gcc/x86_64-pc-linux-gnu/4.5.2/libstdc++.so.6", O_RDONLY) = 3
open("/lib64/libm.so.6", O_RDONLY)      = 3
open("/lib64/libgcc_s.so.1", O_RDONLY)  = 3
open("/lib64/libc.so.6", O_RDONLY)      = 3
                                     
open("/proc/devices", O_RDONLY)         = 3
open("/dev/megaraid_sas_ioctl_node", O_RDONLY) = 3
open("/proc/devices", O_RDONLY)         = 4
uname({sysname="Linux", nodename="Gentoo-11", release="3.0.0-gentoo-r1", version="#1 SMP Mon Aug 1 02:33:28 UTC 2011", machine="x86_64"}) = 0
open("/proc/scsi/megaraid_sas/hba_map/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
open("/proc/scsi/megasr/hba_map/", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
ioctl(3, MCE_GET_RECORD_LEN or MEMGETINFO or MFB_SET_CHROMA_KEY or MTRRIOC32_SET_ENTRY or MTRRIOC_SET_ENTRY, 0x790880) = -1 ENODEV (No such device)

Controller Count: 0.
open("MegaSAS.log", O_WRONLY|O_CREAT|O_APPEND, 0666) = 4

Exit Code: 0x00
open("MegaSAS.log", O_WRONLY|O_CREAT|O_APPEND, 0666) = 4

we found it tried a uname to get system info, then try to read the driver's proc file "/proc/scsi/megaraid_sas/hba_map/", but the current system has megaraid_sas driver but doesn't provide that proc file; through searching online I found that proc file was provided by a megaraid legacy driver in Linux-2.4 kernel, so the problem is probably here, the MegaCli doesn't recognize the kernel release "3.0.0-gentoo-r1" from uname system call, and judged it as Linux-2.4; dam it;

What I clearly remember is several months ago in last Gentoo-11.1 livedvd (surely with linux kernel 2.6) the MegaCli was still working, so the following is how can we fool MegaCli's uname system call as Linux kernel 2.6?

The answer is to fake a uname syscall via LD_PRELOAD;

Gentoo-11 tmp # cat fake-uname.c
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/utsname.h>

#include <stdio.h>
#include <string.h>

int uname(struct utsname *buf)
{
 int ret;

 ret = syscall(SYS_uname, buf);

 printf("uname release: \"%s\"\n", buf->release);
 strcpy(buf->release, "2.6.40");
 printf("uname release set to: \"%s\"\n", buf->release);
 printf("uname version: \"%s\"\n", buf->version);

 return ret;
}

Save it as fake-uname.c, and compile it with

Gentoo-11 tmp # gcc -Wall -fPIC -c fake-uname.c
Gentoo-11 tmp # gcc -Wall -shared -o libfake-uname.so fake-uname.o

Now we get libfake-uname.so, use LD_PRELOAD=./libfake-uname.so to preload it, over uname from glibc:

Gentoo-11 tmp # LD_PRELOAD=./libfake-uname.so LD_LIBRARY_PATH=./opt/lsi/3rdpartylibs/x86_64 ./opt/MegaRAID/MegaCli/MegaCli64 -adpCount
                                     
uname release: "3.0.0-gentoo-r1"
uname release set to: "2.6.40"
uname version: "#1 SMP Mon Aug 1 02:33:28 UTC 2011"

Controller Count: 1.

Exit Code: 0x01

Found the controller! And the strace log:
...
open("/lib64/libc.so.6", O_RDONLY)      = 3
                                     
open("/proc/devices", O_RDONLY)         = 3
open("/dev/megaraid_sas_ioctl_node", O_RDONLY) = 3
open("/proc/devices", O_RDONLY)         = 4
uname({sysname="Linux", nodename="Gentoo-11", release="3.0.0-gentoo-r1", version="#1 SMP Mon Aug 1 02:33:28 UTC 2011", machine="x86_64"}) = 0
uname release: "3.0.0-gentoo-r1"
uname release set to: "2.6.40"
uname version: "#1 SMP Mon Aug 1 02:33:28 UTC 2011"
open("./opt/lsi/3rdpartylibs/x86_64/tls/x86_64/libsysfs.so.2.0.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("./opt/lsi/3rdpartylibs/x86_64/tls/libsysfs.so.2.0.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("./opt/lsi/3rdpartylibs/x86_64/x86_64/libsysfs.so.2.0.2", O_RDONLY) = -1 ENOENT (No such file or directory)
open("./opt/lsi/3rdpartylibs/x86_64/libsysfs.so.2.0.2", O_RDONLY) = 4
open("/sys/class/scsi_host", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
open("/sys/class/scsi_host", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 4
open("/sys/devices/pci0000:00/0000:00:1f.2/host0/scsi_host/host0/proc_name", O_RDONLY) = 4
open("/sys/devices/pci0000:00/0000:00:1f.2/host1/scsi_host/host1/proc_name", O_RDONLY) = 4
open("/sys/devices/pci0000:00/0000:00:1f.2/host2/scsi_host/host2/proc_name", O_RDONLY) = 4
open("/sys/devices/pci0000:00/0000:00:1f.2/host3/scsi_host/host3/proc_name", O_RDONLY) = 4
open("/sys/devices/pci0000:00/0000:00:1f.1/host4/scsi_host/host4/proc_name", O_RDONLY) = 4
open("/sys/devices/pci0000:00/0000:00:1f.1/host5/scsi_host/host5/proc_name", O_RDONLY) = 4
open("/sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/host7/scsi_host/host7/proc_name", O_RDONLY) = 4
ioctl(3, MCE_GET_RECORD_LEN or MEMGETINFO or MFB_SET_CHROMA_KEY or MTRRIOC32_SET_ENTRY or MTRRIOC_SET_ENTRY, 0x790420) = 0

Controller Count: 1.
open("MegaSAS.log", O_WRONLY|O_CREAT|O_APPEND, 0666) = 4

Exit Code: 0x01
open("MegaSAS.log", O_WRONLY|O_CREAT|O_APPEND, 0666) = 4

1 comment:

Guimli said...

Thanks for this trick.
My Megaraid is Alive !