kern/89264: crash dump not implemented for RAID (ar) in 6.0
Garry Belka
garry at NetworkPhysics.COM
Sat Nov 19 01:40:38 GMT 2005
>Number: 89264
>Category: kern
>Synopsis: crash dump not implemented for RAID (ar) in 6.0
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Sat Nov 19 01:40:35 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator: Garry Belka
>Release: FreeBSD 6.0-RELEASE i386
>Organization:
Network Physics
>Environment:
System: FreeBSD tempo 6.0-RELEASE i386 with ATA RAID1 configured:
ar0 consists of ad4 and ad6
>Description:
dumpon /dev/ar0s1b fails because
dump support is not implemented in sys/dev/ata/ata-raid.c
>How-To-Repeat:
configure ar0 and do
dumpon /dev/ar0s1b
>Fix:
implement and enable ata_raid_dump()
patch below is an ar_dump() implementation from an older ATA code,
modified for 6.0
--- ata_raid_dump.patch begins here ---
Index: ata-raid.c
===================================================================
RCS file: /u1/Repo/FreeBSD/sys/dev/ata/ata-raid.c,v
retrieving revision 1.11
diff -u -r1.11 ata-raid.c
--- ata-raid.c 5 Nov 2005 03:24:59 -0000 1.11
+++ ata-raid.c 19 Nov 2005 01:20:53 -0000
@@ -108,7 +108,7 @@
/* device structures */
static disk_strategy_t ata_raid_strategy;
-//static dumper_t ata_raid_dump;
+static dumper_t ata_raid_dump;
static void
ata_raid_attach(struct ar_softc *rdp, int writeback)
@@ -138,7 +138,7 @@
buffer[0] = '\0';
rdp->disk = disk_alloc();
rdp->disk->d_strategy = ata_raid_strategy;
- //rdp->disk->d_dump = ata_raid_dump;
+ rdp->disk->d_dump = ata_raid_dump;
rdp->disk->d_name = "ar";
rdp->disk->d_sectorsize = DEV_BSIZE;
rdp->disk->d_mediasize = (off_t)rdp->total_sectors * DEV_BSIZE;
@@ -228,6 +228,135 @@
break;
}
return error;
+}
+static int
+ata_raid_dump(void *arg, void *virtual, vm_offset_t physical,
+ off_t offset, size_t length)
+{
+# define AD_SOFTC(ar_disk) ((struct ad_softc *)device_get_ivars((ar_disk).dev))
+
+ struct disk *dp = arg;
+ struct ar_softc *rdp = dp->d_drv1;
+
+ struct disk *ap;
+ vm_offset_t pdata;
+ caddr_t vdata;
+ int blkno, count, chunk, error1, error2, lba, lbs, tmplba;
+ int drv = 0;
+
+ if (!rdp || !(rdp->status & AR_S_READY))
+ return ENXIO;
+
+ if (length == 0) {
+ for (drv = 0; drv < rdp->total_disks; drv++) {
+ if (rdp->disks[drv].flags & AR_DF_ONLINE) {
+ ap = AD_SOFTC(rdp->disks[drv])->disk;
+ (void) ap->d_dump(ap, NULL, 0, 0, 0);
+ }
+ }
+ return 0;
+ }
+
+ blkno = offset / DEV_BSIZE;
+ vdata = virtual;
+ pdata = physical;
+
+ for (count = howmany(length, DEV_BSIZE); count > 0;
+ count -= chunk, blkno += chunk, vdata += (chunk * DEV_BSIZE),
+ pdata += (chunk * DEV_BSIZE)) {
+
+ switch (rdp->type) {
+ case AR_T_SPAN:
+ lba = blkno;
+ while (lba >= rdp->disks[drv].sectors)
+ lba -= rdp->disks[drv++].sectors;
+ chunk = min(rdp->disks[drv].sectors - lba, count);
+ break;
+
+ case AR_T_RAID0:
+ case AR_T_RAID01:
+ tmplba = blkno / rdp->interleave;
+ chunk = blkno % rdp->interleave;
+ if (blkno >= (rdp->total_sectors / (rdp->interleave * rdp->width)) *
+ (rdp->interleave * rdp->width) ) {
+ lbs = (rdp->total_sectors -
+ ((rdp->total_sectors / (rdp->interleave * rdp->width)) *
+ (rdp->interleave * rdp->width))) / rdp->width;
+ drv = (blkno -
+ ((rdp->total_sectors / (rdp->interleave * rdp->width)) *
+ (rdp->interleave * rdp->width))) / lbs;
+ lba = ((tmplba / rdp->width) * rdp->interleave) +
+ (blkno - ((tmplba / rdp->width) * rdp->interleave)) % lbs;
+ chunk = min(count, lbs);
+ }
+ else {
+ drv = tmplba % rdp->width;
+ lba = ((tmplba / rdp->width) * rdp->interleave) + chunk;
+ chunk = min(count, rdp->interleave - chunk);
+ }
+ break;
+
+ case AR_T_JBOD:
+ case AR_T_RAID1:
+ drv = 0;
+ lba = blkno;
+ chunk = count;
+ break;
+
+ default:
+ printf("ar%d: unknown array type in ata_raid_dump\n", rdp->lun);
+ return EIO;
+ }
+
+ /* offset on all but "first on HPTv2" */
+ if (!(drv == 0 && rdp->format == AR_F_HPTV2_RAID))
+ lba += rdp->offset_sectors;
+
+ switch (rdp->type) {
+ case AR_T_JBOD:
+ case AR_T_SPAN:
+ case AR_T_RAID0:
+ if (rdp->disks[drv].flags & AR_DF_ONLINE) {
+ ap = AD_SOFTC(rdp->disks[drv])->disk;
+ error1 = ap->d_dump(ap, vdata, pdata,
+ (off_t) lba * DEV_BSIZE,
+ chunk * DEV_BSIZE);
+ } else
+ error1 = EIO;
+ if (error1)
+ return error1;
+ break;
+
+ case AR_T_RAID1:
+ case AR_T_RAID01:
+ if ((rdp->disks[drv].flags & AR_DF_ONLINE) ||
+ ((rdp->status & AR_S_REBUILDING) &&
+ (rdp->disks[drv].flags & AR_DF_SPARE))) {
+ ap = AD_SOFTC(rdp->disks[drv])->disk;
+ error1 = ap->d_dump(ap, vdata, pdata,
+ (off_t) lba * DEV_BSIZE,
+ chunk * DEV_BSIZE);
+ } else
+ error1 = EIO;
+ if ((rdp->disks[drv + rdp->width].flags & AR_DF_ONLINE) ||
+ ((rdp->status & AR_S_REBUILDING) &&
+ (rdp->disks[drv + rdp->width].flags & AR_DF_SPARE))) {
+ ap = AD_SOFTC(rdp->disks[drv + rdp->width])->disk;
+ error2 = ap->d_dump(ap, vdata, pdata,
+ (off_t) lba * DEV_BSIZE,
+ chunk * DEV_BSIZE);
+ } else
+ error2 = EIO;
+ if (error1 && error2)
+ return error1;
+ break;
+
+ default:
+ printf("ar%d: unknown array type in ata_raid_dump\n", rdp->lun);
+ return EIO;
+ }
+ }
+ return 0;
}
static void
--- ata_raid_dump.patch ends here ---
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list