fs.c (5098B)
1 #include <u.h> 2 #include <libc.h> 3 #include <fcall.h> 4 #include <thread.h> 5 #include <9p.h> 6 7 #include "pages.h" 8 9 enum { 10 FrameSize = sizeof(s16int) * 2, 11 }; 12 13 PBuf pg; 14 15 struct { 16 int min; 17 int max; 18 char str[12*3+1]; // see update_selstr 19 } sel; 20 21 void fs_open(Req *r); 22 void fs_read(Req *r); 23 void fs_write(Req *r); 24 25 void fcut_open(Req *r); 26 void fcut_write(Req *r); 27 28 void normalize_sel(void); 29 void update_selstr(void); 30 31 Srv ampsrv = { 32 .read = fs_read, 33 .write = fs_write, 34 .open = fs_open, 35 }; 36 37 File *fdata, *fcut, *fctl; 38 char *service, *mountpath = "/mnt/amp"; 39 40 void 41 usage(void) 42 { 43 fprint(2,"usage: %s\n", argv0); 44 threadexitsall("usage"); 45 } 46 47 void 48 threadmain(int argc, char **argv) 49 { 50 ARGBEGIN { 51 case 'D': 52 chatty9p++; 53 break; 54 case 's': 55 service = EARGF(usage()); 56 break; 57 case 'm': 58 mountpath = EARGF(usage()); 59 break; 60 default: usage(); 61 } ARGEND 62 if (argc != 0) usage(); 63 update_selstr(); 64 ampsrv.tree = alloctree("amp", "amp", DMDIR|0555, nil); 65 fdata = createfile(ampsrv.tree->root, "data", "amp", 0666, nil); 66 fcut = createfile(ampsrv.tree->root, "cut", "amp", 0666, nil); 67 fctl = createfile(ampsrv.tree->root, "ctl", "amp", 0666, nil); 68 threadpostmountsrv(&srv, service, mountpath, MREPL); 69 } 70 71 void 72 fs_open(Req *r) 73 { 74 char *rstr = nil; 75 File *file = r->fid->file; 76 uchar mode = r->ifcall.mode; 77 if (file == fcut) { 78 fcut_open(r); 79 goto end; 80 } 81 if ((mode & OTRUNC) == 0) goto end; 82 if (file == fctl) goto end; 83 if (file == fdata) { 84 pg.length = 0; 85 fdata->length = 0; 86 // TODO: free pages ??? 87 // probably better to do it on fs_close() 88 goto end; 89 } 90 rstr = "what"; 91 end: 92 respond(r, rstr); 93 } 94 95 void 96 fs_read(Req *r) 97 { 98 if (r->fid->file == fdata) { 99 r->ofcall.count = pbread(&pg, r->ofcall.data, 100 r->ifcall.count, r->ifcall.offset); 101 respond(r, nil); 102 } else if (r->fid->file == fcut) { 103 vlong min = sel.min * FrameSize; 104 vlong max = sel.max * FrameSize; 105 r->ifcall.offset += min; 106 if (r->ifcall.offset + r->ifcall.count > max) 107 r->ifcall.count = max - r->ifcall.offset; 108 if (r->ifcall.offset > max) r->ifcall.count = 0; 109 r->ofcall.count = pbread(&pg, r->ofcall.data, 110 r->ifcall.count, r->ifcall.offset); 111 respond(r, nil); 112 } else if (r->fid->file == fctl) { 113 readstr(r, sel.str); 114 respond(r, nil); 115 } else { 116 respond(r, "nope"); 117 } 118 } 119 120 void 121 fs_write(Req *r) 122 { 123 if (r->fid->file == fdata) { 124 r->ofcall.count = pbwrite(&pg, r->ifcall.data, 125 r->ifcall.count, r->ifcall.offset); 126 if (pg.length > fdata->length) fdata->length = pg.length; 127 update_selstr(); 128 respond(r, nil); 129 } else if (r->fid->file == fcut) { 130 fcut_write(r); 131 update_selstr(); 132 respond(r, nil); 133 } else if (r->fid->file == fctl) { 134 int newmin, newmax; 135 char *np, *rp; 136 np = r->ifcall.data; 137 newmin = strtol(np, &rp, 10); 138 if (rp <= np) { 139 respond(r, "bad first value"); 140 return; 141 } 142 newmax = strtol(rp, &rp, 10); 143 if (rp <= np) { 144 respond(r, "bad second value"); 145 return; 146 } 147 if (rp - np > r->ifcall.count) { 148 respond(r, "somehow buffer overrun"); 149 return; 150 } 151 sel.min = newmin; 152 sel.max = newmax; 153 normalize_sel(); 154 update_selstr(); 155 fcut->length = (sel.max - sel.min) * FrameSize; 156 r->ofcall.count = r->ifcall.count; 157 respond(r, nil); 158 } else { 159 respond(r, "nope"); 160 } 161 } 162 163 void 164 fcut_open(Req *r) 165 { 166 vlong min, max; 167 min = sel.min * FrameSize; 168 max = sel.max * FrameSize; 169 170 if ((r->ifcall.mode & OTRUNC) != 0) { 171 Page *maxpg = splitpage(&pg, max); 172 Page *minpg = splitpage(&pg, min); 173 assert(minpg != nil); 174 assert(maxpg != nil); 175 if (minpg->prev != nil) { 176 minpg->prev->next = maxpg; 177 maxpg->prev = minpg->prev; 178 } else { 179 pg.start = maxpg; 180 maxpg->prev = nil; 181 } 182 while (minpg != maxpg) { 183 Page *fp = minpg; 184 fp->as->len = 0; 185 minpg = fp->next; 186 freepage(fp); 187 } 188 pg.length -= max - min; 189 fdata->length = pg.length; 190 fcut->length = 0; 191 sel.max = sel.min; 192 normalize_sel(); 193 } 194 } 195 196 void 197 fcut_write(Req *r) 198 { 199 Page *maxpage; 200 vlong min, max, offset; 201 long count; 202 min = sel.min * FrameSize; 203 max = sel.max * FrameSize; 204 205 maxpage = splitpage(&pg, max); 206 if (maxpage == nil) { 207 maxpage = addpage(&pg); 208 } 209 // insert more pages as needed 210 offset = r->ifcall.offset + min; 211 count = r->ifcall.count; 212 while (offset + count > max) { 213 long n = offset + count - max; 214 if (n > PageSize) n = PageSize; 215 Page *ins = allocpage(); 216 ins->as->len = n; 217 ins->next = maxpage; 218 ins->prev = maxpage->prev; 219 if (maxpage->prev != nil) maxpage->prev->next = ins; 220 else { 221 pg.start = ins; 222 } 223 maxpage->prev = ins; 224 max += n; 225 pg.length += n; 226 } 227 sel.max = max / FrameSize; 228 normalize_sel(); 229 fcut->length = (sel.max - sel.min) * FrameSize; 230 fdata->length = pg.length; 231 // write to pagebuffer as usual 232 r->ofcall.count = pbwrite(&pg, r->ifcall.data, count, offset); 233 } 234 235 void 236 normalize_sel(void) 237 { 238 vlong bufmax = pg.length / FrameSize; 239 if (sel.min > bufmax) sel.min = bufmax; 240 if (sel.max > bufmax) sel.max = bufmax; 241 if (sel.min > sel.max) { 242 int x = sel.max; 243 sel.max = sel.min; 244 sel.min = x; 245 } 246 } 247 248 void 249 update_selstr(void) 250 { 251 snprint(sel.str, sizeof(sel.str), "%11d %11d %11d \n", 252 sel.min, sel.max, (int)(pg.length / FrameSize)); 253 }