1 #include "all.h" 2 3 enum{ 4 MAXWREN = 7, 5 }; 6 7 #define WMAGIC "kfs wren device\n" 8 9 typedef struct Wren Wren; 10 11 struct Wren{ 12 QLock; 13 Device dev; 14 uvlong size; 15 int fd; 16 }; 17 18 static Wren *wrens; 19 static int maxwren; 20 char *wrenfile; 21 int nwren; 22 int badmagic; 23 24 static Wren * 25 wren(Device dev) 26 { 27 int i; 28 29 for(i = 0; i < maxwren; i++) 30 if(devcmp(dev, wrens[i].dev) == 0) 31 return &wrens[i]; 32 panic("can't find wren for %D", dev); 33 return 0; 34 } 35 36 void 37 wreninit(Device dev) 38 { 39 char buf[MAXBUFSIZE]; 40 Wren *w; 41 Dir *d; 42 int fd, i; 43 44 if(wrens == 0) 45 wrens = ialloc(MAXWREN * sizeof *wrens); 46 w = &wrens[maxwren]; 47 fd = open(wrenfile, ORDWR); 48 if(fd < 0) 49 panic("can't open %s", wrenfile); 50 if((d = dirfstat(fd)) == nil) 51 panic("can't stat %s\n", wrenfile); 52 seek(fd, 0, 0); 53 i = read(fd, buf, sizeof buf); 54 if(i < sizeof buf) 55 panic("can't read %s", wrenfile); 56 badmagic = 0; 57 RBUFSIZE = 1024; 58 if(strncmp(buf+256, WMAGIC, strlen(WMAGIC)) == 0){ 59 RBUFSIZE = atol(buf+256+strlen(WMAGIC)); 60 if(RBUFSIZE % 512){ 61 fprint(2, "kfs: bad buffersize(%d): assuming 1k blocks\n", RBUFSIZE); 62 RBUFSIZE = 1024; 63 } 64 }else 65 badmagic = 1; 66 w->dev = dev; 67 w->size = d->length; 68 free(d); 69 w->fd = fd; 70 maxwren++; 71 } 72 73 void 74 wrenream(Device dev) 75 { 76 Wren *w; 77 char buf[MAXBUFSIZE]; 78 int fd, i; 79 80 if(RBUFSIZE % 512) 81 panic("kfs: bad buffersize(%d): restart a multiple of 512\n", RBUFSIZE); 82 if(RBUFSIZE > sizeof(buf)) 83 panic("kfs: bad buffersize(%d): must be at most %d\n", RBUFSIZE, sizeof(buf)); 84 85 print("kfs: reaming the file system using %d byte blocks\n", RBUFSIZE); 86 w = wren(dev); 87 fd = w->fd; 88 memset(buf, 0, sizeof buf); 89 sprint(buf+256, "%s%d\n", WMAGIC, RBUFSIZE); 90 qlock(w); 91 i = seek(fd, 0, 0) < 0 || write(fd, buf, RBUFSIZE) != RBUFSIZE; 92 qunlock(w); 93 if(i < 0) 94 panic("can't ream disk"); 95 } 96 97 int 98 wrentag(char *p, int tag, long qpath) 99 { 100 Tag *t; 101 102 t = (Tag*)(p+BUFSIZE); 103 return t->tag != tag || (qpath&~QPDIR) != t->path; 104 } 105 106 int 107 wrencheck(Device dev) 108 { 109 char buf[MAXBUFSIZE]; 110 111 if(badmagic) 112 return 1; 113 if(RBUFSIZE > sizeof(buf)) 114 panic("kfs: bad buffersize(%d): must be at most %d\n", RBUFSIZE, sizeof(buf)); 115 116 if(wrenread(dev, wrensuper(dev), buf) || wrentag(buf, Tsuper, QPSUPER) 117 || wrenread(dev, wrenroot(dev), buf) || wrentag(buf, Tdir, QPROOT)) 118 return 1; 119 if(((Dentry *)buf)[0].mode & DALLOC) 120 return 0; 121 return 1; 122 } 123 124 long 125 wrensize(Device dev) 126 { 127 return wren(dev)->size / RBUFSIZE; 128 } 129 130 long 131 wrensuper(Device dev) 132 { 133 USED(dev); 134 return 1; 135 } 136 137 long 138 wrenroot(Device dev) 139 { 140 USED(dev); 141 return 2; 142 } 143 144 int 145 wrenread(Device dev, long addr, void *b) 146 { 147 Wren *w; 148 int fd, i; 149 150 w = wren(dev); 151 fd = w->fd; 152 qlock(w); 153 i = seek(fd, (vlong)addr*RBUFSIZE, 0) == -1 || read(fd, b, RBUFSIZE) != RBUFSIZE; 154 qunlock(w); 155 if(i) 156 print("wrenread failed: %r\n"); 157 return i; 158 } 159 160 int 161 wrenwrite(Device dev, long addr, void *b) 162 { 163 Wren *w; 164 int fd, i; 165 166 w = wren(dev); 167 fd = w->fd; 168 qlock(w); 169 i = seek(fd, (vlong)addr*RBUFSIZE, 0) == -1 || write(fd, b, RBUFSIZE) != RBUFSIZE; 170 qunlock(w); 171 if(i) 172 print("wrenwrite failed: %r\n"); 173 return i; 174 } 175