Allocate file memory in blocks instead of one big chunk. Makes

writing large files much cheaper since there's no longer a need to
realloc $lots of memory when the file grows.
This commit is contained in:
pooka 2007-04-01 10:55:38 +00:00
parent 13daf5bc6e
commit 4a480ffabb
3 changed files with 66 additions and 27 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: dtfs.h,v 1.10 2007/03/20 18:30:30 pooka Exp $ */
/* $NetBSD: dtfs.h,v 1.11 2007/04/01 10:55:38 pooka Exp $ */
/*
* Copyright (c) 2006 Antti Kantee. All Rights Reserved.
@ -38,6 +38,12 @@
PUFFSOP_PROTOS(dtfs);
int dtfs_domount(struct puffs_usermount *);
#define DTFS_BLOCKSHIFT (16)
#define DTFS_BLOCKSIZE (1<<DTFS_BLOCKSHIFT)
#define ROUNDUP(a,b) ((a) & ((b)-1))
#define BLOCKNUM(a,b) (((a) & ~((1<<(b))-1)) >> (b))
struct dtfs_mount {
ino_t dtm_nextfileid; /* running number for file id */
@ -48,7 +54,8 @@ struct dtfs_mount {
struct dtfs_file {
union {
struct {
uint8_t *data;
uint8_t **blocks;
size_t numblocks;
size_t datalen;
} reg;
struct {
@ -62,7 +69,8 @@ struct dtfs_file {
dev_t rdev;
} dev;
} u;
#define df_data u.reg.data
#define df_blocks u.reg.blocks
#define df_numblocks u.reg.numblocks
#define df_datalen u.reg.datalen
#define df_dotdot u.dir.dotdot
#define df_dirents u.dir.dirents

View File

@ -1,4 +1,4 @@
/* $NetBSD: dtfs_subr.c,v 1.12 2007/03/20 18:30:30 pooka Exp $ */
/* $NetBSD: dtfs_subr.c,v 1.13 2007/04/01 10:55:38 pooka Exp $ */
/*
* Copyright (c) 2006 Antti Kantee. All Rights Reserved.
@ -203,6 +203,7 @@ dtfs_freenode(struct puffs_node *pn)
{
struct dtfs_file *df = DTFS_PTOF(pn);
struct dtfs_mount *dtm;
int i;
assert(pn->pn_va.va_nlink == 0);
dtm = pn->pn_mnt->pu_privdata;
@ -211,7 +212,8 @@ dtfs_freenode(struct puffs_node *pn)
case VREG:
assert(dtm->dtm_fsizes >= pn->pn_va.va_size);
dtm->dtm_fsizes -= pn->pn_va.va_size;
free(df->df_data);
for (i = 0; i < BLOCKNUM(df->df_datalen, DTFS_BLOCKSHIFT); i++)
free(df->df_blocks[i]);
break;
case VLNK:
free(df->df_linktarget);
@ -236,31 +238,32 @@ dtfs_setsize(struct puffs_node *pn, off_t newsize)
{
struct dtfs_file *df = DTFS_PTOF(pn);
struct dtfs_mount *dtm;
size_t allocsize;
size_t newblocks;
int needalloc, shrinks;
int i;
needalloc = newsize > df->df_datalen;
needalloc = newsize > ROUNDUP(df->df_datalen, DTFS_BLOCKSIZE);
shrinks = newsize < pn->pn_va.va_size;
/*
* quickhack: realloc in 1MB chunks if we're over 1MB in size
*/
if (pn->pn_va.va_size > 1024*1024 && !shrinks) {
allocsize = newsize + 1024*1024;
} else {
allocsize = newsize;
}
if (needalloc || shrinks) {
df->df_data = erealloc(df->df_data, allocsize);
newblocks = BLOCKNUM(newsize, DTFS_BLOCKSHIFT) + 1;
if (shrinks)
for (i = newblocks; i < df->df_numblocks; i++)
free(df->df_blocks[i]);
df->df_blocks = erealloc(df->df_blocks,
newblocks * sizeof(uint8_t *));
/*
* if extended, set storage to zero
* to match correct behaviour
*/
if (!shrinks)
memset(df->df_data+df->df_datalen, 0,
allocsize-df->df_datalen);
df->df_datalen = allocsize;
for (i = df->df_numblocks; i < newblocks; i++)
df->df_blocks[i] = emalloc(DTFS_BLOCKSIZE);
df->df_datalen = newsize;
df->df_numblocks = newblocks;
}
dtm = pn->pn_mnt->pu_privdata;
@ -271,7 +274,7 @@ dtfs_setsize(struct puffs_node *pn, off_t newsize)
}
pn->pn_va.va_size = newsize;
pn->pn_va.va_bytes = df->df_datalen;
pn->pn_va.va_bytes = BLOCKNUM(newsize,DTFS_BLOCKSHIFT)>>DTFS_BLOCKSHIFT;
}
/* add & bump link count */

View File

@ -1,4 +1,4 @@
/* $NetBSD: dtfs_vnops.c,v 1.19 2007/03/22 16:59:34 pooka Exp $ */
/* $NetBSD: dtfs_vnops.c,v 1.20 2007/04/01 10:55:38 pooka Exp $ */
/*
* Copyright (c) 2006 Antti Kantee. All Rights Reserved.
@ -379,6 +379,9 @@ dtfs_node_mknod(struct puffs_cc *pcc, void *opc, void **newnode,
return 0;
}
#define BLOCKOFF(a,b) ((a) & ((b)-1))
#define BLOCKLEFT(a,b) ((b) - BLOCKOFF(a,b))
/*
* Read operation, used both for VOP_READ and VOP_GETPAGES
*/
@ -388,7 +391,9 @@ dtfs_node_read(struct puffs_cc *pcc, void *opc, uint8_t *buf,
{
struct puffs_node *pn = opc;
struct dtfs_file *df = DTFS_CTOF(opc);
quad_t xfer;
quad_t xfer, origxfer;
uint8_t *src, *dest;
size_t copylen;
if (pn->pn_va.va_type != VREG)
return EISDIR;
@ -397,8 +402,18 @@ dtfs_node_read(struct puffs_cc *pcc, void *opc, uint8_t *buf,
if (xfer < 0)
return EINVAL;
memcpy(buf, df->df_data + offset, xfer);
*resid -= xfer;
dest = buf;
origxfer = xfer;
while (xfer > 0) {
copylen = MIN(xfer, BLOCKLEFT(offset, DTFS_BLOCKSIZE));
src = df->df_blocks[BLOCKNUM(offset, DTFS_BLOCKSHIFT)]
+ BLOCKOFF(offset, DTFS_BLOCKSIZE);
memcpy(dest, src, copylen);
offset += copylen;
dest += copylen;
xfer -= copylen;
}
*resid -= origxfer;
dtfs_updatetimes(pn, 1, 0, 0);
@ -414,6 +429,8 @@ dtfs_node_write(struct puffs_cc *pcc, void *opc, uint8_t *buf,
{
struct puffs_node *pn = opc;
struct dtfs_file *df = DTFS_CTOF(opc);
uint8_t *src, *dest;
size_t copylen;
if (pn->pn_va.va_type != VREG)
return EISDIR;
@ -423,8 +440,19 @@ dtfs_node_write(struct puffs_cc *pcc, void *opc, uint8_t *buf,
if (*resid + offset > pn->pn_va.va_size)
dtfs_setsize(pn, *resid + offset);
memcpy(df->df_data + offset, buf, *resid);
*resid = 0;
src = buf;
while (*resid > 0) {
int i;
copylen = MIN(*resid, BLOCKLEFT(offset, DTFS_BLOCKSIZE));
i = BLOCKNUM(offset, DTFS_BLOCKSHIFT);
dest = df->df_blocks[i]
+ BLOCKOFF(offset, DTFS_BLOCKSIZE);
memcpy(dest, src, copylen);
offset += copylen;
dest += copylen;
*resid -= copylen;
}
dtfs_updatetimes(pn, 0, 1, 1);