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

📄 raidreconf.c

📁 create raid tool at linux
💻 C
📖 第 1 页 / 共 2 页
字号:
		}		if (test) {			struct stat sbuf;			if (fstat (fd, &sbuf)) {				fprintf (stderr,					 "Couldn't stat device %s -- %s\n",					 devname, strerror (errno));				return 1;			}			if (((sbuf.st_size >> 9) << 9) != sbuf.st_size) {				fprintf (stderr,					 "Sorry, device %s size %lu is bad\n",					 devname, sbuf.st_size);				return 1;			}			nr_blocks = sbuf.st_size >> 9;		}		else {			if (ioctl			    (fd, BLKGETSIZE,			     (unsigned long) &nr_blocks) == -1) {				fprintf (stderr,					 "couldn't get device size for %s -- %s\n",					 devname, strerror (errno));				return 1;			}		}		*sum += nr_blocks;		close (fd);	}	return 0;}/* The returned arrays oldarry and newarry holds filedescriptors and  * other info. on the raid-disk nr.   oldarry[i] refers to raid-disk i, * not necessarily device number i. */intsetup_disk_arrays (md_cfg_entry_t * oldcfg, rrc_disk_t ** oldarry,		   md_cfg_entry_t * newcfg, rrc_disk_t ** newarry){	int i;	char **didnames;	int cid;	/* allocate fdsets and open files */	*oldarry =	    (rrc_disk_t *) malloc (sizeof (rrc_disk_t) *				   oldcfg->array.param.nr_disks);	*newarry =	    (rrc_disk_t *) malloc (sizeof (rrc_disk_t) *				   newcfg->array.param.nr_disks);	if (!*oldarry || !*newarry) {		fprintf (stderr, "rrc_disk_t array malloc failure!\n");		return 1;	}	didnames =	    (char **) malloc (sizeof (char *) *			      (oldcfg->array.param.nr_disks +			       newcfg->array.param.nr_disks));	if (!didnames) {		fprintf (stderr, "error allocating didnames array\n");		return 1;	}	cid = 0;	didnames[cid] =	    oldcfg->device_name[oldcfg->array.disks[0].raid_disk];	for (i = 0; i != oldcfg->array.param.nr_disks; i++) {		int dnum = oldcfg->array.disks[i].raid_disk;		char *devname = oldcfg->device_name[dnum];		(*oldarry)[i].fd = open (devname, O_RDONLY);		if ((*oldarry)[i].fd == -1) {			fprintf (stderr, "error opening %s for reading\n",				 devname);			return 1;		}		(*oldarry)[i].chunks =		    oldcfg->sb_block_offset[dnum] /		    (oldcfg->array.param.chunk_size / BLOCK_SIZE);		(*oldarry)[i].blocks = oldcfg->sb_block_offset[dnum];		fprintf (stderr,			 "Old raid-disk %i has %lu chunks, %lu blocks\n",			 dnum, (*oldarry)[i].chunks, (*oldarry)[i].blocks);		/* Build new ID. We assume devices are unique, which should be a fair assumption */		if (strcmp (didnames[cid], devname)) {			cid++;			didnames[cid] = devname;		}		(*oldarry)[i].disk_id = cid;	}	for (i = 0; i != newcfg->array.param.nr_disks; i++) {		int dnum = newcfg->array.disks[i].raid_disk;		char *devname = newcfg->device_name[dnum];		int idi;		(*newarry)[i].fd = open (devname, O_WRONLY);		if ((*newarry)[i].fd == -1) {			fprintf (stderr, "error opening %s for writing\n",				 devname);			return 1;		}		(*newarry)[i].chunks =		    newcfg->sb_block_offset[dnum] /		    (newcfg->array.param.chunk_size / BLOCK_SIZE);		(*newarry)[i].blocks = newcfg->sb_block_offset[dnum];		fprintf (stderr,			 "New raid-disk %i has %lu chunks, %lu blocks\n",			 dnum, (*newarry)[i].chunks, (*newarry)[i].blocks);		/* Assign ID. Search the didnames table */		for (idi = 0; idi <= cid; idi++) {			if (!strcmp (didnames[idi], devname))				break;		}		if (idi > cid) {			cid++;			didnames[cid] = devname;			idi = cid;		}		(*newarry)[i].disk_id = idi;	}	free (didnames);	return 0;}static intraid_reconfigure (mdu_version_t *ver){	int fd;	unsigned char buffer[MD_SB_BYTES];	mdp_super_t *phys_sb = (mdp_super_t *) buffer;	md_cfg_entry_t *cptr;	unsigned long oldsum = 0;	unsigned long newsum = 0;	int rc;	const char *ret;	assert (old_md_cfg && new_md_cfg);#if 0	printf ("new device: %s\n", new_md_cfg->md_name);	printcfg (new_md_cfg);	printf ("old device: %s\n", old_md_cfg->md_name);	printcfg (old_md_cfg);#endif	/* Initialize the sb_block_offset fields in the old_md_cfg	 * and new_md_cfg structs.	 */	for (cptr = old_md_cfg; cptr;) {		/* We refuse to touch anything thats active */		if (check_active (cptr))			return 1;		/* If there's no persistent superblock, we give up.  This utility relies		 * on persistent superblocks. */		if (cptr->array.param.not_persistent) {			fprintf (stderr,				 "Sorry, your array MUST use persistent superblocks for this utility to work\n");			return 1;		}		if (read_needed_entries (cptr))			return 1;		/* ``iterate'' */		if (cptr == new_md_cfg)			cptr = 0;		else			cptr = new_md_cfg;	}	/* Read the superblock from the first disk in the (old) array, if we're not importing... */	if (old_md_cfg->array.param.level != RRC_SINGLE_DISK_LEVEL) {		assert (old_md_cfg->array.param.nr_disks);		fd = open (old_md_cfg->device_name[0], O_RDONLY);		if (fd == -1) {			fprintf (stderr,				 "Uhoh, cannot open first disk in array: %s\n",				 *cfg->device_name);			return 1;		}		if (raidseek (fd, old_md_cfg->sb_block_offset[0]) == -1)			return 1;		if ((read (fd, buffer, MD_SB_BYTES)) != MD_SB_BYTES)			return 1;		phys_sb = (mdp_super_t *) buffer;		if (phys_sb->md_magic != MD_SB_MAGIC) {			fprintf (stderr,				 "Sorry, %s doesn't seem to hold a superblock.\n",				 old_md_cfg->device_name[0]);			return 1;		}		close (fd);		/*		 * A few generic checks:		 *		 * 1) Our on-disk array must be clean		 *		 * 2) We could check that the old config matches the superblock read, but this		 *    is not all that important. Besides, it would be great if we could run this		 *    without even having an old config.		 *		 */		if (!(phys_sb->state & (1 << MD_SB_CLEAN))) {			fprintf (stderr,				 "Your on-disk array MUST be clean first.\n");			return 1;		}	}	/* Sum up the number of blocks in the new and the old layout */	rc = raid_get_size (new_md_cfg, &newsum);	rc += raid_get_size (old_md_cfg, &oldsum);	if (rc) {		fprintf (stderr, "Cannot get RAID sizes...\n");		return 1;	}	printf	    ("Size of old array: %lu blocks,  Size of new array: %lu blocks\n",	     oldsum, newsum);	/* Decide what we're supposed to do....	 * What we currently CAN do:	 *	 * Expand/Shrink RAID0	 * Expand/Shrink RAID5	 * Import non-raid data onto RAID 0/5	 * Convert RAID0 to RAID5 or vice-versa	 *	 */	switch (old_md_cfg->array.param.level) {	case RRC_SINGLE_DISK_LEVEL:		source_driver = new_single_driver ();		break;	case 0:		source_driver = new_raid0_driver ();		break;	case 5:		source_driver = new_raid5_driver ();		break;	}	switch (new_md_cfg->array.param.level) {	case RRC_SINGLE_DISK_LEVEL:		sink_driver = new_single_driver ();		break;	case 0:		sink_driver = new_raid0_driver ();		break;	case 5:		sink_driver = new_raid5_driver ();		break;	}	if (!source_driver) {		fprintf (stderr,			 "No source driver available for level %i\n",			 old_md_cfg->array.param.level);		return 1;	}	if (!sink_driver) {		fprintf (stderr, "No sink driver available for level %i\n",			 new_md_cfg->array.param.level);		return 1;	}	/* Just in case we're dealing with a single-disk device, set their chunk_size 	 * to the chunk_size of the real RAID device */	if (old_md_cfg->array.param.level == RRC_SINGLE_DISK_LEVEL	    && new_md_cfg->array.param.level == RRC_SINGLE_DISK_LEVEL) {		fprintf (stderr,			 "Your're using raidreconf to copy data from one single disk to another ?\n"			 "dd is a better tool for that, but nevermind.  Setting block size to 1K\n");		old_md_cfg->array.param.chunk_size =		    new_md_cfg->array.param.chunk_size = MD_BLK_SIZ;	}	else {		if (old_md_cfg->array.param.level == RRC_SINGLE_DISK_LEVEL)			old_md_cfg->array.param.chunk_size =			    new_md_cfg->array.param.chunk_size;		else if (new_md_cfg->array.param.level ==			 RRC_SINGLE_DISK_LEVEL) new_md_cfg->array.param.			    chunk_size =			    old_md_cfg->array.param.chunk_size;	}	rc =	    setup_disk_arrays (old_md_cfg, &old_rrc_cfg, new_md_cfg,			       &new_rrc_cfg);	if (rc) {		fprintf (stderr,			 "There was a fatal error while setting up the arrays for reconfiguration.\n");		return 1;	}	if ((ret = run_reconfiguration ())) {		fprintf (stderr, "Reconfiguration failed: \"%s\"\n", ret);		return 1;	}	return 0;}md_cfg_entry_t *setup_single_config (const char *devname){	/* This piece here is modelled after the code in parser.c */	/* It will fill in the fields in the md_cfg_entry_t that we	 * need to treat the new non-RAID drive as an array (for imports)	 */	md_cfg_entry_t *ret =	    (md_cfg_entry_t *) malloc (sizeof (md_cfg_entry_t));	if (!ret) {		fprintf (stderr,			 "I cannot allocate memory for the new-drive cfg_entry.\n");		exit (1);	}	memset (ret, 0, sizeof (md_cfg_entry_t));	/* We need fields:	 * .array.param.level	 * .array.param.nr_disks	 * .array.disks[i].raid_disk	 * .device_name[i]	 *	 * Later these fields are filled in:	 * .sb_block_offset[i]	 * .array.param.chunk_size  (must be zero from here)	 */	ret->array.param.level = RRC_SINGLE_DISK_LEVEL;	ret->array.param.nr_disks = 1;	ret->array.param.chunk_size = 0;	ret->array.disks[0].raid_disk = 0;	ret->md_name = ret->device_name[0] = strdup (devname);	if (!ret->md_name) {		fprintf (stderr,			 "Cannot allocate memory for strdup in single_drive config\n");		exit (1);	}	return ret;}

⌨️ 快捷键说明

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