1 #include "all.h"
2
3 Dentry*
getdir(Iobuf * p,int slot)4 getdir(Iobuf *p, int slot)
5 {
6 Dentry *d;
7
8 if(!p)
9 return 0;
10 d = (Dentry*)p->iobuf + slot%DIRPERBUF;
11 return d;
12 }
13
14 void
accessdir(Iobuf * p,Dentry * d,int f)15 accessdir(Iobuf *p, Dentry *d, int f)
16 {
17 long t;
18
19 if(p && !isro(p->dev)) {
20 if(!(f & (FWRITE|FWSTAT)) && noatime)
21 return;
22 t = time(nil);
23 if(f & (FREAD|FWRITE|FWSTAT)){
24 d->atime = t;
25 p->flags |= Bmod;
26 }
27 if(f & FWRITE) {
28 d->mtime = t;
29 d->qid.version++;
30 p->flags |= Bmod;
31 }
32 }
33 }
34
35 void
dbufread(Iobuf * p,Dentry * d,long a)36 dbufread(Iobuf *p, Dentry *d, long a)
37 {
38 USED(p, d, a);
39 }
40
41 long
rel2abs(Iobuf * p,Dentry * d,long a,int tag,int putb)42 rel2abs(Iobuf *p, Dentry *d, long a, int tag, int putb)
43 {
44 long addr, qpath;
45 Device dev;
46
47 if(a < 0) {
48 print("dnodebuf: neg\n");
49 return 0;
50 }
51 qpath = d->qid.path;
52 dev = p->dev;
53 if(a < NDBLOCK) {
54 addr = d->dblock[a];
55 if(!addr && tag) {
56 addr = balloc(dev, tag, qpath);
57 d->dblock[a] = addr;
58 p->flags |= Bmod|Bimm;
59 }
60 if(putb)
61 putbuf(p);
62 return addr;
63 }
64 a -= NDBLOCK;
65 if(a < INDPERBUF) {
66 addr = d->iblock;
67 if(!addr && tag) {
68 addr = balloc(dev, Tind1, qpath);
69 d->iblock = addr;
70 p->flags |= Bmod|Bimm;
71 }
72 if(putb)
73 putbuf(p);
74 addr = indfetch(p, d, addr, a, Tind1, tag);
75 return addr;
76 }
77 a -= INDPERBUF;
78 if(a < INDPERBUF2) {
79 addr = d->diblock;
80 if(!addr && tag) {
81 addr = balloc(dev, Tind2, qpath);
82 d->diblock = addr;
83 p->flags |= Bmod|Bimm;
84 }
85 if(putb)
86 putbuf(p);
87 addr = indfetch(p, d, addr, a/INDPERBUF, Tind2, Tind1);
88 addr = indfetch(p, d, addr, a%INDPERBUF, Tind1, tag);
89 return addr;
90 }
91 if(putb)
92 putbuf(p);
93 print("dnodebuf: trip indirect\n");
94 return 0;
95 }
96
97 Iobuf*
dnodebuf(Iobuf * p,Dentry * d,long a,int tag)98 dnodebuf(Iobuf *p, Dentry *d, long a, int tag)
99 {
100 long addr;
101
102 addr = rel2abs(p, d, a, tag, 0);
103 if(addr)
104 return getbuf(p->dev, addr, Bread);
105 return 0;
106 }
107
108 /*
109 * same as dnodebuf but it calls putpuf(p)
110 * to reduce interference.
111 */
112 Iobuf*
dnodebuf1(Iobuf * p,Dentry * d,long a,int tag)113 dnodebuf1(Iobuf *p, Dentry *d, long a, int tag)
114 {
115 long addr;
116 Device dev;
117
118 dev = p->dev;
119 addr = rel2abs(p, d, a, tag, 1);
120 if(addr)
121 return getbuf(dev, addr, Bread);
122 return 0;
123
124 }
125
126 long
indfetch(Iobuf * p,Dentry * d,long addr,long a,int itag,int tag)127 indfetch(Iobuf *p, Dentry *d, long addr, long a, int itag, int tag)
128 {
129 Iobuf *bp;
130
131 if(!addr)
132 return 0;
133 bp = getbuf(p->dev, addr, Bread);
134 if(!bp || checktag(bp, itag, d->qid.path)) {
135 if(!bp) {
136 print("ind fetch bp = 0\n");
137 return 0;
138 }
139 print("ind fetch tag\n");
140 putbuf(bp);
141 return 0;
142 }
143 addr = ((long*)bp->iobuf)[a];
144 if(!addr && tag) {
145 addr = balloc(p->dev, tag, d->qid.path);
146 if(addr) {
147 ((long*)bp->iobuf)[a] = addr;
148 bp->flags |= Bmod;
149 if(localfs || tag == Tdir)
150 bp->flags |= Bimm;
151 settag(bp, itag, d->qid.path);
152 }
153 }
154 putbuf(bp);
155 return addr;
156 }
157
158 void
dtrunc(Iobuf * p,Dentry * d)159 dtrunc(Iobuf *p, Dentry *d)
160 {
161 int i;
162
163 bfree(p->dev, d->diblock, 2);
164 d->diblock = 0;
165 bfree(p->dev, d->iblock, 1);
166 d->iblock = 0;
167 for(i=NDBLOCK-1; i>=0; i--) {
168 bfree(p->dev, d->dblock[i], 0);
169 d->dblock[i] = 0;
170 }
171 d->size = 0;
172 p->flags |= Bmod|Bimm;
173 accessdir(p, d, FWRITE);
174 }
175