svn commit: r256286 - projects/camlock/sys/geom
Alexander Motin
mav at FreeBSD.org
Thu Oct 10 18:34:47 UTC 2013
Author: mav
Date: Thu Oct 10 18:34:46 2013
New Revision: 256286
URL: http://svnweb.freebsd.org/changeset/base/256286
Log:
Avoid BIO clonning (memory allocation) inside GEOM DISK when request is
within maximal allowed size and so it is not going to be splitted.
In such case the only conflicting field in struct bio is bio_done. So,
instead of allocating whole new struct bio for that only field, copy that
field into bio_to, that is GEOM-specific and should not be used by disk
drivers below. On request completion reconstruct original bio_done field
from bio_to and original bio_to field from bio_disk.
Modified:
projects/camlock/sys/geom/geom_disk.c
Modified: projects/camlock/sys/geom/geom_disk.c
==============================================================================
--- projects/camlock/sys/geom/geom_disk.c Thu Oct 10 18:18:04 2013 (r256285)
+++ projects/camlock/sys/geom/geom_disk.c Thu Oct 10 18:34:46 2013 (r256286)
@@ -256,6 +256,25 @@ g_disk_done(struct bio *bp)
g_destroy_bio(bp);
}
+static void
+g_disk_done_single(struct bio *bp)
+{
+ struct bintime now;
+ struct g_disk_softc *sc;
+
+ bp->bio_completed = bp->bio_length - bp->bio_resid;
+ bp->bio_done = (void *)bp->bio_to;
+ bp->bio_to = LIST_FIRST(&bp->bio_disk->d_geom->provider);
+ if ((bp->bio_cmd & (BIO_READ|BIO_WRITE|BIO_DELETE)) != 0) {
+ binuptime(&now);
+ sc = bp->bio_to->private;
+ mtx_lock(&sc->done_mtx);
+ devstat_end_transaction_bio_bt(sc->dp->d_devstat, bp, &now);
+ mtx_unlock(&sc->done_mtx);
+ }
+ g_io_deliver(bp, bp->bio_error);
+}
+
static int
g_disk_ioctl(struct g_provider *pp, u_long cmd, void * data, int fflag, struct thread *td)
{
@@ -281,7 +300,7 @@ g_disk_start(struct bio *bp)
struct disk *dp;
struct g_disk_softc *sc;
int error;
- off_t off;
+ off_t d_maxsize, off;
sc = bp->bio_to->private;
if (sc == NULL || (dp = sc->dp) == NULL || dp->d_destroyed) {
@@ -298,6 +317,22 @@ g_disk_start(struct bio *bp)
/* fall-through */
case BIO_READ:
case BIO_WRITE:
+ d_maxsize = (bp->bio_cmd == BIO_DELETE) ?
+ dp->d_delmaxsize : dp->d_maxsize;
+ if (bp->bio_length <= d_maxsize) {
+ bp->bio_disk = dp;
+ bp->bio_to = (void *)bp->bio_done;
+ bp->bio_done = g_disk_done_single;
+ bp->bio_pblkno = bp->bio_offset / dp->d_sectorsize;
+ bp->bio_bcount = bp->bio_length;
+ mtx_lock(&sc->start_mtx);
+ devstat_start_transaction_bio(dp->d_devstat, bp);
+ mtx_unlock(&sc->start_mtx);
+ g_disk_lock_giant(dp);
+ dp->d_strategy(bp);
+ g_disk_unlock_giant(dp);
+ break;
+ }
off = 0;
bp3 = NULL;
bp2 = g_clone_bio(bp);
@@ -306,10 +341,6 @@ g_disk_start(struct bio *bp)
break;
}
do {
- off_t d_maxsize;
-
- d_maxsize = (bp->bio_cmd == BIO_DELETE) ?
- dp->d_delmaxsize : dp->d_maxsize;
bp2->bio_offset += off;
bp2->bio_length -= off;
if ((bp->bio_flags & BIO_UNMAPPED) == 0) {
@@ -408,15 +439,11 @@ g_disk_start(struct bio *bp)
error = EOPNOTSUPP;
break;
}
- bp2 = g_clone_bio(bp);
- if (bp2 == NULL) {
- g_io_deliver(bp, ENOMEM);
- return;
- }
- bp2->bio_done = g_disk_done;
- bp2->bio_disk = dp;
+ bp->bio_disk = dp;
+ bp->bio_to = (void *)bp->bio_done;
+ bp->bio_done = g_disk_done_single;
g_disk_lock_giant(dp);
- dp->d_strategy(bp2);
+ dp->d_strategy(bp);
g_disk_unlock_giant(dp);
break;
default:
More information about the svn-src-projects
mailing list