Eyal Lebedinsky wrote:
> 
> I have two disks as raid on a BP6 (HPT366) and had one too many
> lockups on hde+hdg, so I decided to move it down to hdb+hdd.
> 
> I could not start the raid, it just complained that the disks
> are not at the major/minor it expected it.
> 
> The first message said that [21:00] is now hdb, then it said
> that it cannot access [22:00] (naturally) so it removed a disk
> from the array, then it said the array expects two disks but
> only one was found.
> 
> How do I tell it that the raid pair is just fine but it had to
> be moved to a new location?
> 
> I tried 'mkraid --upgrade' hoping it will reconfigure but no dice
> (same errors as above).

Attached is the program I ended up writing, which (I think) fixed
the situation for me. Maybe someone who knows can create a nicer
utility (safer too) from it.

--
Eyal Lebedinsky ([EMAIL PROTECTED]) <http://samba.anu.edu.au/eyal/>
/* fixraid.c
 *
 * Last change: 26 Feb 2001
 * Author:      Eyal Lebedinsky ([EMAIL PROTECTED])
 *
 * WARNING:
 * ========
 * This is a very risky program, do not run it unless you fully
 * understand what it does!
 *
 * Fixes RAID superblock from one device to another.
 *
 * SB_DEV is the member to fix. What we fix is the definition of
 * the following member (here we fix /dev/hdb to point to /dev/hdd
 * instead of /dev/hdh).
 *
 * Get the superblock position (SB_SEEKPOS) from a (possibly failed) raidstart.
 *
 * Do not change SB_SEEKSTEP.
 *
 * Set old_0x280 to what the sb had before. (0x22:0x40 is /dev/hdh)
 *
 * Set new_0x280 to the new contents. (0x16:0x40 is /dev/hdd)
*/

#include <stdlib.h>
#include <stdio.h>

#define SB_DEV          "/dev/hdb"      /* device to fix */
#define SB_SEEKPOS      60051520L       /* in K bytes */
#define SB_SEEKSTEP     1000000L        /* in K bytes */

static unsigned char old_0x280[] = {
        0x01, 0x00, 0x00, 0x00,
        0x22, 0x00, 0x00, 0x00,         /* hdh: major */
        0x40, 0x00, 0x00, 0x00};        /* hdh: minor */

static unsigned char new_0x280[] = {
        0x01, 0x00, 0x00, 0x00,
        0x16, 0x00, 0x00, 0x00,         /* hdd: major */        
        0x40, 0x00, 0x00, 0x00};        /* hdd: minor */

int
main (
        int             argc,
        char            **argv)
{
        int             doupdate;
        int             rc;
        FILE            *fin;
        long            pos;
        long            step;
        char            sb[1024];

        fprintf (stderr, "processing RAID superblock on %s at %ldK\n", 
                SB_DEV, SB_SEEKPOS);

        if (argc < 2 || strcmp ("update please", argv[1])) {
                fprintf (stderr, "not updating - please ask nicely\n");
                doupdate = 0;
        } else
                doupdate = 1;

        fin = fopen (SB_DEV, doupdate ? "r+" : "r");
        if (NULL == fin) {
                fprintf (stderr, "open file failed\n");
                return (1);
        }

        for (pos = SB_SEEKPOS; pos > 0; pos -= step) {
                step = pos >= SB_SEEKSTEP ? SB_SEEKSTEP : pos;
                rc = fseek (fin, step*1024L, SEEK_CUR);
                if (rc) {
                        fprintf (stderr, "fseek +%ldK at -%ldK failed\n",
                                step, pos);
                        return (1);
                }
        }

        rc = fread (sb, 1024, 1, fin);
        if (1 != rc) {
                fprintf (stderr, "read failed\n");
                return (1);
        }
        fprintf (stderr, "read superblock OK\n");
        rc = fseek (fin, -1024L, SEEK_CUR);
        if (rc) {
                fprintf (stderr, "fseek back failed\n");
                return (1);
        }

        if (!memcmp (sb+0x280, new_0x280, sizeof (new_0x280))) {
                fprintf (stderr, "superblock already updated\n");
                return (1);
        }
        if (memcmp (sb+0x280, old_0x280, sizeof (old_0x280))) {
                fprintf (stderr, "superblock incorrect\n");
                return (1);
        }
        fprintf (stderr, "superblock is OK\n");

        memcpy (sb+0x280, new_0x280, sizeof (new_0x280));

        if (doupdate) {
                rc = fwrite (sb, 1024, 1, fin);
                if (1 != rc) {
                        fprintf (stderr, "write failed\n");
                        return (1);
                }
                fprintf (stderr, "superblock updated\n");
        }

        fclose (fin);

        return (0);
}

Reply via email to