Plan 9 from Bell Labs’s /usr/web/sources/contrib/blstuart/θfs/free.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


/*
 * 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 {
	Falloc = 1,
	Ffree,
};

typedef struct Freereq Freereq;

struct Freereq {
	int req;
	uvlong blk;
	Channel *resp;
};

static uvlong firstfree;
static Channel *freechan;

static void
_allocblock(Freereq *r)
{
	uchar *p, *tfree;
	vlong ff, fb, i;
	int blk, bit;
	int j, x;

	ff = firstfree;
	fb = firstfree / (8 * BlkSize);
	tfree = cbread(fb + super.freemap);
	blk = (firstfree / 8) % BlkSize;
	bit = firstfree & 7;
	tfree[blk] &= ~(1 << bit);
	cbwrite(fb + super.freemap);
	p = nil; 		/* make the compiler happy */
	for(i = fb; i < super.nfreemap; ++i) {
		for(p = tfree; p < tfree + BlkSize && *p == 0; ++p) ;
		if(p < tfree + BlkSize)
			break;
		brelease(i + super.freemap);
		tfree = cbread(i + 1 + super.freemap);
	}
	if(i >= super.nfreemap)
		sysfatal("No free space");
	brelease(i + super.freemap);
	for(j = 0, x = *p; j < 8 && (x&1) == 0; ++j, x >>= 1) ;
	firstfree = 8 * (i * BlkSize + (p - tfree)) + j;
	--super.nfree;
	send(r->resp, &ff);
}

static void
_freeblock(Freereq *r)
{
	uchar *tfree;
	vlong fb;
	int blk, bit;

	if(!ccanfree(r->blk)) {
		fprint(2, "wanting to free active block\n");
		return;
	}
	blk = (r->blk / 8) % BlkSize;
	bit = r->blk & 7;
	fb = r->blk / (8 * BlkSize);
	tfree = cbread(fb + super.freemap);
	if(tfree == 0) {
		fprint(2, "invalid free block: fb:%lld freemap:%ulld\n", fb, super.freemap);
		return;
	}
	tfree[blk] |= 1 << bit;
	cbwrite(fb + super.freemap);
	brelease(fb + super.freemap);
	++super.nfree;
	if(r->blk < firstfree)
		firstfree = r->blk;
}

static void
handler(void *)
{
	Freereq r;

	while(1) {
		if(recv(freechan, &r) == 0) {
			if(shutdown)
				threadexits(nil);
			continue;
		}
		switch(r.req) {
		case Falloc:
			_allocblock(&r);
			break;
		case Ffree:
			_freeblock(&r);
			break;
		}
	}
}

void
initfree(void)
{
	uchar *p, *tfree;
	vlong i;
	int j, x;

	p = nil;		/* make the compiler happy */
	tfree = nil;
	for(i = 0; i < super.nfreemap; ++i) {
		tfree = cbread(i + super.freemap);
		for(p = tfree; p < tfree + BlkSize && *p == 0; ++p) ;
		if(p < tfree + BlkSize)
			break;
		brelease(i + super.freemap);
	}
	if(i >= super.nfreemap)
		sysfatal("No free space");
	for(j = 0, x = *p; j < 8 && (x&1) == 0; ++j, x >>= 1) ;
	firstfree = 8 * (i * BlkSize + (p - tfree)) + j;
	brelease(i + super.freemap);
	freechan = chancreate(sizeof(Freereq), 2);
	threadcreate(handler, nil, 8192);
}

void
haltfree(void)
{
/*	chanclose(freechan); */
}

uvlong
allocblock(void)
{
	Freereq r;
	uvlong blk;

	r.req = Falloc;
	r.resp = chancreate(sizeof(uvlong), 0);
	send(freechan, &r);
	recv(r.resp, &blk);
	chanfree(r.resp);
	return blk;
}

void
freeblock(uvlong block)
{
	Freereq r;

	if(block < super.firstdat || block > super.nblk) {
		fprint(2, "Bogus block in free from %p: %ulld\n", getcallerpc(&block), block);
		return;
	}
	r.req = Ffree;
	r.blk = block;
	send(freechan, &r);
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].