11 * merge data with that which already exists in a block
13 * we allow only one range per block, always use the new
14 * data if the ranges don't overlap.
17 fmerge(Dptr *p, char *to, char *from, int start, int len)
22 memmove(to+start, from, end-start);
25 * if ranges do not overlap...
27 if(start>p->end || p->start>end){
29 * just use the new data
46 * write a block (or less) of data onto a disk, follow it with any necessary
49 * N.B. ordering is everything
52 fbwrite(Icache *ic, Ibuf *b, char *a, ulong off, int len)
56 Bbuf *dbb; /* data block */
57 Bbuf *ibb; /* indirect block */
61 fbno = off / ic->bsize;
67 * are there any pages for this inode?
69 if(p->bno == Notabno){
75 * is it an indirect block?
78 ibb = bcread(ic, p->bno);
87 * is it the wrong direct block?
89 if((p->fbno%ic->p2b) != (fbno%ic->p2b)){
91 * yes, make an indirect block
95 if(p->bno == Notabno){
99 ibb = bcalloc(ic, p->bno);
104 p = (Dptr*)ibb->data;
105 p += t.fbno % ic->p2b;
107 p = (Dptr*)ibb->data;
114 * get the data block into the block cache
116 if(p->bno == Notabno){
121 if(p->bno == Notabno)
122 return -1; /* no blocks left (maybe) */
123 dbb = bcalloc(ic, p->bno);
128 dbb = bcread(ic, p->bno);
134 * merge in the new data
137 p->start = p->end = 0;
140 fmerge(p, dbb->data, a, off % ic->bsize, len);
143 * write changed blocks back in the
150 if(iwrite(ic, b) < 0)
156 * write `n' bytes to the cache
158 * return number of bytes written
161 fwrite(Icache *ic, Ibuf *b, char *a, ulong off, long n)
166 for(sofar = 0; sofar < n; sofar += len){
167 len = ic->bsize - ((off+sofar)%ic->bsize);
170 if(fbwrite(ic, b, a+sofar, off+sofar, len) < 0)
177 * get a pointer to the next valid data at or after `off'
180 fpget(Icache *ic, Ibuf *b, ulong off)
184 Bbuf *ibb; /* indirect block */
187 fbno = off / ic->bsize;
191 * are there any pages for this inode?
193 if(p->bno == Notabno)
197 * if it's a direct block, life is easy?
199 if(!(p->bno & Indbno)){
201 * a direct block, return p if it's at least past what we want
207 doff = off % ic->bsize;
208 if(doff>=p->start && doff<p->end)
215 * read the indirect block
217 ibb = bcread(ic, p->bno);
222 * find the next valid pointer
224 p0 = (Dptr*)ibb->data;
225 pf = p0 + (fbno % ic->p2b);
226 if(pf->bno!=Notabno && pf->fbno==fbno){
227 doff = off % ic->bsize;
231 for(p = pf+1; p < p0 + ic->p2b; p++){
233 if(p->fbno==fbno && p->bno!=Notabno && p->start<p->end)
236 for(p = p0; p < pf; p++){
238 if(p->fbno==fbno && p->bno!=Notabno && p->start<p->end)
245 * read `n' bytes from the cache.
247 * if we hit a gap and we've read something,
248 * return number of bytes read so far.
250 * if we start with a gap, return minus the number of bytes
253 * if there are no bytes cached, return 0.
256 fread(Icache *ic, Ibuf *b, char *a, ulong off, long n)
263 for(sofar = 0; sofar < n; sofar += len, off += len){
265 * get pointer to next data
268 p = fpget(ic, b, off);
271 * if no more data, return what we have so far
277 * if there's a gap, return the size of the gap
279 gap = (ic->bsize*p->fbno + p->start) - off;
287 * return what we have
289 bb = bcread(ic, p->bno);
292 start = p->start - gap;
293 if(p->end - start < len)
294 len = p->end - start;
295 memmove(a + sofar, bb->data + start, len);