1 #include "all.h" 2 3 enum{ 4 MAXWREN = 7, 5 }; 6 7 static char WMAGIC[] = "kfs wren device\n"; 8 static char MMAGIC[] = "kfs multi-wren device %4d/%4d\n"; 9 10 typedef struct Wren Wren; 11 12 struct Wren{ 13 QLock; 14 Device dev; 15 ulong nblocks; 16 int fd; 17 }; 18 19 static char *wmagic = WMAGIC; 20 static Wren *wrens; 21 static int maxwren; 22 char *wrenfile; 23 int nwren; 24 int badmagic; 25 26 static Wren * 27 wren(Device dev) 28 { 29 int i; 30 31 for(i = 0; i < maxwren; i++) 32 if(devcmp(dev, wrens[i].dev) == 0) 33 return &wrens[i]; 34 panic("can't find wren for %D", dev); 35 return 0; 36 } 37 38 /* 39 * find out the length of a file 40 * given the mesg version of a stat buffer 41 * we call this because convM2D is different 42 * for the file system than in the os 43 */ 44 uvlong 45 statlen(char *ap) 46 { 47 uchar *p; 48 ulong ll, hl; 49 50 p = (uchar*)ap; 51 p += 3*NAMELEN+5*4; 52 ll = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); 53 hl = p[4] | (p[5]<<8) | (p[6]<<16) | (p[7]<<24); 54 return ll | ((uvlong) hl << 32); 55 } 56 57 static void 58 wrenpartinit(Device dev, int k) 59 { 60 char buf[MAXBUFSIZE], d[DIRREC]; 61 char file[128], magic[64]; 62 Wren *w; 63 int fd, i, nmagic; 64 65 if(wrens == 0) 66 wrens = ialloc(MAXWREN * sizeof *wrens); 67 w = &wrens[maxwren]; 68 if(nwren > 0) 69 sprint(file, "%s%d", wrenfile, k); 70 else 71 strcpy(file, wrenfile); 72 fd = open(file, ORDWR); 73 if(fd < 0) 74 panic("can't open %s", file); 75 if(fstat(fd, d) < 0) 76 panic("can't stat %s\n", file); 77 seek(fd, 0, 0); 78 i = read(fd, buf, sizeof buf); 79 if(i < sizeof buf) 80 panic("can't read %s", file); 81 badmagic = 0; 82 RBUFSIZE = 1024; 83 sprint(magic, wmagic, k, nwren); 84 nmagic = strlen(magic); 85 if(strncmp(buf+256, magic, nmagic) == 0){ 86 RBUFSIZE = atol(buf+256+nmagic); 87 if(RBUFSIZE % 512){ 88 fprint(2, "kfs: bad buffersize(%d): assuming 1k blocks\n", RBUFSIZE); 89 RBUFSIZE = 1024; 90 } 91 }else 92 badmagic = 1; 93 w->dev = dev; 94 w->nblocks = statlen(d)/RBUFSIZE; 95 if(k > 0) 96 w->nblocks -= 1; /* don't count magic */ 97 w->fd = fd; 98 maxwren++; 99 } 100 101 void 102 wreninit(Device dev) 103 { 104 int i; 105 106 if(nwren > 0) 107 wmagic = MMAGIC; 108 i = 0; 109 do{ 110 wrenpartinit(dev, i); 111 }while(++i < nwren); 112 } 113 114 static void 115 wrenpartream(Device dev, int k) 116 { 117 Wren *w; 118 char buf[MAXBUFSIZE], magic[64]; 119 int fd, i; 120 121 if(RBUFSIZE % 512) 122 panic("kfs: bad buffersize(%d): restart a multiple of 512\n", RBUFSIZE); 123 print("kfs: reaming the file system using %d byte blocks\n", RBUFSIZE); 124 w = wren(dev)+k; 125 fd = w->fd; 126 memset(buf, 0, sizeof buf); 127 sprint(magic, wmagic, k, nwren); 128 sprint(buf+256, "%s%d\n", magic, RBUFSIZE); 129 qlock(w); 130 i = seek(fd, 0, 0) < 0 || write(fd, buf, RBUFSIZE) != RBUFSIZE; 131 qunlock(w); 132 if(i < 0) 133 panic("can't ream disk"); 134 } 135 136 void 137 wrenream(Device dev) 138 { 139 int i; 140 141 i = 0; 142 do{ 143 wrenpartream(dev, i); 144 }while(++i < nwren); 145 } 146 147 static int 148 wrentag(char *p, int tag, long qpath) 149 { 150 Tag *t; 151 152 t = (Tag*)(p+BUFSIZE); 153 return t->tag != tag || (qpath&~QPDIR) != t->path; 154 } 155 156 int 157 wrencheck(Device dev) 158 { 159 char buf[MAXBUFSIZE]; 160 161 if(badmagic) 162 return 1; 163 if(RBUFSIZE > sizeof buf) 164 panic("bufsize too big"); 165 if(wrenread(dev, wrensuper(dev), buf) || wrentag(buf, Tsuper, QPSUPER) 166 || wrenread(dev, wrenroot(dev), buf) || wrentag(buf, Tdir, QPROOT)) 167 return 1; 168 if(((Dentry *)buf)[0].mode & DALLOC) 169 return 0; 170 return 1; 171 } 172 173 long 174 wrensize(Device dev) 175 { 176 Wren *w; 177 int i, nb; 178 179 w = wren(dev); 180 nb = 0; 181 i = 0; 182 do{ 183 nb += w[i].nblocks; 184 }while(++i < nwren); 185 return nb; 186 } 187 188 long 189 wrensuper(Device dev) 190 { 191 USED(dev); 192 return 1; 193 } 194 195 long 196 wrenroot(Device dev) 197 { 198 USED(dev); 199 return 2; 200 } 201 202 int 203 wrenread(Device dev, long addr, void *b) 204 { 205 Wren *w; 206 int fd, i; 207 208 w = wren(dev); 209 for(i=0; i<nwren; i++){ 210 if(addr < w->nblocks) 211 break; 212 addr -= w->nblocks; 213 ++w; 214 } 215 if(i > 0) 216 addr++; 217 fd = w->fd; 218 qlock(w); 219 i = seek(fd, (vlong)addr*RBUFSIZE, 0) == -1 || read(fd, b, RBUFSIZE) != RBUFSIZE; 220 qunlock(w); 221 return i; 222 } 223 224 int 225 wrenwrite(Device dev, long addr, void *b) 226 { 227 Wren *w; 228 int fd, i; 229 230 w = wren(dev); 231 for(i=0; i<nwren; i++){ 232 if(addr < w->nblocks) 233 break; 234 addr -= w->nblocks; 235 ++w; 236 } 237 if(i > 0) 238 addr++; 239 fd = w->fd; 240 qlock(w); 241 i = seek(fd, (vlong)addr*RBUFSIZE, 0) == -1 || write(fd, b, RBUFSIZE) != RBUFSIZE; 242 qunlock(w); 243 return i; 244 } 245