/* * 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 #include #include #include #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"); }