4 getdir(Iobuf *p, int slot)
8 return (Dentry*)p->iobuf + slot%DIRPERBUF;
12 accessdir(Iobuf *p, Dentry *d, int f, int uid)
16 if(p == nil || p->dev->type == Devro)
19 if(f != FWRITE && noatime)
32 preread(Device *d, Off addr)
38 if(raheadq->count+10 >= raheadq->size) /* ugly knowing layout */
54 rel2abs(Iobuf *p, Dentry *d, Off a, int tag, int putb, int uid)
57 Off addr, qpath, indaddrs = 1, div;
61 fprint(2, "rel2abs: neg offset\n");
71 /* is `a' a direct block? */
75 addr = bufalloc(dev, tag, qpath, uid);
77 p->flags |= Bmod|Bimm;
86 * loop through indirect block depths.
88 for (i = 0; i < NIBLOCK; i++) {
89 indaddrs *= INDPERBUF;
90 /* is a's disk addr in this indir block or one of its kids? */
94 addr = bufalloc(dev, Tind1+i, qpath, uid);
96 p->flags |= Bmod|Bimm;
102 for (; i >= 0; i--) {
105 panic("rel2abs: non-positive divisor");
106 addr = indfetch(dev, qpath, addr,
107 (a/div)%INDPERBUF, Tind1+i,
108 (i == 0? tag: Tind1+i-1), uid);
117 /* quintuple-indirect blocks not implemented. */
118 fprint(2, "rel2abs: no %d-deep indirect\n", NIBLOCK+1);
123 * read-ahead strategy
124 * on second block, read RAGAP blocks,
125 * thereafter, read RAGAP ahead of current pos
128 dbufread(Iobuf *p, Dentry *d, Off a, Off ra, int uid)
134 if(a == 1 && ra == 1) {
135 while(ra < a+RAGAP) {
137 addr = rel2abs(p, d, ra, 0, 0, uid);
140 preread(p->dev, addr);
145 addr = rel2abs(p, d, ra, 0, 0, uid);
148 preread(p->dev, addr);
155 dnodebuf(Iobuf *p, Dentry *d, Off a, int tag, int uid)
159 addr = rel2abs(p, d, a, tag, 0, uid);
161 return getbuf(p->dev, addr, Brd);
166 * same as dnodebuf but it calls putbuf(p)
167 * to reduce interference.
170 dnodebuf1(Iobuf *p, Dentry *d, Off a, int tag, int uid)
176 addr = rel2abs(p, d, a, tag, 1, uid);
178 return getbuf(dev, addr, Brd);
184 indfetch(Device* d, Off qpath, Off addr, Off a, int itag, int tag, int uid)
190 bp = getbuf(d, addr, Brd);
191 if(!bp || checktag(bp, itag, qpath)) {
193 fprint(2, "ind fetch bp = 0\n");
196 fprint(2, "ind fetch tag\n");
200 addr = ((Off *)bp->iobuf)[a];
202 addr = bufalloc(d, tag, qpath, uid);
204 ((Off *)bp->iobuf)[a] = addr;
208 settag(bp, itag, qpath);
215 /* return INDPERBUF^exp */
219 static Off pows[] = {
222 (Off)INDPERBUF*INDPERBUF,
223 (Off)INDPERBUF*(Off)INDPERBUF*INDPERBUF,
224 (Off)INDPERBUF*(Off)INDPERBUF*(Off)INDPERBUF*INDPERBUF,
229 else if (exp >= nelem(pows)) { /* not in table? do it long-hand */
232 while (exp-- > 0 && indpow > 0)
239 /* return sum of INDPERBUF^n for 1 ≤ n ≤ exp */
245 for (; exp > 0; exp--)
246 indsum += ibbpow(exp);
250 /* zero bytes past new file length; return an error code */
252 trunczero(Truncstate *ts)
254 int blkoff = ts->newsize % BUFSIZE;
257 pd = dnodebuf(ts->p, ts->d, ts->lastblk, Tfile, ts->uid);
258 if (pd == nil || checktag(pd, Tfile, QPNONE)) {
264 memset(pd->iobuf+blkoff, 0, BUFSIZE - blkoff);
270 * truncate d (in p) to length `newsize'.
271 * if larger, just increase size.
272 * if smaller, deallocate blocks after last one
273 * still in file at new size. last byte to keep
274 * is newsize-1, due to zero origin.
275 * we free in forward order because it's simpler to get right.
276 * if the final block at the new size is partially-filled,
277 * zero the remainder.
280 dtrunclen(Iobuf *p, Dentry *d, Off newsize, int uid)
289 memset(&trunc, 0, sizeof trunc);
293 trunc.newsize = newsize;
294 trunc.lastblk = newsize/BUFSIZE;
295 if (newsize % BUFSIZE == 0)
299 for (i = 0; i < NDBLOCK; i++)
300 if (trunc.pastlast) {
302 buffree(p->dev, d->dblock[i], 0, &trunc);
304 } else if (i == trunc.lastblk)
306 trunc.relblk = NDBLOCK;
307 for (i = 0; i < NIBLOCK; i++) {
308 pastlast = trunc.pastlast;
309 buffree(p->dev, d->iblocks[i], i+1, &trunc);
315 p->flags |= Bmod|Bimm;
316 accessdir(p, d, FWRITE, uid);
321 * truncate d (in p) to zero length.
322 * freeing blocks in reverse order is traditional, from Unix,
323 * in an attempt to keep the free list contiguous.
326 dtrunc(Iobuf *p, Dentry *d, int uid)
330 for (i = NIBLOCK-1; i >= 0; i--) {
331 buffree(p->dev, d->iblocks[i], i+1, nil);
334 for (i = NDBLOCK-1; i >= 0; i--) {
335 buffree(p->dev, d->dblock[i], 0, nil);
339 p->flags |= Bmod|Bimm;
340 accessdir(p, d, FWRITE, uid);