⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 detect_multipath.c

📁 create raid tool at linux
💻 C
字号:
/* * detect_multipath.c * * Copyright (C) 2000, 2001, Red Hat, Inc. * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; see the file COPYING.  If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. *  * 8/14/01 - Initial version snagged from the scsi_reserve package as * 	     the scan_drives.c file and then modified to only do * 	     multipath detection. *//* * This is a small and simple program that uses the scsi_reserve library * and the md library code to detect and create raidtab entries for any * multipath devices found on a system. */#include <stdio.h>#include <stdarg.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <linux/fs.h>#include <errno.h>#include <unistd.h>#include <popt.h>#include <sys/types.h>#include <sys/ioctl.h>#include <scsi/scsi.h>#include <scsi/sg.h>#include <scsi/scsi_ioctl.h>#include "common.h"#include "parser.h"#include "raidlib.h"#include "raid_io.h"#include "version.h"#include "scsi.h"#define NUM_SCSI_DEVICES	128#define MAX_PARTITIONS		16int global_verbose;int global_superblock;int global_new;struct poptOption popt_options[] = {    {"verbose", 'v', POPT_ARG_NONE, &global_verbose, 0,     "Print out extra information", NULL},    {"superblock", 's', POPT_ARG_NONE, &global_superblock, 0,     "Print out only those devices that already have a valid multipath "     "raid superblock", NULL},    {"new", 'n', POPT_ARG_NONE, &global_new, 0,     "Print out only those devices that don't have a valid multipath "     "superblock", NULL},    POPT_AUTOHELP    {NULL, 0, 0, NULL, 0, NULL, NULL}};intmain(int argc, char *argv[]){    int fd, i, j, num_devs;    scsi_sg_dev_t *sg_dev[NUM_SCSI_DEVICES];    char *buffer[NUM_SCSI_DEVICES];    poptContext context;    context = poptGetContext(argv[0], argc, (const char **)argv,			     (const struct poptOption *)&popt_options, 0);    i = poptGetNextOpt(context);    if (i < -1) {	poptPrintHelp(context, stderr, 0);	exit(1);    }    if (global_superblock && global_new) {	fprintf(stderr, "Only one of the -n or -s options are allowed\n");	exit(1);    }    if(prepare_raidlib())	exit(1);    for (i = 0; i < NUM_SCSI_DEVICES; i++) {	sg_dev[i] = NULL;	buffer[i] = NULL;    }    i = 0;    j = 0;    do {	if ((buffer[j] == NULL) && ((buffer[j] = malloc(128)) == NULL)) {	    fprintf(stderr, "Unable to allocate memory, exiting.\n");	    exit(1);	}	if (i < 26)	    sprintf(buffer[j], "/dev/sd%c", i + 'a');	else	    sprintf(buffer[j], "/dev/sd%c%c", i / 26 + 'a' - 1,		    i % 26 + 'a');	fd = open(buffer[j], O_RDONLY | O_NDELAY);	if (fd != -1) {	    sg_dev[j] = scsi_init_sg_device(fd, buffer[j]);	    if (sg_dev[j] && sg_dev[j]->initialized)		j++;	}    } while (++i < NUM_SCSI_DEVICES);    num_devs = j;    if (global_verbose)	printf("\nChecking for multipath drives...(%d devices)\n",	       num_devs);    for (i = 0; i < num_devs - 1; i++) {	int multipath_array[NUM_SCSI_DEVICES], k, l;	k = 1;	multipath_array[0] = i;	multipath_array[k] = -1;	for (j = i + 1; j < num_devs; j++) {	    int a0, a1, b0, b1;	    if (!sg_dev[i]->initialized || !sg_dev[j]->initialized)		continue;	    a0 = sg_dev[i]->id_eui64[0];	    a1 = sg_dev[i]->id_eui64[1];	    b0 = sg_dev[j]->id_eui64[0];	    b1 = sg_dev[j]->id_eui64[1];	    if ((a0 || a1) && (b0 || b1) && ((a0 == b0) && (a1 == b1))) {		if (global_verbose)		    printf("%s and %s are multiple paths to the same "			   "device (id_eui64)\n", sg_dev[i]->name,			   sg_dev[j]->name);		multipath_array[k++] = j;		continue;	    } else if ((a0 || a1 || b0 || b1) &&		       ((a0 != b0) || (a1 != b1))) {		continue;	    }	    a0 = sg_dev[i]->id_fcph[0];	    a1 = sg_dev[i]->id_fcph[1];	    b0 = sg_dev[j]->id_fcph[0];	    b1 = sg_dev[j]->id_fcph[1];	    if ((a0 || a1) && (b0 || b1) && ((a0 == b0) && (a1 == b1))) {		if (global_verbose)		    printf("%s and %s are multiple paths to the same "			   "device (id_fcph)\n", sg_dev[i]->name,			   sg_dev[j]->name);		multipath_array[k++] = j;		continue;	    } else if ((a0 || a1 || b0 || b1) &&		       ((a0 != b0) || (a1 != b1))) {		continue;	    }	    if ((sg_dev[i]->scsi_dev_id == sg_dev[j]->scsi_dev_id) &&		(sg_dev[i]->scsi_dev_lun == sg_dev[j]->scsi_dev_lun) &&		!strcmp(sg_dev[i]->vendor, sg_dev[j]->vendor) &&		!strcmp(sg_dev[i]->product, sg_dev[j]->product) &&		!strcmp(sg_dev[i]->revision, sg_dev[j]->revision)) {		if (sg_dev[i]->serial_number && sg_dev[j]->serial_number &&		    !strcmp(sg_dev[i]->serial_number,			    sg_dev[j]->serial_number)) {		    if (global_verbose)			printf("%s and %s are multiple paths to the same "			       "device (serial_number)\n", sg_dev[i]->name,			       sg_dev[j]->name);		    multipath_array[k++] = j;		    continue;		} else if (sg_dev[i]->serial_number != NULL ||			   sg_dev[j]->serial_number != NULL) {		    continue;		}		if (sg_dev[i]->id_vendor && sg_dev[j]->id_vendor &&		    !strcmp(sg_dev[i]->id_vendor, sg_dev[j]->id_vendor)) {		    if (global_verbose)			printf("%s and %s are multiple paths to the same "			       "device (id_vendor)\n", sg_dev[i]->name,			       sg_dev[j]->name);		    multipath_array[k++] = j;		    continue;		} else if (sg_dev[i]->id_vendor != NULL ||			   sg_dev[j]->id_vendor != NULL) {		    continue;		}		if (sg_dev[i]->id_nonunique && sg_dev[j]->id_nonunique &&		    !strcmp(sg_dev[i]->id_nonunique,			    sg_dev[j]->id_nonunique)) {		    if (global_verbose)			printf("%s and %s are multiple paths to the same "			       "device (id_nonunique)\n", sg_dev[i]->name,			       sg_dev[j]->name);		    multipath_array[k++] = j;		    continue;		} else if (sg_dev[i]->id_vendor != NULL ||			   sg_dev[j]->id_vendor != NULL) {		    continue;		}	    }	}	if (k > 1) {	    int has_superblock;	    unsigned long nr_blocks;	    unsigned long sb_offset;	    unsigned char sb_buf[MD_SB_BYTES];	    mdp_super_t *sb;	    sb = (mdp_super_t *)&sb_buf[0];	    if (ioctl(sg_dev[i]->disk_fd, BLKGETSIZE, &nr_blocks) == -1) {		perror("ioctl BLKGETSIZE");		fprintf(stderr, "Error getting size for %s\n",			sg_dev[i]->name);		continue;	    }	    if (nr_blocks < MD_RESERVED_BLOCKS) {		fprintf(stderr, "Device %s is too small to be a raid device.\n",			sg_dev[i]->name);		continue;	    }	    nr_blocks >>= 1; /* convert to 1K blocks */	    sb_offset = MD_NEW_SIZE_BLOCKS(nr_blocks);	    if (raidseek(sg_dev[i]->disk_fd, sb_offset) == -1) {		perror("raidseek");		fprintf(stderr, "Unable to seek to superblock offset of %s\n",			sg_dev[i]->name);		continue;	    }	    if (read(sg_dev[i]->disk_fd, sb_buf, MD_SB_BYTES) != MD_SB_BYTES) {		perror("read");		fprintf(stderr, "Short read for superblock from %s\n",			sg_dev[i]->name);		continue;	    }	    if (sb->md_magic == MD_SB_MAGIC && sb->level == MULTIPATH)		has_superblock = 1;	    else		has_superblock = 0;	    if (!(global_superblock && !has_superblock) &&		!(global_new && has_superblock)) {	    	if (k == 2) {		    printf ("%s and %s are multiple paths to ", sg_dev[i]->name,			    sg_dev[multipath_array[1]]->name);		    if(has_superblock)			printf("/dev/md%d\n", sb->md_minor);		    else			printf("the same device\n");		    /* mark it not-initialized, then we won't scan it again */		    sg_dev[multipath_array[1]]->initialized = 0;		} else {		    printf("%s, ", sg_dev[i]->name);		    for (j = 1; j < (k - 1); j++) {			printf("%s, ", sg_dev[multipath_array[j]]->name);			sg_dev[multipath_array[j]]->initialized = 0;		    }		    printf("and %s are multiple paths to ",			   sg_dev[multipath_array[j]]->name);		    if(has_superblock)			printf("/dev/md%d\n", sb->md_minor);		    else			printf("the same device\n");		    sg_dev[multipath_array[j]]->initialized = 0;		}	    }	    /*	     * Now process partitions on the main array device to see if	     * any of them have superblocks.	     */	    for(l=1; l<MAX_PARTITIONS; l++) {		int fd;		char name[256];		sprintf(name,"%s%d",sg_dev[i]->name,l);		if((fd = open(name,O_RDONLY | O_NDELAY)) == -1)		    continue;		if (global_verbose)		    printf("Checking for a superblock on %s\n", name);		if (ioctl(fd, BLKGETSIZE, &nr_blocks) == -1) {		    perror("ioctl BLKGETSIZE");		    fprintf(stderr, "Error getting size for %s\n", name);		    continue;		}		if (nr_blocks < MD_RESERVED_BLOCKS) {		    fprintf(stderr, "Device %s is too small to be a raid "				    "device.\n", name);		    continue;		}		nr_blocks >>= 1; /* convert to 1K blocks */		sb_offset = MD_NEW_SIZE_BLOCKS(nr_blocks);		if (raidseek(fd, sb_offset) == -1) {		    perror("raidseek");		    fprintf(stderr, "Unable to seek to superblock offset of "				    "%s\n", name);		    continue;		}		if (read(fd, sb_buf, MD_SB_BYTES) != MD_SB_BYTES) {		    perror("read");		    fprintf(stderr, "Short read for superblock from %s\n",			    name);		    continue;		}		/* When creating raid arrays, the MULTIPATH personality is		 * enumerated as 7.  However, when parser.c actually puts		 * the level into the param block for being written out to		 * the real superblock, it uses -4 for MULTIPATH.  So,		 * check that the sb->level == -4 here		 */		if (sb->md_magic == MD_SB_MAGIC && sb->level == -4) {		    has_superblock = 1;		} else {		    has_superblock = 0;		}	        if (has_superblock && !global_new) {		    printf("/dev/md%d = ", sb->md_minor);		    printf("%s, ", name);		    for (j = 1; j < (k - 1); j++) {			printf("%s%d, ", sg_dev[multipath_array[j]]->name, l);		    }		    printf("%s%d\n", sg_dev[multipath_array[j]]->name, l);		}	    }	}    }    if (global_verbose)	printf("\n");    exit(0);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -