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 *
wren(Device dev)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
wreninit(Device dev)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
wrenream(Device dev)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
wrentag(char * p,int tag,long qpath)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
wrencheck(Device dev)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
wrensize(Device dev)125 wrensize(Device dev)
126 {
127 return wren(dev)->size / RBUFSIZE;
128 }
129
130 long
wrensuper(Device dev)131 wrensuper(Device dev)
132 {
133 USED(dev);
134 return 1;
135 }
136
137 long
wrenroot(Device dev)138 wrenroot(Device dev)
139 {
140 USED(dev);
141 return 2;
142 }
143
144 int
wrenread(Device dev,long addr,void * b)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
wrenwrite(Device dev,long addr,void * b)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