Search
j0ke.net Open Build Service
>
Projects
>
GFS
>
scsi
> sg3_utils-rdac-support.patch
Sign Up
|
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File sg3_utils-rdac-support.patch of Package scsi
diff -purN sg3_utils-1.19.orig/Makefile sg3_utils-1.19/Makefile --- sg3_utils-1.19.orig/Makefile 2006-01-04 14:00:13.000000000 +0100 +++ sg3_utils-1.19/Makefile 2006-04-04 16:05:30.000000000 +0200 @@ -10,12 +10,12 @@ CC = gcc LD = gcc EXECS = sg_dd sgp_dd sgm_dd sg_read sg_map sg_scan sg_rbuf \ - sginfo sg_readcap sg_turs sg_inq sg_test_rwbuf \ - sg_start sg_reset sg_modes sg_logs sg_senddiag sg_opcodes \ - sg_persist sg_write_long sg_read_long sg_requests sg_ses \ + sginfo sg_readcap sg_turs sg_inq sg_test_rwbuf \ + sg_start sg_reset sg_modes sg_logs sg_senddiag sg_opcodes \ + sg_persist sg_write_long sg_read_long sg_requests sg_ses \ sg_verify sg_emc_trespass sg_luns sg_sync sg_prevent \ sg_get_config sg_wr_mode sg_rtpg sg_reassign sg_format \ - sg_rmsn sg_ident sg_map26 + sg_rmsn sg_ident sg_map26 sg_rdac MAN_PGS = sg_dd.8 sgp_dd.8 sgm_dd.8 sg_read.8 sg_map.8 sg_scan.8 sg_rbuf.8 \ sginfo.8 sg_readcap.8 sg_turs.8 sg_inq.8 sg_test_rwbuf.8 \ @@ -24,7 +24,7 @@ MAN_PGS = sg_dd.8 sgp_dd.8 sgm_dd.8 sg_r sg_requests.8 sg_ses.8 sg_verify.8 sg_emc_trespass.8 \ sg_luns.8 sg_sync.8 sg_prevent.8 sg_get_config.8 sg_wr_mode.8 \ sg_rtpg.8 sg_reassign.8 sg_format.8 sg_rmsn.8 sg_ident.8 \ - sg_map26.8 + sg_map26.8 sg_rdac.8 MAN_PREF = man8 HEADERS = sg_lib.h sg_cmds.h sg_pt.h @@ -190,6 +190,10 @@ sg_ident: sg_ident.o libsgutils.la sg_map26: sg_map26.o libtool --mode=link $(LD) -o $@ $(LDFLAGS) $^ +sg_rdac: sg_rdac.o libsgutils.la + libtool --mode=link $(LD) -o $@ $(LDFLAGS) $^ + + install: $(EXECS) install -d $(INSTDIR) install -d $(LIBDIR) diff -purN sg3_utils-1.19.orig/sg_inq.c sg3_utils-1.19/sg_inq.c --- sg3_utils-1.19.orig/sg_inq.c 2006-01-24 13:41:47.000000000 +0100 +++ sg3_utils-1.19/sg_inq.c 2006-04-03 12:57:44.000000000 +0200 @@ -80,6 +80,8 @@ static char * version_str = "0.57 200501 #define ATA_INFO_VPD 0x89 #define BLOCK_LIMITS_VPD 0xb0 #define UPR_EMC_VPD 0xc0 +#define RDAC_VERS_VPD 0xc2 +#define RDAC_VAC_VPD 0xc9 #define DEF_ALLOC_LEN 252 #define SAFE_STD_INQ_RESP_LEN 36 @@ -181,8 +183,9 @@ static struct vpd_name vpd_name_arr[] = {0xb1, 0x11, "Security token (osd)"}, {0xc0, 0, "vendor: Firmware numbers (seagate); Unit path report (EMC)"}, {0xc1, 0, "vendor: Date code (seagate)"}, - {0xc2, 0, "vendor: Jumper settings (seagate)"}, + {0xc2, 0, "vendor: Jumper settings (seagate); Software version (RDAC)"}, {0xc3, 0, "vendor: Device behavior (seagate)"}, + {0xc9, 0, "Volume Access Control (RDAC)"}, }; const char * get_vpd_page_str(int vpd_page_num, int scsi_ptype) @@ -982,6 +985,83 @@ static void decode_upr_vpd_c0_emc(unsign return; } +static void decode_rdac_vpd_c2(unsigned char * buff, int len) +{ + if (len < 3) { + fprintf(stderr, "Software Version VPD page length too " + "short=%d\n", len); + return; + } + if (buff[4] != 's' && buff[5] != 'w' && buff[6] != 'r') { + fprintf(stderr, "Invalid page identifier %c%c%c%c, decoding " + "possible.\n" , buff[4], buff[5], buff[6], buff[7]); + return; + } + printf(" Software Version: %d.%d.%d\n", buff[8], buff[9], buff[10]); + printf(" Software Date: %02x/%02x/%02x\n", buff[11], buff[12], buff[13]); + printf(" Features:"); + if (buff[14] & 0x01) + printf(" Dual Active,"); + if (buff[14] & 0x02) + printf(" Series 3,"); + if (buff[14] & 0x04) + printf(" Multiple Sub-enclosures,"); + if (buff[14] & 0x08) + printf(" DCE/DRM,"); + if (buff[14] & 0x10) + printf(" AVT,"); + printf("\n"); + printf(" Max. #of LUNS: %d\n", buff[15]); + return; +} + +static void decode_rdac_vpd_c9(unsigned char * buff, int len) +{ + if (len < 3) { + fprintf(stderr, "Volume Access Control VPD page length too " + "short=%d\n", len); + return; + } + if (buff[4] != 'v' && buff[5] != 'a' && buff[6] != 'c') { + fprintf(stderr, "Invalid page identifier %c%c%c%c, decoding " + "possible.\n" , buff[4], buff[5], buff[6], buff[7]); + return; + } + if (buff[7] != '1') { + fprintf(stderr, "Invalid page version '%c' (should be 1)\n", + buff[7]); + } + printf(" AVT:"); + if (buff[8] & 0x80) { + printf(" Enabled"); + if (buff[8] & 0x40) + printf(" (Allow reads on sector 0)"); + printf("\n"); + } else { + printf(" Disabled\n"); + } + printf(" Volume Access via: "); + if (buff[8] & 0x01) + printf("primary controller\n"); + else + printf("alternate controller\n"); + + printf(" Path priority: %d ", buff[9] & 0xf); + switch(buff[9] & 0xf) { + case 0x1: + printf("(preferred path)\n"); + break; + case 0x2: + printf("(secondary path)\n"); + break; + default: + printf("(unknown)\n"); + break; + } + + return; +} + /* Returns 0 if Unit Serial Number VPD page contents found, else -1 */ static int fetch_unit_serial_num(int sg_fd, char * obuff, int obuff_len, int verbose) @@ -1642,6 +1722,64 @@ static int decode_vpd(int sg_fd, int num return 0; } break; + case RDAC_VERS_VPD: + if (!do_raw) + printf("VPD INQUIRY: Software Version (RDAC)\n"); + if (0 == sg_ll_inquiry(sg_fd, 0, 1, RDAC_VERS_VPD, rsp_buff, + DEF_ALLOC_LEN, 1, verbose)) { + len = rsp_buff[3] + 3; + if (RDAC_VERS_VPD != rsp_buff[1]) { + fprintf(stderr, "invalid VPD response; probably not " + "supported\n"); + return 1; + } + if (len > MX_ALLOC_LEN) { + fprintf(stderr, "response length too long: %d > %d\n", len, + MX_ALLOC_LEN); + return 1; + } else if (len > DEF_ALLOC_LEN) { + if (sg_ll_inquiry(sg_fd, 0, 1, RDAC_VERS_VPD, rsp_buff, len, 1, + verbose)) + return 1; + } + if (do_raw) + dStrRaw((const char *)rsp_buff, len); + else if (do_hex) + dStrHex((const char *)rsp_buff, len, 1); + else + decode_rdac_vpd_c2(rsp_buff, len); + return 0; + } + break; + case RDAC_VAC_VPD: + if (!do_raw) + printf("VPD INQUIRY: Volume Access Control (RDAC)\n"); + if (0 == sg_ll_inquiry(sg_fd, 0, 1, RDAC_VAC_VPD, rsp_buff, + DEF_ALLOC_LEN, 1, verbose)) { + len = rsp_buff[3] + 3; + if (RDAC_VAC_VPD != rsp_buff[1]) { + fprintf(stderr, "invalid VPD response; probably not " + "supported\n"); + return 1; + } + if (len > MX_ALLOC_LEN) { + fprintf(stderr, "response length too long: %d > %d\n", len, + MX_ALLOC_LEN); + return 1; + } else if (len > DEF_ALLOC_LEN) { + if (sg_ll_inquiry(sg_fd, 0, 1, RDAC_VAC_VPD, rsp_buff, len, 1, + verbose)) + return 1; + } + if (do_raw) + dStrRaw((const char *)rsp_buff, len); + else if (do_hex) + dStrHex((const char *)rsp_buff, len, 1); + else + decode_rdac_vpd_c9(rsp_buff, len); + return 0; + } + break; case SCSI_PORTS_VPD: if (!do_raw) printf("VPD INQUIRY: SCSI Ports page\n"); diff -purN sg3_utils-1.19.orig/sg_rdac.8 sg3_utils-1.19/sg_rdac.8 --- sg3_utils-1.19.orig/sg_rdac.8 1970-01-01 01:00:00.000000000 +0100 +++ sg3_utils-1.19/sg_rdac.8 2006-04-04 15:42:52.000000000 +0200 @@ -0,0 +1,33 @@ +.TH SG_RDAC "4" "Apr 2006" "sg3_utils-1.09" SG3_UTILS +.SH NAME +sg_rdac \- Display or Modify RDAC Redundant Controller Page +.SH SYNOPSIS +.B sg_rdac +[\fI-a\fR] [\fI-f=<lun>\fR] [\fI-v\fR] \fI<sg_device>\fR +.SH DESCRIPTION +.\" Add any additional description here +.PP +sg_rdac displays or modifies the RDAC controller settings via the +Redundant Controller Page (0x2C). When modifying the settings it +allows to transfer the ownership of individual drives to the +controller the command was received on. +.TP +-a +Transfer all (visible) devices +.TP +-f=<lun> +Transfer the device with LUN <lun>. This command will only work if +the controller supports 'Dual Active Mode' (aka active/active mode). +.TP +.TP +-v +be verbose +.SH AUTHOR +Written by Hannes Reinecke <hare at suse dot com>, based on sg_emc_trespass. +.SH "REPORTING BUGS" +Report bugs to <dgilbert at interlog dot com>. +.SH COPYRIGHT +Copyright \(co 2006 Hannes Reinecke, Douglas Gilbert. +.br +This software is distributed under the GPL version 2. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff -purN sg3_utils-1.19.orig/sg_rdac.c sg3_utils-1.19/sg_rdac.c --- sg3_utils-1.19.orig/sg_rdac.c 1970-01-01 01:00:00.000000000 +0100 +++ sg3_utils-1.19/sg_rdac.c 2006-04-04 15:35:52.000000000 +0200 @@ -0,0 +1,363 @@ +/* + * sg_rdac + * + * Retrieve / set RDAC options. + * + * Copyright (C) 2006 Hannes Reinecke <hare@suse.de> + * + * Based on sg_modes.c and sg_emc_trespass.c; credits from there apply. + * + * 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, or (at your option) + * any later version. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include "sg_lib.h" +#include "sg_cmds.h" +#include "sg_io_linux.h" + +unsigned char mode6_hdr[] = { + 75, /* Length */ + 0, /* medium */ + 0, /* params */ + 8, /* Block descriptor length */ +}; + +unsigned char block_descriptor[] = { + 0, /* Density code */ + 0, 0, 0, /* Number of blocks */ + 0, /* Reserved */ + 0, 0x02, 0, /* 512 byte blocks */ +}; + +struct rdac_legacy_page { + unsigned char page_code; + unsigned char page_length; + char current_serial[16]; + char alternate_serial[16]; + unsigned char current_mode_msb; + unsigned char current_mode_lsb; + unsigned char alternate_mode_msb; + unsigned char alternate_mode_lsb; + unsigned char quiescence; + unsigned char options; + unsigned char lun_table[32]; + unsigned char lun_table_exp[32]; + unsigned short reserved; +}; + +static int do_verbose = 0; + +static void dump_mode_page( unsigned char *page, int len ) +{ + int i, k; + + for (k = 0; k < len; k += 16) { + + printf("%x:",k / 16); + for (i = 0; i < 16; i++) { + printf(" %02x", page[k + i]); + if (k + i >= len) { + printf("\n"); + break; + } + } + printf("\n"); + } + +} + +#define MX_ALLOC_LEN (1024 * 4) +#define RDAC_CONTROLLER_PAGE 0x2c +#define RDAC_CONTROLLER_PAGE_LEN 0x68 +#define LEGACY_PAGE 0x00 +#define EXPANDED_LUN_SPACE_PAGE 0x01 +#define RDAC_FAIL_ALL_PATHS 0x1 +#define RDAC_FAIL_SELECTED_PATHS 0x2 +#define RDAC_FORCE_QUIESCENCE 0x2 +#define RDAC_QUIESCENCE_TIME 10 + +static int fail_all_paths(int fd) +{ + unsigned char fail_paths_pg[118]; + struct rdac_legacy_page *rdac_page; + int res; + + memset(fail_paths_pg, 0, 118); + memcpy(fail_paths_pg, mode6_hdr, 4); + memcpy(fail_paths_pg + 4, block_descriptor, 8); + rdac_page = (struct rdac_legacy_page *)(fail_paths_pg + 4 + 8); + rdac_page->page_code = RDAC_CONTROLLER_PAGE | 0x40; + rdac_page->page_length = RDAC_CONTROLLER_PAGE_LEN; + rdac_page->quiescence = RDAC_QUIESCENCE_TIME; + rdac_page->options = RDAC_FORCE_QUIESCENCE; + rdac_page->current_mode_lsb = RDAC_FAIL_ALL_PATHS; + + res = sg_ll_mode_select6(fd, 1 /* pf */, 0 /* sp */, + fail_paths_pg, 118, + 1, (do_verbose ? 2 : 0)); + + switch (res) { + case 0: + if (do_verbose) + fprintf(stderr, "fail paths successful\n"); + break; + case SG_LIB_CAT_INVALID_OP: + fprintf(stderr, "fail paths page failed (Invalid opcode)\n"); + break; + case SG_LIB_CAT_ILLEGAL_REQ: + fprintf(stderr, "fail paths page failed (illegal request)\n"); + break; + default: + if (do_verbose) + fprintf(stderr, "fail paths failed\n"); + break; + } + + return res; +} + +static int fail_this_path(int fd, int lun) +{ + unsigned char fail_paths_pg[118]; + struct rdac_legacy_page *rdac_page; + int res; + + memset(fail_paths_pg, 0, 118); + memcpy(fail_paths_pg, mode6_hdr, 4); + memcpy(fail_paths_pg + 4, block_descriptor, 8); + rdac_page = (struct rdac_legacy_page *)(fail_paths_pg + 4 + 8); + rdac_page->page_code = RDAC_CONTROLLER_PAGE | 0x40; + rdac_page->page_length = RDAC_CONTROLLER_PAGE_LEN; + rdac_page->current_mode_lsb = RDAC_FAIL_SELECTED_PATHS; + rdac_page->quiescence = RDAC_QUIESCENCE_TIME; + rdac_page->options = RDAC_FORCE_QUIESCENCE; + memset(rdac_page->lun_table, 0x0, 32); + rdac_page->lun_table[lun] = 0x81; + + res = sg_ll_mode_select6(fd, 1 /* pf */, 0 /* sp */, + fail_paths_pg, 118, + 1, (do_verbose ? 2 : 0)); + + switch (res) { + case 0: + if (do_verbose) + fprintf(stderr, "fail paths successful\n"); + break; + case SG_LIB_CAT_INVALID_OP: + fprintf(stderr, "fail paths page failed (Invalid opcode)\n"); + break; + case SG_LIB_CAT_ILLEGAL_REQ: + fprintf(stderr, "fail lun %d page failed (illegal request)\n", + lun); + break; + default: + if (do_verbose) + fprintf(stderr, "fail paths failed\n"); + break; + } + + return res; +} + +static void print_rdac_mode( unsigned char *ptr ) +{ + struct rdac_legacy_page *rdac_ptr; + int i, k, bd_len; + + bd_len = ptr[3]; + + rdac_ptr = (struct rdac_legacy_page *)(ptr + 4 + bd_len); + + printf("RDAC Legacy page\n"); + printf(" Controller serial: %s\n", + rdac_ptr->current_serial); + printf(" Alternate controller serial: %s\n", + rdac_ptr->alternate_serial); + printf(" RDAC mode (redundant processor): "); + switch (rdac_ptr->current_mode_msb) { + case 0x00: + printf("alternate controller not present; "); + break; + case 0x01: + printf("alternate controller present; "); + break; + default: + printf("(Unknown controller status 0x%x); ", + rdac_ptr->current_mode_msb); + break; + } + switch (rdac_ptr->current_mode_lsb) { + case 0x0: + printf("inactive\n"); + break; + case 0x1: + printf("active\n"); + break; + case 0x2: + printf("Dual active mode\n"); + break; + default: + printf("(Unknown mode 0x%x)\n", + rdac_ptr->current_mode_lsb); + } + + printf(" RDAC mode (alternate processor): "); + switch (rdac_ptr->alternate_mode_msb) { + case 0x00: + printf("alternate controller not present; "); + break; + case 0x01: + printf("alternate controller present; "); + break; + case 0x02: + printf("active/active mode; "); + break; + default: + printf("(Unknown status 0x%x); ", + rdac_ptr->alternate_mode_msb); + break; + } + switch (rdac_ptr->alternate_mode_lsb) { + case 0x0: + printf("inactive\n"); + break; + case 0x1: + printf("active\n"); + break; + case 0x2: + printf("Dual active mode\n"); + break; + case 0x04: + printf("held in reset\n"); + break; + default: + printf("(Unknown mode 0x%x)\n", + rdac_ptr->alternate_mode_lsb); + } + printf(" Quiescence timeout: %d\n", rdac_ptr->quiescence); + printf(" RDAC option 0x%x\n", rdac_ptr->options); + printf (" LUN Table:\n"); + for (k = 0; k < 32; k += 8) { + printf(" %x:",k / 8); + for (i = 0; i < 8; i++) { + switch (rdac_ptr->lun_table[k + i]) { + case 0x0: + printf(" x"); + break; + case 0x1: + printf(" p"); + break; + case 0x2: + printf(" a"); + break; + case 0x3: + printf(" u"); + break; + default: + printf(" ?"); + break; + } + } + printf("\n"); + } +} + +static void usage() +{ + printf("Usage: sg_rdac [-a] [-f=<lun>] [-v] <scsi_device>\n" + " where -a transfer all devices to the controller\n" + " serving <scsi_device>.\n" + " -f=<lun> transfer the device with LUN <lun> to the\n" + " controller serving <scsi_device>\n" + " -v verbose\n" + " Display/Modify RDAC Redundant Controller Page 0x2c.\n" + " If [-a] or [-f] is not specified the current settings" + " are displayed.\n"); +} + +int main(int argc, char * argv[]) +{ + unsigned char rsp_buff[MX_ALLOC_LEN]; + char **argptr; + char * file_name = 0; + int res, fd, k, lun = -1; + int fail_all = 0; + int fail_path = 0; + + if (argc < 2) + usage (); + + for (k = 1; k < argc; ++k) { + argptr = argv + k; + if (!strcmp (*argptr, "-v")) + ++do_verbose; + else if (!strncmp(*argptr, "-f=",3)) { + ++fail_path; + lun = strtoul(*argptr + 3, NULL, 0); + } + else if (!strcmp(*argptr, "-a")) { + ++fail_all; + } + else if (*argv[k] == '-') { + fprintf(stderr, "Unrecognized switch: %s\n", argv[k]); + file_name = 0; + break; + } + else if (0 == file_name) + file_name = argv[k]; + else { + fprintf(stderr, "too many arguments\n"); + file_name = 0; + break; + } + } + if (0 == file_name) { + usage(); + return 1; + } + + fd = open(file_name, O_RDWR | O_NONBLOCK); + if (fd < 0) { + fprintf(stderr, "Error trying to open %s\n", file_name); + perror(""); + usage(); + return 2; + } + + if (do_verbose) + dump_mode_page(rsp_buff, rsp_buff[0]); + + if (fail_all) { + res = fail_all_paths(fd); + } else if (fail_path) { + res = fail_this_path(fd, lun); + } else { + res = sg_ll_mode_sense6(fd, /*DBD*/ 0, /* page control */0, + 0x2c, 0, rsp_buff, 252, + 1, do_verbose); + + if (!res) + print_rdac_mode(rsp_buff); + } + if (SG_LIB_CAT_INVALID_OP == res) + fprintf(stderr, ">>>>>> try again without the '-6' " + "switch for a 10 byte MODE SENSE command\n"); + else if (SG_LIB_CAT_ILLEGAL_REQ == res) + fprintf(stderr, "invalid field in cdb (perhaps subpages " + "or page control (PC) not supported)\n"); + else if (res) + fprintf(stderr," mode sense failed\n"); + + close (fd); + return res?1:0; +}