Example #1
0
static int
foreign_show_cfg(int fd, uint32_t opcode, uint8_t cfgidx, int diagnostic)
{
	struct mfi_config_data *config;
	char prefix[26];
	int error;
	uint8_t mbox[4];

	bzero(mbox, sizeof(mbox));
	mbox[0] = cfgidx;
	if (mfi_config_read_opcode(fd, opcode, &config, mbox, sizeof(mbox)) < 0) {
		error = errno;
		warn("Failed to get foreign config %d", error);
		close(fd);
		return (error);
	}

	if (opcode == MFI_DCMD_CFG_FOREIGN_PREVIEW)
		sprintf(prefix, "Foreign configuration preview %d", cfgidx);
	else
		sprintf(prefix, "Foreign configuration %d", cfgidx);
	/*
	 * MegaCli uses DCMD opcodes: 0x03100200 (which fails) followed by
	 * 0x1a721880 which returns what looks to be drive / volume info
	 * but we have no real information on what these are or what they do
	 * so we're currently relying solely on the config returned above
	 */
	if (diagnostic)
		dump_config(fd, config, prefix);
	else {
		char *ld_list;
		int i;

		ld_list = (char *)(config->array);

        	printf("%s: %d arrays, %d volumes, %d spares\n", prefix, 
		       config->array_count, config->log_drv_count,
		       config->spares_count);


		for (i = 0; i < config->array_count; i++)
			 ld_list += config->array_size;

		for (i = 0; i < config->log_drv_count; i++) {
        		const char *level;
        		char size[6], stripe[5];
			struct mfi_ld_config *ld;

			ld = (struct mfi_ld_config *)ld_list;

        		format_stripe(stripe, sizeof(stripe),
            			ld->params.stripe_size);
			/*
			 * foreign configs don't seem to have a secondary raid level
			 * but, we can use span depth here as if a LD spans multiple
			 * arrays of disks (2 raid 1 sets for example), we will have an
			 * indication based on the spam depth. swb
			 */ 
        		level = mfi_raid_level(ld->params.primary_raid_level,
            					(ld->params.span_depth - 1));

        		humanize_number(size, sizeof(size), ld->span[0].num_blocks * 512,
            			"", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);

			printf(" ID%d ", i);
              		printf("(%6s) %-8s |",
				size, level);
			printf("volume spans %d %s\n",	ld->params.span_depth,
							(ld->params.span_depth > 1) ? "arrays" : "array");
			for (int j = 0; j < ld->params.span_depth; j++) {
				char *ar_list;
				struct mfi_array *ar;
				uint16_t device_id;

				printf("      array %u @ ", ld->span[j].array_ref);
        			humanize_number(size, sizeof(size), ld->span[j].num_blocks * 512,
            				"", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
				
				printf("(%6s)\n",size);
				ar_list = (char *)config->array + (ld->span[j].array_ref * config->array_size);

				ar = (struct mfi_array *)ar_list;
				for (int k = 0; k < ar->num_drives; k++) {
					device_id = ar->pd[k].ref.v.device_id;
					if (device_id == 0xffff)
						printf("        drive MISSING\n");
					else {
						printf("        drive %u %s\n", device_id,
			    				mfi_pdstate(ar->pd[k].fw_state));
					}
				}

			}
			ld_list += config->log_drv_size;
		}
	}

	free(config);

	return (0);
}
Example #2
0
/* Display raw data about a config. */
static void
dump_config(int fd, struct mfi_config_data *config)
{
	struct mfi_array *ar;
	struct mfi_ld_config *ld;
	struct mfi_spare *sp;
	struct mfi_pd_info pinfo;
	uint16_t device_id;
	char *p;
	int i, j;

	printf(
	    "mfi%d Configuration (Debug): %d arrays, %d volumes, %d spares\n",
	    mfi_unit, config->array_count, config->log_drv_count,
	    config->spares_count);
	printf("  array size: %u\n", config->array_size);
	printf("  volume size: %u\n", config->log_drv_size);
	printf("  spare size: %u\n", config->spares_size);
	p = (char *)config->array;

	for (i = 0; i < config->array_count; i++) {
		ar = (struct mfi_array *)p;
		printf("    array %u of %u drives:\n", ar->array_ref,
		    ar->num_drives);
		printf("      size = %ju\n", (uintmax_t)ar->size);
		for (j = 0; j < ar->num_drives; j++) {
			device_id = ar->pd[j].ref.v.device_id;
			if (device_id == 0xffff)
				printf("        drive MISSING\n");
			else {
				printf("        drive %u %s\n", device_id,
				    mfi_pdstate(ar->pd[j].fw_state));
				if (mfi_pd_get_info(fd, device_id, &pinfo,
				    NULL) >= 0) {
					printf("          raw size: %ju\n",
					    (uintmax_t)pinfo.raw_size);
					printf("          non-coerced size: %ju\n",
					    (uintmax_t)pinfo.non_coerced_size);
					printf("          coerced size: %ju\n",
					    (uintmax_t)pinfo.coerced_size);
				}
			}
		}
		p += config->array_size;
	}

	for (i = 0; i < config->log_drv_count; i++) {
		ld = (struct mfi_ld_config *)p;
		printf("    volume %s ",
		    mfi_volume_name(fd, ld->properties.ld.v.target_id));
		printf("%s %s",
		    mfi_raid_level(ld->params.primary_raid_level,
			ld->params.secondary_raid_level),
		    mfi_ldstate(ld->params.state));
		if (ld->properties.name[0] != '\0')
			printf(" <%s>", ld->properties.name);
		printf("\n");
		printf("      primary raid level: %u\n",
		    ld->params.primary_raid_level);
		printf("      raid level qualifier: %u\n",
		    ld->params.raid_level_qualifier);
		printf("      secondary raid level: %u\n",
		    ld->params.secondary_raid_level);
		printf("      stripe size: %u\n", ld->params.stripe_size);
		printf("      num drives: %u\n", ld->params.num_drives);
		printf("      init state: %u\n", ld->params.init_state);
		printf("      consistent: %u\n", ld->params.is_consistent);
		printf("      no bgi: %u\n", ld->properties.no_bgi);
		printf("      spans:\n");
		for (j = 0; j < ld->params.span_depth; j++) {
			printf("        array %u @ ", ld->span[j].array_ref);
			printf("%ju : %ju\n",
			    (uintmax_t)ld->span[j].start_block,
			    (uintmax_t)ld->span[j].num_blocks);
		}
		p += config->log_drv_size;
	}

	for (i = 0; i < config->spares_count; i++) {
		sp = (struct mfi_spare *)p;
		printf("    %s spare %u ",
		    sp->spare_type & MFI_SPARE_DEDICATED ? "dedicated" :
		    "global", sp->ref.v.device_id);
		printf("%s", mfi_pdstate(MFI_PD_STATE_HOT_SPARE));
		printf(" backs:\n");
		for (j = 0; j < sp->array_count; j++)
			printf("        array %u\n", sp->array_ref[j]);
		p += config->spares_size;
	}
}