From d25c37a87dcd08eacbdcc602969fa1ae2b50b616 Mon Sep 17 00:00:00 2001 From: brking Date: Mon, 26 Sep 2005 20:19:36 +0000 Subject: [PATCH] Code cleanup, various updates --- Makefile | 4 +- debug/iprcache.c | 102 +++++++++++ debug/iprperf.c | 154 +++++++++++++++++ debug/iprshutdown.c | 86 ++++++++++ debug/iprtest.c | 184 ++++++++++++++++++++ debug/iprwritebuffer.c | 81 +++++++++ iprconfig.8 | 9 + iprconfig.c | 377 +++++++++++++++++++++++------------------ iprdbg.c | 66 +++++++- iprlib.c | 31 +++- iprlib.h | 53 +++--- spec/iprutils.spec | 16 ++ version.mk | 4 +- 13 files changed, 966 insertions(+), 201 deletions(-) create mode 100755 debug/iprcache.c create mode 100755 debug/iprperf.c create mode 100755 debug/iprshutdown.c create mode 100755 debug/iprtest.c create mode 100755 debug/iprwritebuffer.c diff --git a/Makefile b/Makefile index 4af49db..d81f343 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ include version.mk CFLAGS = -g -Wall $(IPR_DEFINES) UTILS_VER = $(IPR_MAJOR_RELEASE).$(IPR_MINOR_RELEASE).$(IPR_FIX_LEVEL) -TAR = cd .. && tar -zcpf iprutils-$(UTILS_VER)-src.tgz --exclude CVS --exclude applied-patches --exclude series --exclude txt --exclude pc --exclude patches --exclude *~* iprutils +TAR = cd .. && tar -zcpf iprutils-$(UTILS_VER)-src.tgz --exclude CVS --exclude applied-patches --exclude series --exclude txt --exclude pc --exclude patches --exclude debug --exclude *~* iprutils all: iprconfig iprupdate iprdump iprinit iprdbg docs @@ -28,7 +28,7 @@ iprinit:iprinit.c iprlib.o $(CC) $(CFLAGS) $(INCLUDEDIR) -o iprinit iprlib.o iprinit.c -lsysfs iprdbg:iprdbg.c iprlib.o - $(CC) $(CFLAGS) $(INCLUDEDIR) -o iprdbg iprlib.o iprdbg.c -lsysfs + $(CC) $(CFLAGS) $(INCLUDEDIR) -o iprdbg iprlib.o iprdbg.c -lsysfs -lncurses iprucode:iprucode.c iprlib.o $(CC) $(CFLAGS) $(INCLUDEDIR) -o iprucode iprlib.o iprucode.c -lsysfs diff --git a/debug/iprcache.c b/debug/iprcache.c new file mode 100755 index 0000000..7178a21 --- /dev/null +++ b/debug/iprcache.c @@ -0,0 +1,102 @@ +/** + * IBM IPR adapter drive write caching utility + * + * (C) Copyright 2005 + * International Business Machines Corporation and others. + * All Rights Reserved. This program and the accompanying + * materials are made available under the terms of the + * Common Public License v1.0 which accompanies this distribution. + * + */ + +/* + * $Header: /cvsroot/iprdd/iprutils/debug/iprcache.c,v 1.1 2005/09/26 20:19:36 brking Exp $ + */ + +#include +#include +#include +#include +#include + +#ifndef iprlib_h +#include "iprlib.h" +#endif + +#include + +char *tool_name = "iprcache"; + +struct ipr_caching_mode_page { + /* Mode page 0x08 */ + struct ipr_mode_page_hdr hdr; +#if defined (__BIG_ENDIAN_BITFIELD) + u8 ic:1; + u8 abpf:1; + u8 cap:1; + u8 disc:1; + u8 size:1; + u8 wce:1; + u8 mf:1; + u8 rcd:1; +#elif defined (__LITTLE_ENDIAN_BITFIELD) + u8 rcd:1; + u8 mf:1; + u8 wce:1; + u8 size:1; + u8 disc:1; + u8 cap:1; + u8 abpf:1; + u8 ic:1; +#endif + + u8 data[17]; +}; + +static int set_caching_page(struct ipr_dev *dev) +{ + struct ipr_mode_pages mode_pages; + struct ipr_caching_mode_page *page; + int rc; + int len; + + rc = ipr_mode_sense(dev, 8, &mode_pages); + if (rc) + return rc; + + page = (struct ipr_caching_mode_page *) (((u8 *)&mode_pages) + + mode_pages.hdr.block_desc_len + + sizeof(mode_pages.hdr)); + + page->wce = 0; + + len = mode_pages.hdr.length + 1; + mode_pages.hdr.length = 0; + mode_pages.hdr.medium_type = 0; + mode_pages.hdr.device_spec_parms = 0; + page->hdr.parms_saveable = 0; + + rc = ipr_mode_select(dev, &mode_pages, len); + + return rc; +} + +int main(int argc, char *argv[]) +{ + struct ipr_dev *dev; + int rc; + + openlog("iprcache", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER); + tool_init(1); + check_current_config(false); + dev = find_gen_dev(argv[1]); + if (!dev) + dev = find_blk_dev(argv[1]); + + if (!dev) { + fprintf(stderr, "Cannot find %s\n", argv[1]); + return -EINVAL; + } + + return set_caching_page(dev); +} diff --git a/debug/iprperf.c b/debug/iprperf.c new file mode 100755 index 0000000..15a5bad --- /dev/null +++ b/debug/iprperf.c @@ -0,0 +1,154 @@ +/** + * IBM IPR adapter performance analysis utility + * + * (C) Copyright 2005 + * International Business Machines Corporation and others. + * All Rights Reserved. This program and the accompanying + * materials are made available under the terms of the + * Common Public License v1.0 which accompanies this distribution. + * + */ + +/* + * $Header: /cvsroot/iprdd/iprutils/debug/iprperf.c,v 1.1 2005/09/26 20:19:36 brking Exp $ + */ + +#include +#include +#include +#include +#include + +#ifndef iprlib_h +#include "iprlib.h" +#endif + +#include + +char *tool_name = "iprperf"; + +struct log_sense { + u8 page_code; + u8 reserved; + u16 len; + u8 reserved2[3]; + u8 parm_len; + u16 num_seeks_0; + u16 num_seeks_gt_2_3; + u16 num_seeks_gt_1_3; + u16 num_seeks_gt_1_6; + u16 num_seeks_gt_1_12; + u16 num_seeks_gt_0; + u8 reserved3[4]; + u16 num_dev_read_buf_overruns; + u16 num_dev_write_buf_overruns; + u32 num_dev_cache_read_hits; + u32 num_dev_cache_partial_read_hits; + u32 num_dev_cache_write_hits; + u32 num_dev_cache_fast_writes; + u32 reserved4[2]; + u32 num_device_read_ops; + u32 num_device_write_ops; + u32 num_ioa_cache_read_hits; + u32 num_ioa_cache_partial_read_hits; + u32 num_ioa_cache_write_hits; + u32 num_ioa_cache_fast_writes; + u32 num_ioa_emul_read_cache_hits; + u32 ioa_idle_loop_count[2]; + u32 ioa_idle_loop_count_value; + u8 ioa_idle_count_value_units; + u8 reserved5[3]; +}; + +static int get_counters(struct ipr_dev *dev, struct log_sense *log) +{ + int fd; + u8 cdb[IPR_CCB_CDB_LEN]; + struct sense_data_t sense_data; + int rc; + + if (strlen(dev->gen_name) == 0) + return -ENOENT; + + fd = open(dev->gen_name, O_RDWR); + if (fd <= 1) { + syslog(LOG_ERR, "Could not open %s. %m\n", dev->gen_name); + return errno; + } + + memset(cdb, 0, IPR_CCB_CDB_LEN); + memset(log, 0, sizeof(*log)); + + cdb[0] = LOG_SENSE; + cdb[2] = 0x70; + cdb[7] = sizeof(*log) >> 8; + cdb[8] = sizeof(*log) & 0xff; + + rc = sg_ioctl(fd, cdb, log, + sizeof(*log), SG_DXFER_FROM_DEV, + &sense_data, IPR_ARRAY_CMD_TIMEOUT); + + if (rc != 0) + scsi_cmd_err(dev, &sense_data, "Log Sense", rc); + + close(fd); + return rc; +} + +static void print_counters(struct ipr_dev *dev, struct log_sense *log) +{ + printf("Number of seeks = zero length : %d\n", ntohs(log->num_seeks_0)); + printf("Number of seeks >= 2/3 disk : %d\n", ntohs(log->num_seeks_gt_2_3)); + printf("Number of seeks >= 1/3 and < 2/3 disk : %d\n", ntohs(log->num_seeks_gt_1_3)); + printf("Number of seeks >= 1/6 and < 1/3 disk : %d\n", ntohs(log->num_seeks_gt_1_6)); + printf("Number of seeks >= 1/12 and < 1/6 disk : %d\n", ntohs(log->num_seeks_gt_1_12)); + printf("Number of seeks > 0 and < 1/12 disk : %d\n", ntohs(log->num_seeks_gt_0)); + printf("Number of device read buffer overruns : %d\n", ntohs(log->num_dev_read_buf_overruns)); + printf("Number of device write buffer underruns : %d\n", ntohs(log->num_dev_write_buf_overruns)); + printf("Number of device cache read hits : %d\n", ntohl(log->num_dev_cache_read_hits)); + printf("Number of device cache partial read hits : %d\n", ntohl(log->num_dev_cache_partial_read_hits)); + printf("Number of device cache write hits : %d\n", ntohl(log->num_dev_cache_write_hits)); + printf("Number of device cache fast writes : %d\n", ntohl(log->num_dev_cache_fast_writes)); + + if (ipr_is_gscsi(dev)) + return; + + printf("\n"); + printf("Number of device read ops : %d\n", ntohl(log->num_device_read_ops)); + printf("Number of device write ops : %d\n", ntohl(log->num_device_write_ops)); + printf("Number of IOA cache read hits : %d\n", ntohl(log->num_ioa_cache_read_hits)); + printf("Number of IOA cache partial read hits : %d\n", ntohl(log->num_ioa_cache_partial_read_hits)); + printf("Number of IOA cache write hits : %d\n", ntohl(log->num_ioa_cache_write_hits)); + printf("Number of IOA cache fast writes : %d\n", ntohl(log->num_ioa_cache_fast_writes)); + printf("Number of IOA emulated read cache hits : %d\n", ntohl(log->num_ioa_emul_read_cache_hits)); + printf("IOA Idle loop count : %X%08X\n", + ntohl(log->ioa_idle_loop_count[0]), ntohl(log->ioa_idle_loop_count[1])); + printf("IOA Idle loop count value : %X\n", ntohl(log->ioa_idle_loop_count_value)); + printf("IOA Idle count value units : %d\n", log->ioa_idle_count_value_units); +} + +int main(int argc, char *argv[]) +{ + struct ipr_dev *dev; + struct log_sense log; + int rc; + + openlog("iprperf", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER); + tool_init(1); + check_current_config(false); + dev = find_gen_dev(argv[1]); + if (!dev) + dev = find_blk_dev(argv[1]); + + if (!dev) { + fprintf(stderr, "Cannot find %s\n", argv[1]); + return -EINVAL; + } + + rc = get_counters(dev, &log); + if (rc) + return rc; + + print_counters(dev, &log); + return 0; +} diff --git a/debug/iprshutdown.c b/debug/iprshutdown.c new file mode 100755 index 0000000..37e093b --- /dev/null +++ b/debug/iprshutdown.c @@ -0,0 +1,86 @@ +/** + * IBM IPR adapter shutdown utility + * + * (C) Copyright 2005 + * International Business Machines Corporation and others. + * All Rights Reserved. This program and the accompanying + * materials are made available under the terms of the + * Common Public License v1.0 which accompanies this distribution. + * + */ + +/* + * $Header: /cvsroot/iprdd/iprutils/debug/iprshutdown.c,v 1.1 2005/09/26 20:19:36 brking Exp $ + */ + +#include +#include +#include +#include +#include + +#ifndef iprlib_h +#include "iprlib.h" +#endif + +#include + +char *tool_name = "iprshutdown"; + +static void init_all() +{ + struct ipr_ioa *ioa; + + tool_init(1); + check_current_config(false); + for_each_ioa(ioa) + ipr_init_ioa(ioa); +} + +static int ipr_ioa_flush(struct ipr_ioa *ioa) +{ + int fd; + u8 cdb[IPR_CCB_CDB_LEN]; + struct sense_data_t sense_data; + int rc; + + if (strlen(ioa->ioa.gen_name) == 0) + return -ENOENT; + + fd = open(ioa->ioa.gen_name, O_RDWR); + if (fd <= 1) { + syslog(LOG_ERR, "Could not open %s. %m\n", ioa->ioa.gen_name); + return errno; + } + + memset(cdb, 0, IPR_CCB_CDB_LEN); + + cdb[0] = 0xF7; + cdb[1] = 0x40; + + rc = sg_ioctl(fd, cdb, ioa->qac_data, + 0, SG_DXFER_TO_DEV, + &sense_data, IPR_ARRAY_CMD_TIMEOUT); + + if (rc != 0) + ioa_cmd_err(ioa, &sense_data, 0xF7, rc); + + close(fd); + return rc; +} + +int main(int argc, char *argv[]) +{ + struct ipr_ioa *ioa; + + tool_init(1); + check_current_config(false); + for_each_ioa(ioa) { + if (!strcmp(ioa->ioa.gen_name, argv[1])) { + ipr_ioa_flush(ioa); + return 0; + } + } + + return -EINVAL; +} diff --git a/debug/iprtest.c b/debug/iprtest.c new file mode 100755 index 0000000..ed8c7b3 --- /dev/null +++ b/debug/iprtest.c @@ -0,0 +1,184 @@ +/** + * IBM IPR adapter performance utility + * + * (C) Copyright 2005 + * International Business Machines Corporation and others. + * All Rights Reserved. This program and the accompanying + * materials are made available under the terms of the + * Common Public License v1.0 which accompanies this distribution. + * + */ + +/* + * $Header: /cvsroot/iprdd/iprutils/debug/iprtest.c,v 1.1 2005/09/26 20:19:36 brking Exp $ + */ + +#include +#include +#include +#include +#include + +#ifndef iprlib_h +#include "iprlib.h" +#endif + +#include + +char *tool_name = "iprperf"; + +struct log_sense { + u8 page_code; + u8 reserved; + u16 len; + u8 reserved2[3]; + u8 parm_len; + u16 num_seeks_0; + u16 num_seeks_gt_2_3; + u16 num_seeks_gt_1_3; + u16 num_seeks_gt_1_6; + u16 num_seeks_gt_1_12; + u16 num_seeks_gt_0; + u8 reserved3[4]; + u16 num_dev_read_buf_overruns; + u16 num_dev_write_buf_overruns; + u32 num_dev_cache_read_hits; + u32 num_dev_cache_partial_read_hits; + u32 num_dev_cache_write_hits; + u32 num_dev_cache_fast_writes; + u32 reserved4[2]; + u32 num_device_read_ops; + u32 num_device_write_ops; + u32 num_ioa_cache_read_hits; + u32 num_ioa_cache_partial_read_hits; + u32 num_ioa_cache_write_hits; + u32 num_ioa_cache_fast_writes; + u32 num_ioa_emul_read_cache_hits; + u32 ioa_idle_loop_count[2]; + u32 ioa_idle_loop_count_value; + u8 ioa_idle_count_value_units; + u8 reserved5[3]; +}; + +static int get_counters(struct ipr_dev *dev, struct log_sense *log) +{ + int fd; + u8 cdb[IPR_CCB_CDB_LEN]; + struct sense_data_t sense_data; + int rc; + + if (strlen(dev->gen_name) == 0) + return -ENOENT; + + fd = open(dev->gen_name, O_RDWR); + if (fd <= 1) { + syslog(LOG_ERR, "Could not open %s. %m\n", dev->gen_name); + return errno; + } + + memset(cdb, 0, IPR_CCB_CDB_LEN); + memset(log, 0, sizeof(*log)); + + cdb[0] = LOG_SENSE; + cdb[2] = 0x70; + cdb[7] = sizeof(*log) >> 8; + cdb[8] = sizeof(*log) & 0xff; + + rc = sg_ioctl(fd, cdb, log, + sizeof(*log), SG_DXFER_FROM_DEV, + &sense_data, IPR_ARRAY_CMD_TIMEOUT); + + if (rc != 0) + scsi_cmd_err(dev, &sense_data, "Log Sense", rc); + + close(fd); + return rc; +} + +#define logd(item, desc, xlate) \ +if (old_log->item != new_log->item) \ + printf("%s: %d\n", desc, xlate(new_log->item) - xlate(old_log->item)); \ + +#define logs(desc, item) logd(item, desc, ntohs) +#define logl(desc, item) logd(item, desc, ntohl) + +static void print_counters(struct ipr_dev *dev, struct log_sense *old_log, struct log_sense *new_log) +{ + printf("===============================================\n"); + scsi_info(dev, "Device counters\n"); + logs("Number of seeks = zero length ", num_seeks_0); + logs("Number of seeks >= 2/3 disk ", num_seeks_gt_2_3); + logs("Number of seeks >= 1/3 and < 2/3 disk ", num_seeks_gt_1_3); + logs("Number of seeks >= 1/6 and < 1/3 disk ", num_seeks_gt_1_6); + logs("Number of seeks >= 1/12 and < 1/6 disk ", num_seeks_gt_1_12); + logs("Number of seeks > 0 and < 1/12 disk ", num_seeks_gt_0); + logs("Number of device read buffer overruns ", num_dev_read_buf_overruns); + logs("Number of device write buffer underruns ", num_dev_write_buf_overruns); + logl("Number of device cache read hits ", num_dev_cache_read_hits); + logl("Number of device cache partial read hits ", num_dev_cache_partial_read_hits); + logl("Number of device cache write hits ", num_dev_cache_write_hits); + logl("Number of device cache fast writes ", num_dev_cache_fast_writes); + + if (ipr_is_gscsi(dev)) { + printf("===============================================\n"); + return; + } + + logl("Number of device read ops ", num_device_read_ops); + logl("Number of device write ops ", num_device_write_ops); + logl("Number of IOA cache read hits ", num_ioa_cache_read_hits); + logl("Number of IOA cache partial read hits ", num_ioa_cache_partial_read_hits); + logl("Number of IOA cache write hits ", num_ioa_cache_write_hits); + logl("Number of IOA cache fast writes ", num_ioa_cache_fast_writes); + logl("Number of IOA emulated read cache hits ", num_ioa_emul_read_cache_hits); + logl("IOA Idle loop count[0] ", ioa_idle_loop_count[0]); + logl("IOA Idle loop count[1] ", ioa_idle_loop_count[1]); + printf("IOA Idle loop count value : %X\n", ntohl(new_log->ioa_idle_loop_count_value)); + printf("IOA Idle count value units : %d\n", new_log->ioa_idle_count_value_units); + printf("===============================================\n"); +} + +int main(int argc, char *argv[]) +{ + struct ipr_dev *dev[2]; + struct log_sense old_log[2], new_log[2]; + int rc, i; + + openlog("iprperf", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER); + tool_init(1); + check_current_config(false); + + for (i = 0; i < 2; i++) { + dev[i] = find_gen_dev(argv[1+i]); + if (!dev[i]) + dev[i] = find_blk_dev(argv[1+i]); + + if (!dev[i]) { + fprintf(stderr, "Cannot find %s\n", argv[1+i]); + return -EINVAL; + } + } + + for (i = 0; i < 2; i++) { + rc = get_counters(dev[i], &old_log[i]); + if (rc) + return rc; + } + + printf("***********************************************\n"); + system(argv[3]); + + for (i = 0; i < 2; i++) { + rc = get_counters(dev[i], &new_log[i]); + if (rc) + return rc; + } + + for (i = 0; i < 2; i++) { + print_counters(dev[i], &old_log[i], &new_log[i]); + } + + printf("***********************************************\n"); + + return 0; +} diff --git a/debug/iprwritebuffer.c b/debug/iprwritebuffer.c new file mode 100755 index 0000000..05909d3 --- /dev/null +++ b/debug/iprwritebuffer.c @@ -0,0 +1,81 @@ +/** + * IBM IPR adapter low level drive microcode update utility + * + * (C) Copyright 2005 + * International Business Machines Corporation and others. + * All Rights Reserved. This program and the accompanying + * materials are made available under the terms of the + * Common Public License v1.0 which accompanies this distribution. + * + */ + +/* + * $Header: /cvsroot/iprdd/iprutils/debug/iprwritebuffer.c,v 1.1 2005/09/26 20:19:36 brking Exp $ + */ + +#include +#include +#include +#include +#include + +#ifndef iprlib_h +#include "iprlib.h" +#endif + +#include + +char *tool_name = "iprwritebuffer"; + +static int ipr_update_ucode(struct ipr_dev *dev, char *fname) +{ + struct stat ucode_stats; + int fd, rc; + char *buffer; + + fd = open(fname, O_RDONLY); + + if (fd < 0) { + syslog_dbg("Could not open firmware file %s.\n", fname); + return; + } + + rc = fstat(fd, &ucode_stats); + + if (rc != 0) { + syslog(LOG_ERR, "Failed to stat firmware file: %s.\n", fname); + close(fd); + return rc; + } + + buffer = mmap(NULL, ucode_stats.st_size, + PROT_READ, MAP_SHARED, fd, 0); + + rc = ipr_write_buffer(dev, buffer, ucode_stats.st_size); + ipr_init_dev(dev); + close(fd); + + return rc; +} + +int main(int argc, char *argv[]) +{ + struct ipr_dev *dev; + + if (argc != 3) { + fprintf(stderr, "Usage iprwritebuffer /dev/sgX ucode_image.bin\n"); + return -EINVAL; + } + + tool_init(1); + check_current_config(false); + dev = find_blk_dev(argv[1]); + if (!dev) + dev = find_gen_dev(argv[1]); + if (!dev) { + fprintf(stderr, "Cannot find device: %s\n", argv[1]); + return -EINVAL; + } + + return ipr_update_ucode(dev, argv[2]); +} diff --git a/iprconfig.8 b/iprconfig.8 index 0859531..2960618 100644 --- a/iprconfig.8 +++ b/iprconfig.8 @@ -173,6 +173,15 @@ name. Only 1 array can be deleted with a single command. Example: .br This would delete the disk array represented by /dev/sda .TP +.B status [device] +.br +Prints the status of the specified device. This is the same status as which shows +up in the last column of the Display hardware status menu. Can specify either a +/dev/sdX name or a /dev/sgX name. Example: +.br +.B iprconfig -c status /dev/sda +.br +.TP .B \-\-version Print version number of .B iprconfig diff --git a/iprconfig.c b/iprconfig.c index f620168..f2e28b9 100644 --- a/iprconfig.c +++ b/iprconfig.c @@ -3517,7 +3517,7 @@ int configure_raid_include(i_container *i_con) struct screen_output *s_out; for_each_icon(temp_i_con) { - cur_raid_cmd = i_con->data; + cur_raid_cmd = temp_i_con->data; if (!cur_raid_cmd) continue; @@ -4534,7 +4534,7 @@ int disk_unit_recovery(i_container *i_con) return rc; } -static void get_res_addr(struct ipr_dev *dev, struct ipr_res_addr *res_addr) +static int get_res_addr(struct ipr_dev *dev, struct ipr_res_addr *res_addr) { struct ipr_dev_record *dev_record = dev->dev_rcd; struct ipr_array_record *array_record = dev->array_rcd; @@ -4555,20 +4555,24 @@ static void get_res_addr(struct ipr_dev *dev, struct ipr_res_addr *res_addr) res_addr->bus = dev_record->resource_addr.bus; res_addr->target = dev_record->resource_addr.target; res_addr->lun = dev_record->resource_addr.lun; - } + } else + return -1; } else if (ipr_is_volume_set(dev)) { if (array_record && array_record->no_config_entry) { res_addr->host = dev->ioa->host_num; res_addr->bus = array_record->last_resource_addr.bus; res_addr->target = array_record->last_resource_addr.target; res_addr->lun = array_record->last_resource_addr.lun; - } else if (dev_record) { + } else if (array_record) { res_addr->host = dev->ioa->host_num; res_addr->bus = array_record->resource_addr.bus; res_addr->target = array_record->resource_addr.target; res_addr->lun = array_record->resource_addr.lun; - } - } + } else + return -1; + } else + return -1; + return 0; } int process_conc_maint(i_container *i_con, int action) @@ -4603,7 +4607,8 @@ int process_conc_maint(i_container *i_con, int action) if (found != 1) return INVALID_OPTION_STATUS; - get_res_addr(dev, &res_addr); + if (get_res_addr(dev, &res_addr)) + return INVALID_OPTION_STATUS; /* FIXME */ if (ipr_is_af_dasd_device(dev) && (action == IPR_VERIFY_CONC_REMOVE || action == IPR_WAIT_CONC_REMOVE)) { @@ -4795,6 +4800,7 @@ int start_conc_maint(i_container *i_con, int action) int toggle = 1; s_node *n_screen; int header_lines; + u8 scsi_id_found; processing(); @@ -4822,8 +4828,13 @@ int start_conc_maint(i_container *i_con, int action) continue; ses_channel = ses->scsi_dev_data->channel; + scsi_id_found = 0; for_each_elem_status(i, &ses_data) { + if (scsi_id_found & (1 << ses_data.elem_status[i].scsi_id)) + continue; + scsi_id_found |= (1 << ses_data.elem_status[i].scsi_id); + if (ses_data.elem_status[i].status == IPR_DRIVE_ELEM_STATUS_EMPTY) { local_dev = realloc(local_dev, (sizeof(void *) * local_dev_count) + 1); @@ -4844,7 +4855,10 @@ int start_conc_maint(i_container *i_con, int action) } for_each_dev(ioa, dev) { - get_res_addr(dev, &res_addr); + if (get_res_addr(dev, &res_addr)) { + scsi_dbg(dev, "Cannot find resource address\n"); + continue; + } if (res_addr.bus == ses_channel && res_addr.target == ses_data.elem_status[i].scsi_id) { if (action == IPR_CONC_REMOVE) { @@ -5012,23 +5026,9 @@ int init_device(i_container *i_con) continue; if (can_init) { - if (dev_init_head) { - dev_init_tail->next = malloc(sizeof(struct devs_to_init_t)); - dev_init_tail = dev_init_tail->next; - } - else - dev_init_head = dev_init_tail = malloc(sizeof(struct devs_to_init_t)); - - memset(dev_init_tail, 0, sizeof(struct devs_to_init_t)); - - dev_init_tail->ioa = ioa; - dev_init_tail->dev_type = dev_type; - dev_init_tail->dev = dev; - dev_init_tail->new_block_size = 0; - + add_format_device(dev, 0); print_dev(k, dev, buffer, "%1", ioa, k); i_con = add_i_con(i_con,"\0",dev_init_tail); - num_devs++; } } @@ -5137,7 +5137,7 @@ int confirm_init_device(i_container *i_con) static int dev_init_complete(u8 num_devs) { - int done_bad; + int done_bad = 0; struct ipr_cmd_status cmd_status; struct ipr_cmd_status_record *status_record; int not_done = 0; @@ -5162,7 +5162,6 @@ static int dev_init_complete(u8 num_devs) } percent_cmplt = 100; - done_bad = 0; for_each_dev_to_init(dev) { if (!dev->do_init || dev->done) @@ -5213,6 +5212,7 @@ static int dev_init_complete(u8 num_devs) if (rc < 0) { dev->done = 1; + done_bad = 1; continue; } @@ -5236,9 +5236,11 @@ static int dev_init_complete(u8 num_devs) continue; ioa = dev->ioa; - if (dev->new_block_size != ioa->af_block_size && ipr_is_gscsi(dev->dev)) { + if (ipr_is_gscsi(dev->dev)) { rc = ipr_test_unit_ready(dev->dev, &sense_data); - if (rc == 0) { + if (rc) { + done_bad = 1; + } else if (dev->new_block_size != ioa->af_block_size) { ipr_write_dev_attr(dev->dev, "rescan", "1"); ipr_init_dev(dev->dev); } @@ -6463,7 +6465,7 @@ int bus_attr_menu(struct ipr_ioa *ioa, struct bus_attr *bus_attr, int start_row, { int i, scsi_id, found; int num_menu_items; - int menu_index; + int menu_index = 0; ITEM **menu_item = NULL; struct ipr_scsi_buses *page_28_cur; struct ipr_dev *dev; @@ -8410,29 +8412,18 @@ int ibm_boot_log(i_container *i_con) return 1; /* return with no status */ } -char *print_device(struct ipr_dev *ipr_dev, char *body, char *option, - struct ipr_ioa *ioa, int type) +static void get_status(struct ipr_dev *ipr_dev, char *buf, int type) { - u16 len = 0; struct scsi_dev_data *scsi_dev_data = ipr_dev->scsi_dev_data; - int i, rc; + struct ipr_ioa *ioa = ipr_dev->ioa; + int rc; struct ipr_query_res_state res_state; - struct ipr_res_addr res_addr; u8 ioctl_buffer[255]; - char raid_str[48]; int status; int format_req = 0; struct ipr_mode_parm_hdr *mode_parm_hdr; struct ipr_block_desc *block_desc; struct sense_data_t sense_data; - char *dev_name = ipr_dev->dev_name; - char *gen_name = ipr_dev->gen_name; - char node_name[7]; - int tab_stop = 0; - char vendor_id[IPR_VENDOR_ID_LEN + 1]; - char product_id[IPR_PROD_ID_LEN + 1]; - struct ipr_common_record *common_record; - struct ipr_dev_record *device_record; struct ipr_array_record *array_record; struct ipr_cmd_status cmd_status; struct ipr_cmd_status_record *status_record; @@ -8440,83 +8431,16 @@ char *print_device(struct ipr_dev *ipr_dev, char *body, char *option, int format_in_progress = 0; int resync_in_progress = 0; - if (body) - len = strlen(body); - body = realloc(body, len + 256); - - if (((type & 3) == 2) && (strlen(gen_name) > 5)) - ipr_strncpy_0(node_name, &gen_name[5], 6); - else if (strlen(dev_name) > 5) - ipr_strncpy_0(node_name, &dev_name[5], 6); - else - node_name[0] = '\0'; - - len += sprintf(body + len, " %s %-6s %s/%d:", - option, - node_name, - ioa->pci_address, - ioa->host_num); - if (scsi_dev_data && scsi_dev_data->type == IPR_TYPE_ADAPTER) { - if (type&1) { - len += sprintf(body + len," %-25s ", get_ioa_desc(ipr_dev->ioa)); - } else - len += sprintf(body + len," %-8s %-16s ", - scsi_dev_data->vendor_id, - scsi_dev_data->product_id); - if (ioa->ioa_dead) - len += sprintf(body + len, "Not Operational\n"); + sprintf(buf, "Not Operational"); else if (ioa->nr_ioa_microcode) - len += sprintf(body + len, "Not Ready\n"); + sprintf(buf, "Not Ready"); else - len += sprintf(body + len, "Operational\n"); - } else if ((scsi_dev_data) && - (scsi_dev_data->type == IPR_TYPE_EMPTY_SLOT)) { - - tab_stop = sprintf(body + len,"%d:%d: ", - scsi_dev_data->channel, - scsi_dev_data->id); - - len += tab_stop; - - for (i = 0; i < 12-tab_stop; i++) - body[len+i] = ' '; - - len += 12-tab_stop; - len += sprintf(body + len, "%-8s %-16s "," ", " "); - len += sprintf(body + len, "Empty\n"); + sprintf(buf, "Operational"); + } else if (scsi_dev_data && scsi_dev_data->type == IPR_TYPE_EMPTY_SLOT) { + sprintf(buf, "Empty"); } else { - get_res_addr(ipr_dev, &res_addr); - - tab_stop = sprintf(body + len,"%d:%d:%d ", res_addr.bus, - res_addr.target, res_addr.lun); - - if (scsi_dev_data) { - ipr_strncpy_0(vendor_id, scsi_dev_data->vendor_id, IPR_VENDOR_ID_LEN); - ipr_strncpy_0(product_id, scsi_dev_data->product_id, IPR_PROD_ID_LEN); - } - else if (ipr_dev->qac_entry) { - common_record = ipr_dev->qac_entry; - if (common_record->record_id == IPR_RECORD_ID_DEVICE_RECORD) { - device_record = (struct ipr_dev_record *)common_record; - ipr_strncpy_0(vendor_id, device_record->vendor_id, IPR_VENDOR_ID_LEN); - ipr_strncpy_0(product_id , device_record->product_id, IPR_PROD_ID_LEN); - } else if (common_record->record_id == IPR_RECORD_ID_ARRAY_RECORD) { - array_record = (struct ipr_array_record *)common_record; - ipr_strncpy_0(vendor_id, array_record->vendor_id, IPR_VENDOR_ID_LEN); - ipr_strncpy_0(product_id , array_record->product_id, - IPR_PROD_ID_LEN); - } - } - - len += tab_stop; - - for (i = 0; i < 12-tab_stop; i++) - body[len+i] = ' '; - - len += 12-tab_stop; - if (ipr_is_volume_set(ipr_dev)) { rc = ipr_query_command_status(&ioa->ioa, &cmd_status); @@ -8537,7 +8461,6 @@ char *print_device(struct ipr_dev *ipr_dev, char *body, char *option, rc = ipr_query_command_status(ipr_dev, &cmd_status); if ((rc == 0) && (cmd_status.num_records != 0)) { - status_record = cmd_status.record; if ((status_record->status != IPR_CMD_STATUS_SUCCESSFUL) && (status_record->status != IPR_CMD_STATUS_FAILED)) { @@ -8560,36 +8483,6 @@ char *print_device(struct ipr_dev *ipr_dev, char *body, char *option, } } - if (!(type&1)) { - len += sprintf(body + len, "%-8s %-16s ", - vendor_id, product_id); - } else { - if (ipr_is_hot_spare(ipr_dev)) - len += sprintf(body + len, "%-25s ", "Hot Spare"); - else if (ipr_is_volume_set(ipr_dev)) { - sprintf(ioctl_buffer, "RAID %s Disk Array", - ipr_dev->prot_level_str); - len += sprintf(body + len, "%-25s ", ioctl_buffer); - } else if (ipr_is_array_member(ipr_dev)) { - if (type&2) - sprintf(raid_str," RAID %s Array Member", - ipr_dev->prot_level_str); - else - sprintf(raid_str,"RAID %s Array Member", - ipr_dev->prot_level_str); - - len += sprintf(body + len, "%-25s ", raid_str); - - } else if (ipr_is_af_dasd_device(ipr_dev)) - len += sprintf(body + len, "%-25s ", "Advanced Function Disk"); - else if (scsi_dev_data && scsi_dev_data->type == TYPE_ENCLOSURE) - len += sprintf(body + len, "%-25s ", "Enclosure"); - else if (scsi_dev_data && scsi_dev_data->type == TYPE_PROCESSOR) - len += sprintf(body + len, "%-25s ", "Processor"); - else - len += sprintf(body + len, "%-25s ", "Physical Disk"); - } - if (ipr_is_af(ipr_dev)) { memset(&res_state, 0, sizeof(res_state)); @@ -8636,43 +8529,165 @@ char *print_device(struct ipr_dev *ipr_dev, char *body, char *option, } if (format_in_progress) - sprintf(body + len, "%d%% Formatted\n", percent_cmplt); + sprintf(buf, "%d%% Formatted", percent_cmplt); else if (!scsi_dev_data && ipr_dev->ioa->is_secondary) - sprintf(body + len, "Remote\n"); + sprintf(buf, "Remote"); else if (!scsi_dev_data) - sprintf(body + len, "Missing\n"); + sprintf(buf, "Missing"); else if (!scsi_dev_data->online) - sprintf(body + len, "Offline\n"); + sprintf(buf, "Offline"); else if (res_state.not_oper || res_state.not_func) - sprintf(body + len, "Failed\n"); + sprintf(buf, "Failed"); else if (res_state.read_write_prot) - sprintf(body + len, "R/W Protected\n"); + sprintf(buf, "R/W Protected"); else if (res_state.prot_dev_failed) - sprintf(body + len, "Failed\n"); + sprintf(buf, "Failed"); else if (ipr_is_volume_set(ipr_dev)) { if (res_state.prot_suspended && ipr_is_volume_set(ipr_dev)) - sprintf(body + len, "Degraded\n"); + sprintf(buf, "Degraded"); else if (res_state.prot_resuming && ipr_is_volume_set(ipr_dev)) { if (!(type&1) || (percent_cmplt == 0)) - sprintf(body + len, "Rebuilding\n"); + sprintf(buf, "Rebuilding"); else - sprintf(body + len, "%d%% Rebuilt\n", percent_cmplt); + sprintf(buf, "%d%% Rebuilt", percent_cmplt); } else if (resync_in_progress) { if (!(type&1) || (percent_cmplt == 0)) - sprintf(body + len, "Checking\n"); + sprintf(buf, "Checking"); else - sprintf(body + len, "%d%% Checked\n", percent_cmplt); + sprintf(buf, "%d%% Checked", percent_cmplt); } else if (res_state.degraded_oper || res_state.service_req) - sprintf(body + len, "Degraded\n"); + sprintf(buf, "Degraded"); else - sprintf(body + len, "Active\n"); + sprintf(buf, "Active"); } else if (format_req) - sprintf(body + len, "Format Required\n"); + sprintf(buf, "Format Required"); else if (ipr_device_is_zeroed(ipr_dev)) - sprintf(body + len, "Zeroed\n"); + sprintf(buf, "Zeroed"); else - sprintf(body + len, "Active\n"); + sprintf(buf, "Active"); } +} + +char *print_device(struct ipr_dev *ipr_dev, char *body, char *option, + struct ipr_ioa *ioa, int type) +{ + u16 len = 0; + struct scsi_dev_data *scsi_dev_data = ipr_dev->scsi_dev_data; + int i; + struct ipr_res_addr res_addr; + u8 ioctl_buffer[255]; + char raid_str[48]; + char *dev_name = ipr_dev->dev_name; + char *gen_name = ipr_dev->gen_name; + char node_name[7], buf[100]; + int tab_stop = 0; + char vendor_id[IPR_VENDOR_ID_LEN + 1]; + char product_id[IPR_PROD_ID_LEN + 1]; + struct ipr_common_record *common_record; + struct ipr_dev_record *device_record; + struct ipr_array_record *array_record; + + if (body) + len = strlen(body); + body = realloc(body, len + 256); + + if (((type & 3) == 2) && (strlen(gen_name) > 5)) + ipr_strncpy_0(node_name, &gen_name[5], 6); + else if (strlen(dev_name) > 5) + ipr_strncpy_0(node_name, &dev_name[5], 6); + else + node_name[0] = '\0'; + + len += sprintf(body + len, " %s %-6s %s/%d:", + option, + node_name, + ioa->pci_address, + ioa->host_num); + + if (scsi_dev_data && scsi_dev_data->type == IPR_TYPE_ADAPTER) { + if (type&1) { + len += sprintf(body + len," %-25s ", get_ioa_desc(ipr_dev->ioa)); + } else + len += sprintf(body + len," %-8s %-16s ", + scsi_dev_data->vendor_id, + scsi_dev_data->product_id); + } else if ((scsi_dev_data) && + (scsi_dev_data->type == IPR_TYPE_EMPTY_SLOT)) { + + tab_stop = sprintf(body + len,"%d:%d: ", + scsi_dev_data->channel, + scsi_dev_data->id); + + len += tab_stop; + + for (i = 0; i < 12-tab_stop; i++) + body[len+i] = ' '; + + len += 12-tab_stop; + len += sprintf(body + len, "%-8s %-16s "," ", " "); + } else { + get_res_addr(ipr_dev, &res_addr); + + tab_stop = sprintf(body + len,"%d:%d:%d ", res_addr.bus, + res_addr.target, res_addr.lun); + + if (scsi_dev_data) { + ipr_strncpy_0(vendor_id, scsi_dev_data->vendor_id, IPR_VENDOR_ID_LEN); + ipr_strncpy_0(product_id, scsi_dev_data->product_id, IPR_PROD_ID_LEN); + } + else if (ipr_dev->qac_entry) { + common_record = ipr_dev->qac_entry; + if (common_record->record_id == IPR_RECORD_ID_DEVICE_RECORD) { + device_record = (struct ipr_dev_record *)common_record; + ipr_strncpy_0(vendor_id, device_record->vendor_id, IPR_VENDOR_ID_LEN); + ipr_strncpy_0(product_id , device_record->product_id, IPR_PROD_ID_LEN); + } else if (common_record->record_id == IPR_RECORD_ID_ARRAY_RECORD) { + array_record = (struct ipr_array_record *)common_record; + ipr_strncpy_0(vendor_id, array_record->vendor_id, IPR_VENDOR_ID_LEN); + ipr_strncpy_0(product_id , array_record->product_id, + IPR_PROD_ID_LEN); + } + } + + len += tab_stop; + + for (i = 0; i < 12-tab_stop; i++) + body[len+i] = ' '; + + len += 12-tab_stop; + + if (!(type&1)) { + len += sprintf(body + len, "%-8s %-16s ", + vendor_id, product_id); + } else { + if (ipr_is_hot_spare(ipr_dev)) + len += sprintf(body + len, "%-25s ", "Hot Spare"); + else if (ipr_is_volume_set(ipr_dev)) { + sprintf(ioctl_buffer, "RAID %s Disk Array", + ipr_dev->prot_level_str); + len += sprintf(body + len, "%-25s ", ioctl_buffer); + } else if (ipr_is_array_member(ipr_dev)) { + if (type&2) + sprintf(raid_str," RAID %s Array Member", + ipr_dev->prot_level_str); + else + sprintf(raid_str,"RAID %s Array Member", + ipr_dev->prot_level_str); + + len += sprintf(body + len, "%-25s ", raid_str); + } else if (ipr_is_af_dasd_device(ipr_dev)) + len += sprintf(body + len, "%-25s ", "Advanced Function Disk"); + else if (scsi_dev_data && scsi_dev_data->type == TYPE_ENCLOSURE) + len += sprintf(body + len, "%-25s ", "Enclosure"); + else if (scsi_dev_data && scsi_dev_data->type == TYPE_PROCESSOR) + len += sprintf(body + len, "%-25s ", "Processor"); + else + len += sprintf(body + len, "%-25s ", "Physical Disk"); + } + } + + get_status(ipr_dev, buf, type); + sprintf(body + len, "%s\n", buf); return body; } @@ -8742,6 +8757,15 @@ static int raid_create_check_num_devs(struct ipr_array_cap_entry *cap, return 0; } +static void curses_init() +{ + /* makes program compatible with all terminals - + originally did not display text correctly when user was running xterm */ + setenv("TERM", "vt100", 1); + setlocale(LC_ALL, ""); + initscr(); +} + static int raid_create(char **args, int num_args) { int i, num_devs = 0, rc; @@ -8753,6 +8777,7 @@ static int raid_create(char **args, int num_args) struct ipr_ioa *ioa = NULL; struct ipr_array_cap_entry *cap; + curses_init(); next_raid_level = 0; next_stripe_size = 0; next_qdepth = 0; @@ -8874,6 +8899,8 @@ static int raid_delete(char **args, int num_args) return -EINVAL; } + curses_init(); + dev->array_rcd->issue_cmd = 1; if (dev->scsi_dev_data) rc = ipr_start_stop_stop(dev); @@ -8883,6 +8910,23 @@ static int raid_delete(char **args, int num_args) return rc; } +static int print_status(char *name) +{ + struct ipr_dev *dev = find_blk_dev(name); + char buf[100]; + + if (!dev) + dev = find_gen_dev(name); + if (!dev) { + printf("Missing\n"); + return -EINVAL; + } + + get_status(dev, buf, 0); + printf("%s\n", buf); + return 0; +} + int main(int argc, char *argv[]) { int next_editor, next_dir, next_cmd, next_dev, i, rc = 0; @@ -8890,11 +8934,6 @@ int main(int argc, char *argv[]) char **dev = NULL; int non_interactive = 0, num_devs = 0; - /* makes program compatible with all terminals - - originally did not display text correctly when user was running xterm */ - setenv("TERM", "vt100", 1); - setlocale(LC_ALL, ""); - strcpy(parm_dir, DEFAULT_LOG_DIR); strcpy(parm_editor, DEFAULT_EDITOR); @@ -8947,7 +8986,6 @@ int main(int argc, char *argv[]) system("modprobe sg"); exit_func = tool_exit_func; tool_init(0); - initscr(); if (non_interactive) { exit_func = cmdline_exit_func; @@ -8967,6 +9005,8 @@ int main(int argc, char *argv[]) rc = raid_create(dev, num_devs); else if (strcmp(cmd, "raid-delete") == 0) rc = raid_delete(dev, num_devs); + else if (strcmp(cmd, "status") == 0) + rc = print_status(dev[0]); else { exit_func(); usage(); @@ -8976,6 +9016,7 @@ int main(int argc, char *argv[]) return rc; } + curses_init(); cbreak(); /* take input chars one at a time, no wait for \n */ keypad(stdscr,TRUE); diff --git a/iprdbg.c b/iprdbg.c index 6a7f93e..1935128 100644 --- a/iprdbg.c +++ b/iprdbg.c @@ -10,7 +10,7 @@ */ /* - * $Header: /cvsroot/iprdd/iprutils/iprdbg.c,v 1.16 2005/03/07 17:20:16 brking Exp $ + * $Header: /cvsroot/iprdd/iprutils/iprdbg.c,v 1.17 2005/09/26 20:19:36 brking Exp $ */ #ifndef iprlib_h @@ -24,6 +24,8 @@ #include #include #include +#include +#include #define IPR_MAX_FLIT_ENTRIES 59 #define IPR_FLIT_TIMESTAMP_LEN 12 @@ -170,6 +172,49 @@ static int format_flit(struct ipr_flit *flit) return 0; } +static char *term; +static char *k_up; +static char *k_down; +static unsigned char hindex; +static char *history[256]; + +static void ipr_fgets(char *buf, int size, FILE *stream) +{ + int i, ch = 0; + + for (i = 0; ch != EOF && i < (size - 1); i++) { + ch = fgetc(stream); + if (ch == '\n') + break; + + buf[i] = ch; + + if (!strcmp(buf, k_up)) { + rewind(stdin); + if (history[hindex]) { + fprintf(stdout, "%s", history[--hindex]); + strcpy(buf, history[hindex]); + i = strlen(buf) + 1; + } + } else if (!strcmp(buf, k_down)) { + rewind(stdin); + if (history[hindex]) { + fprintf(stdout, "%s", history[++hindex]); + strcpy(buf, history[hindex]); + i = strlen(buf) + 1; + } + } + } + + buf[i] = '\0'; + + if (history[hindex]) + free(history[hindex]); + history[hindex] = malloc(strlen(buf) + 2); + strcpy(history[hindex++], buf); + strcat(buf, "\n"); +} + int main(int argc, char *argv[]) { int num_args, address, prev_address = 0; @@ -182,6 +227,23 @@ int main(int argc, char *argv[]) struct ipr_ioa *ioa; char ascii_buffer[17]; struct ipr_flit flit; + char *term_type; + + term_type = getenv ("TERM"); + if (!term_type) { + fprintf(stderr, "Cannot determine terminal type. Is TERM set?\n"); + return -EIO; + } + + rc = tgetent (term, term_type); + if (rc < 0) { + fprintf(stderr, "Cannot determine terminal type\n"); + return -EIO; + } + + + k_up = tgetstr ("ku", NULL); + k_down = tgetstr ("kd", NULL); openlog("iprdbg", LOG_PERROR | /* Print error to stderr as well */ @@ -246,7 +308,7 @@ int main(int argc, char *argv[]) memset(arg, 0, sizeof(arg)); address = 0; - fgets(cmd_line, 999, stdin); + ipr_fgets(cmd_line, 999, stdin); logtofile("\n%s\n", cmd_line); diff --git a/iprlib.c b/iprlib.c index 01d87f8..111ed31 100644 --- a/iprlib.c +++ b/iprlib.c @@ -10,7 +10,7 @@ */ /* - * $Header: /cvsroot/iprdd/iprutils/iprlib.c,v 1.71 2005/07/20 18:07:09 brking Exp $ + * $Header: /cvsroot/iprdd/iprutils/iprlib.c,v 1.72 2005/09/26 20:19:36 brking Exp $ */ #ifndef iprlib_h @@ -1069,6 +1069,7 @@ static void resolve_ioa(struct ipr_ioa *ioa, struct ipr_ioa *old_ioa) for_each_dev(old_ioa, old_dev) { if (!same_dev(dev, old_dev)) continue; + memcpy(&dev->attr, &old_dev->attr, sizeof(dev->attr)); resolve_dev(dev, old_dev); break; } @@ -2575,6 +2576,7 @@ int format_req(struct ipr_dev *dev) } #define IPR_MAX_XFER 0x8000 + const int cdb_size[] ={6, 10, 10, 0, 16, 12, 16, 16}; static int _sg_ioctl(int fd, u8 cdb[IPR_CCB_CDB_LEN], void *data, u32 xfer_len, u32 data_direction, @@ -2588,6 +2590,7 @@ static int _sg_ioctl(int fd, u8 cdb[IPR_CCB_CDB_LEN], int i; int buff_len, segment_size; void *dxferp; + u8 *buf; /* check if scatter gather should be used */ if (xfer_len > IPR_MAX_XFER) { @@ -2599,7 +2602,8 @@ static int _sg_ioctl(int fd, u8 cdb[IPR_CCB_CDB_LEN], for (i = 0; (i < iovec_count) && (buff_len != 0); i++) { iovec[i].iov_base = malloc(segment_size); - memcpy(iovec[i].iov_base, data + (IPR_MAX_XFER * i), segment_size); + if (data_direction == SG_DXFER_TO_DEV) + memcpy(iovec[i].iov_base, data + (IPR_MAX_XFER * i), segment_size); iovec[i].iov_len = segment_size; buff_len -= segment_size; @@ -2644,8 +2648,12 @@ static int _sg_ioctl(int fd, u8 cdb[IPR_CCB_CDB_LEN], } if (iovec_count) { - for (i = 0; i < iovec_count; i++) + for (i = 0, buf = (u8 *)data; i < iovec_count; i++) { + if (data_direction == SG_DXFER_FROM_DEV) + memcpy(buf, iovec[i].iov_base, iovec[i].iov_len); + buf += iovec[i].iov_len; free(iovec[i].iov_base); + } free(iovec); } @@ -2794,11 +2802,11 @@ int get_scsi_dev_data(struct scsi_dev_data **scsi_dev_ref) sysfs_attr = sysfs_get_device_attr(sysfs_device_device, "vendor"); if (sysfs_attr) - ipr_strncpy_0(scsi_dev_data->vendor_id, sysfs_attr->value, IPR_VENDOR_ID_LEN); + ipr_strncpy_0n(scsi_dev_data->vendor_id, sysfs_attr->value, IPR_VENDOR_ID_LEN); sysfs_attr = sysfs_get_device_attr(sysfs_device_device, "model"); if (sysfs_attr) - ipr_strncpy_0(scsi_dev_data->product_id, sysfs_attr->value, IPR_PROD_ID_LEN); + ipr_strncpy_0n(scsi_dev_data->product_id, sysfs_attr->value, IPR_PROD_ID_LEN); strcpy(scsi_dev_data->dev_name,""); strcpy(scsi_dev_data->gen_name,""); @@ -4484,6 +4492,7 @@ void ipr_update_ioa_fw(struct ipr_ioa *ioa, struct stat ucode_stats; u32 fw_version; int fd, rc; + int host_num = ioa->host_num; char *tmp; char ucode_file[200]; DIR *dir; @@ -4545,6 +4554,13 @@ void ipr_update_ioa_fw(struct ipr_ioa *ioa, if (rc != 0) ioa_err(ioa, "Microcode update failed. rc=%d\n", rc); + check_current_config(false); + for_each_ioa(ioa) { + if (ioa->host_num != host_num) + continue; + ipr_init_ioa(ioa); + break; + } } else ipr_log_ucode_error(ioa); @@ -4929,7 +4945,9 @@ static void init_af_dev(struct ipr_dev *dev) if (ipr_set_dasd_timeouts(dev)) return; - if (polling_mode && (!dev->should_init || !dev_init_allowed(dev))) + if (polling_mode && (!dev->should_init && !memcmp(&attr, &dev->attr, sizeof(attr)))) + return; + if (polling_mode && !dev_init_allowed(dev)) return; if (setup_page0x00(dev)) return; @@ -4951,6 +4969,7 @@ static void init_af_dev(struct ipr_dev *dev) if (ipr_modify_dev_attr(dev, &attr)) return; + memcpy(&dev->attr, &attr, sizeof(attr)); if (ipr_set_dev_attr(dev, &attr, 0)) return; } diff --git a/iprlib.h b/iprlib.h index 8afec25..977c60f 100644 --- a/iprlib.h +++ b/iprlib.h @@ -12,7 +12,7 @@ */ /* - * $Header: /cvsroot/iprdd/iprutils/iprlib.h,v 1.56 2005/07/20 18:07:11 brking Exp $ + * $Header: /cvsroot/iprdd/iprutils/iprlib.h,v 1.57 2005/09/26 20:19:36 brking Exp $ */ #include @@ -999,6 +999,20 @@ struct ipr_multi_ioa_status { */ }; +struct ipr_disk_attr { + int queue_depth; + int tcq_enabled; + int format_timeout; +}; + +struct ipr_vset_attr { + int queue_depth; +}; + +struct ipr_ioa_attr { + int preferred_primary; +}; + struct ipr_dev { char dev_name[64]; char gen_name[64]; @@ -1007,6 +1021,7 @@ struct ipr_dev { u32 should_init:1; u32 init_not_allowed:1; struct scsi_dev_data *scsi_dev_data; + struct ipr_disk_attr attr; union { struct ipr_common_record *qac_entry; struct ipr_dev_record *dev_rcd; @@ -1173,20 +1188,6 @@ struct ipr_scsi_buses { struct ipr_scsi_bus_attr bus[IPR_MAX_NUM_BUSES]; }; -struct ipr_disk_attr { - int queue_depth; - int tcq_enabled; - int format_timeout; -}; - -struct ipr_vset_attr { - int queue_depth; -}; - -struct ipr_ioa_attr { - int preferred_primary; -}; - struct ipr_dasd_timeout_record { u8 op_code; u8 reserved; @@ -1456,8 +1457,8 @@ struct ipr_encl_status_ctl_pg }; #define for_each_elem_status(i, ses_data) \ - for (i = 0; i < ((ntohs((ses_data)->byte_count)-8)/sizeof(struct ipr_drive_elem_status)) \ - && i < IPR_NUM_DRIVE_ELEM_STATUS_ENTRIES; i++) + for (i = 0; i < ((ntohs((ses_data)->byte_count)-8)/sizeof(struct ipr_drive_elem_status)) && \ + i < IPR_NUM_DRIVE_ELEM_STATUS_ENTRIES; i++) int sg_ioctl(int, u8 *, void *, u32, u32, struct sense_data_t *, u32); int sg_ioctl_noretry(int, u8 *, void *, u32, u32, struct sense_data_t *, u32); @@ -1639,6 +1640,16 @@ static inline void ipr_strncpy_0(char *dest, char *source, int length) dest[length] = '\0'; } +static inline void ipr_strncpy_0n(char *dest, char *source, int length) +{ + char *ch; + memcpy(dest, source, length); + dest[length] = '\0'; + ch = strchr(dest, '\n'); + if (ch) + *ch = '\0'; +} + #define syslog_dbg(...) \ do { \ if (ipr_debug) \ @@ -1656,10 +1667,10 @@ if (dev->scsi_dev_data && !dev->ioa->ioa_dead) { \ #define scsi_dbg(dev, fmt, ...) \ do { \ -if (dev->scsi_dev_data) { \ - syslog_dbg("%d:%d:%d:%d: " fmt, dev->ioa->host_num, \ - dev->scsi_dev_data->channel, dev->scsi_dev_data->id, \ - dev->scsi_dev_data->lun, ##__VA_ARGS__); \ +if ((dev)->scsi_dev_data) { \ + syslog_dbg("%d:%d:%d:%d: " fmt, (dev)->ioa->host_num, \ + (dev)->scsi_dev_data->channel, (dev)->scsi_dev_data->id, \ + (dev)->scsi_dev_data->lun, ##__VA_ARGS__); \ } \ } while (0) diff --git a/spec/iprutils.spec b/spec/iprutils.spec index e6954a1..877b192 100644 --- a/spec/iprutils.spec +++ b/spec/iprutils.spec @@ -56,6 +56,22 @@ rm -rf $RPM_BUILD_ROOT %{_sysconfdir}/init.d/* %changelog +* Wed Aug 17 2005 Brian King 2.0.15.4 +- Fix a couple of uninitialized variable compile errors +* Wed Jul 27 2005 Brian King 2.0.15.3 +- Fix: iprconfig: IOA microcode update would leave AF DASD + (disks that are in disk arrays) in a state where they were + no longer tagged queueing. Fix iprconfig to run iprinit on the + adapter after a microcode download to ensure all attached devices + are properly setup after a microcode download. +- Fix iprinit: If an IOA was reset for some reason at runtime, + this would cause AF DASD devices to get tagged queueing turned + off and it would never get turned back on. Change iprinit to + detect this and turn tagged queueing back on if this happens. +- Changing the queue depth for a disk array was broken. Fix iprinit + to properly restore the queue depth from the ipr configuration file. +- Fix iprconfig to handle disk format failures better +- Fix potential iprutils segfaults when iterating over disk arrays * Wed Jun 1 2005 Brian King 2.0.15.1 - Fix iprconfig Analyze Log options * Wed May 18 2005 Brian King 2.0.15 diff --git a/version.mk b/version.mk index ed4ff46..f06b9b6 100644 --- a/version.mk +++ b/version.mk @@ -7,8 +7,8 @@ IPR_MAJOR_RELEASE=2 IPR_MINOR_RELEASE=1 IPR_FIX_LEVEL=0 -IPR_RELEASE=dev -IPR_FIX_DATE=(July 20, 2005) +IPR_RELEASE=cvs +IPR_FIX_DATE=(September 23, 2005) IPR_VERSION_STR=$(IPR_MAJOR_RELEASE).$(IPR_MINOR_RELEASE).$(IPR_FIX_LEVEL) $(IPR_FIX_DATE)