1*01a344a2SDavid du Colombier #include "all.h"
2*01a344a2SDavid du Colombier
3*01a344a2SDavid du Colombier Dentry*
getdir(Iobuf * p,int slot)4*01a344a2SDavid du Colombier getdir(Iobuf *p, int slot)
5*01a344a2SDavid du Colombier {
6*01a344a2SDavid du Colombier if(!p)
7*01a344a2SDavid du Colombier return 0;
8*01a344a2SDavid du Colombier return (Dentry*)p->iobuf + slot%DIRPERBUF;
9*01a344a2SDavid du Colombier }
10*01a344a2SDavid du Colombier
11*01a344a2SDavid du Colombier void
accessdir(Iobuf * p,Dentry * d,int f,int uid)12*01a344a2SDavid du Colombier accessdir(Iobuf *p, Dentry *d, int f, int uid)
13*01a344a2SDavid du Colombier {
14*01a344a2SDavid du Colombier Timet t;
15*01a344a2SDavid du Colombier
16*01a344a2SDavid du Colombier if(p && p->dev->type != Devro) {
17*01a344a2SDavid du Colombier p->flags |= Bmod;
18*01a344a2SDavid du Colombier t = time(nil);
19*01a344a2SDavid du Colombier if(f & (FREAD|FWRITE))
20*01a344a2SDavid du Colombier d->atime = t;
21*01a344a2SDavid du Colombier if(f & FWRITE) {
22*01a344a2SDavid du Colombier d->mtime = t;
23*01a344a2SDavid du Colombier d->muid = uid;
24*01a344a2SDavid du Colombier d->qid.version++;
25*01a344a2SDavid du Colombier }
26*01a344a2SDavid du Colombier }
27*01a344a2SDavid du Colombier }
28*01a344a2SDavid du Colombier
29*01a344a2SDavid du Colombier void
preread(Device * d,Off addr)30*01a344a2SDavid du Colombier preread(Device *d, Off addr)
31*01a344a2SDavid du Colombier {
32*01a344a2SDavid du Colombier Rabuf *rb;
33*01a344a2SDavid du Colombier
34*01a344a2SDavid du Colombier if(addr == 0)
35*01a344a2SDavid du Colombier return;
36*01a344a2SDavid du Colombier if(raheadq->count+10 >= raheadq->size) /* ugly knowing layout */
37*01a344a2SDavid du Colombier return;
38*01a344a2SDavid du Colombier lock(&rabuflock);
39*01a344a2SDavid du Colombier rb = rabuffree;
40*01a344a2SDavid du Colombier if(rb == 0) {
41*01a344a2SDavid du Colombier unlock(&rabuflock);
42*01a344a2SDavid du Colombier return;
43*01a344a2SDavid du Colombier }
44*01a344a2SDavid du Colombier rabuffree = rb->link;
45*01a344a2SDavid du Colombier unlock(&rabuflock);
46*01a344a2SDavid du Colombier rb->dev = d;
47*01a344a2SDavid du Colombier rb->addr = addr;
48*01a344a2SDavid du Colombier fs_send(raheadq, rb);
49*01a344a2SDavid du Colombier }
50*01a344a2SDavid du Colombier
51*01a344a2SDavid du Colombier Off
rel2abs(Iobuf * p,Dentry * d,Off a,int tag,int putb,int uid)52*01a344a2SDavid du Colombier rel2abs(Iobuf *p, Dentry *d, Off a, int tag, int putb, int uid)
53*01a344a2SDavid du Colombier {
54*01a344a2SDavid du Colombier int i;
55*01a344a2SDavid du Colombier Off addr, qpath, indaddrs = 1, div;
56*01a344a2SDavid du Colombier Device *dev;
57*01a344a2SDavid du Colombier
58*01a344a2SDavid du Colombier if(a < 0) {
59*01a344a2SDavid du Colombier print("rel2abs: neg offset\n");
60*01a344a2SDavid du Colombier if(putb)
61*01a344a2SDavid du Colombier putbuf(p);
62*01a344a2SDavid du Colombier return 0;
63*01a344a2SDavid du Colombier }
64*01a344a2SDavid du Colombier dev = p->dev;
65*01a344a2SDavid du Colombier qpath = d->qid.path;
66*01a344a2SDavid du Colombier
67*01a344a2SDavid du Colombier /* is `a' a direct block? */
68*01a344a2SDavid du Colombier if(a < NDBLOCK) {
69*01a344a2SDavid du Colombier addr = d->dblock[a];
70*01a344a2SDavid du Colombier if(!addr && tag) {
71*01a344a2SDavid du Colombier addr = bufalloc(dev, tag, qpath, uid);
72*01a344a2SDavid du Colombier d->dblock[a] = addr;
73*01a344a2SDavid du Colombier p->flags |= Bmod|Bimm;
74*01a344a2SDavid du Colombier }
75*01a344a2SDavid du Colombier if(putb)
76*01a344a2SDavid du Colombier putbuf(p);
77*01a344a2SDavid du Colombier return addr;
78*01a344a2SDavid du Colombier }
79*01a344a2SDavid du Colombier a -= NDBLOCK;
80*01a344a2SDavid du Colombier
81*01a344a2SDavid du Colombier /*
82*01a344a2SDavid du Colombier * loop through indirect block depths.
83*01a344a2SDavid du Colombier */
84*01a344a2SDavid du Colombier for (i = 0; i < NIBLOCK; i++) {
85*01a344a2SDavid du Colombier indaddrs *= INDPERBUF;
86*01a344a2SDavid du Colombier /* is a's disk addr in this indir block or one of its kids? */
87*01a344a2SDavid du Colombier if (a < indaddrs) {
88*01a344a2SDavid du Colombier addr = d->iblocks[i];
89*01a344a2SDavid du Colombier if(!addr && tag) {
90*01a344a2SDavid du Colombier addr = bufalloc(dev, Tind1+i, qpath, uid);
91*01a344a2SDavid du Colombier d->iblocks[i] = addr;
92*01a344a2SDavid du Colombier p->flags |= Bmod|Bimm;
93*01a344a2SDavid du Colombier }
94*01a344a2SDavid du Colombier if(putb)
95*01a344a2SDavid du Colombier putbuf(p);
96*01a344a2SDavid du Colombier
97*01a344a2SDavid du Colombier div = indaddrs;
98*01a344a2SDavid du Colombier for (; i >= 0; i--) {
99*01a344a2SDavid du Colombier div /= INDPERBUF;
100*01a344a2SDavid du Colombier if (div <= 0)
101*01a344a2SDavid du Colombier panic("rel2abs: non-positive divisor");
102*01a344a2SDavid du Colombier addr = indfetch(dev, qpath, addr,
103*01a344a2SDavid du Colombier (a/div)%INDPERBUF, Tind1+i,
104*01a344a2SDavid du Colombier (i == 0? tag: Tind1+i-1), uid);
105*01a344a2SDavid du Colombier }
106*01a344a2SDavid du Colombier return addr;
107*01a344a2SDavid du Colombier }
108*01a344a2SDavid du Colombier a -= indaddrs;
109*01a344a2SDavid du Colombier }
110*01a344a2SDavid du Colombier if(putb)
111*01a344a2SDavid du Colombier putbuf(p);
112*01a344a2SDavid du Colombier
113*01a344a2SDavid du Colombier /* quintuple-indirect blocks not implemented. */
114*01a344a2SDavid du Colombier print("rel2abs: no %d-deep indirect\n", NIBLOCK+1);
115*01a344a2SDavid du Colombier return 0;
116*01a344a2SDavid du Colombier }
117*01a344a2SDavid du Colombier
118*01a344a2SDavid du Colombier /*
119*01a344a2SDavid du Colombier * read-ahead strategy
120*01a344a2SDavid du Colombier * on second block, read RAGAP blocks,
121*01a344a2SDavid du Colombier * thereafter, read RAGAP ahead of current pos
122*01a344a2SDavid du Colombier */
123*01a344a2SDavid du Colombier Off
dbufread(Iobuf * p,Dentry * d,Off a,Off ra,int uid)124*01a344a2SDavid du Colombier dbufread(Iobuf *p, Dentry *d, Off a, Off ra, int uid)
125*01a344a2SDavid du Colombier {
126*01a344a2SDavid du Colombier Off addr;
127*01a344a2SDavid du Colombier
128*01a344a2SDavid du Colombier if(a == 0)
129*01a344a2SDavid du Colombier return 1;
130*01a344a2SDavid du Colombier if(a == 1 && ra == 1) {
131*01a344a2SDavid du Colombier while(ra < a+RAGAP) {
132*01a344a2SDavid du Colombier ra++;
133*01a344a2SDavid du Colombier addr = rel2abs(p, d, ra, 0, 0, uid);
134*01a344a2SDavid du Colombier if(!addr)
135*01a344a2SDavid du Colombier return 0;
136*01a344a2SDavid du Colombier preread(p->dev, addr);
137*01a344a2SDavid du Colombier }
138*01a344a2SDavid du Colombier return ra+1;
139*01a344a2SDavid du Colombier }
140*01a344a2SDavid du Colombier if(ra == a+RAGAP) {
141*01a344a2SDavid du Colombier addr = rel2abs(p, d, ra, 0, 0, uid);
142*01a344a2SDavid du Colombier if(!addr)
143*01a344a2SDavid du Colombier return 0;
144*01a344a2SDavid du Colombier preread(p->dev, addr);
145*01a344a2SDavid du Colombier return ra+1;
146*01a344a2SDavid du Colombier }
147*01a344a2SDavid du Colombier return ra;
148*01a344a2SDavid du Colombier }
149*01a344a2SDavid du Colombier
150*01a344a2SDavid du Colombier Iobuf*
dnodebuf(Iobuf * p,Dentry * d,Off a,int tag,int uid)151*01a344a2SDavid du Colombier dnodebuf(Iobuf *p, Dentry *d, Off a, int tag, int uid)
152*01a344a2SDavid du Colombier {
153*01a344a2SDavid du Colombier Off addr;
154*01a344a2SDavid du Colombier
155*01a344a2SDavid du Colombier addr = rel2abs(p, d, a, tag, 0, uid);
156*01a344a2SDavid du Colombier if(addr)
157*01a344a2SDavid du Colombier return getbuf(p->dev, addr, Brd);
158*01a344a2SDavid du Colombier return 0;
159*01a344a2SDavid du Colombier }
160*01a344a2SDavid du Colombier
161*01a344a2SDavid du Colombier /*
162*01a344a2SDavid du Colombier * same as dnodebuf but it calls putbuf(p)
163*01a344a2SDavid du Colombier * to reduce interference.
164*01a344a2SDavid du Colombier */
165*01a344a2SDavid du Colombier Iobuf*
dnodebuf1(Iobuf * p,Dentry * d,Off a,int tag,int uid)166*01a344a2SDavid du Colombier dnodebuf1(Iobuf *p, Dentry *d, Off a, int tag, int uid)
167*01a344a2SDavid du Colombier {
168*01a344a2SDavid du Colombier Off addr;
169*01a344a2SDavid du Colombier Device *dev;
170*01a344a2SDavid du Colombier
171*01a344a2SDavid du Colombier dev = p->dev;
172*01a344a2SDavid du Colombier addr = rel2abs(p, d, a, tag, 1, uid);
173*01a344a2SDavid du Colombier if(addr)
174*01a344a2SDavid du Colombier return getbuf(dev, addr, Brd);
175*01a344a2SDavid du Colombier return 0;
176*01a344a2SDavid du Colombier
177*01a344a2SDavid du Colombier }
178*01a344a2SDavid du Colombier
179*01a344a2SDavid du Colombier Off
indfetch(Device * d,Off qpath,Off addr,Off a,int itag,int tag,int uid)180*01a344a2SDavid du Colombier indfetch(Device* d, Off qpath, Off addr, Off a, int itag, int tag, int uid)
181*01a344a2SDavid du Colombier {
182*01a344a2SDavid du Colombier Iobuf *bp;
183*01a344a2SDavid du Colombier
184*01a344a2SDavid du Colombier if(!addr)
185*01a344a2SDavid du Colombier return 0;
186*01a344a2SDavid du Colombier bp = getbuf(d, addr, Brd);
187*01a344a2SDavid du Colombier if(!bp || checktag(bp, itag, qpath)) {
188*01a344a2SDavid du Colombier if(!bp) {
189*01a344a2SDavid du Colombier print("ind fetch bp = 0\n");
190*01a344a2SDavid du Colombier return 0;
191*01a344a2SDavid du Colombier }
192*01a344a2SDavid du Colombier print("ind fetch tag\n");
193*01a344a2SDavid du Colombier putbuf(bp);
194*01a344a2SDavid du Colombier return 0;
195*01a344a2SDavid du Colombier }
196*01a344a2SDavid du Colombier addr = ((Off *)bp->iobuf)[a];
197*01a344a2SDavid du Colombier if(!addr && tag) {
198*01a344a2SDavid du Colombier addr = bufalloc(d, tag, qpath, uid);
199*01a344a2SDavid du Colombier if(addr) {
200*01a344a2SDavid du Colombier ((Off *)bp->iobuf)[a] = addr;
201*01a344a2SDavid du Colombier bp->flags |= Bmod;
202*01a344a2SDavid du Colombier if(tag == Tdir)
203*01a344a2SDavid du Colombier bp->flags |= Bimm;
204*01a344a2SDavid du Colombier settag(bp, itag, qpath);
205*01a344a2SDavid du Colombier }
206*01a344a2SDavid du Colombier }
207*01a344a2SDavid du Colombier putbuf(bp);
208*01a344a2SDavid du Colombier return addr;
209*01a344a2SDavid du Colombier }
210*01a344a2SDavid du Colombier
211*01a344a2SDavid du Colombier /* return INDPERBUF^exp */
212*01a344a2SDavid du Colombier Off
ibbpow(int exp)213*01a344a2SDavid du Colombier ibbpow(int exp)
214*01a344a2SDavid du Colombier {
215*01a344a2SDavid du Colombier static Off pows[] = {
216*01a344a2SDavid du Colombier 1,
217*01a344a2SDavid du Colombier INDPERBUF,
218*01a344a2SDavid du Colombier (Off)INDPERBUF*INDPERBUF,
219*01a344a2SDavid du Colombier (Off)INDPERBUF*(Off)INDPERBUF*INDPERBUF,
220*01a344a2SDavid du Colombier (Off)INDPERBUF*(Off)INDPERBUF*(Off)INDPERBUF*INDPERBUF,
221*01a344a2SDavid du Colombier };
222*01a344a2SDavid du Colombier
223*01a344a2SDavid du Colombier if (exp < 0)
224*01a344a2SDavid du Colombier return 0;
225*01a344a2SDavid du Colombier else if (exp >= nelem(pows)) { /* not in table? do it long-hand */
226*01a344a2SDavid du Colombier Off indpow = 1;
227*01a344a2SDavid du Colombier
228*01a344a2SDavid du Colombier while (exp-- > 0 && indpow > 0)
229*01a344a2SDavid du Colombier indpow *= INDPERBUF;
230*01a344a2SDavid du Colombier return indpow;
231*01a344a2SDavid du Colombier } else
232*01a344a2SDavid du Colombier return pows[exp];
233*01a344a2SDavid du Colombier }
234*01a344a2SDavid du Colombier
235*01a344a2SDavid du Colombier /* return sum of INDPERBUF^n for 1 ≤ n ≤ exp */
236*01a344a2SDavid du Colombier Off
ibbpowsum(int exp)237*01a344a2SDavid du Colombier ibbpowsum(int exp)
238*01a344a2SDavid du Colombier {
239*01a344a2SDavid du Colombier Off indsum = 0;
240*01a344a2SDavid du Colombier
241*01a344a2SDavid du Colombier for (; exp > 0; exp--)
242*01a344a2SDavid du Colombier indsum += ibbpow(exp);
243*01a344a2SDavid du Colombier return indsum;
244*01a344a2SDavid du Colombier }
245*01a344a2SDavid du Colombier
246*01a344a2SDavid du Colombier /* zero bytes past new file length; return an error code */
247*01a344a2SDavid du Colombier int
trunczero(Truncstate * ts)248*01a344a2SDavid du Colombier trunczero(Truncstate *ts)
249*01a344a2SDavid du Colombier {
250*01a344a2SDavid du Colombier int blkoff = ts->newsize % BUFSIZE;
251*01a344a2SDavid du Colombier Iobuf *pd;
252*01a344a2SDavid du Colombier
253*01a344a2SDavid du Colombier pd = dnodebuf(ts->p, ts->d, ts->lastblk, Tfile, ts->uid);
254*01a344a2SDavid du Colombier if (pd == nil || checktag(pd, Tfile, QPNONE)) {
255*01a344a2SDavid du Colombier if (pd != nil)
256*01a344a2SDavid du Colombier putbuf(pd);
257*01a344a2SDavid du Colombier ts->err = Ephase;
258*01a344a2SDavid du Colombier return Ephase;
259*01a344a2SDavid du Colombier }
260*01a344a2SDavid du Colombier memset(pd->iobuf+blkoff, 0, BUFSIZE - blkoff);
261*01a344a2SDavid du Colombier putbuf(pd);
262*01a344a2SDavid du Colombier return 0;
263*01a344a2SDavid du Colombier }
264*01a344a2SDavid du Colombier
265*01a344a2SDavid du Colombier /*
266*01a344a2SDavid du Colombier * truncate d (in p) to length `newsize'.
267*01a344a2SDavid du Colombier * if larger, just increase size.
268*01a344a2SDavid du Colombier * if smaller, deallocate blocks after last one
269*01a344a2SDavid du Colombier * still in file at new size. last byte to keep
270*01a344a2SDavid du Colombier * is newsize-1, due to zero origin.
271*01a344a2SDavid du Colombier * we free in forward order because it's simpler to get right.
272*01a344a2SDavid du Colombier * if the final block at the new size is partially-filled,
273*01a344a2SDavid du Colombier * zero the remainder.
274*01a344a2SDavid du Colombier */
275*01a344a2SDavid du Colombier int
dtrunclen(Iobuf * p,Dentry * d,Off newsize,int uid)276*01a344a2SDavid du Colombier dtrunclen(Iobuf *p, Dentry *d, Off newsize, int uid)
277*01a344a2SDavid du Colombier {
278*01a344a2SDavid du Colombier int i, pastlast;
279*01a344a2SDavid du Colombier Truncstate trunc;
280*01a344a2SDavid du Colombier
281*01a344a2SDavid du Colombier if (newsize <= 0) {
282*01a344a2SDavid du Colombier dtrunc(p, d, uid);
283*01a344a2SDavid du Colombier return 0;
284*01a344a2SDavid du Colombier }
285*01a344a2SDavid du Colombier memset(&trunc, 0, sizeof trunc);
286*01a344a2SDavid du Colombier trunc.d = d;
287*01a344a2SDavid du Colombier trunc.p = p;
288*01a344a2SDavid du Colombier trunc.uid = uid;
289*01a344a2SDavid du Colombier trunc.newsize = newsize;
290*01a344a2SDavid du Colombier trunc.lastblk = newsize/BUFSIZE;
291*01a344a2SDavid du Colombier if (newsize % BUFSIZE == 0)
292*01a344a2SDavid du Colombier trunc.lastblk--;
293*01a344a2SDavid du Colombier else
294*01a344a2SDavid du Colombier trunczero(&trunc);
295*01a344a2SDavid du Colombier for (i = 0; i < NDBLOCK; i++)
296*01a344a2SDavid du Colombier if (trunc.pastlast) {
297*01a344a2SDavid du Colombier trunc.relblk = i;
298*01a344a2SDavid du Colombier buffree(p->dev, d->dblock[i], 0, &trunc);
299*01a344a2SDavid du Colombier d->dblock[i] = 0;
300*01a344a2SDavid du Colombier } else if (i == trunc.lastblk)
301*01a344a2SDavid du Colombier trunc.pastlast = 1;
302*01a344a2SDavid du Colombier trunc.relblk = NDBLOCK;
303*01a344a2SDavid du Colombier for (i = 0; i < NIBLOCK; i++) {
304*01a344a2SDavid du Colombier pastlast = trunc.pastlast;
305*01a344a2SDavid du Colombier buffree(p->dev, d->iblocks[i], i+1, &trunc);
306*01a344a2SDavid du Colombier if (pastlast)
307*01a344a2SDavid du Colombier d->iblocks[i] = 0;
308*01a344a2SDavid du Colombier }
309*01a344a2SDavid du Colombier
310*01a344a2SDavid du Colombier d->size = newsize;
311*01a344a2SDavid du Colombier p->flags |= Bmod|Bimm;
312*01a344a2SDavid du Colombier accessdir(p, d, FWRITE, uid);
313*01a344a2SDavid du Colombier return trunc.err;
314*01a344a2SDavid du Colombier }
315*01a344a2SDavid du Colombier
316*01a344a2SDavid du Colombier /*
317*01a344a2SDavid du Colombier * truncate d (in p) to zero length.
318*01a344a2SDavid du Colombier * freeing blocks in reverse order is traditional, from Unix,
319*01a344a2SDavid du Colombier * in an attempt to keep the free list contiguous.
320*01a344a2SDavid du Colombier */
321*01a344a2SDavid du Colombier void
dtrunc(Iobuf * p,Dentry * d,int uid)322*01a344a2SDavid du Colombier dtrunc(Iobuf *p, Dentry *d, int uid)
323*01a344a2SDavid du Colombier {
324*01a344a2SDavid du Colombier int i;
325*01a344a2SDavid du Colombier
326*01a344a2SDavid du Colombier for (i = NIBLOCK-1; i >= 0; i--) {
327*01a344a2SDavid du Colombier buffree(p->dev, d->iblocks[i], i+1, nil);
328*01a344a2SDavid du Colombier d->iblocks[i] = 0;
329*01a344a2SDavid du Colombier }
330*01a344a2SDavid du Colombier for (i = NDBLOCK-1; i >= 0; i--) {
331*01a344a2SDavid du Colombier buffree(p->dev, d->dblock[i], 0, nil);
332*01a344a2SDavid du Colombier d->dblock[i] = 0;
333*01a344a2SDavid du Colombier }
334*01a344a2SDavid du Colombier d->size = 0;
335*01a344a2SDavid du Colombier p->flags |= Bmod|Bimm;
336*01a344a2SDavid du Colombier accessdir(p, d, FWRITE, uid);
337*01a344a2SDavid du Colombier }
338