Ticket #252: patch.diff

File patch.diff, 11.6 KB (added by Alex Samorukov, 11 years ago)

Updated patch with --scan-open fix

  • os_linux.cpp

     
    6565#include <stddef.h>  // for offsetof()
    6666#include <sys/uio.h>
    6767#include <sys/types.h>
     68#include <dirent.h>
    6869#ifndef makedev // old versions of types.h do not include sysmacros.h
    6970#include <sys/sysmacros.h>
    7071#endif
     
    122123  int get_fd() const
    123124    { return m_fd; }
    124125
     126  void set_fd(int fd)
     127    { m_fd = fd; }
     128
    125129private:
    126130  int m_fd; ///< filedesc, -1 if not open.
    127131  int m_flags; ///< Flags for ::open()
     
    901905   m_fd(-1), pt_cmd(0)
    902906{
    903907  set_info().info_name = strprintf("%s [megaraid_disk_%02d]", dev_name, m_disknum);
     908  set_info().dev_type = strprintf("megaraid,%d", tgt);
    904909}
    905910
    906911linux_megaraid_device::~linux_megaraid_device() throw()
     
    944949    ata_device * newdev = smi()->autodetect_sat_device(this, req_buff, len);
    945950    if (newdev) {
    946951      // NOTE: 'this' is now owned by '*newdev'
    947       newdev->close();
    948       newdev->set_err(ENOSYS, "SATA device detected,\n"
    949         "MegaRAID SAT layer is reportedly buggy, use '-d sat+megaraid,N' to try anyhow");
    950952      return newdev;
    951953    }
    952954  }
     
    963965  FILE *fp;
    964966  int report = scsi_debugmode;
    965967
    966   if (!linux_smart_device::open())
    967     return false;
    968 
    969   /* Get device HBA */
    970   struct sg_scsi_id sgid;
    971   if (ioctl(get_fd(), SG_GET_SCSI_ID, &sgid) == 0) {
    972     m_hba = sgid.host_no;
    973   }
    974   else if (ioctl(get_fd(), SCSI_IOCTL_GET_BUS_NUMBER, &m_hba) != 0) {
    975     int err = errno;
     968  if(sscanf(get_dev_name(),"/dev/bus/%d", &m_hba) == 0) {
     969    if (!linux_smart_device::open())
     970      return false;
     971    /* Get device HBA */
     972    struct sg_scsi_id sgid;
     973    if (ioctl(get_fd(), SG_GET_SCSI_ID, &sgid) == 0) {
     974      m_hba = sgid.host_no;
     975    }
     976    else if (ioctl(get_fd(), SCSI_IOCTL_GET_BUS_NUMBER, &m_hba) != 0) {
     977      int err = errno;
     978      linux_smart_device::close();
     979      return set_err(err, "can't get bus number");
     980    } // we dont need this device anymore
    976981    linux_smart_device::close();
    977     return set_err(err, "can't get bus number");
    978982  }
    979 
    980983  /* Perform mknod of device ioctl node */
    981984  fp = fopen("/proc/devices", "r");
    982985  while (fgets(line, sizeof(line), fp) != NULL) {
    983986        n1=0;
    984987        if (sscanf(line, "%d megaraid_sas_ioctl%n", &mjr, &n1) == 1 && n1 == 22) {
    985            n1=mknod("/dev/megaraid_sas_ioctl_node", S_IFCHR, makedev(mjr, 0));
    986            if(report > 0)
    987              pout("Creating /dev/megaraid_sas_ioctl_node = %d\n", n1 >= 0 ? 0 : errno);
    988            if (n1 >= 0 || errno == EEXIST)
     988                n1=mknod("/dev/megaraid_sas_ioctl_node", S_IFCHR, makedev(mjr, 0));
     989                if(report > 0)
     990                        pout("Creating /dev/megaraid_sas_ioctl_node = %d\n", n1 >= 0 ? 0 : errno);
     991                if (n1 >= 0 || errno == EEXIST)
    989992              break;
    990         }
    991         else if (sscanf(line, "%d megadev%n", &mjr, &n1) == 1 && n1 == 11) {
    992            n1=mknod("/dev/megadev0", S_IFCHR, makedev(mjr, 0));
    993            if(report > 0)
    994              pout("Creating /dev/megadev0 = %d\n", n1 >= 0 ? 0 : errno);
    995            if (n1 >= 0 || errno == EEXIST)
     993          }
     994          else if (sscanf(line, "%d megadev%n", &mjr, &n1) == 1 && n1 == 11) {
     995                n1=mknod("/dev/megadev0", S_IFCHR, makedev(mjr, 0));
     996                if(report > 0)
     997                        pout("Creating /dev/megadev0 = %d\n", n1 >= 0 ? 0 : errno);
     998                if (n1 >= 0 || errno == EEXIST)
    996999              break;
    997         }
     1000          }
    9981001  }
    9991002  fclose(fp);
    10001003
     
    10101013    linux_smart_device::close();
    10111014    return set_err(err, "cannot open /dev/megaraid_sas_ioctl_node or /dev/megadev0");
    10121015  }
    1013 
     1016  set_fd(m_fd);
    10141017  return true;
    10151018}
    10161019
     1020
    10171021bool linux_megaraid_device::close()
    10181022{
    10191023  if (m_fd >= 0)
    10201024    ::close(m_fd);
    10211025  m_fd = -1; m_hba = 0; pt_cmd = 0;
    1022   return linux_smart_device::close();
     1026  set_fd(m_fd);
     1027  return true;
    10231028}
    10241029
    10251030bool linux_megaraid_device::scsi_pass_through(scsi_cmnd_io *iop)
     
    23132318
    23142319    // DELL?
    23152320    if (!memcmp(req_buff + 8, "DELL    PERC", 12) || !memcmp(req_buff + 8, "MegaRAID", 8)
    2316         || !memcmp(req_buff + 16, "PERC H700", 9)
     2321        || !memcmp(req_buff + 16, "PERC H700", 9) || !memcmp(req_buff + 8, "LSI\0",4)
    23172322    ) {
    23182323      close();
    23192324      set_err(EINVAL, "DELL or MegaRaid controller, please try adding '-d megaraid,N'");
     
    24332438private:
    24342439  bool get_dev_list(smart_device_list & devlist, const char * pattern,
    24352440    bool scan_ata, bool scan_scsi, const char * req_type, bool autodetect);
    2436 
     2441  bool get_dev_megasas(smart_device_list & devlist);
    24372442  smart_device * missing_option(const char * opt);
     2443  int megasas_dcmd_cmd(int bus_no, uint32_t opcode, void *buf,
     2444    size_t bufsize, uint8_t *mbox, size_t mboxlen, uint8_t *statusp);
     2445  int megasas_pd_add_list(int bus_no, smart_device_list & devlist);
    24382446};
    24392447
    24402448std::string linux_smart_interface::get_os_version_str()
     
    25472555        devlist.push_back(dev);
    25482556    }
    25492557  }
    2550 
     2558 
    25512559  // free memory
    25522560  globfree(&globbuf);
     2561  return true;
     2562}
    25532563
     2564// getting devices from LSI SAS MegaRaid, if available
     2565bool linux_smart_interface::get_dev_megasas(smart_device_list & devlist)
     2566{
     2567  /* Scanning of disks on MegaRaid device */
     2568  /* Perform mknod of device ioctl node */
     2569  int   mjr, n1;
     2570  FILE *fp;
     2571  char line[128];
     2572  bool scan_megasas = false;
     2573  fp = fopen("/proc/devices", "r");
     2574  while (fgets(line, sizeof(line), fp) != NULL) {
     2575        n1=0;
     2576        if (sscanf(line, "%d megaraid_sas_ioctl%n", &mjr, &n1) == 1 && n1 == 22) {
     2577                scan_megasas = true;
     2578                n1=mknod("/dev/megaraid_sas_ioctl_node", S_IFCHR, makedev(mjr, 0));
     2579                if(scsi_debugmode > 0)
     2580                        pout("Creating /dev/megaraid_sas_ioctl_node = %d\n", n1 >= 0 ? 0 : errno);
     2581                if (n1 >= 0 || errno == EEXIST)
     2582              break;
     2583          }
     2584  }
     2585  fclose(fp);
     2586 
     2587  if(!scan_megasas)
     2588        return false;
     2589 
     2590  // getting bus numbers with megasas devices
     2591  DIR *dp;
     2592  struct dirent *ep;
     2593  unsigned int host_no = 0, i;
     2594  char sysfsdir[256];
     2595 
     2596  /* we are using sysfs to get list of all scsi hosts */
     2597  dp = opendir ("/sys/class/scsi_host/");
     2598  if (dp != NULL)
     2599  {
     2600        while ((ep = readdir (dp)) != NULL) {
     2601            if (!sscanf(ep->d_name, "host%d", &host_no))
     2602                continue;
     2603            /* proc_name should be megaraid_sas */
     2604            snprintf(sysfsdir, sizeof(sysfsdir) - 1,
     2605                "/sys/class/scsi_host/host%d/proc_name", host_no);
     2606            if((fp = fopen(sysfsdir, "r")) == NULL)
     2607                continue;
     2608            if(fgets(line, sizeof(line), fp) != NULL && !strncmp(line,"megaraid_sas",12)) {
     2609                megasas_pd_add_list(host_no, devlist);
     2610            }
     2611            fclose(fp);
     2612           
     2613          }
     2614        (void) closedir (dp);
     2615  } else { /* sysfs not mounted ? */
     2616        for(i = 0; i <=16; i++) // trying to add devices on first 16 buses
     2617                megasas_pd_add_list(i, devlist);
     2618  }
    25542619  return true;
    25552620}
    25562621
     
    25782643    get_dev_list(devlist, "/dev/sd[a-z]", false, true, type, autodetect);
    25792644    // Support up to 104 devices
    25802645    get_dev_list(devlist, "/dev/sd[a-c][a-z]", false, true, type, autodetect);
     2646    // get device list from the megaraid device
     2647    get_dev_megasas(devlist);
    25812648  }
    25822649
    25832650  // if we found traditional links, we are done
     
    26052672  return 0;
    26062673}
    26072674
     2675int
     2676linux_smart_interface::megasas_dcmd_cmd(int bus_no, uint32_t opcode, void *buf,
     2677  size_t bufsize, uint8_t *mbox, size_t mboxlen, uint8_t *statusp)
     2678{
     2679  struct megasas_iocpacket ioc;
     2680  struct megasas_dcmd_frame *dcmd;
     2681  int r;
     2682 
     2683  if ((mbox != NULL && (mboxlen == 0 || mboxlen > MFI_MBOX_SIZE)) ||
     2684    (mbox == NULL && mboxlen != 0))
     2685  {
     2686    errno = EINVAL;
     2687    return (-1);
     2688  }
     2689 
     2690  bzero(&ioc, sizeof(ioc));
     2691  dcmd = &ioc.frame.dcmd;
     2692  ioc.host_no = bus_no;
     2693  if (mbox)
     2694    bcopy(mbox, dcmd->mbox.w, mboxlen);
     2695  dcmd->cmd = MFI_CMD_DCMD;
     2696  dcmd->timeout = 0;
     2697  dcmd->flags = 0;
     2698  dcmd->data_xfer_len = bufsize;
     2699  dcmd->opcode = opcode;
     2700 
     2701  if (bufsize > 0) {
     2702    dcmd->sge_count = 1;
     2703    dcmd->data_xfer_len = bufsize;
     2704    dcmd->sgl.sge32[0].phys_addr = (intptr_t)buf;
     2705    dcmd->sgl.sge32[0].length = (uint32_t)bufsize;
     2706  }
     2707 
     2708  if (bufsize > 0) {
     2709    ioc.sge_count = 1;
     2710    ioc.sgl_off = offsetof(struct megasas_dcmd_frame, sgl);
     2711    ioc.sgl[0].iov_base = buf;
     2712    ioc.sgl[0].iov_len = bufsize;
     2713  }
     2714  int fd;
     2715  if ((fd = ::open("/dev/megaraid_sas_ioctl_node", O_RDWR)) <= 0) {
     2716    return (errno);
     2717  }
     2718 
     2719  r = ioctl(fd, MEGASAS_IOC_FIRMWARE, &ioc);
     2720  if (r < 0) {
     2721    return (r);
     2722  }
     2723 
     2724  if (statusp != NULL)
     2725    *statusp = dcmd->cmd_status;
     2726  else if (dcmd->cmd_status != MFI_STAT_OK) {
     2727    fprintf(stderr, "command %x returned error status %x\n",
     2728      opcode, dcmd->cmd_status);
     2729    errno = EIO;
     2730    return (-1);
     2731  }
     2732  return (0);
     2733}
     2734
     2735int
     2736linux_smart_interface::megasas_pd_add_list(int bus_no, smart_device_list & devlist)
     2737{
     2738  struct megasas_pd_list *list;
     2739  uint32_t list_size;
     2740  unsigned int i;
     2741  char line[128];
     2742  smart_device * dev;
     2743 
     2744  /*
     2745  * Keep fetching the list in a loop until we have a large enough
     2746  * buffer to hold the entire list.
     2747  */
     2748  list = NULL;
     2749  list_size = 1024;
     2750fetch:
     2751  list = (megasas_pd_list *)realloc(list, list_size);
     2752  if (list == NULL)
     2753    return (-1);
     2754  bzero(list, list_size);
     2755  if (megasas_dcmd_cmd(bus_no, MFI_DCMD_PD_GET_LIST, list, list_size, NULL, 0,
     2756    NULL) < 0)
     2757  {
     2758    free(list);
     2759    return (-1);
     2760  }
     2761  if (list->size > list_size) {
     2762    list_size = list->size;
     2763    goto fetch;
     2764  }
     2765  // adding new to devlist devices
     2766  // adding all SCSI devices
     2767  for (i = 0; i < list->count; i++) {
     2768    if(list->addr[i].scsi_dev_type)
     2769      continue; /* non disk device found */
     2770    snprintf(line, sizeof(line) - 1, "/dev/bus/%d", bus_no);
     2771    dev = new linux_megaraid_device(this, line, 0, list->addr[i].device_id);
     2772    if (dev)
     2773      devlist.push_back(dev);
     2774  }
     2775  free(list);
     2776  return (0);
     2777}
     2778
    26082779// Return kernel release as integer ("2.6.31" -> 206031)
    26092780static unsigned get_kernel_release()
    26102781{
  • megaraid.h

     
    107107#define MEGASAS_IOC_FIRMWARE   _IOWR(MEGASAS_MAGIC, 1, struct megasas_iocpacket)
    108108
    109109#define MFI_CMD_PD_SCSI_IO        0x04
     110#define MFI_CMD_DCMD              0x05
    110111#define MFI_FRAME_SGL64           0x02
    111 #define MFI_FRAME_DIR_READ        0x10
     112#define MFI_FRAME_DIR_READ        0x10
     113#define MFI_STAT_OK               0x00
     114#define MFI_DCMD_PD_GET_LIST      0x02010000
     115/*
     116 * Number of mailbox bytes in DCMD message frame
     117 */
     118#define MFI_MBOX_SIZE             12
     119#define MAX_IOCTL_SGE             16
    112120
    113 #define MAX_IOCTL_SGE                   16
     121#define MAX_SYS_PDS   240
    114122
    115123struct megasas_sge32 {
    116124
     
    220228                u8 raw[128];
    221229                struct megasas_header hdr;
    222230                struct megasas_pthru_frame pthru;
     231                struct megasas_dcmd_frame dcmd;
    223232        } frame;
    224233
    225234        struct iovec sgl[MAX_IOCTL_SGE];
     235} __attribute__ ((packed));
    226236
     237struct megasas_pd_address {
     238        u16 device_id;
     239        u16 encl_device_id;
     240        u8 encl_index;
     241        u8 slot_number;
     242        u8 scsi_dev_type; /* 0 = disk */
     243        u8 connect_port_bitmap;
     244        u64 sas_addr[2];
     245}   __attribute__ ((packed));
     246
     247struct megasas_pd_list {
     248        u32 size;
     249        u32 count;
     250        struct megasas_pd_address addr[MAX_SYS_PDS];
    227251} __attribute__ ((packed));
    228252
    229253#undef u8
  • scsiata.cpp

     
    141141    hide_ata(); // Start as SCSI, switch to ATA in autodetect_open()
    142142  else
    143143    hide_scsi(); // ATA always
     144 
     145  if (strcmp(scsidev->get_dev_type(),"scsi")) // RAID devices                                                                                                     
     146    set_info().dev_type = strprintf("sat+%s", scsidev->get_dev_type());                                                                       
    144147
    145148  set_info().info_name = strprintf("%s [%sSAT]", scsidev->get_info_name(),
    146149                                   (enable_auto ? "SCSI/" : ""));