code: mafs

ref: 7038b412045ad003366804789e7fecaf0552f77c
dir: /updatefrees.c/

View raw version
#include <u.h>
#include <libc.h>
#include "dat.h"
#include "fns.h"
#include "extents.h"

/*
	update /a/frees

	disk/unused <{disk/used tests/test.0/disk} 32 | tr -d '	' > /mnt/term/tmp/unused.blocks
	cat /mnt/term/tmp/unused.blocks
	disk/updatefrees tests/test.0/disk /mnt/term/tmp/unused.blocks

	TODO
		does not work when the size of free extents > Maxdatablocksize
 */

int chatty9p;
int debug = 0;
char *devfile = nil, *freesfile = nil;

Extents frees = {0};
void *emalloc(u32);
void panic(char *fmt, ...);

static void
usage(void)
{
	fprint(2, "usage: updatefrees [-D] fsfile freecontentfile\n");
	exits("usage");
}

void
main(int argc, char *argv[])
{
	u64 size, freeblkno, nblocks;
	s32 nfreesize;
	s8 buf[Blocksize], freesdata[Maxdatablockunits*Blocksize];
	int fd;
	Data *f;
	Dentry *d;
	u64 *f64;
	Errenv env = {0};

	envpp = privalloc();
	*envpp = &env;
	if(waserror()){
		panic(0, "err stack %d: %lux %lux %lux %lux %lux %lux",
			env.nlabel,
			env.label[0][JMPBUFPC], env.label[1][JMPBUFPC],
			env.label[2][JMPBUFPC], env.label[3][JMPBUFPC],
			env.label[4][JMPBUFPC], env.label[5][JMPBUFPC]);
	}

	ARGBEGIN{
	default:	usage();
	case 'D':	debug++; break;
	}ARGEND

	if(argc != 2)
		usage();

	devfile = argv[0];
	if(devfile == nil)
		sysfatal("no disk file");

	freesfile = strdup(argv[1]);
	if(freesfile == nil)
		sysfatal("no frees file");

	memset(buf, 0, Blocksize);
	memset(freesdata, 0, Maxdatablockunits*Blocksize);
	f = (Data*)freesdata;
	f64 = (u64*)freesdata;

	fd = open(freesfile, OREAD);
	if(fd < 0)
		sysfatal("updatefrees: cannot open freesfile %s\n", freesfile);

	nfreesize = readn(fd, f->buf, Maxdatablocksize);
	if(nfreesize <= 0)
		sysfatal("updatefrees: nfreesize %d <= 0\n", nfreesize);
	if(nfreesize > (Maxdatablocksize -sizeof(Datahdr) -sizeof(u64 /* trailing path */)))
		sysfatal("updatefrees: unsupported nfreesize %d needs more than a block Datablocksize %llud\n",
					nfreesize, Maxdatablocksize -sizeof(Datahdr) -sizeof(u64 /* trailing path */));
	if(nfreesize >= Maxdatablocksize)
		sysfatal("updatefrees: unsupported nfreesize %d > Datablocksize %llud\n",
					nfreesize, Maxdatablocksize);
	close(fd);

	if (access(devfile, AREAD|AWRITE) == -1)
		sysfatal("%s cannot access device", devfile);

	size = devinit(devfile);
	if(size == 0)
		panic("null size %s", devfile);

	if(debug){
		print("Servicelen %d\n", Servicelen);
		print("Dentry size %d\n", sizeof(Dentry));
	}

	devread(Bdfrees, buf, 1);
	// showblock(1, buf);
	d = (Dentry*)buf;

	if(d->size != nfreesize)
		print("changed size: %llud to %d\n", d->size, nfreesize);
	memset(d->buf, 0, Ddatasize);
	d->size = nfreesize;
	if(nfreesize <= Ddatasize){
		strncpy(d->buf, (s8*)f->buf, nfreesize);
		devwrite(Bdfrees, buf, 1);
	}else{
		initextents(&frees, "frees", 0, 0, 2, nil, fprint, panic, emalloc);
		loadextents(&frees, (s8*)f->buf, nfreesize);
		nblocks = nlastdatablocks(nfreesize);
		 ualloc(&frees, nblocks, &freeblkno);

		d->dblocks[0] = freeblkno;
		f->tag = Tdata;
		f->len = nblocks;
		f64[nblocks*Nu64perblock -1] = Qpfrees;

		devwrite(Bdfrees, buf, 1);
		devwrite(freeblkno, (s8*)freesdata, nblocks);
	}
	close(devfd);
	exits(0);
}