Ticket #782: sgio.2.patch

File sgio.2.patch, 10.7 KB (added by Alex Samorukov, 2 years ago)

Updated SG_IO patch to use v3 and v4 api from the same function

  • os_linux.cpp

     
    6363#include <scsi/scsi.h>
    6464#include <scsi/scsi_ioctl.h>
    6565#include <scsi/sg.h>
     66#include <linux/bsg.h>
    6667#include <stdlib.h>
    6768#include <string.h>
    6869#include <sys/ioctl.h>
     
    510511#define SCSI_IOCTL_SEND_COMMAND 1
    511512#endif
    512513
    513 #define SG_IO_PRESENT_UNKNOWN 0
    514 #define SG_IO_PRESENT_YES 1
    515 #define SG_IO_PRESENT_NO 2
     514#define SG_IO_USE_DETECT 0
     515#define SG_IO_UNSUPP 1
     516#define SG_IO_USE_V3 3
     517#define SG_IO_USE_V4 4
    516518
    517519static int sg_io_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report,
    518                          int unknown);
     520                         int sgio_ver);
    519521static int sisc_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report);
    520522
    521 static int sg_io_state = SG_IO_PRESENT_UNKNOWN;
     523static int sg_io_state = SG_IO_USE_DETECT;
    522524
    523525/* Preferred implementation for issuing SCSI commands in linux. This
    524526 * function uses the SG_IO ioctl. Return 0 if command issued successfully
    525527 * (various status values should still be checked). If the SCSI command
    526528 * cannot be issued then a negative errno value is returned. */
    527529static int sg_io_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report,
    528                          int unknown)
     530                         int sg_io_ver)
    529531{
    530532#ifndef SG_IO
    531533    ARGUSED(dev_fd); ARGUSED(iop); ARGUSED(report);
    532534    return -ENOTTY;
    533535#else
    534     struct sg_io_hdr io_hdr;
    535536
     537    /* we are filling structures for both versions, but using only one requested */
     538    struct sg_io_hdr io_hdr_v3;
     539    struct sg_io_v4  io_hdr_v4;
     540
    536541    if (report > 0) {
    537542        int k, j;
    538543        const unsigned char * ucp = iop->cmnd;
     
    540545        char buff[256];
    541546        const int sz = (int)sizeof(buff);
    542547
     548        pout(">>>> do_scsi_cmnd_io: sg_io_ver=%d\n", sg_io_ver);
    543549        np = scsi_get_opcode_name(ucp[0]);
    544550        j = snprintf(buff, sz, " [%s: ", np ? np : "<unknown opcode>");
    545551        for (k = 0; k < (int)iop->cmnd_len; ++k)
     
    558564            snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n");
    559565        pout("%s", buff);
    560566    }
    561     memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
    562     io_hdr.interface_id = 'S';
    563     io_hdr.cmd_len = iop->cmnd_len;
    564     io_hdr.mx_sb_len = iop->max_sense_len;
    565     io_hdr.dxfer_len = iop->dxfer_len;
    566     io_hdr.dxferp = iop->dxferp;
    567     io_hdr.cmdp = iop->cmnd;
    568     io_hdr.sbp = iop->sensep;
     567    memset(&io_hdr_v3, 0, sizeof(struct sg_io_hdr));
     568    memset(&io_hdr_v4, 0, sizeof(struct sg_io_v4));
     569
     570    io_hdr_v3.interface_id =       'S';
     571    io_hdr_v3.cmd_len =            iop->cmnd_len;
     572    io_hdr_v3.mx_sb_len =          iop->max_sense_len;
     573    io_hdr_v3.dxfer_len =          iop->dxfer_len;
     574    io_hdr_v3.dxferp =             iop->dxferp;
     575    io_hdr_v3.cmdp =               iop->cmnd;
     576    io_hdr_v3.sbp =                iop->sensep;
    569577    /* sg_io_hdr interface timeout has millisecond units. Timeout of 0
    570578       defaults to 60 seconds. */
    571     io_hdr.timeout = ((0 == iop->timeout) ? 60 : iop->timeout) * 1000;
     579    io_hdr_v3.timeout =         ((0 == iop->timeout) ? 60 : iop->timeout) * 1000;
     580
     581    io_hdr_v4.guard =              'Q';
     582    io_hdr_v4.request_len =        iop->cmnd_len;
     583    io_hdr_v4.request =            __u64(iop->cmnd);
     584    io_hdr_v4.max_response_len =   iop->max_sense_len;
     585    io_hdr_v4.response =           __u64(iop->sensep);
     586    io_hdr_v4.timeout =            ((0 == iop->timeout) ? 60 : iop->timeout) * 1000; // msec
     587
    572588    switch (iop->dxfer_dir) {
    573589        case DXFER_NONE:
    574             io_hdr.dxfer_direction = SG_DXFER_NONE;
     590            io_hdr_v3.dxfer_direction = SG_DXFER_NONE;
    575591            break;
    576592        case DXFER_FROM_DEVICE:
    577             io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
     593            io_hdr_v3.dxfer_direction = SG_DXFER_FROM_DEV;
     594            io_hdr_v4.din_xfer_len =    iop->dxfer_len;
     595            io_hdr_v4.din_xferp =       __u64(iop->dxferp);
    578596            break;
    579597        case DXFER_TO_DEVICE:
    580             io_hdr.dxfer_direction = SG_DXFER_TO_DEV;
     598            io_hdr_v3.dxfer_direction = SG_DXFER_TO_DEV;
     599            io_hdr_v4.dout_xfer_len =   iop->dxfer_len;
     600            io_hdr_v4.dout_xferp =      __u64(iop->dxferp);
    581601            break;
    582602        default:
    583603            pout("do_scsi_cmnd_io: bad dxfer_dir\n");
    584604            return -EINVAL;
    585605    }
     606
    586607    iop->resp_sense_len = 0;
    587608    iop->scsi_status = 0;
    588609    iop->resid = 0;
    589     if (ioctl(dev_fd, SG_IO, &io_hdr) < 0) {
    590         if (report && (! unknown))
    591             pout("  SG_IO ioctl failed, errno=%d [%s]\n", errno,
    592                  strerror(errno));
     610
     611    void * io_hdr = NULL;
     612
     613    switch (sg_io_ver) {
     614      case SG_IO_USE_V3:
     615          io_hdr = &io_hdr_v3;
     616          break;
     617      case SG_IO_USE_V4:
     618          io_hdr = &io_hdr_v4;
     619          break;
     620      default:
     621          // should never be reached
     622          errno = EOPNOTSUPP;
     623          return -errno;
     624    }
     625
     626    if (ioctl(dev_fd, SG_IO, io_hdr) < 0) {
     627        if (report)
     628            pout("  SG_IO ioctl failed, errno=%d [%s], SG_IO_V%d\n", errno,
     629                 strerror(errno), sg_io_ver);
    593630        return -errno;
    594631    }
    595     iop->resid = io_hdr.resid;
    596     iop->scsi_status = io_hdr.status;
     632
     633    unsigned int sg_driver_status = 0,  sg_transport_status = 0, sg_info = 0,
     634        sg_duration = 0;
     635
     636    if (sg_io_ver == SG_IO_USE_V3) {
     637        iop->resid =            io_hdr_v3.resid;
     638        iop->scsi_status =      io_hdr_v3.status;
     639        sg_driver_status =      io_hdr_v3.driver_status;
     640        sg_transport_status =   io_hdr_v3.host_status;
     641        sg_info =               io_hdr_v3.info;
     642        iop->resp_sense_len =   io_hdr_v3.sb_len_wr;
     643        sg_duration =           io_hdr_v3.duration;
     644    }
     645
     646    if (sg_io_ver == SG_IO_USE_V4) {
     647       switch (iop->dxfer_dir) {
     648           case DXFER_NONE:
     649               iop->resid = 0;
     650               break;
     651           case DXFER_FROM_DEVICE:
     652               iop->resid = io_hdr_v4.din_resid;
     653               break;
     654           case DXFER_TO_DEVICE:
     655               iop->resid = io_hdr_v4.dout_resid;
     656               break;
     657       }
     658       iop->scsi_status =       io_hdr_v4.device_status;
     659       sg_driver_status =       io_hdr_v4.driver_status;
     660       sg_transport_status =    io_hdr_v4.transport_status;
     661       sg_info =                io_hdr_v4.info;
     662       iop->resp_sense_len =    io_hdr_v4.response_len;
     663       sg_duration =            io_hdr_v4.duration;
     664    }
     665
    597666    if (report > 0) {
    598         pout("  scsi_status=0x%x, host_status=0x%x, driver_status=0x%x\n"
    599              "  info=0x%x  duration=%d milliseconds  resid=%d\n", io_hdr.status,
    600              io_hdr.host_status, io_hdr.driver_status, io_hdr.info,
    601              io_hdr.duration, io_hdr.resid);
     667        pout("  scsi_status=0x%x, sg_transport_status=0x%x, sg_driver_status=0x%x\n"
     668             "  sg_info=0x%x  sg_duration=%d milliseconds  resid=%d\n", iop->scsi_status,
     669             sg_transport_status, sg_driver_status, sg_info,
     670             sg_duration, iop->resid);
     671
    602672        if (report > 1) {
    603673            if (DXFER_FROM_DEVICE == iop->dxfer_dir) {
    604674                int trunc, len;
     
    616686        }
    617687    }
    618688
    619     if (io_hdr.info & SG_INFO_CHECK) { /* error or warning */
    620         int masked_driver_status = (LSCSI_DRIVER_MASK & io_hdr.driver_status);
     689    if (sg_info & SG_INFO_CHECK) { /* error or warning */
     690        int masked_driver_status = (LSCSI_DRIVER_MASK & sg_driver_status);
    621691
    622         if (0 != io_hdr.host_status) {
    623             if ((LSCSI_DID_NO_CONNECT == io_hdr.host_status) ||
    624                 (LSCSI_DID_BUS_BUSY == io_hdr.host_status) ||
    625                 (LSCSI_DID_TIME_OUT == io_hdr.host_status))
     692        if (0 != sg_transport_status) {
     693            if ((LSCSI_DID_NO_CONNECT == sg_transport_status) ||
     694                (LSCSI_DID_BUS_BUSY == sg_transport_status) ||
     695                (LSCSI_DID_TIME_OUT == sg_transport_status))
    626696                return -ETIMEDOUT;
    627697            else
    628698               /* Check for DID_ERROR - workaround for aacraid driver quirk */
    629                if (LSCSI_DID_ERROR != io_hdr.host_status) {
     699               if (LSCSI_DID_ERROR != sg_transport_status) {
    630700                       return -EIO; /* catch all if not DID_ERR */
    631701               }
    632702        }
     
    638708        }
    639709        if (LSCSI_DRIVER_SENSE == masked_driver_status)
    640710            iop->scsi_status = SCSI_STATUS_CHECK_CONDITION;
    641         iop->resp_sense_len = io_hdr.sb_len_wr;
    642711        if ((SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) &&
    643712            iop->sensep && (iop->resp_sense_len > 0)) {
    644713            if (report > 1) {
     
    807876     * other than ENODEV (no device) or permission then assume
    808877     * SCSI_IOCTL_SEND_COMMAND is the only option. */
    809878    switch (sg_io_state) {
    810     case SG_IO_PRESENT_UNKNOWN:
     879    case SG_IO_USE_DETECT:
    811880        /* ignore report argument */
    812         if (0 == (res = sg_io_cmnd_io(dev_fd, iop, report, 1))) {
    813             sg_io_state = SG_IO_PRESENT_YES;
     881        /* Try SG_IO V3 first */
     882        if (0 == (res = sg_io_cmnd_io(dev_fd, iop, report, SG_IO_USE_V3))) {
     883            sg_io_state = SG_IO_USE_V3;
    814884            return 0;
    815885        } else if ((-ENODEV == res) || (-EACCES == res) || (-EPERM == res))
    816886            return res;         /* wait until we see a device */
    817         sg_io_state = SG_IO_PRESENT_NO;
     887        /* See if we can use SG_IO V4 * */
     888        if (0 == (res = sg_io_cmnd_io(dev_fd, iop, report, SG_IO_USE_V4))) {
     889            sg_io_state = SG_IO_USE_V4;
     890            return 0;
     891        } else if ((-ENODEV == res) || (-EACCES == res) || (-EPERM == res))
     892            return res;         /* wait until we see a device */
     893        /* fallback to the SCSI_IOCTL_SEND_COMMAND */
     894        sg_io_state = SG_IO_UNSUPP;
    818895        /* drop through by design */
    819     case SG_IO_PRESENT_NO:
     896    case SG_IO_UNSUPP:
     897        /* depricated SCSI_IOCTL_SEND_COMMAND ioctl */
    820898        return sisc_cmnd_io(dev_fd, iop, report);
    821     case SG_IO_PRESENT_YES:
    822         return sg_io_cmnd_io(dev_fd, iop, report, 0);
     899    case SG_IO_USE_V3:
     900    case SG_IO_USE_V4:
     901        /* use SG_IO V3 or V4 ioctl, depending on availabiliy */
     902        return sg_io_cmnd_io(dev_fd, iop, report, sg_io_state);
    823903    default:
    824904        pout(">>>> do_scsi_cmnd_io: bad sg_io_state=%d\n", sg_io_state);
    825         sg_io_state = SG_IO_PRESENT_UNKNOWN;
     905        sg_io_state = SG_IO_USE_DETECT;
    826906        return -EIO;    /* report error and reset state */
    827907    }
    828908}
     
    31993279  if (str_starts_with(test_name, "scsi/"))
    32003280    return new linux_scsi_device(this, name, "");
    32013281
     3282  // form /dev/bsg/* or bsg/*
     3283  if (str_starts_with(test_name, "bsg/"))
     3284    return new linux_scsi_device(this, name, "");
     3285
    32023286  // form /dev/ns* or ns*
    32033287  if (str_starts_with(test_name, "ns"))
    32043288    return new linux_scsi_device(this, name, "");