]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cfs/bcache.c
audiohda: fix syntax error
[plan9front.git] / sys / src / cmd / cfs / bcache.c
1 #include <u.h>
2 #include <libc.h>
3 #include "cformat.h"
4 #include "lru.h"
5 #include "bcache.h"
6
7 int
8 bcinit(Bcache *bc, int f, int bsize)
9 {
10         Bbuf *b;
11
12         /*
13          *  allocate space for all buffers
14          *  point all buffers into outer space
15          */
16         bc->dfirst = 0;
17         bc->bsize = bsize;
18         bc->f = f;
19         lruinit(bc);
20         for(b = bc->bb; b < &bc->bb[Nbcache]; b++){
21                 b->inuse = 0;
22                 b->next = 0;
23                 b->dirty = 0;
24                 if(b->data == 0)
25                         b->data = (char *)malloc(bc->bsize);
26                 if(b->data == 0)
27                         return -1;
28                 lruadd(bc, b);
29         }
30
31         return 0;
32 }
33
34 /*
35  *  Find a buffer for block b.  If it's dirty, write it out.
36  */
37 Bbuf *
38 bcfind(Bcache *bc, ulong bno)
39 {
40         Bbuf *b;
41
42         if(bno == Notabno)
43                 error("bcfind: Notabno");
44         bno &= ~Indbno;
45
46         /*
47          *  if we already have a buffer for this bno, use it
48          */
49         for(b = bc->bb; b < &bc->bb[Nbcache]; b++)
50                 if(b->inuse && b->bno==bno)
51                         goto out;
52
53         /*
54          *  get least recently used block
55          */
56         b = (Bbuf*)bc->lnext;
57 out:
58         /*
59          *  if dirty, write it out
60          */
61         if(b->dirty)
62                 if(bcwrite(bc, b) < 0)
63                         warning("writing dirty page");
64         lruref(bc, b);
65         return b;
66 }
67
68 /*
69  *  allocate a buffer block for a block.  it's guaranteed to be there till
70  *  the next Nbcache bcread's.
71  */
72 Bbuf *
73 bcalloc(Bcache *bc, ulong bno)
74 {
75         Bbuf *b;
76
77         b = bcfind(bc, bno);
78         bno &= ~Indbno;
79         b->bno = bno;
80         b->inuse = 1;
81         return b;
82 }
83
84 /*
85  *  read a block into a buffer cache.  it's guaranteed to be there till
86  *  the next Nbcache bcread's.
87  */
88 Bbuf *
89 bcread(Bcache *bc, ulong bno)
90 {
91         Bbuf *b;
92
93         b = bcfind(bc, bno);
94         bno &= ~Indbno;
95         if(b->bno!=bno || !b->inuse)
96                 /*
97                  *  read in the one we really want
98                  */
99                 if(bread(bc, bno, b->data) < 0){
100                         b->inuse = 0;
101                         return 0;
102                 }
103         b->bno = bno;
104         b->inuse = 1;
105         return b;
106 }
107
108 /*
109  *  mark a page dirty, if it's already dirty force a write
110  *
111  *      N.B: ordering is important.
112  */
113 void
114 bcmark(Bcache *bc, Bbuf *b)
115 {
116         lruref(bc, b);
117
118         if(b->dirty){
119                 bcwrite(bc, b);
120                 return;
121         }
122
123         b->dirty = 1;
124         if(bc->dfirst)
125                 bc->dlast->next = b;
126         else
127                 bc->dfirst = b;
128         bc->dlast = b;
129 }
130
131 /*
132  *  write out a page (and all preceding dirty ones)
133  */
134 int
135 bcwrite(Bcache *bc, Bbuf *b)
136 {
137         Bbuf *nb;
138
139         /*
140          *  write out all preceding pages
141          */
142         while(nb = bc->dfirst){
143                 if(bwrite(bc, nb->bno, nb->data) < 0)
144                         return -1;
145                 nb->dirty = 0;
146                 bc->dfirst = nb->next;
147                 nb->next = 0;
148                 if(nb == b)
149                         return 0;
150         }
151
152         /*
153          *  write out this page
154          */
155         if(bwrite(bc, b->bno, b->data) < 0)
156                 return -1;
157         b->dirty = 0;
158         b->next = 0;
159         return 0;
160 }
161
162 /*
163  *  write out all dirty pages (in order)
164  */
165 int
166 bcsync(Bcache *bc)
167 {
168         if(bc->dfirst)
169                 return bcwrite(bc, bc->dlast);
170         return 0;
171 }
172
173 /*
174  *  read a block from disk
175  */
176 int
177 bread(Bcache *bc, ulong bno, void *buf)
178 {
179         uvlong x = (uvlong)bno * bc->bsize;
180
181         if(pread(bc->f, buf, bc->bsize, x) != bc->bsize)
182                 return -1;
183         return 0;
184 }
185
186 /*
187  *  write a block to disk
188  */
189 int
190 bwrite(Bcache *bc, ulong bno, void *buf)
191 {
192         uvlong x = (uvlong)bno * bc->bsize;
193
194         if(pwrite(bc->f, buf, bc->bsize, x) != bc->bsize)
195                 return -1;
196         return 0;
197 }