]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/dossrv/xfile.c
rio, kbdfs: increase read buffer for high latency kbdfs support
[plan9front.git] / sys / src / cmd / dossrv / xfile.c
1 #include <u.h>
2 #include <libc.h>
3 #include "iotrack.h"
4 #include "dat.h"
5 #include "fns.h"
6
7 #define FIDMOD  127     /* prime */
8
9 static Xfs      *xhead;
10 static Xfile    *xfiles[FIDMOD], *freelist;
11 static MLock    xlock, xlocks[FIDMOD], freelock;
12
13 Xfs *
14 getxfs(char *user, char *name)
15 {
16         Xfs *xf, *fxf;
17         Dir *dir;
18         Qid dqid;
19         char *p, *q;
20         vlong offset;
21         int fd, omode;
22
23         USED(user);
24         if(name==nil || name[0]==0)
25                 name = deffile;
26         if(name == nil){
27                 errno = Enofilsys;
28                 return 0;
29         }
30
31         /*
32          * If the name passed is of the form 'name:offset' then
33          * offset is used to prime xf->offset. This allows accessing
34          * a FAT-based filesystem anywhere within a partition.
35          * Typical use would be to mount a filesystem in the presence
36          * of a boot manager programme at the beginning of the disc.
37          */
38         offset = 0;
39         if(p = strrchr(name, ':')){
40                 *p++ = 0;
41                 offset = strtoll(p, &q, 0);
42                 chat("name %s, offset %lld\n", p, offset);
43                 if(offset < 0 || p == q){
44                         errno = Enofilsys;
45                         return 0;
46                 }
47                 offset *= Sectorsize;
48         }
49
50         if(readonly)
51                 omode = OREAD;
52         else
53                 omode = ORDWR;
54         fd = open(name, omode);
55
56         if(fd < 0 && omode==ORDWR){
57                 omode = OREAD;
58                 fd = open(name, omode);
59         }
60
61         if(fd < 0){
62                 chat("can't open %s: %r\n", name);
63                 errno = Eerrstr;
64                 return 0;
65         }
66         dir = dirfstat(fd);
67         if(dir == nil){
68                 errno = Eio;
69                 close(fd);
70                 return 0;
71         }
72
73         dqid = dir->qid;
74         free(dir);
75         mlock(&xlock);
76         for(fxf=0,xf=xhead; xf; xf=xf->next){
77                 if(xf->ref == 0){
78                         if(fxf == 0)
79                                 fxf = xf;
80                         continue;
81                 }
82                 if(!eqqid(xf->qid, dqid))
83                         continue;
84                 if(strcmp(xf->name, name) != 0 || xf->dev < 0)
85                         continue;
86                 if(devcheck(xf) < 0) /* look for media change */
87                         continue;
88                 if(offset && xf->offset != offset)
89                         continue;
90                 chat("incref \"%s\", dev=%d...", xf->name, xf->dev);
91                 ++xf->ref;
92                 unmlock(&xlock);
93                 close(fd);
94                 return xf;
95         }
96         if(fxf == nil){
97                 fxf = malloc(sizeof(Xfs));
98                 if(fxf == nil){
99                         unmlock(&xlock);
100                         close(fd);
101                         errno = Enomem;
102                         return nil;
103                 }
104                 fxf->next = xhead;
105                 xhead = fxf;
106         }
107         chat("alloc \"%s\", dev=%d...", name, fd);
108         fxf->name = strdup(name);
109         fxf->ref = 1;
110         fxf->qid = dqid;
111         fxf->dev = fd;
112         fxf->fmt = 0;
113         fxf->offset = offset;
114         fxf->ptr = nil;
115         fxf->isfat32 = 0;
116         fxf->omode = omode;
117         unmlock(&xlock);
118         return fxf;
119 }
120
121 void
122 refxfs(Xfs *xf, int delta)
123 {
124         mlock(&xlock);
125         xf->ref += delta;
126         if(xf->ref == 0){
127                 chat("free \"%s\", dev=%d...", xf->name, xf->dev);
128                 free(xf->name);
129                 free(xf->ptr);
130                 purgebuf(xf);
131                 if(xf->dev >= 0){
132                         close(xf->dev);
133                         xf->dev = -1;
134                 }
135         }
136         unmlock(&xlock);
137 }
138
139 Xfile *
140 xfile(int fid, int flag)
141 {
142         Xfile **hp, *f, *pf;
143         int k;
144
145         k = ((ulong)fid) % FIDMOD;
146         hp = &xfiles[k];
147         mlock(&xlocks[k]);
148         pf = nil;
149         for(f=*hp; f; f=f->next){
150                 if(f->fid == fid)
151                         break;
152                 pf = f;
153         }
154         if(f && pf){
155                 pf->next = f->next;
156                 f->next = *hp;
157                 *hp = f;
158         }
159         switch(flag){
160         default:
161                 panic("xfile");
162         case Asis:
163                 unmlock(&xlocks[k]);
164                 return (f && f->xf && f->xf->dev < 0) ? nil : f;
165         case Clean:
166                 break;
167         case Clunk:
168                 if(f){
169                         *hp = f->next;
170                         unmlock(&xlocks[k]);
171                         clean(f);
172                         mlock(&freelock);
173                         f->next = freelist;
174                         freelist = f;
175                         unmlock(&freelock);
176                 } else
177                         unmlock(&xlocks[k]);
178                 return nil;
179         }
180         unmlock(&xlocks[k]);
181         if(f)
182                 return clean(f);
183         mlock(&freelock);
184         if(f = freelist){       /* assign = */
185                 freelist = f->next;
186                 unmlock(&freelock);
187         } else {
188                 unmlock(&freelock);
189                 f = malloc(sizeof(Xfile));
190                 if(f == nil){
191                         errno = Enomem;
192                         return nil;
193                 }
194         }
195         mlock(&xlocks[k]);
196         f->next = *hp;
197         *hp = f;
198         unmlock(&xlocks[k]);
199         f->fid = fid;
200         f->flags = 0;
201         f->qid = (Qid){0,0,0};
202         f->xf = nil;
203         f->ptr = nil;
204         return f;
205 }
206
207 Xfile *
208 clean(Xfile *f)
209 {
210         if(f->ptr){
211                 free(f->ptr);
212                 f->ptr = nil;
213         }
214         if(f->xf){
215                 refxfs(f->xf, -1);
216                 f->xf = nil;
217         }
218         f->flags = 0;
219         f->qid = (Qid){0,0,0};
220         return f;
221 }
222
223 /*
224  * the file at <addr, offset> has moved
225  * relocate the dos entries of all fids in the same file
226  */
227 void
228 dosptrreloc(Xfile *f, Dosptr *dp, vlong addr, ulong offset)
229 {
230         int i;
231         Xfile *p;
232         Dosptr *xdp;
233
234         for(i=0; i < FIDMOD; i++){
235                 for(p = xfiles[i]; p != nil; p = p->next){
236                         xdp = p->ptr;
237                         if(p != f && p->xf == f->xf
238                         && xdp != nil && xdp->addr == addr && xdp->offset == offset){
239                                 memmove(xdp, dp, sizeof(Dosptr));
240                                 xdp->p = nil;
241                                 xdp->d = nil;
242                                 p->qid.path = QIDPATH(xdp);
243                         }
244                 }
245         }
246 }