Edit

IABSD.fr/src/usr.sbin/installboot/softraid.c

Branch :

  • Show log

    Commit

  • Author : kn
    Date : 2022-11-14 13:39:37
    Hash : 6dfaf0df
    Message : Check for offline chunks first, then check for keydisks Like keydisks, offline data chunks also report a size of zero, so skipping zero sized chunks before doing the offline check means not printing the "softraid chunk N not online - skipping..." warning. Restore order to make this warning appear on degraded volumes again.

  • usr.sbin/installboot/softraid.c
  • /*	$OpenBSD: softraid.c,v 1.9 2022/11/14 13:39:37 kn Exp $	*/
    /*
     * Copyright (c) 2012 Joel Sing <jsing@openbsd.org>
     *
     * Permission to use, copy, modify, and distribute this software for any
     * purpose with or without fee is hereby granted, provided that the above
     * copyright notice and this permission notice appear in all copies.
     *
     * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     */
    
    #include <sys/types.h>
    #include <sys/disklabel.h>
    #include <sys/dkio.h>
    #include <sys/ioctl.h>
    
    #include <dev/biovar.h>
    
    #include <err.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <util.h>
    
    #include "installboot.h"
    
    static int sr_volume(int, char *, int *, int *);
    
    static void
    sr_prepare_chunk(int devfd, int vol, int disk)
    {
    	struct bioc_disk bd;
    	char *realdev;
    	char part;
    	int diskfd;
    
    	diskfd = sr_open_chunk(devfd, vol, disk, &bd, &realdev, &part);
    	if (diskfd == -1)
    		return;
    
    	/* Prepare file system on device. */
    	md_prepareboot(diskfd, realdev);
    
    	close(diskfd);
    }
    
    void
    sr_prepareboot(int devfd, char *dev)
    {
    	int vol = -1, ndisks = 0, disk;
    
    	/* Use the normal process if this is not a softraid volume. */
    	if (!sr_volume(devfd, dev, &vol, &ndisks)) {
    		md_prepareboot(devfd, dev);
    		return;
    	}
    
    	/* Prepare file system on each disk that is part of this volume. */
    	for (disk = 0; disk < ndisks; disk++)
    		sr_prepare_chunk(devfd, vol, disk);
    }
    
    void
    sr_installboot(int devfd, char *dev)
    {
    	int	vol = -1, ndisks = 0, disk;
    
    	/* Use the normal process if this is not a softraid volume. */
    	if (!sr_volume(devfd, dev, &vol, &ndisks)) {
    		md_installboot(devfd, dev);
    		return;
    	}
    
    	/* Install boot loader in softraid volume. */
    	sr_install_bootldr(devfd, dev);
    
    	/* Install boot block on each disk that is part of this volume. */
    	for (disk = 0; disk < ndisks; disk++)
    		sr_install_bootblk(devfd, vol, disk);
    }
    
    int
    sr_volume(int devfd, char *dev, int *vol, int *disks)
    {
    	struct	bioc_inq bi;
    	struct	bioc_vol bv;
    	int	i;
    
    	/*
    	 * Determine if the given device is a softraid volume.
    	 */
    
    	/* Get volume information. */
    	memset(&bi, 0, sizeof(bi));
    	if (ioctl(devfd, BIOCINQ, &bi) == -1)
    		return 0;
    
    	/* XXX - softraid volumes will always have a "softraid0" controller. */
    	if (strncmp(bi.bi_dev, "softraid0", sizeof("softraid0")))
    		return 0;
    
    	/*
    	 * XXX - this only works with the real disk name (e.g. sd0) - this
    	 * should be extracted from the device name, or better yet, fixed in
    	 * the softraid ioctl.
    	 */
    	/* Locate specific softraid volume. */
    	for (i = 0; i < bi.bi_novol; i++) {
    		memset(&bv, 0, sizeof(bv));
    		bv.bv_volid = i;
    		if (ioctl(devfd, BIOCVOL, &bv) == -1)
    			err(1, "BIOCVOL");
    
    		if (strncmp(dev, bv.bv_dev, sizeof(bv.bv_dev)) == 0) {
    			*vol = i;
    			*disks = bv.bv_nodisk;
    			break;
    		}
    	}
    
    	if (verbose)
    		fprintf(stderr, "%s: softraid volume with %i disk(s)\n",
    		    dev, *disks);
    
    	return 1;
    }
    
    void
    sr_status(struct bio_status *bs)
    {
    	int	i;
    
    	for (i = 0; i < bs->bs_msg_count; i++)
    		warnx("%s", bs->bs_msgs[i].bm_msg);
    
    	if (bs->bs_status == BIO_STATUS_ERROR) {
    		if (bs->bs_msg_count == 0)
    			errx(1, "unknown error");
    		else
    			exit(1);
    	}
    }
    
    int
    sr_open_chunk(int devfd, int vol, int disk, struct bioc_disk *bd,
        char **realdev, char *part)
    {
    	int diskfd;
    
    	/* Get device name for this disk/chunk. */
    	memset(bd, 0, sizeof(*bd));
    	bd->bd_volid = vol;
    	bd->bd_diskid = disk;
    	if (ioctl(devfd, BIOCDISK, bd) == -1)
    		err(1, "BIOCDISK");
    
    	/* Check disk status. */
    	if (bd->bd_status != BIOC_SDONLINE &&
    	    bd->bd_status != BIOC_SDREBUILD) {
    		fprintf(stderr, "softraid chunk %u not online - skipping...\n",
    		    disk);
    		return -1;
    	}
    
    	/* Keydisks always have a size of zero. */
    	if (bd->bd_size == 0)
    		return -1;
    
    	if (strlen(bd->bd_vendor) < 1)
    		errx(1, "invalid disk name");
    	*part = bd->bd_vendor[strlen(bd->bd_vendor) - 1];
    	if (*part < 'a' || *part >= 'a' + MAXPARTITIONS)
    		errx(1, "invalid partition %c\n", *part);
    	bd->bd_vendor[strlen(bd->bd_vendor) - 1] = '\0';
    
    	/* Open device. */
    	if ((diskfd = opendev(bd->bd_vendor, (nowrite ? O_RDONLY : O_RDWR),
    	    OPENDEV_PART, realdev)) == -1)
    		err(1, "open: %s", *realdev);
    
    	return diskfd;
    }