/*
*****************************************************************************
* *
* (C) Copyright 2007 Hewlett-Packard Development Company, L.P *
* *
* 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 the Free*
* Software Foundation; either version 2 of the License, or (at your option)*
* any later version. *
* *
* This program is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY*
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
* for more details. *
* *
* You should have received a copy of the GNU General Public License along *
* with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
*****************************************************************************
*/
/*
* This program originally derived from and inspired by
* Christophe Varoqui's tur.c, part of libchecker.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include "checkers.h"
#include "cciss.h"
#define TUR_CMD_LEN 6
#define HEAVY_CHECK_COUNT 10
struct cciss_tur_checker_context {
void * dummy;
};
int libcheck_init (__attribute__((unused)) struct checker * c)
{
return 0;
}
void libcheck_free (__attribute__((unused)) struct checker * c)
{
return;
}
int libcheck_check(struct checker * c)
{
int rc;
int ret;
unsigned int lun = 0;
struct cciss_tur_checker_context * ctxt = NULL;
LogvolInfo_struct lvi; // logical "volume" info
IOCTL_Command_struct cic; // cciss ioctl command
if ((c->fd) < 0) {
c->msgid = CHECKER_MSGID_NO_FD;
ret = -1;
goto out;
}
rc = ioctl(c->fd, CCISS_GETLUNINFO, &lvi);
if ( rc != 0) {
perror("Error: ");
fprintf(stderr, "cciss TUR failed in CCISS_GETLUNINFO: %s\n",
strerror(errno));
c->msgid = CHECKER_MSGID_DOWN;
ret = PATH_DOWN;
goto out;
} else {
lun = lvi.LunID;
}
memset(&cic, 0, sizeof(cic));
cic.LUN_info.LogDev.VolId = lun & 0x3FFFFFFF;
cic.LUN_info.LogDev.Mode = 0x01; /* logical volume addressing */
cic.Request.CDBLen = 6; /* need to try just 2 bytes here */
cic.Request.Type.Type = TYPE_CMD; // It is a command.
cic.Request.Type.Attribute = ATTR_SIMPLE;
cic.Request.Type.Direction = XFER_NONE;
cic.Request.Timeout = 0;
cic.Request.CDB[0] = 0;
cic.Request.CDB[1] = 0;
cic.Request.CDB[2] = 0;
cic.Request.CDB[3] = 0;
cic.Request.CDB[4] = 0;
cic.Request.CDB[5] = 0;
rc = ioctl(c->fd, CCISS_PASSTHRU, &cic);
if (rc < 0) {
fprintf(stderr, "cciss TUR failed: %s\n",
strerror(errno));
c->msgid = CHECKER_MSGID_DOWN;
ret = PATH_DOWN;
goto out;
}
if ((cic.error_info.CommandStatus | cic.error_info.ScsiStatus )) {
c->msgid = CHECKER_MSGID_DOWN;
ret = PATH_DOWN;
goto out;
}
c->msgid = CHECKER_MSGID_UP;
ret = PATH_UP;
out:
/*
* caller told us he doesn't want to keep the context :
* free it
*/
if (!c->context)
free(ctxt);
return(ret);
}