#define min(a, b) (((b) < (a))?(b):(a))
#define ISDELOP(op) (((op).buf == NULL) && ((op).fillfn == NULL))
-ssize_t btget(struct store *st, struct btnode *tree, block_t bl, void *buf, size_t len)
+ssize_t btget(struct store *st, struct btnode *tree, block_t bl, void *buf, size_t len, size_t blsize)
{
int d;
block_t c, sel;
- struct btnode indir[BT_INDSZ];
+ struct btnode indir[1 << blsize];
ssize_t sz;
if(tree->d == 0) {
/* This check should really only be necessary on the first
* iteration, but I felt it was easier to put it in the
* loop. */
- if((bl >> (d * BT_INDBITS)) > 0) {
+ if((bl >> (d * blsize)) > 0) {
errno = ERANGE;
return(-1);
}
return(storeget(st, buf, len, &tree->a));
/* Luckily, this is tail recursive */
- if((sz = storeget(st, indir, BT_INDBSZ, &tree->a)) < 0)
+ if((sz = storeget(st, indir, sizeof(indir), &tree->a)) < 0)
return(-1);
c = sz / sizeof(struct btnode);
- sel = bl >> ((d - 1) * BT_INDBITS);
+ sel = bl >> ((d - 1) * blsize);
if(sel >= c) {
errno = ERANGE;
return(-1);
}
tree = &indir[sel];
- bl &= (1LL << ((d - 1) * BT_INDBITS)) - 1;
+ bl &= (1LL << ((d - 1) * blsize)) - 1;
}
return(0);
}
* blputmany() in many ways makes the code uglier, but it saves a
* *lot* of space, since it doesn't need to store intermediary blocks.
*/
-static int btputmany2(struct store *st, struct btnode *tree, struct btop *ops, int numops, block_t bloff)
+static int btputmany2(struct store *st, struct btnode *tree, struct btop *ops, int numops, size_t blsize, block_t bloff)
{
int i, subops, d, f, hasid;
block_t c, sel, bl, nextsz;
struct addr na;
- struct btnode indir[BT_INDSZ];
+ struct btnode indir[1 << blsize];
ssize_t sz;
d = tree->d & 0x7f;
continue;
}
- if(f && (bl == (1LL << (d * BT_INDBITS)))) {
+ if(f && (bl == (1LL << (d * blsize)))) {
/* New level of indirection */
if(hasid) {
if(storeput(st, indir, c * sizeof(struct btnode), &na))
}
/* Assume that numops == largest block number + 1 -- gaps
* will be detected as errors later */
- for(bl = numops - 1; bl > 0; d++, bl <<= BT_INDBITS);
+ for(bl = numops - 1; bl > 0; d++, bl <<= blsize);
tree->d = d;
c = 0;
hasid = 1;
} else {
/* Get indirect block */
if(!hasid) {
- if((sz = storeget(st, indir, BT_INDBSZ, &tree->a)) < 0)
+ if((sz = storeget(st, indir, sizeof(indir), &tree->a)) < 0)
return(-1);
c = sz / sizeof(struct btnode);
hasid = 1;
}
}
- sel = bl >> ((d - 1) * BT_INDBITS);
+ sel = bl >> ((d - 1) * blsize);
if(sel > c) {
errno = ERANGE;
return(-1);
indir[c].d = 0;
c++;
}
- nextsz = 1LL << ((d - 1) * BT_INDBITS);
+ nextsz = 1LL << ((d - 1) * blsize);
subops = countops(ops + i, numops - i, bloff + (sel * nextsz), nextsz);
- if(btputmany2(st, &indir[sel], ops + i, subops, bloff + (sel * nextsz)))
+ if(btputmany2(st, &indir[sel], ops + i, subops, blsize, bloff + (sel * nextsz)))
return(-1);
i += subops;
- if((sel == BT_INDSZ - 1) && (indir[sel].d == ((d - 1) | 0x80))) {
+ if((sel == (1 << blsize) - 1) && (indir[sel].d == ((d - 1) | 0x80))) {
/* Filled up */
tree->d |= 0x80;
f = 1;
return(0);
}
-int btputmany(struct store *st, struct btnode *tree, struct btop *ops, int numops)
+int btputmany(struct store *st, struct btnode *tree, struct btop *ops, int numops, size_t blsize)
{
- return(btputmany2(st, tree, ops, numops, 0));
+ return(btputmany2(st, tree, ops, numops, blsize, 0));
}
-int btput(struct store *st, struct btnode *tree, block_t bl, void *buf, size_t len)
+int btput(struct store *st, struct btnode *tree, block_t bl, void *buf, size_t len, size_t blsize)
{
- struct btop ops[1];
+ struct btop ops;
- ops[0].blk = bl;
- ops[0].buf = buf;
- ops[0].len = len;
- return(btputmany(st, tree, ops, 1));
+ memset(&ops, 0, sizeof(ops));
+ ops.blk = bl;
+ ops.buf = buf;
+ ops.len = len;
+ return(btputmany(st, tree, &ops, 1, blsize));
}
void btmkop(struct btop *op, block_t bl, void *buf, size_t len)
qsort(ops, numops, sizeof(*ops), (int (*)(const void *, const void *))opcmp);
}
-block_t btcount(struct store *st, struct btnode *tree)
+block_t btcount(struct store *st, struct btnode *tree, size_t blsize)
{
int d, f;
- struct btnode indir[BT_INDSZ];
+ struct btnode indir[1 << blsize];
block_t c, ret;
ssize_t sz;
f = tree->d & 0x80;
if(f)
- return(1LL << (d * BT_INDBITS));
+ return(1LL << (d * blsize));
if(d == 0)
return(0);
ret = 0;
while(1) {
- if((sz = storeget(st, indir, BT_INDBSZ, &tree->a)) < 0)
+ if((sz = storeget(st, indir, sizeof(indir), &tree->a)) < 0)
return(-1);
c = sz / sizeof(struct btnode);
- ret += (c - 1) * (1LL << ((d - 1) * BT_INDBITS));
+ ret += (c - 1) * (1LL << ((d - 1) * blsize));
d = indir[c - 1].d & 0x7f;
f = indir[c - 1].d & 0x80;
if(f)
- return(ret + (1LL << (d * BT_INDBITS)));
+ return(ret + (1LL << (d * blsize)));
tree = &indir[c - 1];
}
}
#include "store.h"
#include "inttypes.h"
-#define BT_INDBITS 10
-#define BT_INDSZ (1 << BT_INDBITS)
-#define BT_INDBSZ (sizeof(struct btnode) * BT_INDSZ)
-
typedef loff_t block_t;
struct btnode {
void *pdata;
};
-ssize_t btget(struct store *st, struct btnode *tree, block_t bl, void *buf, size_t len);
-int btputmany(struct store *st, struct btnode *tree, struct btop *ops, int numops);
-int btput(struct store *st, struct btnode *tree, block_t bl, void *buf, size_t len);
-block_t btcount(struct store *st, struct btnode *tree);
+ssize_t btget(struct store *st, struct btnode *tree, block_t bl, void *buf, size_t len, size_t blsize);
+int btputmany(struct store *st, struct btnode *tree, struct btop *ops, int numops, size_t blsize);
+int btput(struct store *st, struct btnode *tree, block_t bl, void *buf, size_t len, size_t blsize);
+block_t btcount(struct store *st, struct btnode *tree, size_t blsize);
void btsortops(struct btop *ops, int numops);
void btmkop(struct btop *op, block_t bl, void *buf, size_t len);
root.data.d = 0;
root.xattr.d = 0;
strcpy(dots.name, ".");
- if(btput(st, &root.data, 0, &dots, sizeof(dots) - sizeof(dots.name) + 2)) {
+ if(btput(st, &root.data, 0, &dots, sizeof(dots) - sizeof(dots.name) + 2, DIRBLSIZE)) {
fprintf(stderr, "mkfs.vc: could not create root directory entries: %s\n", strerror(errno));
exit(1);
}
strcpy(dots.name, "..");
- if(btput(st, &root.data, 1, &dots, sizeof(dots) - sizeof(dots.name) + 3)) {
+ if(btput(st, &root.data, 1, &dots, sizeof(dots) - sizeof(dots.name) + 3, DIRBLSIZE)) {
fprintf(stderr, "mkfs.vc: could not create root directory entries: %s\n", strerror(errno));
exit(1);
}
frev.ct = now;
frev.root.d = 0;
- if(btput(st, &frev.root, 0, &root, sizeof(root))) {
+ if(btput(st, &frev.root, 0, &root, sizeof(root), INOBLSIZE)) {
fprintf(stderr, "mkfs.vc: could not store root directory inode: %s\n", strerror(errno));
exit(1);
}
}
fsd->inocser = 1;
cacheinode(fsd, 0, nilnode);
- if((fsd->nextino = btcount(fsd->st, &fsd->inotab)) < 0) {
+ if((fsd->nextino = btcount(fsd->st, &fsd->inotab, INOBLSIZE)) < 0) {
flog(LOG_ERR, "could not count inodes: %s");
close(fsd->revfd);
releasestore(fsd->st);
ssize_t sz;
for(i = 0; ; i++) {
- if((sz = btget(fsd->st, dirdata, i, &dent, sizeof(dent))) < 0) {
+ if((sz = btget(fsd->st, dirdata, i, &dent, sizeof(dent), DIRBLSIZE)) < 0) {
if(errno == ERANGE)
errno = ENOENT;
return(-1);
if(inotab.d == 0)
inotab = fsd->inotab;
- if((sz = btget(fsd->st, &inotab, ino, buf, sizeof(*buf))) < 0)
+ if((sz = btget(fsd->st, &inotab, ino, buf, sizeof(*buf), INOBLSIZE)) < 0)
return(-1);
if(sz != sizeof(*buf)) {
flog(LOG_ERR, "illegal size for inode %i", ino);
buf = NULL;
while(bsz < size) {
memset(&dent, 0, sizeof(dent));
- if((sz = btget(fsd->st, &file.data, off++, &dent, sizeof(dent))) < 0) {
+ if((sz = btget(fsd->st, &file.data, off++, &dent, sizeof(dent), DIRBLSIZE)) < 0) {
if(errno == ERANGE) {
if(buf != NULL)
break;
return(-1);
}
if(di == ino->size - 1) {
- if(btput(fsd->st, &ino->data, ino->size - 1, NULL, 0))
+ if(btput(fsd->st, &ino->data, ino->size - 1, NULL, 0, DIRBLSIZE))
return(-1);
} else {
- if((sz = btget(fsd->st, &ino->data, ino->size - 1, &dent, sizeof(dent))) < 0)
+ if((sz = btget(fsd->st, &ino->data, ino->size - 1, &dent, sizeof(dent), DIRBLSIZE)) < 0)
return(-1);
btmkop(ops + 0, di, &dent, sz);
btmkop(ops + 1, ino->size - 1, NULL, 0);
- if(btputmany(fsd->st, &ino->data, ops, 2))
+ if(btputmany(fsd->st, &ino->data, ops, 2, DIRBLSIZE))
return(-1);
}
+ ino->size--;
return(0);
}
dent.inode = target;
sz = sizeof(dent) - sizeof(dent.name) + strlen(name) + 1;
if((di == -1) || (di == ino->size)) {
- if(btput(fsd->st, &ino->data, ino->size, &dent, sz))
+ if(btput(fsd->st, &ino->data, ino->size, &dent, sz, DIRBLSIZE))
return(-1);
ino->size++;
return(0);
}
- return(btput(fsd->st, &ino->data, di, &dent, sz));
+ return(btput(fsd->st, &ino->data, di, &dent, sz, DIRBLSIZE));
}
static void fusemkdir(fuse_req_t req, fuse_ino_t parent, const char *name, mode_t mode)
file.links++;
btmkop(ops + 0, inoc->inode, &file, sizeof(file));
btmkop(ops + 1, fsd->nextino, &new, sizeof(new));
- if(btputmany(fsd->st, &inotab, ops, 2)) {
+ if(btputmany(fsd->st, &inotab, ops, 2, INOBLSIZE)) {
fuse_reply_err(req, errno);
return;
}
fuse_reply_err(req, errno);
return;
}
- if(btput(fsd->st, &inotab, inoc->inode, &file, sizeof(file))) {
+ if(btput(fsd->st, &inotab, inoc->inode, &file, sizeof(file), INOBLSIZE)) {
fuse_reply_err(req, errno);
return;
}
#include "blocktree.h"
+#define DIRBLSIZE 4
+#define INOBLSIZE 4
+
typedef loff_t vc_ino_t;
typedef loff_t vc_rev_t;