All of lore.kernel.org
 help / color / mirror / Atom feed
From: Douglas Gilbert <dougg@torque.net>
To: Jeff Garzik <jgarzik@pobox.com>
Cc: linux-scsi@vger.kernel.org
Subject: Re: [PATCH RFC] use struct scsi_lun in generic code
Date: Sun, 23 Oct 2005 15:22:22 +1000	[thread overview]
Message-ID: <435B1E0E.8060409@torque.net> (raw)
In-Reply-To: <20051023043301.GA22615@havoc.gtf.org>

[-- Attachment #1: Type: text/plain, Size: 1383 bytes --]

_rbuf_getJeff Garzik wrote:
> A further experiment:  once dev_printk() has been used to eliminate
> direct references to HCIL address (see previous patch), we can see what
> happens when we update the core to use struct scsi_lun.
> 
> DO NOT APPLY.
> 
> Depends on previous "kill scsi_device::{channel,id} in generic code"
> patch.
> 
> Changes:
> 
> * replace 'unsigned int lun' with 'struct scsi_lun lun' in struct scsi_device
> 
> * change various function args to receive 'const struct scsi_lun *'
>   rather than unsigned int.
> 
> * export scsilun_to_int()
> 
> * create scsilun_to_str() helper
> 
> * create scsilun_eq() helper
> 
> * update all references to scsi_device::lun, as caught by the compiler.
> 
>   Again, generic code was 100% converted, driver code 0% converted.
> 
> * int_to_scsilun() is used to convert SCSI-2 luns, and luns passed
>   from userspace as integers, to struct scsi_lun.
> 
> * shost->max_lun check moved into scsi_scan_host_selected() callers

Jeff,
With 8 byte luns, max_lun is legacy. I found it a nuisance
when I played with wluns (well known lus). Looks like
you may be coping with that.

If you want to decode SAM-4 luns, perhaps for verbose
error purposes, feel free to borrow code from the
attached sg_luns (which is slightly more up to date
than the one found in sg3_utils version 1.17).

Back to libata's MODE SELECT ...

Doug Gilbert

[-- Attachment #2: sg_luns.c --]
[-- Type: text/x-csrc, Size: 11679 bytes --]

/*
 * Copyright (c) 2004 Douglas Gilbert.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 */

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <getopt.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "sg_include.h"
#include "sg_lib.h"
#include "sg_cmds.h"

/* A utility program for the Linux OS SCSI subsystem.
 *
 *
 * This program issues the SCSI command REPORT LUNS to the given SCSI device. 
 */

static char * version_str = "1.04 20051013";

#define REPORT_LUNS_BUFF_LEN 1024

#define ME "sg_luns: "


static struct option long_options[] = {
        {"decode", 0, 0, 'd'},
        {"help", 0, 0, 'h'},
        {"select", 1, 0, 's'},
        {"verbose", 0, 0, 'v'},
        {"version", 0, 0, 'V'},
        {0, 0, 0, 0},
};

static void usage()
{
    fprintf(stderr, "Usage: "
          "sg_luns    [--decode] [--help] [--select=<n>] [--verbose] "
          "[--version]\n"
          "                   <scsi_device>\n"
          "  where: --decode|-d        decode all luns into parts\n"
          "         --help|-h          print out usage message\n"
          "         --select=<n>|-s <n>  select report <n> (def: 0)\n"
          "                               0 -> luns apart from 'well "
          "known' lus\n"
          "                               1 -> only 'well known' "
          "logical unit numbers\n"
          "                               2 -> all luns\n"
          "         --verbose|-v       increase verbosity\n"
          "         --version|-V       print version string and exit\n\n"
          "Performs a REPORT LUNS SCSI command\n"
          );

}

/* Decoded according to SAM-4 rev 3 (plus 05-376r2). Note that one
 * draft: BCC rev 0, defines its own "bridge addressing method" in
 * place of the SAM-3 "logical addressing method".  */ 
static void decode_lun(const char * leadin, unsigned char * lunp)
{
    int k, j, x, a_method, bus_id, target, lun, len, e_a_method, next_level;
    unsigned char not_spec[8] = {0xff, 0xff, 0xff, 0xff,
                                 0xff, 0xff, 0xff, 0xff};
    char l_leadin[128];
    unsigned long long ull;

    if (0 == memcmp(lunp, not_spec, sizeof(not_spec))) {
        printf("%sLogical unit not specified\n", leadin);
        return;
    }
    memset(l_leadin, 0, sizeof(l_leadin));
    for (k = 0; k < 4; ++k, lunp += 2) {
        next_level = 0;
        strncpy(l_leadin, leadin, sizeof(l_leadin) - 3);
        if (k > 0) {
            printf("%s>>%s level addressing:\n", l_leadin,
                   ((1 == k) ? "Second" : ((2 == k) ? "Third" : "Fourth")));
            strcat(l_leadin, "  ");
        }
        a_method = (lunp[0] >> 6) & 0x3;
        switch (a_method) {
        case 0:         /* peripheral device addressing method */
            bus_id = lunp[0] & 0x3f;
            if (0 == bus_id)
                printf("%sPeripheral device addressing: lun=%d\n",
                       l_leadin, lunp[1]);
            else {
                printf("%sPeripheral device addressing: bus_id=%d, "
                       "target=%d\n", l_leadin, bus_id, lunp[1]);
                next_level = 1;
            }
            break;
        case 1:         /* flat space addressing method */
            lun = ((lunp[0] & 0x3f) << 8) + lunp[1];
            printf("%sFlat space addressing: lun=%d\n", l_leadin, lun);
            break;
        case 2:         /* logical unit addressing method */
            target = (lunp[0] & 0x3f);
            bus_id = (lunp[1] >> 5) & 0x7;
            lun = lunp[1] & 0x1f;
            printf("%sLogical unit addressing: bus_id=%d, target=%d, "
                   "lun=%d\n", l_leadin, bus_id, target, lun);
            break;
        case 3:         /* extended logical unit addressing method */
            len = (lunp[0] & 0x30) >> 4;
            e_a_method = lunp[0] & 0xf;
            x = lunp[1];
            if ((0 == len) && (1 == e_a_method)) {
                switch (x) {
                case 1:
                    printf("%sREPORT LUNS well known logical unit\n",
                           l_leadin);
                    break;
                case 2:
                    printf("%sACCESS CONTROLS well known logical unit\n",
                           l_leadin);
                    break;
                case 3:
                    printf("%sTARGET LOG PAGES well known logical unit\n",
                           l_leadin);
                    break;
                default:
                    printf("%swell known logical unit %d\n", l_leadin, x);
                    break;
                }
            } else if ((1 == len) && (2 == e_a_method)) {
                x = (lunp[1] << 16) + (lunp[2] << 8) + lunp[3];
                printf("%sExtended flat space logical unit addressing: "
                       "value=0x%x\n", l_leadin, x);
            } else if ((3 == len) && (0xf == e_a_method))
                printf("%sLogical unit _not_ specified addressing\n",
                       l_leadin);
            else {
                if (len < 2) {
                    if (1 == len)
                        x = (lunp[1] << 16) + (lunp[2] << 8) + lunp[3];
                    printf("%sExtended logical unit addressing: length=%d, "
                           "e.a. method=%d, value=0x%x\n", l_leadin, len,
                           e_a_method, x);
                } else {
                    ull = 0;
                    x = (2 == len) ? 5 : 7;
                    for (j = 0; j < x; ++j) {
                        if (j > 0)
                            ull <<= 8;
                        ull |= lunp[1 + j];
                    }
                    printf("%sExtended logical unit addressing: length=%d, "
                           "e. a. method=%d, value=0x%llx\n", l_leadin, len,
                           e_a_method, ull);
                }
            }
            break;
        default:
            printf("%s<<decode_lun: faulty logic>>\n", l_leadin);
            break;
        }
        if (next_level)
            continue;
        if ((2 == a_method) && (k < 3) && (lunp[2] || lunp[3]))
            printf("%s<<unexpected data at next level, continue>>\n",
                   l_leadin);
        break;
    }
}

int main(int argc, char * argv[])
{
    int sg_fd, k, m, off, res, c, list_len, luns, trunc;
    unsigned char reportLunsBuff[REPORT_LUNS_BUFF_LEN];
    int decode = 0;
    int select_rep = 0;
    int verbose = 0;
    char device_name[256];
    int ret = 1;

    memset(device_name, 0, sizeof device_name);
    while (1) {
        int option_index = 0;

        c = getopt_long(argc, argv, "dhs:vV", long_options,
                        &option_index);
        if (c == -1)
            break;

        switch (c) {
        case 'd':
            decode = 1;
            break;
        case 'h':
        case '?':
            usage();
            return 0;
        case 's':
           if ((1 != sscanf(optarg, "%d", &select_rep)) ||
               (select_rep < 0) || (select_rep > 255)) {
                fprintf(stderr, "bad argument to '--select'\n");
                return 1;
            }
            break;
        case 'v':
            ++verbose;
            break;
        case 'V':
            fprintf(stderr, ME "version: %s\n", version_str);
            return 0;
        default:
            fprintf(stderr, "unrecognised switch code 0x%x ??\n", c);
            usage();
            return 1;
        }
    }
    if (optind < argc) {
        if ('\0' == device_name[0]) {
            strncpy(device_name, argv[optind], sizeof(device_name) - 1);
            device_name[sizeof(device_name) - 1] = '\0';
            ++optind;
        }
        if (optind < argc) {
            for (; optind < argc; ++optind)
                fprintf(stderr, "Unexpected extra argument: %s\n",
                        argv[optind]);
            usage();
            return 1;
        }
    }

    if (0 == device_name[0]) {
        fprintf(stderr, "missing device name!\n");
        usage();
        return 1;
    }
    sg_fd = open(device_name, O_RDWR | O_NONBLOCK);
    if (sg_fd < 0) {
        fprintf(stderr, ME "open error: %s: ", device_name);
        perror("");
        return 1;
    }

    memset(reportLunsBuff, 0x0, sizeof(reportLunsBuff));
    trunc = 0;

    res = sg_ll_report_luns(sg_fd, select_rep, reportLunsBuff,
                            sizeof(reportLunsBuff), 1, verbose);
    if (0 == res) {
        list_len = (reportLunsBuff[0] << 24) + (reportLunsBuff[1] << 16) +
                   (reportLunsBuff[2] << 8) + reportLunsBuff[3];
        luns = (list_len / 8);
        printf("Lun list length = %d which imples %d lun entr%s\n",
               list_len, luns, ((1 == luns) ? "y" : "ies"));
        if ((list_len + 8) > (int)sizeof(reportLunsBuff)) {
            luns = ((sizeof(reportLunsBuff) - 8) / 8);
            trunc = 1;
            printf("  <<too many luns for internal buffer, will show %d "
                   "luns>>\n", luns);
        }
        if (verbose) {
            fprintf(stderr, "\nOutput response in hex\n");
            dStrHex((const char *)reportLunsBuff,
                    (trunc ? (int)sizeof(reportLunsBuff) : list_len + 8), 1);
        }
        for (k = 0, off = 8; k < luns; ++k) {
            if (0 == k)
                printf("Report luns [select_report=%d]:\n", select_rep);
            printf("    ");
            for (m = 0; m < 8; ++m, ++off)
                printf("%02x", reportLunsBuff[off]);
            printf("\n");
            if (decode)
                decode_lun("      ", reportLunsBuff + off - 8);
        }
        ret = 0;
    } else if (SG_LIB_CAT_INVALID_OP == res)
        fprintf(stderr, "Report Luns command not supported (support "
                "mandatory in SPC-3)\n");
    else if (SG_LIB_CAT_ILLEGAL_REQ == res)
        fprintf(stderr, "Report Luns command has bad fields in cdb\n");
    else {
        fprintf(stderr, "Report Luns command failed\n");
        if (0 == verbose)
            fprintf(stderr, "    try '-v' option for more information\n");
    }

    res = close(sg_fd);
    if (res < 0) {
        perror(ME "close error");
        return 1;
    }
    return ret;
}

  parent reply	other threads:[~2005-10-23  5:21 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-10-23  4:33 [PATCH RFC] use struct scsi_lun in generic code Jeff Garzik
2005-10-23  4:49 ` [PATCH RFC] more struct scsi_lun Jeff Garzik
2005-10-23  9:47   ` Stefan Richter
2005-10-23 13:14     ` Stefan Richter
2005-10-23 16:49       ` Jeff Garzik
2005-10-24 16:27         ` Luben Tuikov
2005-10-24 20:03           ` Stefan Richter
2005-10-24 20:10             ` Luben Tuikov
2005-10-24 20:28             ` Mark Rustad
2005-10-24 22:27             ` Douglas Gilbert
2005-10-23  5:20 ` [PATCH RFC] use struct scsi_lun in generic code Jeff Garzik
2005-10-23  5:22 ` Douglas Gilbert [this message]
2005-10-23  7:01   ` Jeff Garzik
2005-10-24 14:55   ` Luben Tuikov
2005-10-23  7:00 ` [PATCH RFC] yet more struct scsi_lun Jeff Garzik
2005-10-23 10:48   ` Douglas Gilbert
2005-10-23 11:53     ` Arjan van de Ven
2005-10-23 14:27       ` max_sectors [was Re: [PATCH RFC] yet more struct scsi_lun] Douglas Gilbert
2005-10-23 14:42         ` Arjan van de Ven
2005-10-23 16:44       ` [PATCH RFC] yet more struct scsi_lun Jeff Garzik
2005-10-23 16:43     ` Jeff Garzik
2005-10-23 18:53       ` Kai Makisara
2005-10-24  7:59       ` Jens Axboe
2005-10-28 17:24         ` Mike Christie
2005-10-31 10:24           ` Jens Axboe
2005-11-04  2:23             ` Mike Christie
2005-11-04  2:25               ` Mike Christie
2005-11-04  7:37               ` Jens Axboe
2005-11-04 17:27                 ` Mike Christie
2005-10-23  7:16 ` [PATCH RFC] even " Jeff Garzik
2005-10-24 15:27 ` [PATCH RFC] use struct scsi_lun in generic code Patrick Mansfield
2005-10-24 22:40   ` Douglas Gilbert

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=435B1E0E.8060409@torque.net \
    --to=dougg@torque.net \
    --cc=jgarzik@pobox.com \
    --cc=linux-scsi@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.