📄 raidreconf.c
字号:
} 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 + -