From e38e0b155508103a79cec55a39c8d0556823eaf2 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Sun, 24 Feb 2008 19:48:45 +0000 Subject: [PATCH] HAMMER 31A/many: File data size optimization I've been meaning to do this for a while. When writing a data record for the last block in a file, for example for small files, there is no need to write out the entire 16K buffer. Just write out the actual number of bytes of data to file EOF. This results in *EXTREME* data compaction and very high performance when manipulating small files. The smallest possible file requires two 96 byte records (inode record and data record), two 64 byte B-Tree elements, a 64 byte data element (the file data), and a 128 byte data element (the inode structure), for a grand total of 512 bytes. --- sys/vfs/hammer/hammer_object.c | 7 +++++-- sys/vfs/hammer/hammer_vnops.c | 21 ++++++++++++++++++--- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/sys/vfs/hammer/hammer_object.c b/sys/vfs/hammer/hammer_object.c index 34edf973c9..4c62214f82 100644 --- a/sys/vfs/hammer/hammer_object.c +++ b/sys/vfs/hammer/hammer_object.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_object.c,v 1.33 2008/02/23 21:55:50 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_object.c,v 1.34 2008/02/24 19:48:45 dillon Exp $ */ #include "hammer.h" @@ -446,6 +446,10 @@ hammer_ip_add_record(struct hammer_transaction *trans, hammer_record_t record) * is responsible for actually writing a data record out to the disk. * * This can only occur non-historically (i.e. 'current' data only). + * + * The file offset must be HAMMER_BUFSIZE aligned but the data length + * can be truncated. The record (currently) always represents a BUFSIZE + * swath of space whether the data is truncated or not. */ int hammer_ip_sync_data(hammer_transaction_t trans, hammer_inode_t ip, @@ -459,7 +463,6 @@ hammer_ip_sync_data(hammer_transaction_t trans, hammer_inode_t ip, int error; KKASSERT((offset & HAMMER_BUFMASK) == 0); - KKASSERT((bytes & HAMMER_BUFMASK) == 0); retry: error = hammer_init_cursor_hmp(&cursor, &ip->cache[0], ip->hmp); if (error) diff --git a/sys/vfs/hammer/hammer_vnops.c b/sys/vfs/hammer/hammer_vnops.c index 1f05eed705..254596e1b1 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.33 2008/02/23 21:55:50 dillon Exp $ + * $DragonFly: src/sys/vfs/hammer/hammer_vnops.c,v 1.34 2008/02/24 19:48:45 dillon Exp $ */ #include @@ -1786,11 +1786,26 @@ hammer_vop_strategy_write(struct vop_strategy_args *ap) } /* - * Add a single record to cover the write + * Add a single record to cover the write. We can write a record + * with only the actual file data - for example, a small 200 byte + * file does not have to write out a 16K record. + * + * While the data size does not have to be aligned, we still do it + * to reduce fragmentation in a future allocation model. */ if (error == 0) { + int limit_size; + + if (ip->ino_rec.ino_size - bio->bio_offset > bp->b_bufsize) { + limit_size = bp->b_bufsize; + } else { + limit_size = (int)(ip->ino_rec.ino_size - + bio->bio_offset); + KKASSERT(limit_size >= 0); + limit_size = (limit_size + 63) & ~63; + } error = hammer_ip_sync_data(&trans, ip, bio->bio_offset, - bp->b_data, bp->b_bufsize); + bp->b_data, limit_size); } /* -- 2.11.4.GIT