code: mafs

Download patch

ref: b0b3ed10547c57a781c4e72b995cfbabe4cc476e
parent: 4bcd3cda781639d1ac322363b603b5a20f92ac37
author: 9ferno <gophone2015@gmail.com>
date: Sun Nov 6 12:47:51 EST 2022

programs to update /adm/frees contents

--- a/9p.c
+++ b/9p.c
@@ -915,6 +915,8 @@
 	if(chatty9p > 1)
 		dprint("shutdown: exiting\n");
 	/* chkqunlock(&superlock); exit while holding the lock */
+
+	close(devfd);
 }
 
 void
--- a/TODO
+++ b/TODO
@@ -9,6 +9,7 @@
 	RWlock is better than the Qlock. Just need to enforce it better.
 file system checker
 	fsck will be a different user space program
+	update /adm/frees block from disk/used
 EXCL files - maintain a list of locks in the tree
 APPEND files
 ORCLOSE
@@ -19,6 +20,7 @@
 test -A announce
 Split out the Free Blocks - Extents section in the document.
 Add a section on sizing npendingwrites
+	((ups time in seconds )/2) * (diskspeed in bytes/second) / Rawblocksize
 Clean up the Iobuf locking description
 man/mafs.4 man/mafs.8
 	Add EXAMPLES
--- a/block.c
+++ b/block.c
@@ -48,5 +48,6 @@
 
 	devread(blkno, buf);
 	showblock(1, buf);
+	close(devfd);
 	exits(0);
 }
--- a/extents.c
+++ b/extents.c
@@ -218,7 +218,7 @@
 	}
 
 	/* using the previously used extent */
-	e = es->lru;
+	eprev = e = es->lru;
 	dir = belongs(es->lru, start, len);
 	if(chatty9p > 7){
 		print(" 	belongs(e %llud %llud start %llud .. %llud) %lld\n",
--- a/free.c
+++ b/free.c
@@ -54,6 +54,7 @@
 	getfrees(Bdfrees);
 // showextents("after getfrees", &frees);
 	showblocknos(1, &frees);
+	close(devfd);
 	exits(0);
 }
 
--- a/mkfile
+++ b/mkfile
@@ -1,6 +1,6 @@
 </$objtype/mkfile
 
-TARG=mafs used reconcile block find free
+TARG=mafs used reconcile block find free unused updatefrees
 
 OFILES=\
 	9p.$O\
@@ -34,6 +34,12 @@
 </sys/src/cmd/mkmany
 
 # LDFLAGS=-p
+
+$O.updatefrees:	blk.$O dat.$O dev.$O misc.$O updatefrees.$O
+	$LD $LDFLAGS -o $target $prereq
+
+$O.unused:	dat.$O dev.$O extents.$O unused.$O misc.$O
+	$LD $LDFLAGS -o $target $prereq
 
 $O.used:	blk.$O dat.$O dev.$O misc.$O used.$O
 	$LD $LDFLAGS -o $target $prereq
--- a/reconcile.c
+++ b/reconcile.c
@@ -43,7 +43,7 @@
 };
 typedef struct Stream Stream;
 
-void init(Stream *s);
+static void init(Stream *s);
 void collect(Stream * s);
 void *emalloc(u32);
 s8 *estrdup(s8 *);
@@ -136,7 +136,7 @@
 	print("\n");
 }
 
-void
+static void
 init(Stream *s)
 {
 	s->buf = emalloc(MiB);
--- a/tests/check.rc
+++ b/tests/check.rc
@@ -24,3 +24,6 @@
 # reconcile the used and free blocks
 echo reconcile $disk $nblocks
 disk/reconcile -u <{disk/used $disk} -F <{disk/free $disk} $nblocks
+
+diff <{disk/unused -l <{disk/used $disk} $nblocks}} \
+	 <{disk/free $disk}
--- /dev/null
+++ b/unused.c
@@ -1,0 +1,157 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "extents.h"
+#include <bio.h>
+
+/*
+	indentify block numbers that are not used.
+	These blocks can be used to update /adm/frees as they are free to use.
+
+	watch -e '6\.unused' 'date; ./6.unused -D <{seq 1 1 3; seq 5 1 6} 7 '
+
+	disk/unused -D <{seq 1 1 3; seq 5 1 6} 7
+collect used +1 +2 +3 +5 +6
+show used
+	1 .. 3
+	5 .. 6
+show unused
+	3 .. 5
+
+	disk/unused `{disk/used /dev/sdF1/fs} \
+	`{dd -if /dev/sdF1/fs -bs 512 -iseek 1 -count 1 -quiet 1 | awk '$1 == "nblocks" { print $2 }'}
+
+	# this crashes the rc window, too much memory?
+	disk/unused `{disk/used /dev/sdF1/fs} 11721040049
+
+	disk/used /dev/sdF1/fs > /mnt/term/tmp/used.blocks
+	sort -n /mnt/term/tmp/used.blocks -o /mnt/term/tmp/used.blocks.sorted
+	disk/unused /mnt/term/tmp/used.blocks.sorted 11721040049
+
+	diff <{ disk/unused -l <{disk/used tests/test.0/disk} 32} <{ disk/free tests/test.0/disk }
+ */
+
+enum {
+	FileNameLen = KiB,
+};
+
+int debug = 0;
+int chatty9p = 0;
+
+struct Stream {
+	struct Extents *es;
+	Biobufhdr bp;
+	int fd;
+	s8 *buf;
+	char *file;
+	s8 name[32];
+};
+typedef struct Stream Stream;
+
+static void init(Stream *s);
+void collect(Stream * s);
+void *emalloc(u32);
+s8 *estrdup(s8 *);
+void show(Stream * s);
+s8 find(Extents *es, u64 bno);
+void common(Stream *u, Stream *f);
+void missing(u64 nblocks, Stream *u, Stream *f);
+
+static void
+usage(void)
+{
+	fprint(2, "usage: unused -l [-D ] list_of_used_blocks_file nblocks\n");
+	exits("usage");
+}
+
+void
+main(int argc, char *argv[])
+{
+	Stream u;	/* u = used */
+	struct Extents unused;
+	u64 nblocks, i;
+	int listblocks = 0;
+
+	ARGBEGIN{
+	default:	usage();
+	case 'D':	chatty9p = ++debug;	break;
+	case 'l':	listblocks++;		break;
+	}ARGEND
+
+	if(argc != 2)
+		usage();
+
+	u.file = estrdup(argv[0]);
+	nblocks = atoll(argv[1]);
+
+	if(u.file == nil)
+		sysfatal("no used file");
+	if(nblocks == 0)
+		sysfatal("nblocks == 0");
+
+	strncpy(u.name, "used", 32);
+	init(&u);
+
+	collect(&u);
+	if(debug)
+		show(&u);
+
+	/* identify unused blocks */
+	initextents(&unused);
+	for(i = 0; i < nblocks; i++){
+		if(find(u.es, i) == 0){
+			add(&unused, i, 1);
+		}
+	}
+	if(listblocks)
+		showblocknos(1, &unused);
+	else
+		showextents(1, "", &unused);
+
+	/* why bother? just exits(nil) as cinap suggests */
+	Bterm(&u.bp);
+	free(u.buf);
+	close(u.fd);
+	exits(nil);
+}
+
+static void
+init(Stream *s)
+{
+	s->buf = emalloc(MiB);
+	s->fd = open(s->file, OREAD);
+	if(Binits(&s->bp, s->fd, OREAD, (u8*)s->buf, MiB) == Beof)
+		sysfatal
+		    ("%s: Binits on msin failed: status code: Beof, errstr: %r",
+		     argv0);
+	Blethal(&s->bp, nil);
+}
+
+void
+collect(Stream * s)
+{
+	u64 bno;
+
+	if(debug)
+		print("collect %s ", s->name);
+	s->es = emalloc(sizeof(Extents));
+	initextents(s->es);
+	while((s->buf = Brdstr(&s->bp, '\n', 1)) != nil) {
+		bno = atoll(s->buf);
+		add(s->es, bno, 1);
+// show(s);
+	}
+	if(debug)
+		print("\n");
+}
+
+void
+show(Stream * s)
+{
+	print("show %s\n", s->name);
+	if(s == nil || s->es == nil){
+		print("nil\n");
+		return;
+	}
+	showextents(1, "show stream: ", s->es);
+}
--- /dev/null
+++ b/updatefrees.c
@@ -1,0 +1,98 @@
+#include <u.h>
+#include <libc.h>
+#include "dat.h"
+#include "fns.h"
+
+/*
+	update /adm/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
+ */
+
+int debug = 0;
+char *devfile = nil, *freesfile = nil;
+
+static void
+usage(void)
+{
+	fprint(2, "usage: updatefrees [-D] fsfile freecontentfile\n");
+	exits("usage");
+}
+
+void
+main(int argc, char *argv[])
+{
+	u64 size, freeblkno;
+	s32 nfreesize;
+	u8 buf[Rawblocksize], frees[Rawblocksize];
+	int fd;
+	Content *c;
+
+	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,Rawblocksize);
+	memset(frees, 0, Rawblocksize);
+
+	fd = open(freesfile, OREAD);
+	if(fd < 0)
+		sysfatal("updatefrees: cannot open freesfile %s\n", freesfile);
+
+	nfreesize = read(fd, frees, Rawblocksize);
+	if(nfreesize <= 0)
+		sysfatal("updatefrees: nfreesize %d <= 0\n", nfreesize);
+	if(nfreesize > Blocksize)
+		sysfatal("updatefrees: unsupported nfreesize %d > Blocksize %llud\n",
+					nfreesize, Blocksize);
+	close(fd);
+
+	freeblkno = atoll((s8*)frees);
+
+	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("Dentry1 size %d Namelen %llud\n", sizeof(Dentry1), Namelen);
+		print("Dentry size %d\n", sizeof(Dentry));
+	}
+
+	devread(Bdfrees, buf);
+	// showblock(1, buf);
+
+	c = (Content*)buf;
+	if(c->d.size != nfreesize)
+		print("changed size: %llud to %d\n", c->d.size, nfreesize);
+	c->d.size = nfreesize;
+	if(c->d.dblocks[0] != freeblkno)
+		print("changed dblocks[0]: %llud to %llud\n", c->d.dblocks[0], freeblkno);
+	c->d.dblocks[0] = freeblkno;
+
+	c = (Content*)frees;
+	c->type = Tdata;
+	c->path = Qpfrees;
+
+	devwrite(Bdfrees, buf);
+	devwrite(freeblkno, frees);
+
+	close(devfd);
+	exits(0);
+}
--- a/used.c
+++ b/used.c
@@ -50,6 +50,7 @@
 
 	checkblock(Bmagicb, Tmagic, Qpmagic);
 	walkdentry(Broot);
+	close(devfd);
 	exits(0);
 }