예제 #1
0
 bool reallocateWithCopy(OldAllocator &oldAllocator, NewAllocator &newAllocator, block &b,
                         size_t n)
 {
   auto newBlock = newAllocator.allocate(n);
   if (!newBlock) {
     return false;
   }
   blockCopy(b, newBlock);
   oldAllocator.deallocate(b);
   b = newBlock;
   return true;
 }
예제 #2
0
void Blocks::build(bool block[], int round) {
	int i = 0, j = 0;

	bool * copy;
	//////////////////////

	if (round < size) {
		for (i = 0; i < size; i++) {
			for (j = 0; j + i < size && j + i <= round; j++) {
				if (cellCheck(block, i, j)) {
					copy = blockCopy(block);
					copy[convert(i, j)] = one;
					build(copy, round + 1);
				}
			}
		}
	}
	else {
		add(block);
	}
}
예제 #3
0
파일: fs.c 프로젝트: bhanug/harvey
static int
bumpEpoch(Fs *fs, int doarchive)
{
	uint8_t oscore[VtScoreSize];
	uint32_t oldaddr;
	Block *b, *bs;
	Entry e;
	Source *r;
	Super super;

	/*
	 * Duplicate the root block.
	 *
	 * As a hint to flchk, the garbage collector,
	 * and any (human) debuggers, store a pointer
	 * to the old root block in entry 1 of the new root block.
	 */
	r = fs->source;
	b = cacheGlobal(fs->cache, r->score, BtDir, RootTag, OReadOnly);
	if(b == nil)
		return 0;

	memset(&e, 0, sizeof e);
	e.flags = VtEntryActive | VtEntryLocal | VtEntryDir;
	memmove(e.score, b->score, VtScoreSize);
	e.tag = RootTag;
	e.snap = b->l.epoch;

	b = blockCopy(b, RootTag, fs->ehi+1, fs->elo);
	if(b == nil){
		fprint(2, "%s: bumpEpoch: blockCopy: %R\n", argv0);
		return 0;
	}

	if(0) fprint(2, "%s: snapshot root from %d to %d\n", argv0, oldaddr, b->addr);
	entryPack(&e, b->data, 1);
	blockDirty(b);

	/*
	 * Update the superblock with the new root and epoch.
	 */
	if((bs = superGet(fs->cache, &super)) == nil)
		return 0;

	fs->ehi++;
	memmove(r->score, b->score, VtScoreSize);
	r->epoch = fs->ehi;

	super.epochHigh = fs->ehi;
	oldaddr = super.active;
	super.active = b->addr;
	if(doarchive)
		super.next = oldaddr;

	/*
	 * Record that the new super.active can't get written out until
	 * the new b gets written out.  Until then, use the old value.
	 */
	localToGlobal(oldaddr, oscore);
	blockDependency(bs, b, 0, oscore, nil);
	blockPut(b);

	/*
	 * We force the super block to disk so that super.epochHigh gets updated.
	 * Otherwise, if we crash and come back, we might incorrectly treat as active
	 * some of the blocks that making up the snapshot we just created.
	 * Basically every block in the active file system and all the blocks in
	 * the recently-created snapshot depend on the super block now.
	 * Rather than record all those dependencies, we just force the block to disk.
	 *
	 * Note that blockWrite might actually (will probably) send a slightly outdated
	 * super.active to disk.  It will be the address of the most recent root that has
	 * gone to disk.
	 */
	superWrite(bs, &super, 1);
	blockRemoveLink(bs, globalToLocal(oscore), BtDir, RootTag, 0);
	blockPut(bs);

	return 1;
}
예제 #4
0
파일: fs.c 프로젝트: bhanug/harvey
Fs *
fsOpen(char *file, VtSession *z, int32_t ncache, int mode)
{
	int fd, m;
	uint8_t oscore[VtScoreSize];
	Block *b, *bs;
	Disk *disk;
	Fs *fs;
	Super super;

	switch(mode){
	default:
		vtSetError(EBadMode);
		return nil;
	case OReadOnly:
		m = OREAD;
		break;
	case OReadWrite:
		m = ORDWR;
		break;
	}
	fd = open(file, m);
	if(fd < 0){
		vtSetError("open %s: %r", file);
		return nil;
	}

	bwatchInit();
	disk = diskAlloc(fd);
	if(disk == nil){
		vtSetError("diskAlloc: %R");
		close(fd);
		return nil;
	}

	fs = vtMemAllocZ(sizeof(Fs));
	fs->mode = mode;
	fs->name = vtStrDup(file);
	fs->blockSize = diskBlockSize(disk);
	fs->elk = vtLockAlloc();
	fs->cache = cacheAlloc(disk, z, ncache, mode);
	if(mode == OReadWrite && z)
		fs->arch = archInit(fs->cache, disk, fs, z);
	fs->z = z;

	b = cacheLocal(fs->cache, PartSuper, 0, mode);
	if(b == nil)
		goto Err;
	if(!superUnpack(&super, b->data)){
		blockPut(b);
		vtSetError("bad super block");
		goto Err;
	}
	blockPut(b);

	fs->ehi = super.epochHigh;
	fs->elo = super.epochLow;

//fprint(2, "%s: fs->ehi %d fs->elo %d active=%d\n", argv0, fs->ehi, fs->elo, super.active);

	fs->source = sourceRoot(fs, super.active, mode);
	if(fs->source == nil){
		/*
		 * Perhaps it failed because the block is copy-on-write.
		 * Do the copy and try again.
		 */
		if(mode == OReadOnly || strcmp(vtGetError(), EBadRoot) != 0)
			goto Err;
		b = cacheLocalData(fs->cache, super.active, BtDir, RootTag,
			OReadWrite, 0);
		if(b == nil){
			vtSetError("cacheLocalData: %R");
			goto Err;
		}
		if(b->l.epoch == fs->ehi){
			blockPut(b);
			vtSetError("bad root source block");
			goto Err;
		}
		b = blockCopy(b, RootTag, fs->ehi, fs->elo);
		if(b == nil)
			goto Err;
		localToGlobal(super.active, oscore);
		super.active = b->addr;
		bs = cacheLocal(fs->cache, PartSuper, 0, OReadWrite);
		if(bs == nil){
			blockPut(b);
			vtSetError("cacheLocal: %R");
			goto Err;
		}
		superPack(&super, bs->data);
		blockDependency(bs, b, 0, oscore, nil);
		blockPut(b);
		blockDirty(bs);
		blockRemoveLink(bs, globalToLocal(oscore), BtDir, RootTag, 0);
		blockPut(bs);
		fs->source = sourceRoot(fs, super.active, mode);
		if(fs->source == nil){
			vtSetError("sourceRoot: %R");
			goto Err;
		}
	}

//fprint(2, "%s: got fs source\n", argv0);

	vtRLock(fs->elk);
	fs->file = fileRoot(fs->source);
	fs->source->file = fs->file;		/* point back */
	vtRUnlock(fs->elk);
	if(fs->file == nil){
		vtSetError("fileRoot: %R");
		goto Err;
	}

//fprint(2, "%s: got file root\n", argv0);

	if(mode == OReadWrite){
		fs->metaFlush = periodicAlloc(fsMetaFlush, fs, 1000);
		fs->snap = snapInit(fs);
	}
	return fs;

Err:
fprint(2, "%s: fsOpen error\n", argv0);
	fsClose(fs);
	return nil;
}
예제 #5
0
파일: source.c 프로젝트: npe9/harvey
static Block *
blockWalk(Block *p, int index, int mode, Fs *fs, Entry *e)
{
    Block *b;
    Cache *c;
    uint32_t addr;
    int type;
    uint8_t oscore[VtScoreSize], score[VtScoreSize];
    Entry oe;

    c = fs->cache;

    if((p->l.type & BtLevelMask) == 0) {
        assert(p->l.type == BtDir);
        type = entryType(e);
        b = cacheGlobal(c, e->score, type, e->tag, mode);
    } else {
        type = p->l.type - 1;
        b = cacheGlobal(c, p->data + index*VtScoreSize, type, e->tag, mode);
    }

    if(b)
        b->pc = getcallerpc(&p);

    if(b == nil || mode == OReadOnly)
        return b;

    if(p->l.epoch != fs->ehi) {
        fprint(2, "blockWalk: parent not writable\n");
        abort();
    }
    if(b->l.epoch == fs->ehi)
        return b;

    oe = *e;

    /*
     * Copy on write.
     */
    if(e->tag == 0) {
        assert(p->l.type == BtDir);
        e->tag = tagGen();
        e->flags |= VtEntryLocal;
    }

    addr = b->addr;
    b = blockCopy(b, e->tag, fs->ehi, fs->elo);
    if(b == nil)
        return nil;

    b->pc = getcallerpc(&p);
    assert(b->l.epoch == fs->ehi);

    blockDirty(b);
    memmove(score, b->score, VtScoreSize);
    if(p->l.type == BtDir) {
        memmove(e->score, b->score, VtScoreSize);
        entryPack(e, p->data, index);
        blockDependency(p, b, index, nil, &oe);
    } else {
        memmove(oscore, p->data+index*VtScoreSize, VtScoreSize);
        memmove(p->data+index*VtScoreSize, b->score, VtScoreSize);
        blockDependency(p, b, index, oscore, nil);
    }
    blockDirty(p);

    if(addr != NilBlock)
        blockRemoveLink(p, addr, type, e->tag, 0);

    return b;
}