Ticket #1653: os_linux.cpp.diff

File os_linux.cpp.diff, 11.7 KB (added by steven.song, 17 months ago)
  • os_linux.cpp

    diff --git a/os_linux.cpp b/os_linux.cpp
    index aadd93d..dd37b12 100644
    a b  
    7373#include "utility.h"
    7474#include "cciss.h"
    7575#include "megaraid.h"
     76#include "sssraid.h"
    7677#include "aacraid.h"
    7778#include "nvmecmds.h"
    7879
    bool linux_megaraid_device::megadev_cmd(int cdbLen, void *cdb,  
    14991500  return true;
    15001501}
    15011502
     1503/////////////////////////////////////////////////////////////////////////////
     1504/// 3SNIC RAID support
     1505
     1506class linux_sssraid_device
     1507: public /* implements */ scsi_device,
     1508  public /* extends */ linux_smart_device
     1509{
     1510public:
     1511  linux_sssraid_device(smart_interface *intf, const char *name,
     1512    unsigned int eid, unsigned int sid);
     1513
     1514  virtual bool scsi_pass_through(scsi_cmnd_io *iop) override;
     1515
     1516private:
     1517  unsigned int m_eid;
     1518  unsigned int m_sid;
     1519
     1520  bool scsi_cmd(int cdbLen, void *cdb, int dataLen, void *data, int direction);
     1521};
     1522
     1523linux_sssraid_device::linux_sssraid_device(smart_interface *intf,
     1524  const char *dev_name, unsigned int eid, unsigned int sid)
     1525 : smart_device(intf, dev_name, "sssraid", "sssraid"),
     1526   linux_smart_device(O_RDWR | O_NONBLOCK),
     1527   m_eid(eid), m_sid(sid)
     1528{
     1529  set_info().info_name = strprintf("%s [sssraid_disk_%02d_%02d]", dev_name, eid, sid);
     1530  set_info().dev_type = strprintf("sssraid,%d,%d", eid, sid);
     1531}
     1532
     1533bool linux_sssraid_device::scsi_pass_through(scsi_cmnd_io *iop)
     1534{
     1535  int report = scsi_debugmode;
     1536  if (report > 0) {
     1537    int k, j;
     1538    const unsigned char * ucp = iop->cmnd;
     1539    const char * np;
     1540    char buff[256];
     1541    const int sz = (int)sizeof(buff);
     1542
     1543    np = scsi_get_opcode_name(ucp[0]);
     1544    j = snprintf(buff, sz, " [%s: ", np ? np : "<unknown opcode>");
     1545    for (k = 0; k < (int)iop->cmnd_len; ++k)
     1546      j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]);
     1547    if ((report > 1) && (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) {
     1548      int trunc = (iop->dxfer_len > 256) ? 1 : 0;
     1549
     1550      snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n  Outgoing "
     1551              "data, len=%d%s:\n", (int)iop->dxfer_len,
     1552              (trunc ? " [only first 256 bytes shown]" : ""));
     1553      dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
     1554    }
     1555    else
     1556      snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n");
     1557    pout("%s", buff);
     1558  }
     1559
     1560  bool r = scsi_cmd(iop->cmnd_len, iop->cmnd,
     1561          iop->dxfer_len, iop->dxferp, iop->dxfer_dir);
     1562  return r;
     1563}
     1564
     1565/* Issue passthrough scsi commands to sssraid controllers */
     1566bool linux_sssraid_device::scsi_cmd(int cdbLen, void *cdb,
     1567  int dataLen, void *data, int dxfer_dir)
     1568{
     1569  struct sg_io_v4 io_hdr_v4;
     1570  struct cmd_scsi_passthrough scsi_param;
     1571  unsigned char sense_buff[96] = { 0 };
     1572  struct bsg_ioctl_cmd bsg_param;
     1573  memset(&io_hdr_v4, 0, sizeof(io_hdr_v4));
     1574  memset(&scsi_param, 0, sizeof(scsi_param));
     1575  memset(&bsg_param, 0, sizeof(bsg_param));
     1576  scsi_param.sense_buffer = sense_buff;
     1577  scsi_param.sense_buffer_len = 96;
     1578  scsi_param.cdb_len = cdbLen;
     1579  memcpy(scsi_param.cdb, cdb, cdbLen);
     1580  scsi_param.loc.enc_id = m_eid;
     1581  scsi_param.loc.slot_id = m_sid;
     1582
     1583  io_hdr_v4.guard = 'Q';
     1584  io_hdr_v4.protocol = BSG_PROTOCOL_SCSI;
     1585  io_hdr_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_TRANSPORT;
     1586  io_hdr_v4.response = (uintptr_t)sense_buff;
     1587  io_hdr_v4.max_response_len = ADM_SCSI_CDB_SENSE_MAX_LEN;
     1588  io_hdr_v4.request_len = sizeof(struct bsg_ioctl_cmd);
     1589  io_hdr_v4.request = (uintptr_t)(&bsg_param);
     1590  io_hdr_v4.timeout =  BSG_APPEND_TIMEOUT_MS + DEFAULT_CONMMAND_TIMEOUT_MS;
     1591
     1592  switch (dxfer_dir) {
     1593    case DXFER_NONE:
     1594    case DXFER_FROM_DEVICE:
     1595      io_hdr_v4.din_xferp = (uintptr_t)data;
     1596      io_hdr_v4.din_xfer_len = dataLen;
     1597      bsg_param.ioctl_pthru.opcode = ADM_RAID_READ;
     1598      break;
     1599    case DXFER_TO_DEVICE:
     1600      io_hdr_v4.dout_xferp = (uintptr_t)data;
     1601      io_hdr_v4.dout_xfer_len = dataLen;
     1602      bsg_param.ioctl_pthru.opcode = ADM_RAID_WRITE;
     1603      break;
     1604    default:
     1605      pout("scsi_cmd: bad dxfer_dir\n");
     1606      return set_err(EINVAL, "scsi_cmd: bad dxfer_dir\n");
     1607  }
     1608
     1609  bsg_param.msgcode = ADM_BSG_MSGCODE_SCSI_PTHRU;
     1610  bsg_param.ioctl_pthru.timeout_ms = DEFAULT_CONMMAND_TIMEOUT_MS;
     1611  bsg_param.ioctl_pthru.info_1.subopcode = ADM_CMD_SCSI_PASSTHROUGH;
     1612  bsg_param.ioctl_pthru.addr = (uintptr_t)data;
     1613  bsg_param.ioctl_pthru.data_len = dataLen;
     1614
     1615  bsg_param.ioctl_pthru.info_0.cdb_len = scsi_param.cdb_len;
     1616  bsg_param.ioctl_pthru.sense_addr = (uintptr_t)scsi_param.sense_buffer;
     1617  bsg_param.ioctl_pthru.info_0.res_sense_len = scsi_param.sense_buffer_len;
     1618  io_hdr_v4.response = (uintptr_t)scsi_param.sense_buffer;
     1619  io_hdr_v4.response_len = scsi_param.sense_buffer_len;
     1620  bsg_param.ioctl_pthru.info_3.eid = scsi_param.loc.enc_id;
     1621  bsg_param.ioctl_pthru.info_3.sid = scsi_param.loc.slot_id;
     1622  bsg_param.ioctl_pthru.info_4.did = scsi_param.loc.did;
     1623  bsg_param.ioctl_pthru.info_4.did_flag = scsi_param.loc.flag;
     1624
     1625  memcpy(&bsg_param.ioctl_pthru.cdw16, scsi_param.cdb, scsi_param.cdb_len);
     1626
     1627  int r = ioctl(get_fd(), SG_IO, &io_hdr_v4);
     1628  if (r < 0) {
     1629    return (r);
     1630  }
     1631
     1632  return true;
     1633}
     1634
    15021635/////////////////////////////////////////////////////////////////////////////
    15031636/// CCISS RAID support
    15041637
    private:  
    28332966  int megasas_dcmd_cmd(int bus_no, uint32_t opcode, void *buf,
    28342967    size_t bufsize, uint8_t *mbox, size_t mboxlen, uint8_t *statusp);
    28352968  int megasas_pd_add_list(int bus_no, smart_device_list & devlist);
     2969  bool get_dev_sssraid(smart_device_list & devlist);
     2970  int sssraid_pd_add_list(int bus_no, smart_device_list & devlist);
     2971  int sssraid_pdlist_cmd(int bus_no, uint16_t start_idx, void *buf, size_t bufsize, uint8_t *statusp);
    28362972};
    28372973
    28382974std::string linux_smart_interface::get_os_version_str()
    bool linux_smart_interface::get_dev_megasas(smart_device_list & devlist)  
    30133149  return true;
    30143150}
    30153151
     3152// getting devices from 3SNIC Raid, if available
     3153bool linux_smart_interface::get_dev_sssraid(smart_device_list & devlist)
     3154{
     3155  /* Scanning of disks on sssraid device */
     3156  char line[128];
     3157  FILE * fp = NULL;
     3158
     3159  // getting bus numbers with 3snic sas devices
     3160  // we are using sysfs to get list of all scsi hosts
     3161  DIR * dp = opendir ("/sys/class/scsi_host/");
     3162  if (dp != NULL)
     3163  {
     3164    struct dirent *ep;
     3165    while ((ep = readdir (dp)) != NULL) {
     3166      unsigned int host_no = 0;
     3167      if (!sscanf(ep->d_name, "host%u", &host_no))
     3168        continue;
     3169      /* proc_name should be sssraid */
     3170      char sysfsdir[256];
     3171      snprintf(sysfsdir, sizeof(sysfsdir) - 1,
     3172        "/sys/class/scsi_host/host%u/proc_name", host_no);
     3173      if((fp = fopen(sysfsdir, "r")) == NULL)
     3174        continue;
     3175      if(fgets(line, sizeof(line), fp) != NULL && !strncmp(line,"sssraid",7)) {
     3176        sssraid_pd_add_list(host_no, devlist);
     3177      }
     3178      fclose(fp);
     3179    }
     3180    (void) closedir (dp);
     3181  } else { /* sysfs not mounted ? */
     3182    for(unsigned i = 0; i <=16; i++) // trying to add devices on first 16 buses
     3183      sssraid_pd_add_list(i, devlist);
     3184  }
     3185  return true;
     3186}
     3187
    30163188bool linux_smart_interface::scan_smart_devices(smart_device_list & devlist,
    30173189  const smart_devtype_list & types, const char * pattern /*= 0*/)
    30183190{
    bool linux_smart_interface::scan_smart_devices(smart_device_list & devlist,  
    30693241
    30703242    // get device list from the megaraid device
    30713243    get_dev_megasas(devlist);
     3244    // get device list from the sssraid device
     3245    get_dev_sssraid(devlist);
    30723246  }
    30733247
    30743248  if (type_nvme) {
    linux_smart_interface::megasas_pd_add_list(int bus_no, smart_device_list & devli  
    31953369  return (0);
    31963370}
    31973371
     3372int
     3373linux_smart_interface::sssraid_pdlist_cmd(int bus_no, uint16_t start_idx_param, void *buf, size_t bufsize, uint8_t *statusp)
     3374{
     3375  struct sg_io_v4 io_hdr_v4;
     3376  unsigned char sense_buff[ADM_SCSI_CDB_SENSE_MAX_LEN] = { 0 };
     3377  struct bsg_ioctl_cmd bsg_param;
     3378  u8 cmd_param[24] = { 0 };
     3379
     3380  memset(&io_hdr_v4, 0, sizeof(io_hdr_v4));
     3381  memset(&bsg_param, 0, sizeof(bsg_param));
     3382  io_hdr_v4.guard = 'Q';
     3383  io_hdr_v4.protocol = BSG_PROTOCOL_SCSI;
     3384  io_hdr_v4.subprotocol = BSG_SUB_PROTOCOL_SCSI_TRANSPORT;
     3385  io_hdr_v4.response = (uintptr_t)sense_buff;
     3386  io_hdr_v4.max_response_len = ADM_SCSI_CDB_SENSE_MAX_LEN;
     3387  io_hdr_v4.request_len = sizeof(struct bsg_ioctl_cmd);
     3388  io_hdr_v4.request = (uintptr_t)(&bsg_param);
     3389  io_hdr_v4.timeout = BSG_APPEND_TIMEOUT_MS + DEFAULT_CONMMAND_TIMEOUT_MS;
     3390
     3391  if (bufsize >0)  {
     3392    io_hdr_v4.din_xferp = (uintptr_t)buf;
     3393    io_hdr_v4.din_xfer_len = bufsize;
     3394  }
     3395
     3396  bsg_param.msgcode = 0;
     3397  bsg_param.ioctl_r64.opcode = ADM_RAID_READ;
     3398  bsg_param.ioctl_r64.timeout_ms = DEFAULT_CONMMAND_TIMEOUT_MS;
     3399  bsg_param.ioctl_r64.info_0.subopcode = ADM_CMD_SHOW_PDLIST;
     3400  bsg_param.ioctl_r64.addr = (uintptr_t)buf;
     3401  bsg_param.ioctl_r64.info_1.data_len = bufsize;
     3402  bsg_param.ioctl_r64.data_len = bufsize;
     3403  bsg_param.ioctl_r64.info_1.param_len = sizeof(struct cmd_pdlist_idx);
     3404  memset(&cmd_param, 0, 24);
     3405  struct cmd_pdlist_idx *p_cmd_param = (struct cmd_pdlist_idx *)(&cmd_param);
     3406  p_cmd_param->start_idx = start_idx_param;
     3407  p_cmd_param->count = CMD_PDLIST_ONCE_NUM;
     3408  memcpy((u32*)&bsg_param.ioctl_r64.cdw10, cmd_param, sizeof(struct cmd_pdlist_idx));
     3409
     3410  int fd;
     3411  char line[128];
     3412  snprintf(line, sizeof(line) - 1, "/dev/bsg/sssraid%d", bus_no);
     3413  if ((fd = ::open(line, O_RDONLY)) < 0) {
     3414    pout("open %s error %d\n", line, fd);
     3415    return (errno);
     3416  }
     3417
     3418  int r = ioctl(fd, SG_IO, &io_hdr_v4);
     3419  ::close(fd);
     3420  if (r < 0) {
     3421    return (r);
     3422  }
     3423
     3424  if (statusp != NULL) {
     3425    *statusp = (io_hdr_v4.transport_status << 0x8) | io_hdr_v4.device_status;
     3426    pout("statusp = 0x%x\n", *statusp);
     3427    if (*statusp) {
     3428      pout("controller returns an error - 0x%x", *statusp);
     3429      return (-1);
     3430    }
     3431  }
     3432  return (0);
     3433}
     3434
     3435int
     3436linux_smart_interface::sssraid_pd_add_list(int bus_no, smart_device_list & devlist)
     3437{
     3438  unsigned disk_num = 0;
     3439  struct cmd_pdlist_entry pdlist[CMD_PDS_MAX_NUM];
     3440  while (disk_num < CMD_PDS_MAX_NUM) {
     3441    struct cmd_show_pdlist list;
     3442    memset(&list, 0, sizeof(list));
     3443    if (sssraid_pdlist_cmd(bus_no, disk_num, &list, sizeof(struct cmd_show_pdlist), NULL) < 0)
     3444    {
     3445      return (-1);
     3446    }
     3447    if (list.num == 0)
     3448      break;
     3449    memcpy(&pdlist[disk_num], list.disks, list.num * sizeof(struct cmd_pdlist_entry));
     3450    disk_num += list.num;
     3451    if (list.num < CMD_PDLIST_ONCE_NUM)
     3452      break;
     3453  }
     3454
     3455  // adding all SCSI devices
     3456  for (unsigned i = 0; i < disk_num; i++) {
     3457    if(!(pdlist[i].interface == ADM_DEVICE_TYPE_SATA || pdlist[i].interface == ADM_DEVICE_TYPE_SAS
     3458        || pdlist[i].interface == ADM_DEVICE_TYPE_NVME))
     3459      continue; /* non disk device found */
     3460    char line[128];
     3461    snprintf(line, sizeof(line) - 1, "/dev/bsg/sssraid%d", bus_no);
     3462    smart_device * dev = new linux_sssraid_device(this, line, (unsigned int)pdlist[i].enc_id, (unsigned int)pdlist[i].slot_id);
     3463    devlist.push_back(dev);
     3464  }
     3465  return (0);
     3466}
     3467
    31983468// Return kernel release as integer ("2.6.31" -> 206031)
    31993469static unsigned get_kernel_release()
    32003470{
    smart_device * linux_smart_interface::get_custom_smart_device(const char * name,  
    34523722    return new linux_megaraid_device(this, name, disknum);
    34533723  }
    34543724
     3725  // SSSRAID
     3726  unsigned eid = -1, sid = -1;
     3727  if (sscanf(type, "sssraid,%u,%u", &eid, &sid) == 2) {
     3728    return get_sat_device("sat,auto", new linux_sssraid_device(this, name, eid, sid));
     3729  }
     3730
    34553731  //aacraid?
    34563732  unsigned host, chan, device;
    34573733  if (sscanf(type, "aacraid,%u,%u,%u", &host, &chan, &device) == 3) {
    smart_device * linux_smart_interface::get_custom_smart_device(const char * name,  
    34663742
    34673743std::string linux_smart_interface::get_valid_custom_dev_types_str()
    34683744{
    3469   return "marvell, areca,N/E, 3ware,N, hpt,L/M/N, megaraid,N, aacraid,H,L,ID"
     3745  return "marvell, areca,N/E, 3ware,N, hpt,L/M/N, megaraid,N, aacraid,H,L,ID, sssraid,E,S"
    34703746#ifdef HAVE_LINUX_CCISS_IOCTL_H
    34713747                                              ", cciss,N"
    34723748#endif