From b4f86ea3cc005dec41539fde163eeb5606e81cb8 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Tue, 11 Jan 2011 19:43:23 -0800 Subject: [PATCH] HAMMER VFS - Remove B-Tree allocation hints, add double_buffer option. * Remove the allocation hints when allocating b-tree nodes and remove over-full test in the blockmap allocator for b-tree and meta-data elements. The hinting and leaving some space unused in the big-blocks did not improve performance. Write performance is actually slightly better when new allocations are made linearly. * Either way we have to depend on the reblocker to reorganize the B-Tree. * Add a sysctl vfs.hammer.double_buffer, defaulting to off. This is currently used for debugging and testing live-dedup. Normally only small-data blocks are run through the device vnode's buffer cache (allowing us to consolidate many small data blocks within the device vnode's buffer cache), and large data blocks are read directly into the file vnode's buffer. Turning on double_buffer cases ALL file data to run through the device vnode's buffer cache, resulting in double data caching which is not normally useful, so leave this off for now. It will not improve performance. --- sys/vfs/hammer/hammer.h | 1 + sys/vfs/hammer/hammer_blockmap.c | 2 ++ sys/vfs/hammer/hammer_btree.c | 10 ++++------ sys/vfs/hammer/hammer_reblock.c | 2 +- sys/vfs/hammer/hammer_vfsops.c | 3 +++ sys/vfs/hammer/hammer_vnops.c | 20 +++++++++++++++----- 6 files changed, 26 insertions(+), 12 deletions(-) diff --git a/sys/vfs/hammer/hammer.h b/sys/vfs/hammer/hammer.h index 09f338bbcb..cd600c2d77 100644 --- a/sys/vfs/hammer/hammer.h +++ b/sys/vfs/hammer/hammer.h @@ -1055,6 +1055,7 @@ extern int hammer_bio_count; extern int hammer_verify_zone; extern int hammer_verify_data; extern int hammer_write_mode; +extern int hammer_double_buffer; extern int hammer_yield_check; extern int hammer_fsync_mode; extern int hammer_autoflush; diff --git a/sys/vfs/hammer/hammer_blockmap.c b/sys/vfs/hammer/hammer_blockmap.c index 16160da311..f97909f8fe 100644 --- a/sys/vfs/hammer/hammer_blockmap.c +++ b/sys/vfs/hammer/hammer_blockmap.c @@ -241,6 +241,7 @@ again: goto again; } +#if 0 /* * If operating in the current non-hint blockmap block, do not * allow it to get over-full. Also drop any active hinting so @@ -260,6 +261,7 @@ again: goto again; } } +#endif /* * We need the lock from this point on. We have to re-check zone diff --git a/sys/vfs/hammer/hammer_btree.c b/sys/vfs/hammer/hammer_btree.c index 44e53820c0..d0461d65cc 100644 --- a/sys/vfs/hammer/hammer_btree.c +++ b/sys/vfs/hammer/hammer_btree.c @@ -1576,8 +1576,7 @@ btree_split_internal(hammer_cursor_t cursor) * modifications until we know the whole operation will work. */ if (ondisk->parent == 0) { - parent = hammer_alloc_btree(cursor->trans, node->node_offset, - &error); + parent = hammer_alloc_btree(cursor->trans, 0, &error); if (parent == NULL) goto done; hammer_lock_ex(&parent->lock); @@ -1627,7 +1626,7 @@ btree_split_internal(hammer_cursor_t cursor) * B O O O B B N N B <--- inner boundary points are 'P' * 0 1 2 3 4 5 6 */ - new_node = hammer_alloc_btree(cursor->trans, hint, &error); + new_node = hammer_alloc_btree(cursor->trans, 0, &error); if (new_node == NULL) { if (made_root) { hammer_unlock(&parent->lock); @@ -1845,8 +1844,7 @@ btree_split_leaf(hammer_cursor_t cursor) * until we know the whole operation will work. */ if (ondisk->parent == 0) { - parent = hammer_alloc_btree(cursor->trans, leaf->node_offset, - &error); + parent = hammer_alloc_btree(cursor->trans, 0, &error); if (parent == NULL) goto done; hammer_lock_ex(&parent->lock); @@ -1901,7 +1899,7 @@ btree_split_leaf(hammer_cursor_t cursor) * / \ * L L L L L L L L */ - new_leaf = hammer_alloc_btree(cursor->trans, hint, &error); + new_leaf = hammer_alloc_btree(cursor->trans, 0, &error); if (new_leaf == NULL) { if (made_root) { hammer_unlock(&parent->lock); diff --git a/sys/vfs/hammer/hammer_reblock.c b/sys/vfs/hammer/hammer_reblock.c index dd51889e59..64e28f6d46 100644 --- a/sys/vfs/hammer/hammer_reblock.c +++ b/sys/vfs/hammer/hammer_reblock.c @@ -550,7 +550,7 @@ hammer_reblock_int_node(struct hammer_ioc_reblock *reblock, hint = onode->ondisk->elms[0].internal.subtree_offset; else hint = 0; - nnode = hammer_alloc_btree(cursor->trans, hint, &error); + nnode = hammer_alloc_btree(cursor->trans, 0, &error); if (nnode == NULL) goto done; diff --git a/sys/vfs/hammer/hammer_vfsops.c b/sys/vfs/hammer/hammer_vfsops.c index 6f483b2294..b097b61952 100644 --- a/sys/vfs/hammer/hammer_vfsops.c +++ b/sys/vfs/hammer/hammer_vfsops.c @@ -113,6 +113,7 @@ int hammer_bio_count; int hammer_verify_zone; int hammer_verify_data = 1; int hammer_write_mode; +int hammer_double_buffer; int hammer_yield_check = 16; int hammer_fsync_mode = 3; int64_t hammer_contention_count; @@ -276,6 +277,8 @@ SYSCTL_INT(_vfs_hammer, OID_AUTO, verify_data, CTLFLAG_RW, &hammer_verify_data, 0, ""); SYSCTL_INT(_vfs_hammer, OID_AUTO, write_mode, CTLFLAG_RW, &hammer_write_mode, 0, ""); +SYSCTL_INT(_vfs_hammer, OID_AUTO, double_buffer, CTLFLAG_RW, + &hammer_double_buffer, 0, ""); SYSCTL_INT(_vfs_hammer, OID_AUTO, yield_check, CTLFLAG_RW, &hammer_yield_check, 0, ""); SYSCTL_INT(_vfs_hammer, OID_AUTO, fsync_mode, CTLFLAG_RW, diff --git a/sys/vfs/hammer/hammer_vnops.c b/sys/vfs/hammer/hammer_vnops.c index 53a4682993..ff3f334921 100644 --- a/sys/vfs/hammer/hammer_vnops.c +++ b/sys/vfs/hammer/hammer_vnops.c @@ -2667,6 +2667,7 @@ hammer_vop_strategy_read(struct vop_strategy_args *ap) int boff; int roff; int n; + int isdedupable; bio = ap->a_bio; bp = bio->bio_buf; @@ -2678,9 +2679,14 @@ hammer_vop_strategy_read(struct vop_strategy_args *ap) * a BMAP operation, or else should be NOOFFSET. * * Checking the high bits for a match against zone-2 should suffice. + * + * In cases where a lot of data duplication is present it may be + * more beneficial to drop through and doubule-buffer through the + * device. */ nbio = push_bio(bio); - if ((nbio->bio_offset & HAMMER_OFF_ZONE_MASK) == + if (hammer_double_buffer == 0 && + (nbio->bio_offset & HAMMER_OFF_ZONE_MASK) == HAMMER_ZONE_LARGE_DATA) { lwkt_gettoken(&hmp->fs_token); error = hammer_io_direct_read(hmp, nbio, NULL); @@ -2821,19 +2827,23 @@ hammer_vop_strategy_read(struct vop_strategy_args *ap) * truncation point from above. */ disk_offset = cursor.leaf->data_offset + roff; - if (boff == 0 && n == bp->b_bufsize && - hammer_cursor_ondisk(&cursor) && - (disk_offset & HAMMER_BUFMASK) == 0) { + isdedupable = (boff == 0 && n == bp->b_bufsize && + hammer_cursor_ondisk(&cursor) && + ((int)disk_offset & HAMMER_BUFMASK) == 0); + + if (isdedupable && hammer_double_buffer == 0) { KKASSERT((disk_offset & HAMMER_OFF_ZONE_MASK) == HAMMER_ZONE_LARGE_DATA); nbio->bio_offset = disk_offset; error = hammer_io_direct_read(hmp, nbio, cursor.leaf); - if (hammer_live_dedup) + if (hammer_live_dedup && error == 0) hammer_dedup_cache_add(ip, cursor.leaf); goto done; } else if (n) { error = hammer_ip_resolve_data(&cursor); if (error == 0) { + if (hammer_live_dedup && isdedupable) + hammer_dedup_cache_add(ip, cursor.leaf); bcopy((char *)cursor.data + roff, (char *)bp->b_data + boff, n); } -- 2.41.0