diff -Nur mpt-status-1.2.0-RC6/doc/Changelog mpt-status-1.2.0-RC7/doc/Changelog --- mpt-status-1.2.0-RC6/doc/Changelog 2006-04-24 19:29:45.000000000 +0200 +++ mpt-status-1.2.0-RC7/doc/Changelog 2006-05-02 19:42:29.000000000 +0200 @@ -1,3 +1,17 @@ +2006-04-20- +2006-05-02, ratz [ratz@drugphish.ch]: + * Version: 1.2.0-RC6 (not released), after 3 almost complete rewrites + too many changes happened in between the last two weeks to + list them properly. Kernel header sanitizing might not be + possible after all. + + o mpt-status.c + - proper support for 64-bit nodes + - added support for spare disk information + - added preliminary support for the sync percentage information + o doc/TODO + - updated + 2006-04-20, ratz [ratz@drugphish.ch]: o mpt-status.c - reworked physical disk section diff -Nur mpt-status-1.2.0-RC6/doc/DeveloperNotes mpt-status-1.2.0-RC7/doc/DeveloperNotes --- mpt-status-1.2.0-RC6/doc/DeveloperNotes 2006-05-01 22:54:25.000000000 +0200 +++ mpt-status-1.2.0-RC7/doc/DeveloperNotes 2006-05-02 19:47:30.000000000 +0200 @@ -128,3 +128,6 @@ "$@"; } +After having diffed the 2.4.x and 2.6.x kernel trees with regard to the MPT, +I'm quite convinved that a kernel header sanitation will not work in the end. + diff -Nur mpt-status-1.2.0-RC6/doc/INSTALL mpt-status-1.2.0-RC7/doc/INSTALL --- mpt-status-1.2.0-RC6/doc/INSTALL 2006-04-24 19:29:45.000000000 +0200 +++ mpt-status-1.2.0-RC7/doc/INSTALL 2006-05-02 19:59:09.000000000 +0200 @@ -9,9 +9,15 @@ make KERNEL_PATH=/path/to/your/kernel/src If this does not work, send me (Roberto Nibali) an email with the output and I -try to fix it. You might also need to minor tweak the Makefile shipped with this +try to fix it. You might also need to tweak the Makefile shipped with this package. +IMPORTANT: Try to compile mpt-status on a machine with the same kernel headers + on which kernel version the resulting mpt-status binary will run on. + If you compile mpt-status with 2.6.x headers and deploy the binary + on a 2.4.x kernel based system, it might be that the tool will try + to fetch the wrong pages and this can result in major havoc! + How can I install mpt-status ---------------------------- diff -Nur mpt-status-1.2.0-RC6/doc/README mpt-status-1.2.0-RC7/doc/README --- mpt-status-1.2.0-RC6/doc/README 2006-04-24 19:29:45.000000000 +0200 +++ mpt-status-1.2.0-RC7/doc/README 2006-05-02 19:54:56.000000000 +0200 @@ -1,7 +1,7 @@ About ----- The mpt-status software is a query tool to access the running configuration and -status of LSI SCSI HBAs. This is a heavily modified version of the original +status of LSI SCSI HBAs. This is a completely rewritten version of the original mpt-status-1.0 tool written by Matt Braithwaite. mpt-status allows you to monitor the health and status of your RAID setup. @@ -42,7 +42,9 @@ Turbolinux I have provided spec (for RPM) files for OpenSuSE and Red Hat, however they are -mostly untested. Have a look into the contrib sub directory. +mostly untested. Have a look into the contrib sub directory. I also opened a +bug report at OpenSuSE, however was redirected to add it to the wishlist, which +I'm most certainly not going to do. How can I compile, install or uninstall mpt-status? @@ -89,6 +91,20 @@ phys_id 1 ONLINE phys_id 0 ONLINE +A new style output has made it into the sources, however due to backwards +compatibility reasons it's not on per default. You can enable the new style +output by invoking mpt-status as follows: + + mpt-status --newstyle + +There is also a debug mode since the mpt-status-1.2.0 release. It can be set +either by the old style parameter passing or via following call: + + MPT_STATUS_DEBUG=1 mpt-status + +This will enable the debug engine inside mpt-status with debug level 1. + + Hardware, Software and Distribution Compatibility ------------------------------------------------- The mpt-status software is known and reported to compile and work on following @@ -104,8 +120,8 @@ Architectures: i386 -x86_64 (currently broken for some systems, EMT64 works) -ultra sparc (only compilation) +x86_64 +Ultra Sparc (only compilation) List of Hardware configuration diff -Nur mpt-status-1.2.0-RC6/doc/TODO mpt-status-1.2.0-RC7/doc/TODO --- mpt-status-1.2.0-RC6/doc/TODO 2006-04-24 19:29:45.000000000 +0200 +++ mpt-status-1.2.0-RC7/doc/TODO 2006-05-02 19:29:05.000000000 +0200 @@ -1,17 +1,17 @@ This file is a wishlist compiled out of various people's ideas. It should eventually be prioritized into "important, normal, nice to have". - -Ratz' ideas ------------ o find out the remaining pieces of magic around the kernel structs and document them accordingly o get in contact with LSI for feedback and support -o support for spare disk status output -o sanitize kernel headers and remove the __user and __kernel stuff -o test 64bit - +o check if there is really the need for other RAID types and add support for + them. A diff from the 2.4.x to the 2.6.x kernel in this header: -User requests -------------- -o [Klaus Ade Johnstad] add raid status line of sync process, like /proc/mdstat + #define MPI_RAID_VOL_TYPE_IS (0x00) + #define MPI_RAID_VOL_TYPE_IME (0x01) + #define MPI_RAID_VOL_TYPE_IM (0x02) ++#define MPI_RAID_VOL_TYPE_RAID_5 (0x03) ++#define MPI_RAID_VOL_TYPE_RAID_6 (0x04) ++#define MPI_RAID_VOL_TYPE_RAID_10 (0x05) ++#define MPI_RAID_VOL_TYPE_RAID_50 (0x06) ++#define MPI_RAID_VOL_TYPE_UNKNOWN (0xFF) diff -Nur mpt-status-1.2.0-RC6/Makefile mpt-status-1.2.0-RC7/Makefile --- mpt-status-1.2.0-RC6/Makefile 2006-04-25 20:55:58.000000000 +0200 +++ mpt-status-1.2.0-RC7/Makefile 2006-05-02 20:01:54.000000000 +0200 @@ -2,7 +2,7 @@ PREFIX := /usr KERNEL_PATH := /usr/src/linux CFLAGS := -Iincl -Wall -W -O2 -I${KERNEL_PATH}/drivers/message/fusion -DFLAGS := -DNEWSTYLE #-DSANITIZED_KERNEL_HEADERS +DFLAGS := #-DSANITIZED_KERNEL_HEADERS LDFLAGS := DESTDIR := CC := gcc @@ -13,10 +13,6 @@ CFLAGS := -Iincl -Wall -W -O2 -m64 -pipe \ -mcpu=ultrasparc -mcmodel=medlow endif -# This part is for the 1.2.0 version of mpt-status -#ifeq "${ARCH}" "x86_64" -# CFLAGS := -Iincl -Wall -W -O2 -m64 -I${KERNEL_PATH}/drivers/message/fusion -#endif ${PROG}: ${PROG}.c ${PROG}.h ${CC} ${DFLAGS} ${CFLAGS} -o $@ $< ${LDFLAGS} diff -Nur mpt-status-1.2.0-RC6/mpt-status.c mpt-status-1.2.0-RC7/mpt-status.c --- mpt-status-1.2.0-RC6/mpt-status.c 2006-05-02 18:50:45.000000000 +0200 +++ mpt-status-1.2.0-RC7/mpt-status.c 2006-05-11 21:39:00.000000000 +0200 @@ -5,6 +5,7 @@ Copyright (C) 2004 CNET Networks, Inc. Copyright (C) 2005-2006 Roberto Nibali +Copyright (C) 2006 by LSI Logic This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -50,6 +51,7 @@ static int id_of_primary_device = 0; static int ioc_unit = 0; static int newstyle = 0; +static int sync_state[2] = { 0, 0 }; static int sel; static const struct option long_options[] = { @@ -66,7 +68,7 @@ { "version", no_argument, NULL, 'V' }, { 0, no_argument, NULL, 0 }, }; -static const char* const short_options = "d:hi:pqsu:vV"; +static const char* const short_options = "d:hi:npqsu:vV"; static const char* const usage_template = "Usage: %s [ options ]\n" "\n" @@ -135,6 +137,7 @@ static void GetVolumeInfo(void); static void GetPhysDiskInfo(RaidVol0PhysDisk_t *, int); static void GetHotSpareInfo(void); +static void GetResyncPercentageSilent(RaidVol0PhysDisk_t *, unsigned char *, int); static void GetResyncPercentage(RaidVol0PhysDisk_t *, unsigned char *, int); static void do_init(void); /* internal-functions declaration */ @@ -276,7 +279,7 @@ int result; va_list ap; - if (debug) + if (!debug) return 0; /* debug_level is also set at this point */ va_start(ap, format); @@ -325,10 +328,7 @@ ConfigRequest->PageAddress = scsi_id; status = read_page2(MPT_FLAGS_KEEP_MEM); - if (status != 0) { - freeMem(); - return -1; - } else if (pReply->Header.PageLength == 0) { + if (status != 0 || pReply->Header.PageLength == 0) { freeMem(); return -1; } @@ -338,7 +338,6 @@ freeMem(); return -1; } - ConfigRequest->Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ConfigRequest->Header.PageVersion = pReply->Header.PageVersion; ConfigRequest->Header.PageLength = pReply->Header.PageLength; @@ -377,11 +376,9 @@ status = 0; } } - if ((flags & MPT_FLAGS_KEEP_MEM) == 0) { freeMem(); } - return status; } @@ -394,7 +391,7 @@ unsigned char pdisk_vol[16]; uint numBytes; int status; - int ii, id; + int i, id; int pdisk_cnt = 0; unsigned bus = id_of_primary_device; @@ -424,16 +421,10 @@ ConfigRequest->PageAddress = bus; status = read_page2(MPT_FLAGS_KEEP_MEM); - if (status != 0) { - printf("Logical Volume Information: unsupported\n"); - freeMem(); - return; - } else if (pReply->Header.PageLength == 0) { - printf("Logical Volume Information: none\n"); + if (status != 0 || pReply->Header.PageLength == 0) { freeMem(); return; } - mpiBlkPtr->dataInSize = pReply->Header.PageLength * 4; if (allocDataFrame(DATA_DIR_IN)) { mpt_printf("Increase data buffer size"); @@ -460,10 +451,10 @@ } else { __print_volume_advanced(pRVP0); } - for (ii = pdisk_cnt; ii < pdisk_cnt + pRVP0->NumPhysDisks; ii++) { - disk_num[ii].PhysDiskNum = pRVP0->PhysDisk[ii].PhysDiskNum; - disk_num[ii].PhysDiskMap = pRVP0->PhysDisk[ii].PhysDiskMap; - pdisk_vol[ii] = pRVP0->VolumeID; + for (i = pdisk_cnt; i < pdisk_cnt + pRVP0->NumPhysDisks; i++) { + disk_num[i].PhysDiskNum = pRVP0->PhysDisk[i].PhysDiskNum; + disk_num[i].PhysDiskMap = pRVP0->PhysDisk[i].PhysDiskMap; + pdisk_vol[i] = pRVP0->VolumeID; } pdisk_cnt += pRVP0->NumPhysDisks; } else if (pRVP0->NumPhysDisks == 0) { @@ -471,6 +462,11 @@ mpt_exit(MPT_EXIT_UNKNOWN); } freeMem(); + /* this should be woven into the GetPhysDiskInfo part correctly */ + if (newstyle) /* && resync_on) */ { + GetResyncPercentageSilent((RaidVol0PhysDisk_t *) &disk_num, + (unsigned char *) &pdisk_vol, pdisk_cnt); + } if (pdisk_cnt > 0) { GetPhysDiskInfo((RaidVol0PhysDisk_t *) &disk_num, pdisk_cnt); } @@ -491,7 +487,7 @@ ConfigReply_t *pReply = NULL; uint numBytes; int status; - int ii; + int i; numBytes = (sizeof(Config_t) - sizeof(SGE_IO_UNION)) + sizeof (SGESimple64_t); if ((mpiBlkPtr = allocIoctlBlk(numBytes)) == NULL) @@ -523,8 +519,8 @@ ConfigRequest->Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ConfigRequest->Header.PageVersion = pReply->Header.PageVersion; ConfigRequest->Header.PageLength = pReply->Header.PageLength; - for (ii = 0; ii < count; ii++){ - ConfigRequest->PageAddress = cpu_to_le32((uint)pDisk[ii].PhysDiskNum); + for (i = 0; i < count; i++){ + ConfigRequest->PageAddress = cpu_to_le32((uint)pDisk[i].PhysDiskNum); status = read_page2(MPT_FLAGS_KEEP_MEM); if (status == 0) { @@ -570,23 +566,16 @@ ConfigRequest->PageAddress = 0; status = read_page2(MPT_FLAGS_KEEP_MEM); - if (status != 0) { - printf("\tUnsupported.\n"); - freeMem(); - return; - } else if (pReply->Header.PageLength == 0 ) { - printf("\tNone.\n"); + if (status != 0 || pReply->Header.PageLength == 0) { freeMem(); return; } - mpiBlkPtr->dataInSize = pReply->Header.PageLength * 4; if (allocDataFrame(DATA_DIR_IN)) { mpt_printf("Increase data buffer size"); freeMem(); return; } - ConfigRequest->Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ConfigRequest->Header.PageVersion = pReply->Header.PageVersion; ConfigRequest->Header.PageLength = pReply->Header.PageLength; @@ -598,24 +587,22 @@ { // Get Phys Disk Information Ioc5HotSpare_t disk_num[num_spares]; - unsigned int ii; + unsigned int i; - for (ii = 0; ii < num_spares; ii++) { - disk_num[ii].PhysDiskNum = pPg5->HotSpare[ii].PhysDiskNum; - disk_num[ii].HotSparePool = pPg5->HotSpare[ii].HotSparePool; + for (i = 0; i < num_spares; i++) { + disk_num[i].PhysDiskNum = pPg5->HotSpare[i].PhysDiskNum; + disk_num[i].HotSparePool = pPg5->HotSpare[i].HotSparePool; } - - freeMem(); /* Do not reference pPg5 any more */ - - numBytes = (sizeof(Config_t) - sizeof(SGE_IO_UNION)) + sizeof (SGESimple64_t); + freeMem(); /* Do not reference pPg5 any more */ + numBytes = (sizeof(Config_t) - sizeof(SGE_IO_UNION)) + + sizeof (SGESimple64_t); if ((mpiBlkPtr = allocIoctlBlk(numBytes)) == NULL) return; - ConfigRequest = (Config_t *) mpiBlkPtr->MF; mpiBlkPtr->dataInSize = mpiBlkPtr->dataOutSize = 0; mpiBlkPtr->dataInBufPtr = mpiBlkPtr->dataOutBufPtr = NULL; - mpiBlkPtr->dataSgeOffset = (sizeof (Config_t) - sizeof(SGE_IO_UNION))/4; - + mpiBlkPtr->dataSgeOffset = (sizeof (Config_t) + - sizeof(SGE_IO_UNION))/4; pReply = (ConfigReply_t *)mpiBlkPtr->replyFrameBufPtr; ConfigRequest->Action = MPI_CONFIG_ACTION_PAGE_HEADER; @@ -637,24 +624,63 @@ ConfigRequest->Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; ConfigRequest->Header.PageVersion = pReply->Header.PageVersion; ConfigRequest->Header.PageLength = pReply->Header.PageLength; - for (ii = 0; ii < num_spares; ii++){ - ConfigRequest->PageAddress = cpu_to_le32((uint)disk_num[ii].PhysDiskNum); + for (i = 0; i < num_spares; i++){ + ConfigRequest->PageAddress = cpu_to_le32((uint)disk_num[i].PhysDiskNum); status = read_page2(MPT_FLAGS_KEEP_MEM); if (status == 0) { RaidPhysDiskPage0_t *pRPD0 = (RaidPhysDiskPage0_t *) mpiBlkPtr->dataInBufPtr; __print_physdisk_advanced(pRPD0, 1); - } else { - //printf("\t\tNot Available.\n"); } } } - /* - } else if (status == 0) { - printf("Not Available.\n"); - } else { - printf("No Hot Spare Disks.\n"); - */ + } + freeMem(); + return; +} + +static void GetResyncPercentageSilent(RaidVol0PhysDisk_t *pDisk, unsigned char *pVol, int count) { + MpiRaidActionRequest_t *pRequest; + uint blks_done; + uint numBytes; + int i; + uint tot_blks, blks_left; + int status; + + numBytes = (sizeof(MpiRaidActionRequest_t) - sizeof(SGE_IO_UNION)) + + sizeof (SGESimple64_t); + if ((mpiBlkPtr = allocIoctlBlk(numBytes)) == NULL) + return; + pRequest = (MpiRaidActionRequest_t *) mpiBlkPtr->MF; + mpiBlkPtr->dataSgeOffset = (sizeof (MpiRaidActionRequest_t) + - sizeof(SGE_IO_UNION))/4; + mpiBlkPtr->dataInSize = mpiBlkPtr->dataOutSize = 0; + pRequest->Action = MPI_RAID_ACTION_INDICATOR_STRUCT; + pRequest->Function = MPI_FUNCTION_RAID_ACTION; + pRequest->MsgContext = -1; + pRequest->ActionDataWord = 0; /* action data is 0 */ + for (i = 0; i < count; i++) { + pRequest->VolumeID = (u8) pVol[i]; + pRequest->PhysDiskNum = pDisk[i].PhysDiskNum; + status = read_page2(MPT_FLAGS_KEEP_MEM); + if (status == 0) { + // pDisk[i].PhysDiskNum == scsi_id + uint *pdata = (uint *) mpiBlkPtr->replyFrameBufPtr; + pdata += 6; + tot_blks = *pdata; + pdata++; + pdata++; + blks_left = *pdata; + pdata++; + blks_done = tot_blks - blks_left; + //mpt_printf("scsi_id:%d", pDisk[i].PhysDiskNum); + if (blks_left == 0) { + sync_state[pDisk[i].PhysDiskNum%2] = 100; + } else { + sync_state[pDisk[i].PhysDiskNum%2] = + ((blks_done >> 6)*100)/(tot_blks >> 6); + } + } } freeMem(); return; @@ -664,7 +690,7 @@ MpiRaidActionRequest_t *pRequest; uint blks_done; uint numBytes; - int ii; + int i; uint tot_blks, blks_left; int status; @@ -684,13 +710,12 @@ pRequest->MsgContext = -1; pRequest->ActionDataWord = 0; /* action data is 0 */ - for (ii = 0; ii < count; ii++ ) { - pRequest->VolumeID = (u8) pVol[ii]; - pRequest->PhysDiskNum = pDisk[ii].PhysDiskNum; - + for (i = 0; i < count; i++ ) { + pRequest->VolumeID = (u8) pVol[i]; + pRequest->PhysDiskNum = pDisk[i].PhysDiskNum; status = read_page2(MPT_FLAGS_KEEP_MEM); if (status == 0) { - // pDisk[ii].PhysDiskNum == scsi_id + // pDisk[i].PhysDiskNum == scsi_id uint *pdata = (uint *) mpiBlkPtr->replyFrameBufPtr; mpt_debug("DEBUG: *pdata=%d\n", *pdata); pdata += 6; @@ -702,7 +727,7 @@ mpt_debug("DEBUG: blks_left=%d\n", blks_left); pdata++; blks_done = tot_blks - blks_left; - mpt_printf("scsi_id:%d", pDisk[ii].PhysDiskNum); + mpt_printf("scsi_id:%d", pDisk[i].PhysDiskNum); if (blks_left == 0) { mpt_printf(" 100%%\n"); } else { @@ -766,7 +791,30 @@ mpt_printf(" NONE"); } } - mpt_printf("\n"); + /* since mpt_printf() returns without output when quiet mode is enabled + we need to explicitly write that CR + */ + printf("\n"); + /* + CONFIG_PAGE_HEADER Header; // 00h + U8 VolumeID; // 04h + U8 VolumeBus; // 05h + U8 VolumeIOC; // 06h + U8 VolumeType; // 07h + RAID_VOL0_STATUS VolumeStatus; // 08h + RAID_VOL0_SETTINGS VolumeSettings; // 0Ch + U32 MaxLBA; // 10h + U32 Reserved1; // 14h + U32 StripeSize; // 18h + U32 Reserved2; // 1Ch + U32 Reserved3; // 20h + U8 NumPhysDisks; // 24h + U8 DataScrubRate; // 25h + U8 ResyncRate; // 26h + U8 InactiveStatus; // 27h + RAID_VOL0_PHYS_DISK PhysDisk[MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX]; + */ + //mpt_debug(VolumeID); } static void __print_volume_classic(RaidVolumePage0_t *page) { @@ -819,7 +867,10 @@ mpt_printf(" NONE"); } } - mpt_printf("\n"); + /* since mpt_printf() returns without output when quiet mode is enabled + we need to explicitly write that CR + */ + printf("\n"); } static void __print_physdisk_advanced(RaidPhysDiskPage0_t *phys, int spare) { @@ -902,7 +953,15 @@ mpt_printf(" NONE"); } /* SYNC RATE */ - mpt_printf(" sync_state: "); + //mpt_printf(" sync_state: %d%%", GetResyncPercentageDisk(phys)); + /* this is such a gross hack it's almost unbelieveable ... + it will be fixed in the next release */ + if (spare != 1) { + mpt_printf(" sync_state: %d", + sync_state[phys->PhysDiskID%2]); + } else { + mpt_printf(" sync_state: n/a"); + } /* ASC/ASCQ information */ mpt_printf(" ASC/ASCQ:0x%02x/0x%02x SMART ASC/ASCQ:0x%02x/0x%02x", phys->ErrorData.ErrorASC, @@ -910,7 +969,10 @@ phys->ErrorData.SmartASC, phys->ErrorData.SmartASCQ); } - mpt_printf("\n"); + /* since mpt_printf() returns without output when quiet mode is enabled + we need to explicitly write that CR + */ + printf("\n"); } static void __print_physdisk_classic(RaidPhysDiskPage0_t *phys) { @@ -992,7 +1054,10 @@ mpt_printf(" NONE"); } } - mpt_printf("\n"); + /* since mpt_printf() returns without output when quiet mode is enabled + we need to explicitly write that CR + */ + printf("\n"); } static void do_init(void) { diff -Nur mpt-status-1.2.0-RC6/mpt-status.h mpt-status-1.2.0-RC7/mpt-status.h --- mpt-status-1.2.0-RC6/mpt-status.h 2006-05-01 23:33:35.000000000 +0200 +++ mpt-status-1.2.0-RC7/mpt-status.h 2006-05-02 18:53:57.000000000 +0200 @@ -26,7 +26,7 @@ #include "mptctl.h" #endif // SANITIZED_KERNEL_HEADERS -#define VERSION "1.2.0-RC6" +#define VERSION "1.2.0-RC7" #define BIG 1024 #define REALLYBIG 10240