📄 raid.c
字号:
/* raid.c - The RAID-1 hooks for LILO *//*Copyright 2001-2005 John Coffman.All rights reserved.Licensed under the terms contained in the file 'COPYING' in the source directory.*/#define _GNU_SOURCE#include <stdlib.h>#include <unistd.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <fcntl.h>#include <errno.h>#include <sys/stat.h>/*#include <asm/page.h>*/#include "config.h"#include "lilo.h"#include "common.h"#include "raid.h"#include "boot.h"#include "device.h"#include "geometry.h"#include "bsect.h"#include "cfg.h"#include "partition.h"#include "md-int.h"static int lowest;static DT_ENTRY *md_disk;static DT_ENTRY *disk;static unsigned int raid_base, raid_offset[MAX_RAID];static char *raid_mbr[MAX_RAID];static int raid_device[MAX_RAID+1];static int raid_bios[MAX_RAID+1];static int device;enum {MD_NULL=0, MD_PARALLEL, MD_MIXED, MD_SKEWED};int do_md_install, ndisk, md_bios;static char *raid_list[MAX_RAID];static int list_index[MAX_RAID];static int nlist, faulty;static int autocount;static char *boot;#define IS_COVERED 0x1000#define TO_BE_COVERED 0x2000#define COVERED (IS_COVERED|TO_BE_COVERED)static int is_primary(int device){ int mask; mask = has_partitions(device); if (!mask) die("is_primary: Not a valid device 0x%04X", device); mask = device & ~mask; return (mask && mask<=PART_MAX);}static int master(int device){ int mask; if (MAJOR(device) == MAJOR_FD) return device; mask = has_partitions(device); if (!mask) die("master: Not a valid device 0x%04X", device); return device & mask;}static int is_accessible(int device){ int mask; mask = has_partitions(device); if (!mask) die("is_accessible: Not a valid device 0x%04X", device); mask = device & ~mask; return (mask<=PART_MAX);}int raid_setup(void){ int pass, mask; struct stat st; int md_fd; struct md_version md_version_info; md_disk_info_t md_disk_info; md_array_info_t md_array_info; GEOMETRY geo; DEVICE dev; char *extrap; int raid_offset_set, all_pri_eq, pri_index; int pri_offset; int raid_limit; if (!(boot=cfg_get_strg(cf_options,"boot"))) { boot = "/"; if (!nowarn) fprintf(errstd,"Warning: RAID1 install implied by omitted 'boot='\n"); } if (stat(boot,&st)<0) die("raid_setup: stat(\"%s\")", boot); if (verbose>=5) printf("raid_setup: dev=%04X rdev=%04X\n", (int)st.st_dev, (int)st.st_rdev);#if BETA_TEST fflush(stdout);#endif if ( MAJOR(st.st_rdev) != MAJOR_MD ) { /* not raid */ if (cfg_get_strg(cf_options, RAID_EXTRA_BOOT)) die("Not a RAID install, '" RAID_EXTRA_BOOT "=' not allowed"); return 0L; } else { /* It is a RAID installation *//* scan the devices in /proc/partitions */ pf_hard_disk_scan(); if ((md_fd=dev_open(&dev, st.st_rdev, O_NOACCESS) ) < 0) die("Unable to open %s",boot); boot = stralloc(dev.name); if (fstat(md_fd,&st) < 0) die("Unable to stat %s",boot); if (!S_ISBLK(st.st_mode)) die("%s is not a block device",boot); boot_dev_nr = st.st_rdev; /* set this very early */ if (ioctl(md_fd,RAID_VERSION,&md_version_info) < 0) die("Unable to get RAID version on %s", boot); if (md_version_info.major > 0) die("Raid major versions > 0 are not supported"); if (md_version_info.minor < 90) die("Raid versions < 0.90 are not supported"); if (ioctl(md_fd,GET_ARRAY_INFO,&md_array_info) < 0) die("Unable to get RAID info on %s",boot); if ((md_array_info.major_version != md_version_info.major) && (md_array_info.minor_version != md_version_info.minor)) die("Inconsistent Raid version information on %s", boot); if (md_array_info.level != 1) die("Only RAID1 devices are supported as boot devices"); if (!linear && !lba32) { lba32 = 1; if (!nowarn) fprintf(errstd,"Warning: RAID install requires LBA32 or LINEAR;" " LBA32 assumed.\n"); } extrap = cfg_get_strg(cf_options, RAID_EXTRA_BOOT); extra = !extrap ? X_AUTO : !strcasecmp(extrap,"none") ? X_NONE : !strcasecmp(extrap,"auto") ? X_AUTO : !strcasecmp(extrap,"mbr-only") ? X_MBR_ONLY : !strcasecmp(extrap,"mbr") ? X_MBR : X_SPEC; do_md_install = MD_PARALLEL; all_pri_eq = 1; raid_offset_set = pri_index = pri_offset = 0; raid_flags = FLAG_RAID; md_bios = 0xFF; /* we want to find the minimum */ ndisk = 0; /* count the number of disks on-line */ nlist = 0; faulty = 0; device = MKDEV(MD_MAJOR, md_array_info.md_minor); /* search the disk table for a definition */ md_disk = disktab; while (md_disk && md_disk->device != device) md_disk = md_disk->next; if (!md_disk) { md_disk = alloc_t(DT_ENTRY); md_disk->device = MKDEV(MD_MAJOR, md_array_info.md_minor); md_disk->bios = -1; /* use the default */ md_disk->next = disktab; disktab = md_disk; } if (verbose >= 2) { printf("RAID info: nr=%d, raid=%d, active=%d, working=%d, failed=%d, spare=%d\n", md_array_info.nr_disks, md_array_info.raid_disks, md_array_info.active_disks, md_array_info.working_disks, md_array_info.failed_disks, md_array_info.spare_disks ); } /* scan through all the RAID devices */ raid_limit = md_array_info.raid_disks + md_array_info.spare_disks; raid_index = 0; for (pass=0; pass < raid_limit; pass++) { DEVICE dev; int disk_fd; char new_name[MAX_TOKEN+1]; char *np; md_disk_info.number = pass; if (ioctl(md_fd,GET_DISK_INFO,&md_disk_info) < 0)#if 1 die("raid: GET_DISK_INFO: %s, pass=%d", strerror(errno), pass);#else { printf("raid: GET_DISK_INFO: %s, pass=%d\n", strerror(errno), pass); continue; }#endif device = MKDEV(md_disk_info.major, md_disk_info.minor); if(verbose>=3) printf("md: RAIDset device %d = 0x%04X\n", pass, device); if (device == 0) { /* empty slot left over from recovery process */ faulty++; if (!nowarn) fprintf(errstd,"Warning: Faulty disk in RAID-1 array; boot with caution!!\n"); continue; } disk_fd = dev_open(&dev,device,O_NOACCESS); if (md_disk_info.state & (1 << MD_DISK_FAULTY)) { printf("disk %s marked as faulty, skipping\n",dev.name); faulty++; continue; } geo_get(&geo, device, -1, 1); disk = alloc_t(DT_ENTRY); if (verbose>=3) printf("RAID scan: geo_get: returns geo->device = 0x%02X" " for device %04X\n", geo.device, device); disk->bios = geo.device; /* will be overwritten */ disk->device = device; /* used to mask above with 0xFFF0; forces MBR; sloppy, mask may be: 0xFFF8 */ disk->sectors = geo.sectors; disk->heads = geo.heads; disk->cylinders = geo.cylinders; disk->start = geo.start; if (ndisk==0) { raid_base = geo.start; raid_index = pass; } raid_offset[ndisk] = geo.start - raid_base; raid_device[ndisk] = device; if (raid_offset[ndisk]) { do_md_install = MD_SKEWED; /* flag non-zero raid_offset */ } if (all_pri_eq && is_primary(device)) { if (raid_offset_set) { all_pri_eq &= (pri_offset == raid_offset[ndisk]); } else { pri_offset = raid_offset[ndisk]; raid_offset_set = 1; pri_index = ndisk; } }#if 1 if (geo.device < md_bios) { /* OLD: use smallest device code */#else if (ndisk==0) { /* NEW: use the device code of the first device */#endif md_bios = geo.device; /* find smallest device code, period */ lowest = ndisk; /* record where */ } raid_bios[ndisk] = geo.device; /* record device code */ disk->next = disktab; disktab = disk; if (verbose >= 3 && do_md_install) { printf("disk->start = %d\t\traid_offset = %d (%08X)\n", disk->start, (int)raid_offset[ndisk], (int)raid_offset[ndisk]); } /* derive the MBR name, which may be needed later */ strncpy(new_name,dev.name,MAX_TOKEN); new_name[MAX_TOKEN] = '\0'; np = boot_mbr(dev.name, 0); if (!np) np = stralloc(new_name); raid_mbr[ndisk] = np; if (ndisk==0) { /* use the first disk geometry */ md_disk->sectors = geo.sectors; md_disk->heads = geo.heads; md_disk->cylinders = geo.cylinders; md_disk->start = geo.start; } ndisk++; /* count the disk */ } /* for (pass=... */ dev_close(&dev); raid_bios[ndisk] = 0; /* mark the end */ raid_device[ndisk] = 0; all_pri_eq &= raid_offset_set; if (all_pri_eq && do_md_install == MD_SKEWED) { do_md_install = MD_MIXED; } else pri_index = lowest;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -