From 34d829f7812a187a49168cbf616eae8ddf7b184f Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Sun, 10 Feb 2008 18:58:23 +0000 Subject: [PATCH] HAMMER 28A/many: Translation and write performance optimizations * Cache a buffer's virtual (zoneX->zone2) translation to avoid unnecessary re-translations when a hot-cached buffer is available. * Use the sequential heuristic provided by the kernel to detect sequential writes and call bawrite() instead bdwrite() in such cases. This prevents the buffer cache from hitting slow fallback cases and completely solves the write performance issue. Note that the undo fifo is not yet in place and performance will drop slightly once it is, but what you see now is basically what you're gonna get in the final. * Performance is now on par with UFS. --- sys/vfs/hammer/hammer.h | 5 +++-- sys/vfs/hammer/hammer_blockmap.c | 10 +--------- sys/vfs/hammer/hammer_io.c | 4 ++-- sys/vfs/hammer/hammer_ondisk.c | 27 +++++++++++++++++++-------- sys/vfs/hammer/hammer_vnops.c | 12 +++++++++++- 5 files changed, 36 insertions(+), 22 deletions(-) diff --git a/sys/vfs/hammer/hammer.h b/sys/vfs/hammer/hammer.h index 811c210d6f..ed156f3f37 100644 --- a/sys/vfs/hammer/hammer.h +++ b/sys/vfs/hammer/hammer.h @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.36 2008/02/10 09:51:01 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer.h,v 1.37 2008/02/10 18:58:22 dillon Exp $ */ /* * This header file contains structures used internally by the HAMMERFS @@ -309,7 +309,8 @@ struct hammer_buffer { RB_ENTRY(hammer_buffer) rb_node; void *ondisk; struct hammer_volume *volume; - hammer_off_t buf_offset; + hammer_off_t zone2_offset; + hammer_off_t zoneX_offset; struct hammer_node_list clist; }; diff --git a/sys/vfs/hammer/hammer_blockmap.c b/sys/vfs/hammer/hammer_blockmap.c index 517cb388db..eff44e38ab 100644 --- a/sys/vfs/hammer/hammer_blockmap.c +++ b/sys/vfs/hammer/hammer_blockmap.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_blockmap.c,v 1.1 2008/02/10 09:51:01 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_blockmap.c,v 1.2 2008/02/10 18:58:22 dillon Exp $ */ /* @@ -94,11 +94,7 @@ hammer_blockmap_alloc(hammer_mount_t hmp, int zone, int bytes, int *errorp) bzero(blockmap, sizeof(*blockmap)); blockmap->phys_offset = hammer_freemap_alloc(hmp, errorp); KKASSERT(*errorp == 0); - kprintf("ALLOC LAYER2 %016llx\n", blockmap->phys_offset); } -#if 0 - kprintf("blkmap_alloc %016llx [%2d@%016llx]", alloc_offset, i, blockmap->phys_offset); -#endif KKASSERT(blockmap->phys_offset); /* @@ -118,14 +114,10 @@ hammer_blockmap_alloc(hammer_mount_t hmp, int zone, int bytes, int *errorp) blockmap->phys_offset = hammer_freemap_alloc(hmp, errorp); blockmap->bytes_free = HAMMER_LARGEBLOCK_SIZE; KKASSERT(*errorp == 0); - kprintf("ALLOC LAYER1 %016llx\n", blockmap->phys_offset); } hammer_modify_buffer(buffer, blockmap, sizeof(*blockmap)); blockmap->bytes_free -= bytes; -#if 0 - kprintf("[%2d@%016llx] free=%d phys %016llx\n", i, blockmap->phys_offset, blockmap->bytes_free, blockmap->phys_offset + (result_offset & HAMMER_LARGEBLOCK_MASK64)); -#endif hammer_modify_volume(root_volume, &rootmap->alloc_offset, sizeof(rootmap->alloc_offset)); diff --git a/sys/vfs/hammer/hammer_io.c b/sys/vfs/hammer/hammer_io.c index e55b6344e1..f79c9c7055 100644 --- a/sys/vfs/hammer/hammer_io.c +++ b/sys/vfs/hammer/hammer_io.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_io.c,v 1.20 2008/02/08 08:30:59 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_io.c,v 1.21 2008/02/10 18:58:22 dillon Exp $ */ /* * IO Primitives and buffer cache management @@ -402,7 +402,7 @@ hammer_modify_buffer(hammer_buffer_t buffer, void *base, int len) intptr_t rel_offset = (intptr_t)base - (intptr_t)buffer->ondisk; KKASSERT((rel_offset & ~(intptr_t)HAMMER_BUFMASK) == 0); hammer_generate_undo(buffer->volume->hmp, - buffer->buf_offset + rel_offset, + buffer->zone2_offset + rel_offset, base, len); } } diff --git a/sys/vfs/hammer/hammer_ondisk.c b/sys/vfs/hammer/hammer_ondisk.c index 1022e34950..26cb8f7db0 100644 --- a/sys/vfs/hammer/hammer_ondisk.c +++ b/sys/vfs/hammer/hammer_ondisk.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_ondisk.c,v 1.29 2008/02/10 09:51:01 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_ondisk.c,v 1.30 2008/02/10 18:58:22 dillon Exp $ */ /* * Manage HAMMER's on-disk structures. These routines are primarily @@ -103,9 +103,9 @@ hammer_vol_rb_compare(hammer_volume_t vol1, hammer_volume_t vol2) static int hammer_buf_rb_compare(hammer_buffer_t buf1, hammer_buffer_t buf2) { - if (buf1->buf_offset < buf2->buf_offset) + if (buf1->zone2_offset < buf2->zone2_offset) return(-1); - if (buf1->buf_offset > buf2->buf_offset) + if (buf1->zone2_offset > buf2->zone2_offset) return(1); return(0); } @@ -123,7 +123,7 @@ hammer_nod_rb_compare(hammer_node_t node1, hammer_node_t node2) /* * Note: The lookup function for hammer_ino_rb_tree winds up being named * hammer_ino_rb_tree_RB_LOOKUP_INFO(root, info). The other lookup - * functions are normal, e.g. hammer_buf_rb_tree_RB_LOOKUP(root, buf_offset). + * functions are normal, e.g. hammer_buf_rb_tree_RB_LOOKUP(root, zone2_offset). */ RB_GENERATE(hammer_ino_rb_tree, hammer_inode, rb_node, hammer_ino_rb_compare); RB_GENERATE_XLOOKUP(hammer_ino_rb_tree, INFO, hammer_inode, rb_node, @@ -131,7 +131,7 @@ RB_GENERATE_XLOOKUP(hammer_ino_rb_tree, INFO, hammer_inode, rb_node, RB_GENERATE2(hammer_vol_rb_tree, hammer_volume, rb_node, hammer_vol_rb_compare, int32_t, vol_no); RB_GENERATE2(hammer_buf_rb_tree, hammer_buffer, rb_node, - hammer_buf_rb_compare, hammer_off_t, buf_offset); + hammer_buf_rb_compare, hammer_off_t, zone2_offset); RB_GENERATE2(hammer_nod_rb_tree, hammer_node, rb_node, hammer_nod_rb_compare, hammer_off_t, node_offset); @@ -498,9 +498,11 @@ hammer_get_buffer(hammer_mount_t hmp, hammer_off_t buf_offset, { hammer_buffer_t buffer; hammer_volume_t volume; + hammer_off_t zoneX_offset; int vol_no; int zone; + zoneX_offset = buf_offset; zone = HAMMER_ZONE_DECODE(buf_offset); if (zone > HAMMER_ZONE_RAW_BUFFER_INDEX) { buf_offset = hammer_blockmap_lookup(hmp, buf_offset, errorp); @@ -529,7 +531,7 @@ again: if (buffer == NULL) { ++hammer_count_buffers; buffer = kmalloc(sizeof(*buffer), M_HAMMER, M_WAITOK|M_ZERO); - buffer->buf_offset = buf_offset; + buffer->zone2_offset = buf_offset; buffer->volume = volume; hammer_io_init(&buffer->io, HAMMER_STRUCTURE_BUFFER); buffer->io.offset = volume->ondisk->vol_buf_beg + @@ -552,6 +554,12 @@ again: hammer_ref(&buffer->io.lock); } + /* + * Cache the blockmap translation + */ + if ((zoneX_offset & HAMMER_ZONE_RAW_BUFFER) != HAMMER_ZONE_RAW_BUFFER) + buffer->zoneX_offset = zoneX_offset; + /* * Deal with on-disk info */ @@ -704,9 +712,11 @@ hammer_bread(hammer_mount_t hmp, hammer_off_t buf_offset, int *errorp, int32_t xoff = (int32_t)buf_offset & HAMMER_BUFMASK; buf_offset &= ~HAMMER_BUFMASK64; + KKASSERT((buf_offset & HAMMER_OFF_ZONE_MASK) != 0); buffer = *bufferp; - if (buffer == NULL || buffer->buf_offset != buf_offset) { + if (buffer == NULL || (buffer->zone2_offset != buf_offset && + buffer->zoneX_offset != buf_offset)) { if (buffer) hammer_rel_buffer(buffer, 0); buffer = hammer_get_buffer(hmp, buf_offset, 0, errorp); @@ -741,7 +751,8 @@ hammer_bnew(hammer_mount_t hmp, hammer_off_t buf_offset, int *errorp, buf_offset &= ~HAMMER_BUFMASK64; buffer = *bufferp; - if (buffer == NULL || buffer->buf_offset != buf_offset) { + if (buffer == NULL || (buffer->zone2_offset != buf_offset && + buffer->zoneX_offset != buf_offset)) { if (buffer) hammer_rel_buffer(buffer, 0); buffer = hammer_get_buffer(hmp, buf_offset, 1, errorp); diff --git a/sys/vfs/hammer/hammer_vnops.c b/sys/vfs/hammer/hammer_vnops.c index 50365fecb4..b036dd82b9 100644 --- a/sys/vfs/hammer/hammer_vnops.c +++ b/sys/vfs/hammer/hammer_vnops.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.30 2008/02/10 09:51:01 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.31 2008/02/10 18:58:23 dillon Exp $ */ #include @@ -381,6 +381,16 @@ hammer_vop_write(struct vop_write_args *ap) bwrite(bp); } else if (ap->a_ioflag & IO_DIRECT) { bawrite(bp); + } else if ((ap->a_ioflag >> 16) > 1 && + (uio->uio_offset & HAMMER_BUFMASK) == 0) { + /* + * If seqcount indicates sequential operation and + * we just finished filling a buffer, push it out + * now to prevent the buffer cache from becoming + * too full, which would trigger non-optimal + * flushes. + */ + bawrite(bp); } else { bdwrite(bp); } -- 2.41.0