xref: /plan9-contrib/sys/src/cmd/disk/kfs/devwren.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
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 	ulong	size;
15 	int	fd;
16 };
17 
18 static Wren	*wrens;
19 static int	maxwren;
20 char		*wrenfile;
21 int		badmagic;
22 
23 static Wren *
24 wren(Device dev)
25 {
26 	int i;
27 
28 	for(i = 0; i < maxwren; i++)
29 		if(devcmp(dev, wrens[i].dev) == 0)
30 			return &wrens[i];
31 	panic("can't find wren for %D", dev);
32 	return 0;
33 }
34 
35 /*
36  * find out the length of a file
37  * given the mesg version of a stat buffer
38  * we call this because convM2D is different
39  * for the file system than in the os
40  */
41 long
42 statlen(char *ap)
43 {
44 	uchar *p;
45 
46 	p = (uchar*)ap;
47 	p += 3*NAMELEN+5*4;
48 	return p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
49 }
50 
51 void
52 wreninit(Device dev)
53 {
54 	char buf[8*1024], d[DIRREC];
55 	Wren *w;
56 	int fd, i;
57 
58 	if(wrens == 0)
59 		wrens = ialloc(MAXWREN * sizeof *wrens);
60 	w = &wrens[maxwren];
61 	fd = open(wrenfile, ORDWR);
62 	if(fd < 0)
63 		panic("can't open %s", wrenfile);
64 	if(fstat(fd, d) < 0)
65 		panic("can't stat %s\n", wrenfile);
66 	seek(fd, 0, 0);
67 	i = read(fd, buf, sizeof buf);
68 	if(i < sizeof buf)
69 		panic("can't read %s", wrenfile);
70 	badmagic = 0;
71 	RBUFSIZE = 1024;
72 	if(strncmp(buf+256, WMAGIC, strlen(WMAGIC)) == 0){
73 		RBUFSIZE = atol(buf+256+strlen(WMAGIC));
74 		if(RBUFSIZE % 512){
75 			fprint(2, "kfs: bad buffersize(%d): assuming 1k blocks\n", RBUFSIZE);
76 			RBUFSIZE = 1024;
77 		}
78 	}else
79 		badmagic = 1;
80 	w->dev = dev;
81 	w->size = statlen(d);
82 	w->fd = fd;
83 	maxwren++;
84 }
85 
86 void
87 wrenream(Device dev)
88 {
89 	Wren *w;
90 	char buf[8*1024];
91 	int fd, i;
92 
93 	if(RBUFSIZE % 512)
94 		panic("kfs: bad buffersize(%d): restart a multiple of 512\n", RBUFSIZE);
95 	print("kfs: reaming the file system using %d byte blocks\n", RBUFSIZE);
96 	w = wren(dev);
97 	fd = w->fd;
98 	memset(buf, 0, sizeof buf);
99 	sprint(buf+256, "%s%d\n", WMAGIC, RBUFSIZE);
100 	qlock(w);
101 	i = seek(fd, 0, 0) < 0 || write(fd, buf, RBUFSIZE) != RBUFSIZE;
102 	qunlock(w);
103 	if(i < 0)
104 		panic("can't ream disk");
105 }
106 
107 int
108 wrentag(char *p, int tag, long qpath)
109 {
110 	Tag *t;
111 
112 	t = (Tag*)(p+BUFSIZE);
113 	return t->tag != tag || (qpath&~QPDIR) != t->path;
114 }
115 
116 int
117 wrencheck(Device dev)
118 {
119 	char buf[8*1024];
120 
121 	if(badmagic)
122 		return 1;
123 	if(RBUFSIZE > sizeof buf)
124 		panic("bufsize too big");
125 	if(wrenread(dev, wrensuper(dev), buf) || wrentag(buf, Tsuper, QPSUPER)
126 	|| wrenread(dev, wrenroot(dev), buf) || wrentag(buf, Tdir, QPROOT))
127 		return 1;
128 	if(((Dentry *)buf)[0].mode & DALLOC)
129 		return 0;
130 	return 1;
131 }
132 
133 long
134 wrensize(Device dev)
135 {
136 	return wren(dev)->size / RBUFSIZE;
137 }
138 
139 long
140 wrensuper(Device dev)
141 {
142 	USED(dev);
143 	return 1;
144 }
145 
146 long
147 wrenroot(Device dev)
148 {
149 	USED(dev);
150 	return 2;
151 }
152 
153 int
154 wrenread(Device dev, long addr, void *b)
155 {
156 	Wren *w;
157 	int fd, i;
158 
159 	w = wren(dev);
160 	fd = w->fd;
161 	qlock(w);
162 	i = seek(fd, addr*RBUFSIZE, 0) < 0 || read(fd, b, RBUFSIZE) != RBUFSIZE;
163 	qunlock(w);
164 	return i;
165 }
166 
167 int
168 wrenwrite(Device dev, long addr, void *b)
169 {
170 	Wren *w;
171 	int fd, i;
172 
173 	w = wren(dev);
174 	fd = w->fd;
175 	qlock(w);
176 	i = seek(fd, addr*RBUFSIZE, 0) < 0 || write(fd, b, RBUFSIZE) != RBUFSIZE;
177 	qunlock(w);
178 	return i;
179 }
180