/*
* read in the disk structures, return -1 if the format
* is inconsistent.
*/
int
dinit(Disk *d, int f, int psize, char *expname)
{
ulong i;
uvlong length;
char buf[1024];
Bbuf *b;
Dalloc *ba;
Dir *dir;
/*
* get disk size
*/
dir = dirfstat(f);
if(dir == nil){
perror("dinit: stat");
return -1;
}
length = dir->length;
free(dir);
if (expname != nil && strncmp(d->name, expname, sizeof d->name) != 0) {
/* Mismatch with recorded name; fail here to force a format */
fprint(2, "cfs: name mismatch\n");
return -1;
}
/*
* check allocation blocks for consistency
*/
if(bcinit(d, f, d->bsize) < 0){
fprint(2, "dinit: couldn't init block cache\n");
return -1;
}
for(i = 0; i < d->nab; i++){
b = bcread(d, i);
if(b == 0){
perror("dinit: read");
return -1;
}
ba = (Dalloc*)b->data;
if(ba->magic != Amagic){
fprint(2, "dinit: bad magic in alloc block %uld\n", i);
return -1;
}
if(d->bsize != ba->bsize){
fprint(2, "dinit: bad bsize in alloc block %uld\n", i);
return -1;
}
if(d->nab != ba->nab){
fprint(2, "dinit: bad nab in alloc block %uld\n", i);
return -1;
}
if(strncmp(d->name, ba->name, sizeof(d->name))){
fprint(2, "dinit: bad name in alloc block %uld\n", i);
return -1;
}
}
return 0;
}
/*
* format the disk as a cache
*/
int
dformat(Disk *d, int f, char *name, ulong bsize, ulong psize)
{
int i;
uvlong length;
Bbuf *b;
Dalloc *ba;
Dir *dir;
Dptr dptr;
/*
* allocate a block from a bit vector page
*
* a return value of Notabno means no blocks left
*/
static ulong
_balloc(Dalloc *ba, ulong max)
{
int len; /* number of valid words */
ulong i; /* bit position in long */
ulong m; /* 1<<i */
ulong v; /* old value of long */
ulong *p, *e;
/*
* find a word with a 0 bit
*/
len = (max+BtoUL-1)/BtoUL;
for(p = ba->bits, e = p + len; p < e; p++)
if(*p != 0xFFFFFFFF)
break;
if(p == e)
return Notabno;
/*
* find the first 0 bit
*/
v = *p;
for(m = 1, i = 0; i < BtoUL; i++, m <<= 1)
if((m|v) != v)
break;
/*
* calculate block number
*/
i += (p - ba->bits)*BtoUL;
if(i >= max)
return Notabno;
/*
* set bit to 1
*/
*p = v | m;
return i;
}
/*
* allocate a block
*
* return Notabno if none left
*/
ulong
dalloc(Disk *d, Dptr *p)
{
ulong bno, max, rv;
Bbuf *b;
Dalloc *ba;
/*
* then all the pages it points to
*
* DANGER: this algorithm may fail if there are more
* allocation blocks than block buffers
*/
b = bcread(d, bno);
if(b == 0)
return -1;
sp = (Dptr*)b->data;
for(ep = sp + d->p2b; sp < ep; sp++)
if(dfree(d, sp) < 0)
return -1;
return 0;
}