📄 raidreconf.c
字号:
/* * raidreconf.c: RAID Reconfiguration Utility, for resizing and reconfiguration * of RAID sets. * (C) 1999,2000 by Jakob Oestergaard * * This code is based on the mkraid.c program by Ingo Molnar and others. * * This source is covered by the GNU GPL, the same as all Linux kernel * sources. */#include "raidreconf.h"/* * The strategy is: * * 1) Read the raidtabs * 2) Read the superblocks, and perform some consistency checks... * 3) Find the difference(s) between the two, and decide what to do * 4) If possible, convert array * * TOFIX: * Add linear and raid-5 * * Test this on large arrays (100+GB) * * Checkpoint file (to allow continuation without data loss * after eg. power-surge) * */void printcfg (md_cfg_entry_t * cfg);level_driver_t *source_driver = 0, *sink_driver = 0;static int raid_reconfigure (mdu_version_t *);voidusage (void){ printf ("usage: raidreconf [--version] [--test] {-o <old_raidtab>|-i <import_device>} {-n <new_raidtab>| -e<export device>} [-m <md device>]\n" "examples:\n" " Resize an existing array:\n" " raidreconf -o /etc/raidtab.old -n /etc/raidtab.new -m /dev/md3\n" " Import data on a disk into an array:\n" " raidreconf -i /dev/sda3 -n /etc/raidtab -m /dev/md3\n");}intmain (int argc, const char *argv[]){ FILE *fp = 0; md_cfg_entry_t *p = 0; int exit_status = 0; int version = 0, help = 0; char *old_raidtab = 0, *import_device = 0, *new_raidtab = 0, *export_device = 0, *md_device = 0; poptContext optCon; int i; struct poptOption optionsTable[] = { {"help", 'h', POPT_ARG_NONE, &help, 0}, {"version", 'V', POPT_ARG_NONE, &version, 0}, {"test", 't', POPT_ARG_NONE, &test, 0}, {"old", 'o', POPT_ARG_STRING, &old_raidtab, 0}, {"import", 'i', POPT_ARG_STRING, &import_device, 0}, {"new", 'n', POPT_ARG_STRING, &new_raidtab, 0}, {"export", 'e', POPT_ARG_STRING, &export_device, 0}, {"mddev", 'm', POPT_ARG_STRING, &md_device, 0}, {0, 0, 0, 0, 0} }; optCon = poptGetContext ("raidreconf", argc, argv, optionsTable, 0); if ((i = poptGetNextOpt (optCon)) < -1) { fprintf (stderr, "%s: %s\n", poptBadOption (optCon, POPT_BADOPTION_NOALIAS), poptStrerror (i)); usage (); return EXIT_FAILURE; } if (i != -1) { fprintf (stderr, "Extra arguments given - giving up.\n"); usage (); return EXIT_FAILURE; } if (!test && prepare_raidlib ()) return EXIT_FAILURE; if (help) { usage (); return EXIT_FAILURE; } if (version) { printf ("raidreconf 0.1.2 for mkraid version %d.%d.%d\n", MKRAID_MAJOR_VERSION, MKRAID_MINOR_VERSION, MKRAID_PATCHLEVEL_VERSION); return EXIT_VERSION; } if (test) { printf ("test mode - plain files are used, no kernel RAID interaction\n"); } if (!test && getMdVersion (&ver)) return EXIT_FAILURE; /* * Check that mandatory arguments are given */ if (!md_device) { fprintf (stderr, "no md device given\n"); usage(); return EXIT_FAILURE; } /* * Check for mutually exclusive arguments */ if (import_device && export_device) { fprintf (stderr, "cannot both import and export\n"); return EXIT_FAILURE; } if (old_raidtab && import_device) { fprintf (stderr, "cannot both have an import device and an old raidtab\n"); return EXIT_FAILURE; } if (new_raidtab && export_device) { fprintf (stderr, "cannot both have an export device and a new raidtab\n"); return EXIT_FAILURE; } /* * Check source -> destination path */ if (old_raidtab && !(new_raidtab || export_device)) { fprintf (stderr, "old raidtab given, but no new raidtab and no export device\n"); return EXIT_FAILURE; } if (import_device && !new_raidtab) { fprintf (stderr, "import device given, but no new raidtab\n"); return EXIT_FAILURE; } /* * Good, now let's move on */ printf ("Working with device %s\n", md_device); /* * Treat import setup */ if (import_device) { printf ("I assume %s is a device you want to import\n", import_device); old_md_cfg = setup_single_config (import_device); if (!old_md_cfg) { fprintf (stderr, "Import of device failed!\n"); return EXIT_FAILURE; } } if (old_raidtab) { fp = fopen (old_raidtab, "r"); if (!fp) { fprintf (stderr, "Couldn't open %s -- %s\n", old_raidtab, strerror (errno)); return EXIT_FAILURE; } fprintf (stderr, "Parsing %s\n", old_raidtab); if (parse_config (fp)) { fprintf (stderr, "Cannot parse old-array configuration file"); return EXIT_FAILURE; } for (p = cfg_head; p; p = p->next) { if (strcmp (p->md_name, md_device)) continue; old_md_cfg = p; break; } if (!p) { fprintf (stderr, "device %s is not described in config file\n", md_device); exit_status++; } fclose (fp); } /* * Read the NEW configuration file */ if (export_device) { printf ("I assume %s is a device you want to export to\n", export_device); new_md_cfg = setup_single_config (export_device); if (!new_md_cfg) { fprintf (stderr, "Export to device failed!\n"); return EXIT_FAILURE; } } if (new_raidtab) { fp = fopen (new_raidtab, "r"); if (!fp) { fprintf (stderr, "Couldn't open %s -- %s\n", new_raidtab, strerror (errno)); return EXIT_FAILURE; } fprintf (stderr, "Parsing %s\n", new_raidtab); if (parse_config (fp)) { fprintf (stderr, "Cannot parse new-array configuration file.\n"); return EXIT_FAILURE; } /* Seek from where we left. */ for (p = (p ? p->next : cfg_head); p; p = p->next) { if (strcmp (p->md_name, md_device)) continue; new_md_cfg = p; break; } if (!p) { fprintf (stderr, "device %s is not described in config file\n", md_device); exit_status++; return EXIT_FAILURE; } } if (raid_reconfigure (&ver)) { fprintf (stderr, "reconfiguration failed\n"); return EXIT_FAILURE; } return 0;}#define P(x) printf("%18s: \t %d\n",#x,cfg->array.param.x)#define DP(x) printf("%18s: \t %d\n",#x,cfg->array.disks[i].x)voidprintcfg (md_cfg_entry_t * cfg){ int i; P (major_version); P (minor_version); P (patch_version); P (ctime); P (level); P (size); P (nr_disks); P (raid_disks); P (md_minor); P (utime); P (state); P (active_disks); P (working_disks); P (failed_disks); P (spare_disks); P (layout); P (chunk_size); for (i = 0; i < cfg->array.param.nr_disks; i++) { printf ("\n"); DP (number); DP (major); DP (minor); DP (raid_disk); DP (state); }}static intread_needed_entries (md_cfg_entry_t * cfg){ int i; for (i = 0; i != cfg->array.param.nr_disks; i++) { int disk_num = cfg->array.disks[i].raid_disk; char *devname = cfg->device_name[disk_num]; int fd = open (devname, O_RDWR); int nr_blocks; /* sb_block_offset code */ if (fd == -1) { fprintf (stderr, "Cannot open %s for read/write\n", devname); return 1; } 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 >> 10) << 10) != sbuf.st_size) { fprintf (stderr, "Sorry, device %s size %lu is bad\n", devname, sbuf.st_size); return 1; } nr_blocks = sbuf.st_size >> 10; } 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; } nr_blocks >>= 1; } if (nr_blocks < MD_RESERVED_BLOCKS * 2) { fprintf (stderr, "%s: device too small (%dkB)\n", devname, nr_blocks); return 1; } cfg->sb_block_offset[i] = MD_NEW_SIZE_BLOCKS (nr_blocks); close (fd); } return 0;}intraid_get_size (md_cfg_entry_t * cfg, unsigned long *sum){ int i; *sum = 0; for (i = 0; i != cfg->array.param.nr_disks; i++) { int dnum = cfg->array.disks[i].raid_disk; char *devname = cfg->device_name[dnum]; int fd = open (devname, O_RDONLY); unsigned long nr_blocks; if (fd == -1) { fprintf (stderr, "Cannot open %s for read/write\n", devname); return 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -