xref: /plan9/sys/src/cmd/disk/kfs/devwren.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
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