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:
parent
13daf5bc6e
commit
4a480ffabb
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue