aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/venti/part.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/venti/part.c')
-rw-r--r--src/cmd/venti/part.c130
1 files changed, 130 insertions, 0 deletions
diff --git a/src/cmd/venti/part.c b/src/cmd/venti/part.c
new file mode 100644
index 00000000..dbf7b860
--- /dev/null
+++ b/src/cmd/venti/part.c
@@ -0,0 +1,130 @@
+#include "stdinc.h"
+#include "dat.h"
+#include "fns.h"
+
+u32int maxblocksize;
+int readonly;
+
+Part*
+initpart(char *name, int writable)
+{
+ Part *part;
+ Dir *dir;
+ int how;
+
+ part = MK(Part);
+ part->name = estrdup(name);
+ if(!writable && readonly)
+ how = OREAD;
+ else
+ how = ORDWR;
+ part->fd = open(name, how);
+ if(part->fd < 0){
+ if(how == ORDWR)
+ part->fd = open(name, OREAD);
+ if(part->fd < 0){
+ freepart(part);
+ seterr(EOk, "can't open partition='%s': %r", name);
+ return nil;
+ }
+ fprint(2, "warning: %s opened for reading only\n", name);
+ }
+ dir = dirfstat(part->fd);
+ if(dir == nil){
+ freepart(part);
+ seterr(EOk, "can't stat partition='%s': %r", name);
+ return nil;
+ }
+ part->size = dir->length;
+ part->blocksize = 0;
+ free(dir);
+ return part;
+}
+
+void
+freepart(Part *part)
+{
+ if(part == nil)
+ return;
+ close(part->fd);
+ free(part->name);
+ free(part);
+}
+
+void
+partblocksize(Part *part, u32int blocksize)
+{
+ if(part->blocksize)
+ sysfatal("resetting partition=%s's block size", part->name);
+ part->blocksize = blocksize;
+ if(blocksize > maxblocksize)
+ maxblocksize = blocksize;
+}
+
+int
+writepart(Part *part, u64int addr, u8int *buf, u32int n)
+{
+ long m, mm, nn;
+
+ qlock(&stats.lock);
+ stats.diskwrites++;
+ stats.diskbwrites += n;
+ qunlock(&stats.lock);
+
+ if(addr > part->size || addr + n > part->size){
+ seterr(ECorrupt, "out of bounds write to partition='%s'", part->name);
+ return -1;
+ }
+ print("write %s %lud at %llud\n", part->name, n, addr);
+ for(nn = 0; nn < n; nn += m){
+ mm = n - nn;
+ if(mm > MaxIo)
+ mm = MaxIo;
+ m = pwrite(part->fd, &buf[nn], mm, addr + nn);
+ if(m != mm){
+ if(m < 0){
+ seterr(EOk, "can't write partition='%s': %r", part->name);
+ return -1;
+ }
+ logerr(EOk, "truncated write to partition='%s' n=%ld wrote=%ld", part->name, mm, m);
+ }
+ }
+ return 0;
+}
+
+int
+readpart(Part *part, u64int addr, u8int *buf, u32int n)
+{
+ long m, mm, nn;
+ int i;
+
+ qlock(&stats.lock);
+ stats.diskreads++;
+ stats.diskbreads += n;
+ qunlock(&stats.lock);
+
+ if(addr > part->size || addr + n > part->size){
+ seterr(ECorrupt, "out of bounds read from partition='%s': addr=%lld n=%d size=%lld", part->name, addr, n, part->size);
+ return -1;
+ }
+ print("read %s %lud at %llud\n", part->name, n, addr);
+ for(nn = 0; nn < n; nn += m){
+ mm = n - nn;
+ if(mm > MaxIo)
+ mm = MaxIo;
+ m = -1;
+ for(i=0; i<4; i++) {
+ m = pread(part->fd, &buf[nn], mm, addr + nn);
+ if(m == mm)
+ break;
+ }
+ if(m != mm){
+ if(m < 0){
+ seterr(EOk, "can't read partition='%s': %r", part->name);
+ return -1;
+ }
+ logerr(EOk, "warning: truncated read from partition='%s' n=%ld read=%ld", part->name, mm, m);
+ }
+ }
+ return 0;
+}