Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 26 Jan 2011 13:18:26 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r217884 - projects/graid/head/sys/geom/raid
Message-ID:  <201101261318.p0QDIQAr077842@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Wed Jan 26 13:18:26 2011
New Revision: 217884
URL: http://svn.freebsd.org/changeset/base/217884

Log:
  Add kerneldump() method to the transformation modules API -- minimalistic
  shortcut for robust kernel dumps writing. When method is not implemented,
  previously made wrappers around regular code will try to handle the things.
  
  Implement kernel dumping for RAID0 and RAID1 transformation modules without
  using memory allocations, locks and other extra calls.

Modified:
  projects/graid/head/sys/geom/raid/g_raid.c
  projects/graid/head/sys/geom/raid/g_raid.h
  projects/graid/head/sys/geom/raid/g_raid_tr_if.m
  projects/graid/head/sys/geom/raid/tr_raid0.c
  projects/graid/head/sys/geom/raid/tr_raid1.c

Modified: projects/graid/head/sys/geom/raid/g_raid.c
==============================================================================
--- projects/graid/head/sys/geom/raid/g_raid.c	Wed Jan 26 13:10:07 2011	(r217883)
+++ projects/graid/head/sys/geom/raid/g_raid.c	Wed Jan 26 13:18:26 2011	(r217884)
@@ -716,28 +716,26 @@ g_raid_unidle(struct g_raid_volume *vol)
 }
 
 static void
-g_raid_dumpdone(struct bio *bp)
+g_raid_tr_kerneldump_common_done(struct bio *bp)
 {
 
 	bp->bio_flags |= BIO_DONE;
 }
 
-static int
-g_raid_dump(void *arg,
+int
+g_raid_tr_kerneldump_common(struct g_raid_tr_object *tr,
     void *virtual, vm_offset_t physical, off_t offset, size_t length)
 {
 	struct g_raid_softc *sc;
 	struct g_raid_volume *vol;
 	struct bio bp;
 
-	vol = (struct g_raid_volume *)arg;
+	vol = tr->tro_volume;
 	sc = vol->v_softc;
-	G_RAID_DEBUG(3, "Dumping at off %llu len %llu.",
-	    (long long unsigned)offset, (long long unsigned)length);
 
 	bzero(&bp, sizeof(bp));
 	bp.bio_cmd = BIO_WRITE;
-	bp.bio_done = g_raid_dumpdone;
+	bp.bio_done = g_raid_tr_kerneldump_common_done;
 	bp.bio_attribute = NULL;
 	bp.bio_offset = offset;
 	bp.bio_length = length;
@@ -751,9 +749,26 @@ g_raid_dump(void *arg,
 		DELAY(10);
 	}
 
-	G_RAID_DEBUG(3, "Dumping at off %llu len %llu done.",
+	return (bp.bio_error != 0 ? EIO : 0);
+}
+
+static int
+g_raid_dump(void *arg,
+    void *virtual, vm_offset_t physical, off_t offset, size_t length)
+{
+	struct g_raid_volume *vol;
+	int error;
+
+	vol = (struct g_raid_volume *)arg;
+	G_RAID_DEBUG(3, "Dumping at off %llu len %llu.",
 	    (long long unsigned)offset, (long long unsigned)length);
-	return (0);
+
+	error = G_RAID_TR_KERNELDUMP(vol->v_tr,
+	    virtual, physical, offset, length);
+
+	G_RAID_DEBUG(3, "Dumping at off %llu len %llu done: %d.",
+	    (long long unsigned)offset, (long long unsigned)length, error);
+	return (error);
 }
 
 static void
@@ -1020,30 +1035,41 @@ g_raid_subdisk_iostart(struct g_raid_sub
 		vol->v_writes++;
 
 	cp = sd->sd_disk->d_consumer;
-	bp->bio_done = g_raid_disk_done;
 	bp->bio_from = sd->sd_disk->d_consumer;
 	bp->bio_to = sd->sd_disk->d_consumer->provider;
-	bp->bio_offset += sd->sd_offset;
 	bp->bio_caller1 = sd;
 	cp->index++;
 	if (dumping) {
 		G_RAID_LOGREQ(3, bp, "Sending dumping request.");
-		if (sd->sd_disk->d_kd.di.dumper == NULL) {
+		if (bp->bio_cmd == BIO_WRITE) {
+			bp->bio_error = g_raid_subdisk_kerneldump(sd,
+			    bp->bio_data, 0, bp->bio_offset, bp->bio_length);
+		} else
 			bp->bio_error = EOPNOTSUPP;
-			g_raid_disk_done(bp);
-			return;
-		}
-		dump_write(&sd->sd_disk->d_kd.di,
-		    bp->bio_data, 0,
-		    sd->sd_disk->d_kd.di.mediaoffset + bp->bio_offset,
-		    bp->bio_length);
 		g_raid_disk_done(bp);
 	} else {
+		bp->bio_done = g_raid_disk_done;
+		bp->bio_offset += sd->sd_offset;
 		G_RAID_LOGREQ(3, bp, "Sending request.");
 		g_io_request(bp, cp);
 	}
 }
 
+int
+g_raid_subdisk_kerneldump(struct g_raid_subdisk *sd,
+    void *virtual, vm_offset_t physical, off_t offset, size_t length)
+{
+
+	if (sd->sd_disk == NULL)
+		return (ENXIO);
+	if (sd->sd_disk->d_kd.di.dumper == NULL)
+		return (EOPNOTSUPP);
+	return (dump_write(&sd->sd_disk->d_kd.di,
+	    virtual, physical,
+	    sd->sd_disk->d_kd.di.mediaoffset + sd->sd_offset + offset,
+	    length));
+}
+
 static void
 g_raid_disk_done(struct bio *bp)
 {

Modified: projects/graid/head/sys/geom/raid/g_raid.h
==============================================================================
--- projects/graid/head/sys/geom/raid/g_raid.h	Wed Jan 26 13:10:07 2011	(r217883)
+++ projects/graid/head/sys/geom/raid/g_raid.h	Wed Jan 26 13:18:26 2011	(r217884)
@@ -307,6 +307,8 @@ int g_raid_destroy_disk(struct g_raid_di
 
 void g_raid_iodone(struct bio *bp, int error);
 void g_raid_subdisk_iostart(struct g_raid_subdisk *sd, struct bio *bp);
+int g_raid_subdisk_kerneldump(struct g_raid_subdisk *sd,
+    void *virtual, vm_offset_t physical, off_t offset, size_t length);
 
 void g_raid_kill_consumer(struct g_raid_softc *sc, struct g_consumer *cp);
 
@@ -319,6 +321,9 @@ void g_raid_write_metadata(struct g_raid
 void g_raid_fail_disk(struct g_raid_softc *sc,
     struct g_raid_subdisk *sd, struct g_raid_disk *disk);
 
+int g_raid_tr_kerneldump_common(struct g_raid_tr_object *tr,
+    void *virtual, vm_offset_t physical, off_t offset, size_t length);
+
 u_int g_raid_ndisks(struct g_raid_softc *sc, int state);
 u_int g_raid_nsubdisks(struct g_raid_volume *vol, int state);
 #define	G_RAID_DESTROY_SOFT		0

Modified: projects/graid/head/sys/geom/raid/g_raid_tr_if.m
==============================================================================
--- projects/graid/head/sys/geom/raid/g_raid_tr_if.m	Wed Jan 26 13:10:07 2011	(r217883)
+++ projects/graid/head/sys/geom/raid/g_raid_tr_if.m	Wed Jan 26 13:18:26 2011	(r217884)
@@ -91,6 +91,15 @@ METHOD void iodone {
 	struct bio *bp;
 };
 
+# kerneldump() - optimized for rebustness (simplified) kernel dumping routine.
+METHOD int kerneldump {
+	struct g_raid_tr_object *tr;
+	void *virtual;
+	vm_offset_t physical;
+	off_t offset;
+	size_t length;
+} DEFAULT g_raid_tr_kerneldump_common;
+
 # locked() - callback method for lock().
 METHOD int locked {
 	struct g_raid_tr_object *tr;

Modified: projects/graid/head/sys/geom/raid/tr_raid0.c
==============================================================================
--- projects/graid/head/sys/geom/raid/tr_raid0.c	Wed Jan 26 13:10:07 2011	(r217883)
+++ projects/graid/head/sys/geom/raid/tr_raid0.c	Wed Jan 26 13:18:26 2011	(r217884)
@@ -54,6 +54,7 @@ static g_raid_tr_start_t g_raid_tr_start
 static g_raid_tr_stop_t g_raid_tr_stop_raid0;
 static g_raid_tr_iostart_t g_raid_tr_iostart_raid0;
 static g_raid_tr_iodone_t g_raid_tr_iodone_raid0;
+static g_raid_tr_kerneldump_t g_raid_tr_kerneldump_raid0;
 static g_raid_tr_free_t g_raid_tr_free_raid0;
 
 static kobj_method_t g_raid_tr_raid0_methods[] = {
@@ -63,6 +64,7 @@ static kobj_method_t g_raid_tr_raid0_met
 	KOBJMETHOD(g_raid_tr_stop,	g_raid_tr_stop_raid0),
 	KOBJMETHOD(g_raid_tr_iostart,	g_raid_tr_iostart_raid0),
 	KOBJMETHOD(g_raid_tr_iodone,	g_raid_tr_iodone_raid0),
+	KOBJMETHOD(g_raid_tr_kerneldump,	g_raid_tr_kerneldump_raid0),
 	KOBJMETHOD(g_raid_tr_free,	g_raid_tr_free_raid0),
 	{ 0, 0 }
 };
@@ -274,6 +276,57 @@ failure:
 	g_raid_iodone(bp, bp->bio_error);
 }
 
+int
+g_raid_tr_kerneldump_raid0(struct g_raid_tr_object *tr,
+    void *virtual, vm_offset_t physical, off_t boffset, size_t blength)
+{
+	struct g_raid_softc *sc;
+	struct g_raid_volume *vol;
+	char *addr;
+	off_t offset, start, length, nstripe;
+	u_int no, strip_size;
+	int error;
+
+	vol = tr->tro_volume;
+	if (vol->v_state != G_RAID_VOLUME_S_OPTIMAL)
+		return (ENXIO);
+	sc = vol->v_softc;
+
+	addr = virtual;
+	strip_size = vol->v_strip_size;
+	/* Stripe number. */
+	nstripe = boffset / strip_size;
+	/* Start position in stripe. */
+	start = boffset % strip_size;
+	/* Disk number. */
+	no = nstripe % vol->v_disks_count;
+	/* Start position in disk. */
+	offset = (nstripe / vol->v_disks_count) * strip_size + start;
+	/* Length of data to operate. */
+	length = MIN(blength, strip_size - start);
+
+	error = g_raid_subdisk_kerneldump(&vol->v_subdisks[no],
+	    addr, 0, offset, length);
+	if (error != 0)
+		return (error);
+
+	offset -= offset % strip_size;
+	addr += length;
+	length = blength - length;
+	for (no++; length > 0;
+	    no++, length -= strip_size, addr += strip_size) {
+		if (no > vol->v_disks_count - 1) {
+			no = 0;
+			offset += strip_size;
+		}
+		error = g_raid_subdisk_kerneldump(&vol->v_subdisks[no],
+		    addr, 0, offset, MIN(strip_size, length));
+		if (error != 0)
+			return (error);
+	}
+	return (0);
+}
+
 static void
 g_raid_tr_iodone_raid0(struct g_raid_tr_object *tr,
     struct g_raid_subdisk *sd,struct bio *bp)

Modified: projects/graid/head/sys/geom/raid/tr_raid1.c
==============================================================================
--- projects/graid/head/sys/geom/raid/tr_raid1.c	Wed Jan 26 13:10:07 2011	(r217883)
+++ projects/graid/head/sys/geom/raid/tr_raid1.c	Wed Jan 26 13:18:26 2011	(r217884)
@@ -54,6 +54,7 @@ static g_raid_tr_start_t g_raid_tr_start
 static g_raid_tr_stop_t g_raid_tr_stop_raid1;
 static g_raid_tr_iostart_t g_raid_tr_iostart_raid1;
 static g_raid_tr_iodone_t g_raid_tr_iodone_raid1;
+static g_raid_tr_kerneldump_t g_raid_tr_kerneldump_raid1;
 static g_raid_tr_locked_t g_raid_tr_locked_raid1;
 static g_raid_tr_free_t g_raid_tr_free_raid1;
 
@@ -64,6 +65,7 @@ static kobj_method_t g_raid_tr_raid1_met
 	KOBJMETHOD(g_raid_tr_stop,	g_raid_tr_stop_raid1),
 	KOBJMETHOD(g_raid_tr_iostart,	g_raid_tr_iostart_raid1),
 	KOBJMETHOD(g_raid_tr_iodone,	g_raid_tr_iodone_raid1),
+	KOBJMETHOD(g_raid_tr_kerneldump,	g_raid_tr_kerneldump_raid1),
 	KOBJMETHOD(g_raid_tr_locked,	g_raid_tr_locked_raid1),
 	KOBJMETHOD(g_raid_tr_free,	g_raid_tr_free_raid1),
 	{ 0, 0 }
@@ -361,6 +363,37 @@ g_raid_tr_iodone_raid1(struct g_raid_tr_
 	}
 }
 
+int
+g_raid_tr_kerneldump_raid1(struct g_raid_tr_object *tr,
+    void *virtual, vm_offset_t physical, off_t offset, size_t length)
+{
+	struct g_raid_volume *vol;
+	struct g_raid_subdisk *sd;
+	int error, i, ok;
+
+	vol = tr->tro_volume;
+	error = 0;
+	ok = 0;
+	for (i = 0; i < vol->v_disks_count; i++) {
+		sd = &vol->v_subdisks[i];
+		switch (sd->sd_state) {
+		case G_RAID_SUBDISK_S_ACTIVE:
+			break;
+//		case G_RAID_DISK_STATE_SYNCHRONIZING:
+//			if (bp->bio_offset >= sync->ds_offset)
+//				continue;
+//			break;
+		default:
+			continue;
+		}
+		error = g_raid_subdisk_kerneldump(sd,
+		    virtual, physical, offset, length);
+		if (error == 0)
+			ok++;
+	}
+	return (ok > 0 ? 0 : error);
+}
+
 static int
 g_raid_tr_locked_raid1(struct g_raid_tr_object *tr, void *argp)
 {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201101261318.p0QDIQAr077842>