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);
}