/*
* Copyright (c) 2013, Coraid, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Coraid nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL CORAID BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <u.h>
#include <libc.h>
#include <thread.h>
#include <fcall.h>
#include <9p.h>
#include "dat.h"
enum {
Nht = 67108859,
};
static ulong primes[] = {1048573, 2097143, 4194301, 8388593,
16777213, 33554393, 67108859, 134217689, 268435399};
static Lock slock;
Super super;
void
loadsuper(void)
{
Super *sp;
lock(&slock);
sp = cbread(0);
if(sp->magic != Magicθ)
sysfatal("Bad super magic");
memmove(&super, sp, sizeof(Super));
brelease(0);
if(super.nht == 0) {
super.nht = Nht;
super.nhashblk = (super.nht + NPerBlk - 1) / NPerBlk;
}
if(super.snaptime == 0)
super.snaptime = (3 * 60 + 15) * 60;
initfree();
unlock(&slock);
}
static char supbuf[1024];
char *
prsuper(void)
{
char *p, *e;
p = supbuf;
e = p + nelem(supbuf);
p = seprint(p, e, "Superblock:\n");
p = seprint(p, e, "magic: %ulld(0x%ullx)\n", super.magic, super.magic);
p = seprint(p, e, "qgen: %ulld(0x%ullx)\n", super.qgen, super.qgen);
p = seprint(p, e, "nblk: %ulld(0x%ullx)\n", super.nblk, super.nblk);
p = seprint(p, e, "nfreemap: %ulld(0x%ullx)\n", super.nfreemap, super.nfreemap);
p = seprint(p, e, "freemap: %ulld(0x%ullx)\n", super.freemap, super.freemap);
p = seprint(p, e, "stat: %ulld(0x%ullx)\n", super.state, super.state);
p = seprint(p, e, "firstdat: %ulld(0x%ullx)\n", super.firstdat, super.firstdat);
p = seprint(p, e, "nfree: %ulld(0x%ullx)\n", super.nfree, super.nfree);
p = seprint(p, e, "firstlun: %ulld(0x%ullx)\n", super.firstlun, super.firstlun);
p = seprint(p, e, "nmeta: %ulld(0x%ullx)\n", super.nmeta, super.nmeta);
p = seprint(p, e, "firstmeta: %ulld(0x%ullx)\n", super.firstmeta, super.firstmeta);
p = seprint(p, e, "ffmeta: %ulld(0x%ullx)\n", super.ffmeta, super.ffmeta);
p = seprint(p, e, "nblob: %ulld(0x%ullx)\n", super.nblob, super.nblob);
p = seprint(p, e, "firstblob: %ulld(0x%ullx)\n", super.firstblob, super.firstblob);
p = seprint(p, e, "ffblob: %ulld(0x%ullx)\n", super.ffblob, super.ffblob);
p = seprint(p, e, "lfblob: %ulld(0x%ullx)\n", super.lfblob, super.lfblob);
p = seprint(p, e, "nht: %ulld(0x%ullx)\n", super.nht, super.nht);
seprint(p, e, "nhashblk: %ulld(0x%ullx)\n", super.nhashblk, super.nhashblk);
return supbuf;
}
void
savesuper(void)
{
char *p;
lock(&slock);
p = cbread(0);
memset(p, 0, BlkSize);
memmove(p, &super, sizeof(Super));
cbwrite(0);
brelease(0);
unlock(&slock);
}
void
ream(char *dev)
{
Qid rootqid;
char *me;
uchar *bigbuf;
uvlong meta, firstnon, lastnon, i;
vlong bperb;
vlong now;
int j, k, sfd;
int ndot = 0;
fprint(2, "reaming %s\n", dev);
sfd = open(dev, ORDWR);
if(sfd < 0)
sysfatal("Couldn't open device for write: %r");
/*
* Init superblock
*/
super.magic = Magicθ;
super.version = 1;
super.qgen = 1 | ((uvlong)TFile << 60);
i = devsize(dev);
if(i == ~0ULL)
sysfatal("couldn't get device size:%r\n");
super.nblk = i / BlkSize;
for(i = 0; i < nelem(primes) - 1 && super.nblk > primes[i]; ++i) ;
super.nht = primes[i];
super.nhashblk = (super.nht + NPerBlk - 1) / NPerBlk;
bperb = 8 * BlkSize;
super.nfreemap = (super.nblk + bperb - 1) / bperb;
super.freemap = 2 * super.nhashblk + 1;
super.nmeta = super.nblk / 200;
super.firstmeta = super.freemap + super.nfreemap;
super.ffmeta = 1;
super.nblob = super.nblk / 200;
super.firstblob = super.firstmeta + super.nmeta;
super.ffblob = super.firstblob * BlkSize;
super.lfblob = super.ffblob + (super.nblob - 1) * BlkSize + BlkSize/2;
super.state = FSClean;
super.firstdat = super.firstblob + super.nblob;
super.nfree = super.nblk - super.firstdat;
fprint(2, "writing superblock: freemap=%ulld nfreemap=%ulld firstdat=%ulld nmeta=%ulld firstmeta=%ulld\n", super.freemap, super.nfreemap, super.firstdat, super.nmeta, super.firstmeta);
savesuper();
/*
* Clear hash tables
*/
bigbuf = malloc(1024*1024);
j = (1024 * 1024) / BlkSize;
memset(bigbuf, 0, 1024 * 1024);
for(i = 1; i < super.freemap; i += j)
{
fprint(2, ".");
if(++ndot % 60 == 0) fprint(2, "\n");
pwrite(sfd, bigbuf, 1024 * 1024, i * BlkSize);
}
fprint(2, "\n");
/*
* Init free bit map
*/
firstnon = super.firstdat / (BlkSize * 8);
lastnon = super.nblk / (BlkSize * 8);
memset(bigbuf, 0, BlkSize);
for(i = 0; i < firstnon; ++i)
pwrite(sfd, bigbuf, BlkSize, (super.freemap + i) * BlkSize);
for(i = firstnon; i <= lastnon; ++i) {
memset(bigbuf, 0xff, BlkSize);
if(i == firstnon) {
j = super.firstdat % (BlkSize * 8);
k = j % 8;
memset(bigbuf, 0, j/8);
bigbuf[j/8] = ~((1 << k) - 1);
}
if(i == lastnon) {
j = super.nblk % (BlkSize * 8);
k = j % 8;
bigbuf[j/8] = (1 << k) - 1;
memset(bigbuf + j/8 + 1, 0, BlkSize - (j/8 + 1));
}
pwrite(sfd, bigbuf, BlkSize, (super.freemap + i) * BlkSize);
}
memset(bigbuf, 0, BlkSize);
for(i = lastnon + 1; i < super.nfreemap; ++i)
pwrite(sfd, bigbuf, BlkSize, (super.freemap + i) * BlkSize);
free(bigbuf);
loadsuper();
/*
* Initialize the metadata regions
*/
reammeta(sfd);
/*
* Create root directory
*/
rootqid.path = p2q(-1, "/", 1);
meta = q2m(-1, rootqid.path, 1);
setmetastr(meta, "name", nil, "/", 0);
rootqid.vers = 0;
rootqid.type = QTDIR;
setmetaint(meta, "qpath", nil, rootqid.path);
setmetaint(meta, "qvers", nil, rootqid.vers);
setmetaint(meta, "qtype", nil, rootqid.type);
setmetaint(meta, "mode", nil, DMDIR | 0775);
now = nsec();
setmetaint(meta, "atime", nil, now);
setmetaint(meta, "mtime", nil, now);
setmetaint(meta, "length", nil, 0);
me = getuser();
setmetastr(meta, "uid", nil, me, 0);
setmetastr(meta, "gid", nil, me, 0);
setmetastr(meta, "muid", nil, me, 0);
setmetaint(meta, "child", nil, 0);
setqhash(rootqid.path, meta);
savesuper();
fprint(2, "Done with ream\n");
}
|