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>