--- lilo.new/lilo.c.noraid Tue Sep 21 23:58:01 1999 +++ lilo.new/lilo.c Wed Sep 22 04:18:22 1999 @@ -24,11 +24,11 @@ #include "cfg.h" #include "identify.h" #include "partition.h" - +#include "md-int.h" #define S2(x) #x #define S(x) S2(x) - +#define MAX_TOKEN 200 static void show_other(int fd) { @@ -227,15 +227,21 @@ { char *name,*config_file,*reboot_arg,*identify,*ident_opt,*new_root; char *uninst_dev; - int query,more,version,uninstall,validate; + int query,more,version,uninstall,validate,do_md_install,pass; BOOT_SECTOR dummy; IMAGE_DESCR dummy2; struct stat st; - int fd; + int fd, md_fd; + md_array_info_t md_array_info; + md_disk_info_t md_disk_info; + char md_boot_name[MAX_TOKEN+1]; + char md_boot_map[MAX_TOKEN+1]; + DT_ENTRY md_disk; + DT_ENTRY *disk; config_file = DFL_CONFIG; reboot_arg = identify = ident_opt = new_root = uninst_dev = NULL; - query = version = uninstall = validate = 0; + pass = do_md_install = query = version = uninstall = validate = 0; name = *argv++; argc--; cfg_init(cf_options); @@ -414,43 +420,117 @@ } preload_dev_cache(); if (identify) identify_image(identify,ident_opt); - if (uninstall) - bsect_uninstall(uninst_dev ? uninst_dev : cfg_get_strg(cf_options, - "boot"),cfg_get_strg(cf_options,"backup"),validate); - compact = cfg_get_flag(cf_options,"compact"); - linear = cfg_get_flag(cf_options,"linear"); - nowarn = cfg_get_flag(cf_options,"nowarn"); - if (cfg_get_strg(cf_options,"verbose")) - verbose += to_number(cfg_get_strg(cf_options,"verbose")); - if (reboot_arg) { - map_patch_first(cfg_get_strg(cf_options,"map") ? cfg_get_strg( - cf_options,"map") : MAP_FILE,reboot_arg); - exit(0); - } - if (argc) usage(name); - geo_init(cfg_get_strg(cf_options,"disktab")); - if (query) - show_images(!cfg_get_strg(cf_options,"map") ? MAP_FILE : - cfg_get_strg(cf_options,"map")); - bsect_open(cfg_get_strg(cf_options,"boot"),cfg_get_strg(cf_options,"map") ? - cfg_get_strg(cf_options,"map") : MAP_FILE,cfg_get_strg(cf_options, - "install"),cfg_get_strg(cf_options,"delay") ? to_number(cfg_get_strg( - cf_options,"delay")) : 0,cfg_get_strg(cf_options,"timeout") ? - to_number(cfg_get_strg(cf_options,"timeout")) : -1); - if (more) { - cfg_init(cf_top); - if (cfg_parse(cf_top)) cfg_error("Syntax error"); - } - if (!bsect_number()) die("No images have been defined."); - check_fallback(); - if (!test) - if (cfg_get_strg(cf_options,"force-backup")) - bsect_update(cfg_get_strg(cf_options,"force-backup"),1); - else bsect_update(cfg_get_strg(cf_options,"backup"),0); - else { - bsect_cancel(); - fprintf(stderr,"The boot sector and the map file have *NOT* been " - "altered.\n"); + if (strncmp("/dev/md",cfg_get_strg(cf_options,"boot"),7) == 0) { + if ((md_fd=open(cfg_get_strg(cf_options,"boot"),O_NOACCESS)) < 0) + die("Unable to open %s",cfg_get_strg(cf_options,"boot")); + if (fstat(md_fd,&st) < 0) + die("Unable to stat %s",cfg_get_strg(cf_options,"boot")); + if (!S_ISBLK(st.st_mode)) + die("%s is not a block device",cfg_get_strg(cf_options,"boot")); + if (ioctl(md_fd,GET_ARRAY_INFO,&md_array_info) < 0) + die("Unable to get RAID info on %s",cfg_get_strg(cf_options,"boot")); + if ((md_array_info.major_version == 0) && (md_array_info.minor_version < 90)) + die("Raid versions < 0.90 are not supported"); + if (md_array_info.level != 1) + die("Only RAID1 devices are supported as boot devices"); + do_md_install = 1; + strcpy(md_boot_name,cfg_get_strg(cf_options,"boot")); + if (cfg_get_strg(cf_options,"map")) + strcpy(md_boot_map,cfg_get_strg(cf_options,"map")); + else + strcpy(md_boot_map,MAP_FILE); + md_disk.device = (MD_MAJOR << 8) | md_array_info.md_minor; + md_disk.bios = 0x80; + md_disk.next = disktab; + disktab = &md_disk; + } + while( (pass == 0) || (do_md_install && (pass < md_array_info.nr_disks)) ) { + if(do_md_install) { + GEOMETRY geo; + DEVICE dev; + int device,disk_fd; + char new_name[MAX_TOKEN+1]; + + if(pass > 0) { + close(fd); + cfg_init(cf_options); + fd = cfg_open(config_file); + more = cfg_parse(cf_options); + } + md_disk_info.number = pass; + if (ioctl(md_fd,GET_DISK_INFO,&md_disk_info) < 0) + die("main: GET_DISK_INFO: %s", strerror(errno)); + device = (md_disk_info.major << 8) | md_disk_info.minor; + disk_fd = dev_open(&dev,device,O_NOACCESS); + if (md_disk_info.state == MD_DISK_FAULTY) { + printf("disk %s marked as faulty, skipping\n",dev.name); + pass++; + continue; + } + geo_query_dev(&geo,device,1); + disk = alloc_t(DT_ENTRY); + disk->bios = 0x80; + disk->device = device & 0xfff0; + disk->sectors = geo.sectors; + disk->heads = geo.heads; + disk->cylinders = geo.cylinders; + disk->start = geo.start; + disk->next = disktab; + disktab = disk; + if (cfg_get_strg(cf_options,"boot")) cfg_unset(cf_options,"boot"); + if (cfg_get_strg(cf_options,"map")) cfg_unset(cf_options,"map"); + strncpy(new_name,dev.name,8); + new_name[8] = '\0'; + cfg_set(cf_options,"boot",new_name,NULL); + snprintf(new_name,MAX_TOKEN,"%s.%04x",md_boot_map,device); + cfg_set(cf_options,"map",new_name,NULL); + printf("boot = %s, map = %s\n", cfg_get_strg(cf_options,"boot"), + cfg_get_strg(cf_options,"map")); + md_disk.sectors = geo.sectors; + md_disk.heads = geo.heads; + md_disk.cylinders = geo.cylinders; + md_disk.start = geo.start; + } + + pass++; + if (uninstall) + bsect_uninstall(uninst_dev ? uninst_dev : cfg_get_strg(cf_options, + "boot"),cfg_get_strg(cf_options,"backup"),validate); + compact = cfg_get_flag(cf_options,"compact"); + linear = cfg_get_flag(cf_options,"linear"); + nowarn = cfg_get_flag(cf_options,"nowarn"); + if (cfg_get_strg(cf_options,"verbose")) + verbose += to_number(cfg_get_strg(cf_options,"verbose")); + if (reboot_arg) { + map_patch_first(cfg_get_strg(cf_options,"map") ? cfg_get_strg( + cf_options,"map") : MAP_FILE,reboot_arg); + exit(0); + } + if (argc) usage(name); + geo_init(cfg_get_strg(cf_options,"disktab")); + if (query) + show_images(!cfg_get_strg(cf_options,"map") ? MAP_FILE : + cfg_get_strg(cf_options,"map")); + bsect_open(cfg_get_strg(cf_options,"boot"),cfg_get_strg(cf_options,"map") ? + cfg_get_strg(cf_options,"map") : MAP_FILE,cfg_get_strg(cf_options, + "install"),cfg_get_strg(cf_options,"delay") ? to_number(cfg_get_strg( + cf_options,"delay")) : 0,cfg_get_strg(cf_options,"timeout") ? + to_number(cfg_get_strg(cf_options,"timeout")) : -1); + if (more) { + cfg_init(cf_top); + if (cfg_parse(cf_top)) cfg_error("Syntax error"); + } + if (!bsect_number()) die("No images have been defined."); + check_fallback(); + if (!test) + if (cfg_get_strg(cf_options,"force-backup")) + bsect_update(cfg_get_strg(cf_options,"force-backup"),1); + else bsect_update(cfg_get_strg(cf_options,"backup"),0); + else { + bsect_cancel(); + fprintf(stderr,"The boot sector and the map file have *NOT* been " + "altered.\n"); + } } return 0; } --- lilo.new/geometry.c.noraid Wed Sep 22 00:55:32 1999 +++ lilo.new/geometry.c Wed Sep 22 03:13:29 1999 @@ -35,18 +35,9 @@ struct stat st; } ST_BUF; -typedef struct _dt_entry { - int device,bios; - int sectors; - int heads; /* 0 if inaccessible */ - int cylinders; - int start; - struct _dt_entry *next; -} DT_ENTRY; - -static DT_ENTRY *disktab = NULL; -static int old_disktab = 0; +DT_ENTRY *disktab = NULL; +int old_disktab = 0; void geo_init(char *name) @@ -260,7 +251,7 @@ } -static void geo_query_dev(GEOMETRY *geo,int device,int all) +void geo_query_dev(GEOMETRY *geo,int device,int all) { DEVICE dev; int fd,get_all; --- lilo.new/geometry.h.noraid Wed Sep 22 00:56:06 1999 +++ lilo.new/geometry.h Wed Sep 22 03:12:23 1999 @@ -18,6 +18,17 @@ int boot; /* non-zero after geo_open_boot */ } GEOMETRY; +typedef struct _dt_entry { + int device,bios; + int sectors; + int heads; /* 0 if inaccessible */ + int cylinders; + int start; + struct _dt_entry *next; +} DT_ENTRY; + +extern DT_ENTRY *disktab; + void geo_init(char *name); /* Loads the disk geometry table. */ @@ -59,5 +70,10 @@ /* lseeks in the file associated with GEO for the sector at address ADDR. Returns a non-zero integer on success, zero on failure. */ + +void geo_query_dev(GEOMETRY *geo,int device,int all); + +/* opens the specified device and gets the geometry information. That + information is then stored in *geo */ #endif --- lilo.new/md-int.h.noraid Wed Sep 22 13:06:36 1999 +++ lilo.new/md-int.h Tue Sep 21 22:57:41 1999 @@ -0,0 +1,290 @@ +/* + md.h : Multiple Devices driver for Linux + Copyright (C) 1994-96 Marc ZYNGIER + or + + + 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. + + You should have received a copy of the GNU General Public License + (for example /usr/src/linux/COPYING); if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef MD_INT_H +#define MD_INT_H + +/* don't include the kernel RAID header! */ +#define _MD_H + +typedef unsigned int md_u32; +typedef unsigned short md_u16; +typedef unsigned char md_u8; + +#include +#include + +/* + * Different major versions are not compatible. + * Different minor versions are only downward compatible. + * Different patchlevel versions are downward and upward compatible. + */ + +struct md_version { + int major; + int minor; + int patchlevel; +}; + +/* + * default readahead + */ +#define MD_READAHEAD (256 * 1024) + +/* These are the ioctls for md versions < 0.50 */ +#define REGISTER_MD_DEV _IO (MD_MAJOR, 1) +#define START_MD _IO (MD_MAJOR, 2) +#define STOP_MD _IO (MD_MAJOR, 3) + +/* status */ +#define RAID_VERSION _IOR (MD_MAJOR, 0x10, struct md_version) +#define GET_ARRAY_INFO _IOR (MD_MAJOR, 0x11, md_array_info_t) +#define GET_DISK_INFO _IOR (MD_MAJOR, 0x12, md_disk_info_t) +#define PRINT_RAID_DEBUG _IO (MD_MAJOR, 0x13) + +/* configuration */ +#define CLEAR_ARRAY _IO (MD_MAJOR, 0x20) +#define ADD_NEW_DISK _IOW (MD_MAJOR, 0x21, md_disk_info_t) +#define HOT_REMOVE_DISK _IO (MD_MAJOR, 0x22) +#define SET_ARRAY_INFO _IOW (MD_MAJOR, 0x23, md_array_info_t) +#define SET_DISK_INFO _IO (MD_MAJOR, 0x24) +#define WRITE_RAID_INFO _IO (MD_MAJOR, 0x25) +#define UNPROTECT_ARRAY _IO (MD_MAJOR, 0x26) +#define PROTECT_ARRAY _IO (MD_MAJOR, 0x27) +#define HOT_ADD_DISK _IO (MD_MAJOR, 0x28) + +/* usage */ +#define RUN_ARRAY _IOW (MD_MAJOR, 0x30, struct md_param) +#define START_ARRAY _IO (MD_MAJOR, 0x31) +#define STOP_ARRAY _IO (MD_MAJOR, 0x32) +#define STOP_ARRAY_RO _IO (MD_MAJOR, 0x33) +#define RESTART_ARRAY_RW _IO (MD_MAJOR, 0x34) + + +/* for raid < 0.50 only */ +#define MD_PERSONALITY_SHIFT 16 + +#define MD_RESERVED 0UL +#define LINEAR 1UL +#define STRIPED 2UL +#define RAID0 STRIPED +#define RAID1 3UL +#define RAID5 4UL +#define TRANSLUCENT 5UL +#define LVM 6UL +#define MAX_PERSONALITY 7UL + +/* + * MD superblock. + * + * The MD superblock maintains some statistics on each MD configuration. + * Each real device in the MD set contains it near the end of the device. + * Some of the ideas are copied from the ext2fs implementation. + * + * We currently use 4096 bytes as follows: + * + * word offset function + * + * 0 - 31 Constant generic MD device information. + * 32 - 63 Generic state information. + * 64 - 127 Personality specific information. + * 128 - 511 12 32-words descriptors of the disks in the raid set. + * 512 - 911 Reserved. + * 912 - 1023 Disk specific descriptor. + */ + +/* + * If x is the real device size in bytes, we return an apparent size of: + * + * y = (x & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES + * + * and place the 4kB superblock at offset y. + */ +#define MD_RESERVED_BYTES (64 * 1024) +#define MD_RESERVED_SECTORS (MD_RESERVED_BYTES / 512) +#define MD_RESERVED_BLOCKS (MD_RESERVED_BYTES / BLOCK_SIZE) + +#define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) - MD_RESERVED_SECTORS) +#define MD_NEW_SIZE_BLOCKS(x) ((x & ~(MD_RESERVED_BLOCKS - 1)) - MD_RESERVED_BLOCKS) + +#define MD_SB_BYTES 4096 +#define MD_SB_WORDS (MD_SB_BYTES / 4) +#define MD_SB_BLOCKS (MD_SB_BYTES / BLOCK_SIZE) +#define MD_SB_SECTORS (MD_SB_BYTES / 512) + +/* + * The following are counted in 32-bit words + */ +#define MD_SB_GENERIC_OFFSET 0 +#define MD_SB_PERSONALITY_OFFSET 64 +#define MD_SB_DISKS_OFFSET 128 +#define MD_SB_DESCRIPTOR_OFFSET 992 + +#define MD_SB_GENERIC_CONSTANT_WORDS 32 +#define MD_SB_GENERIC_STATE_WORDS 32 +#define MD_SB_GENERIC_WORDS (MD_SB_GENERIC_CONSTANT_WORDS + MD_SB_GENERIC_STATE_WORDS) +#define MD_SB_PERSONALITY_WORDS 64 +#define MD_SB_DISKS_WORDS 384 +#define MD_SB_DESCRIPTOR_WORDS 32 +#define MD_SB_RESERVED_WORDS (1024 - MD_SB_GENERIC_WORDS - MD_SB_PERSONALITY_WORDS - MD_SB_DISKS_WORDS - MD_SB_DESCRIPTOR_WORDS) +#define MD_SB_EQUAL_WORDS (MD_SB_GENERIC_WORDS + MD_SB_PERSONALITY_WORDS + MD_SB_DISKS_WORDS) +#define MD_SB_DISKS (MD_SB_DISKS_WORDS / MD_SB_DESCRIPTOR_WORDS) + +/* + * Device "operational" state bits + */ +#define MD_DISK_FAULTY 0 /* disk is faulty / operational */ +#define MD_DISK_ACTIVE 1 /* disk is running or spare disk */ +#define MD_DISK_SYNC 2 /* disk is in sync with the raid set */ + +typedef struct md_device_descriptor_s { + md_u32 number; /* 0 Device number in the entire set */ + md_u32 major; /* 1 Device major number */ + md_u32 minor; /* 2 Device minor number */ + md_u32 raid_disk; /* 3 The role of the device in the raid set */ + md_u32 state; /* 4 Operational state */ + md_u32 reserved[MD_SB_DESCRIPTOR_WORDS - 5]; +} md_descriptor_t; + +#define MD_SB_MAGIC 0xa92b4efc + +/* + * Superblock state bits + */ +#define MD_SB_CLEAN 0 +#define MD_SB_ERRORS 1 + +typedef struct md_superblock_s { + /* + * Constant generic information + */ + md_u32 md_magic; /* 0 MD identifier */ + md_u32 major_version; /* 1 major version to which the set conforms */ + md_u32 minor_version; /* 2 minor version ... */ + md_u32 patch_version; /* 3 patchlevel version ... */ + md_u32 gvalid_words; /* 4 Number of used words in this section */ + md_u32 set_magic; /* 5 Raid set identifier */ + md_u32 ctime; /* 6 Creation time */ + md_u32 level; /* 7 Raid personality */ + md_u32 size; /* 8 Apparent size of each individual disk */ + md_u32 nr_disks; /* 9 total disks in the raid set */ + md_u32 raid_disks; /* 10 disks in a fully functional raid set */ + md_u32 md_minor; /* 11 preferred MD minor device number */ + md_u32 gstate_creserved[MD_SB_GENERIC_CONSTANT_WORDS - 12]; + + /* + * Generic state information + */ + md_u32 utime; /* 0 Superblock update time */ + md_u32 state; /* 1 State bits (clean, ...) */ + md_u32 active_disks; /* 2 Number of currently active disks */ + md_u32 working_disks; /* 3 Number of working disks */ + md_u32 failed_disks; /* 4 Number of failed disks */ + md_u32 spare_disks; /* 5 Number of spare disks */ + md_u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 6]; + + /* + * Personality information + */ + md_u32 layout; /* 0 the array's physical layout */ + md_u32 chunk_size; /* 1 chunk size in bytes */ + md_u32 pstate_reserved[MD_SB_PERSONALITY_WORDS - 2]; + + /* + * Disks information + */ + md_descriptor_t disks[MD_SB_DISKS]; + + /* + * Reserved + */ + md_u32 reserved[MD_SB_RESERVED_WORDS]; + + /* + * Active descriptor + */ + md_descriptor_t descriptor; + +} md_superblock_t; + +/* + * options passed in raidstart: + */ + +#define MAX_CHUNK_SIZE (4096*1024) + +struct md_param +{ + int personality; /* 1,2,3,4 */ + int chunk_size; /* in bytes */ + int max_fault; /* unused for now */ +}; + +typedef struct md_array_info_s { + /* + * Generic constant information + */ + md_u32 major_version; + md_u32 minor_version; + md_u32 patch_version; + md_u32 ctime; + md_u32 level; + md_u32 size; + md_u32 nr_disks; + md_u32 raid_disks; + md_u32 md_minor; + md_u32 not_persistent; + + /* + * Generic state information + */ + md_u32 utime; /* 0 Superblock update time */ + md_u32 state; /* 1 State bits (clean, ...) */ + md_u32 active_disks; /* 2 Number of currently active disks */ + md_u32 working_disks; /* 3 Number of working disks */ + md_u32 failed_disks; /* 4 Number of failed disks */ + md_u32 spare_disks; /* 5 Number of spare disks */ + + /* + * Personality information + */ + md_u32 layout; /* 0 the array's physical layout */ + md_u32 chunk_size; /* 1 chunk size in bytes */ + +} md_array_info_t; + +typedef struct md_disk_info_s { + /* + * configuration/status of one particular disk + */ + md_u32 number; + md_u32 major; + md_u32 minor; + md_u32 raid_disk; + md_u32 state; + +} md_disk_info_t; + + +/* + * Supported RAID5 algorithms + */ +#define RAID5_ALGORITHM_LEFT_ASYMMETRIC 0 +#define RAID5_ALGORITHM_RIGHT_ASYMMETRIC 1 +#define RAID5_ALGORITHM_LEFT_SYMMETRIC 2 +#define RAID5_ALGORITHM_RIGHT_SYMMETRIC 3 + +#endif _MD_H