sysfile.c: bump up the read size using a constant
[akaros.git] / kern / src / ns / sysfile.c
1 // INFERNO
2 #include <vfs.h>
3 #include <kfs.h>
4 #include <slab.h>
5 #include <kmalloc.h>
6 #include <kref.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <assert.h>
10 #include <error.h>
11 #include <cpio.h>
12 #include <pmap.h>
13 #include <smp.h>
14 #include <ip.h>
15
16 enum {
17         DIRSIZE = STATFIXLEN + 32 * 4,
18         DIRREADLIM = 2048,      /* should handle the largest reasonable directory entry */
19         DIRREADSIZE=8192,       /* Just read a lot. Memory is cheap, lots of bandwidth,
20                                  * and RPCs are very expensive. At the same time,
21                                  * let's not yet exceed a common MSIZE. */
22
23 };
24
25 static int growfd(struct fgrp *f, int fd)
26 {
27         
28         int n;
29         struct chan **nfd, **ofd;
30
31         if (fd < f->nfd) {
32                 return 0;
33         }
34         n = f->nfd + DELTAFD;
35         if (n > MAXNFD)
36                 n = MAXNFD;
37         if (fd >= n) {
38                 return -1;
39         }
40         nfd = kzmalloc(n * sizeof(struct chan *), 0);
41         if (nfd == NULL) {
42                 return -1;
43         }
44         ofd = f->fd;
45         memmove(nfd, ofd, f->nfd * sizeof(struct chan *));
46         f->fd = nfd;
47         f->nfd = n;
48         kfree(ofd);
49         return 0;
50 }
51
52 int newfd(struct chan *c)
53 {
54         
55         int i;
56         struct fgrp *f = current->fgrp;
57
58         spin_lock(&f->lock);
59         if (f->closed) {
60                 spin_unlock(&f->lock);
61                 return -1;
62         }
63         /* VFS hack */
64         /* We'd like to ask it to start at f->minfd, but that would require us to
65          * know if we closed anything.  Since we share the FD numbers with the VFS,
66          * there is no way to know that. */
67         i = get_fd(&current->open_files, 0);
68         while (i >= f->nfd) {
69                 if (growfd(f, i) < 0) {
70                         spin_unlock(&f->lock);
71                         exhausted("file descriptors");
72                         return -1;
73                 }
74                 cpu_relax();
75         }
76         assert(f->fd[i] == 0);
77 #if 0   // 9ns style
78         /* TODO: use a unique integer allocator */
79         for (i = f->minfd; i < f->nfd; i++)
80                 if (f->fd[i] == 0)
81                         break;
82         if (i >= f->nfd && growfd(f, i) < 0) {
83                 spin_unlock(&f->lock);
84                 exhausted("file descriptors");
85                 return -1;
86         }
87 #endif
88         f->minfd = i + 1;
89         if (i > f->maxfd)
90                 f->maxfd = i;
91         f->fd[i] = c;
92         spin_unlock(&f->lock);
93         return i;
94 }
95
96 struct chan *fdtochan(struct fgrp *f, int fd, int mode, int chkmnt, int iref)
97 {
98         
99         struct chan *c;
100
101         c = 0;
102
103         spin_lock(&f->lock);
104         if (f->closed) {
105                 spin_unlock(&f->lock);
106                 error("File group closed");
107         }
108         if (fd < 0 || f->maxfd < fd || (c = f->fd[fd]) == 0) {
109                 spin_unlock(&f->lock);
110                 error(Ebadfd);
111         }
112         if (iref)
113                 chan_incref(c);
114         spin_unlock(&f->lock);
115
116         if (chkmnt && (c->flag & CMSG)) {
117                 if (iref)
118                         cclose(c);
119                 error(Ebadusefd);
120         }
121
122         if (mode < 0 || c->mode == ORDWR) {
123                 return c;
124         }
125
126         if ((mode & OTRUNC) && IS_RDONLY(c->mode)) {
127                 if (iref)
128                         cclose(c);
129                 error(Ebadusefd);
130         }
131
132         /* TODO: this is probably wrong.  if you get this from a dev, in the dev's
133          * open, you are probably saving mode directly, without passing it through
134          * openmode. */
135         if ((mode & ~OTRUNC) != c->mode) {
136                 warn("Trunc mode issue: mode %o, mode minus trunc %o, chan mode %o\n",
137                          mode, mode & ~OTRUNC, c->mode);
138                 if (iref)
139                         cclose(c);
140                 error(Ebadusefd);
141         }
142
143         return c;
144 }
145
146 long kchanio(void *vc, void *buf, int n, int mode)
147 {
148         ERRSTACK(1);
149         int r;
150         struct chan *c;
151
152         c = vc;
153         if (waserror()) {
154                 poperror();
155                 return -1;
156         }
157
158         if (IS_RDONLY(mode))
159                 r = devtab[c->type].read(c, buf, n, c->offset);
160         else
161                 r = devtab[c->type].write(c, buf, n, c->offset);
162
163         spin_lock(&c->lock);
164         c->offset += r;
165         spin_unlock(&c->lock);
166         poperror();
167         return r;
168 }
169
170 int openmode(uint32_t omode)
171 {
172 /* GIANT WARNING: if this ever throws, ipopen (and probably many others) will
173  * screw up refcnts of Qctl, err, data, etc */
174 #if 0
175         /* this is the old plan9 style.  i think they want to turn exec into read,
176          * and strip off anything higher, and just return the RD/WR style bits.  not
177          * stuff like ORCLOSE.  the lack of OEXCL might be a bug on their part (it's
178          * the only one of their non-RW-related flags that isn't masked out) */
179         if (o >= (OTRUNC | OCEXEC | ORCLOSE | OEXEC))
180                 error(Ebadarg);
181         o &= ~(OTRUNC | OCEXEC | ORCLOSE);
182         if (o > OEXEC)
183                 error(Ebadarg);
184         if (o == OEXEC)
185                 return OREAD;
186         return o;
187 #endif
188         /* no error checking (we have a shitload of flags anyway), and we return the
189          * basic access modes (RD/WR/ETC) */
190         if (omode == O_EXEC) {
191         return O_RDONLY;
192         }
193         return omode & O_ACCMODE;
194 }
195
196 void fdclose(struct fgrp *f, int fd)
197 {
198         
199         int i;
200         struct chan *c;
201
202         spin_lock(&f->lock);
203         if (f->closed) {
204                 spin_unlock(&f->lock);
205                 return;
206         }
207         c = f->fd[fd];
208         if (c == 0) {
209                 /* can happen for users with shared fd tables */
210                 spin_unlock(&f->lock);
211                 return;
212         }
213         f->fd[fd] = 0;
214         if (fd == f->maxfd)
215                 for (i = fd; --i >= 0 && f->fd[i] == 0;)
216                         f->maxfd = i;
217         if (fd < f->minfd)
218                 f->minfd = fd;
219         /* VFS hack: give the FD back to VFS */
220         put_fd(&current->open_files, fd);
221         spin_unlock(&f->lock);
222         cclose(c);
223 }
224
225 int syschdir(char *path)
226 {
227         ERRSTACK(1);
228         struct chan *c;
229         struct pgrp *pg;
230
231         if (waserror()) {
232                 poperror();
233                 return -1;
234         }
235
236         c = namec(path, Atodir, 0, 0);
237         pg = current->pgrp;
238         cclose(pg->dot);
239         pg->dot = c;
240         poperror();
241         return 0;
242 }
243
244 int fgrpclose(struct fgrp *f, int fd)
245 {
246         ERRSTACK(1);
247         if (waserror()) {
248                 poperror();
249                 return -1;
250         }
251
252         /*
253          * Take no reference on the chan because we don't really need the
254          * data structure, and are calling fdtochan only for error checks.
255          * fdclose takes care of processes racing through here.
256          */
257         fdtochan(f, fd, -1, 0, 0);
258         fdclose(f, fd);
259         poperror();
260         return 0;
261 }
262
263 int sysclose(int fd)
264 {
265         return fgrpclose(current->fgrp, fd);
266 }
267
268 int syscreate(char *path, int mode, uint32_t perm)
269 {
270         ERRSTACK(2);
271         int fd;
272         struct chan *c;
273
274         if (waserror()) {
275                 poperror();
276                 return -1;
277         }
278
279         openmode(mode & ~OEXCL);        /* error check only; OEXCL okay here */
280         c = namec(path, Acreate, mode, perm);
281         if (waserror()) {
282                 cclose(c);
283                 nexterror();
284         }
285         fd = newfd(c);
286         if (fd < 0)
287                 error(Enofd);
288         poperror();
289
290         poperror();
291         return fd;
292 }
293
294 int sysdup(int old, int new)
295 {
296         ERRSTACK(2);
297         int fd;
298         struct chan *c, *oc;
299         struct fgrp *f = current->fgrp;
300
301         if (waserror()) {
302                 poperror();
303                 return -1;
304         }
305
306         c = fdtochan(current->fgrp, old, -1, 0, 1);
307         if (c->qid.type & QTAUTH) {
308                 cclose(c);
309                 error(Eperm);
310         }
311         fd = new;
312         if (fd != -1) {
313                 /* ideally we'll be done with the VFS before we fix this */
314                 /* double check the ccloses when you fix this */
315                 panic("Need to sync with the VFS");
316                 spin_lock(&f->lock);
317                 if (f->closed) {
318                         spin_unlock(&f->lock);
319                         cclose(c);
320                         return -1;
321                 }
322                 if (fd < 0 || growfd(f, fd) < 0) {
323                         spin_unlock(&f->lock);
324                         cclose(c);
325                         error(Ebadfd);
326                 }
327                 if (fd > f->maxfd)
328                         f->maxfd = fd;
329                 oc = f->fd[fd];
330                 f->fd[fd] = c;
331                 spin_unlock(&f->lock);
332                 if (oc)
333                         cclose(oc);
334         } else {
335                 if (waserror()) {
336                         cclose(c);
337                         nexterror();
338                 }
339                 fd = newfd(c);
340                 if (fd < 0)
341                         error(Enofd);
342                 poperror();
343         }
344         poperror();
345         return fd;
346 }
347
348 char *sysfd2path(int fd)
349 {
350         ERRSTACK(1);
351         struct chan *c;
352         char *s;
353
354         if (waserror()) {
355                 poperror();
356                 return NULL;
357         }
358         c = fdtochan(current->fgrp, fd, -1, 0, 1);
359         s = NULL;
360         if (c->name != NULL) {
361                 s = kzmalloc(c->name->len + 1, 0);
362                 if (s == NULL) {
363                         cclose(c);
364                         error(Enomem);
365                 }
366                 memmove(s, c->name->s, c->name->len + 1);
367         }
368         cclose(c);
369         poperror();
370         return s;
371 }
372
373 int sysfauth(int fd, char *aname)
374 {
375         ERRSTACK(2);
376         struct chan *c, *ac;
377
378         if (waserror()) {
379                 poperror();
380                 return -1;
381         }
382
383         validname(aname, 0);
384         c = fdtochan(current->fgrp, fd, ORDWR, 0, 1);
385         if (waserror()) {
386                 cclose(c);
387                 nexterror();
388         }
389
390         ac = mntauth(c, aname);
391
392         /* at this point ac is responsible for keeping c alive */
393         poperror();     /* c */
394         cclose(c);
395
396         if (waserror()) {
397                 cclose(ac);
398                 nexterror();
399         }
400
401         fd = newfd(ac);
402         if (fd < 0)
403                 error(Enofd);
404         poperror();     /* ac */
405
406         poperror();
407
408         return fd;
409 }
410
411 int sysfversion(int fd, unsigned int msize, char *vers, unsigned int arglen)
412 {
413         ERRSTACK(2);
414         int m;
415         struct chan *c;
416
417         if (waserror()) {
418                 poperror();
419                 return -1;
420         }
421
422         /* check there's a NUL in the version string */
423         if (arglen == 0 || memchr(vers, 0, arglen) == 0)
424                 error(Ebadarg);
425
426         c = fdtochan(current->fgrp, fd, ORDWR, 0, 1);
427         if (waserror()) {
428                 cclose(c);
429                 nexterror();
430         }
431
432         m = mntversion(c, vers, msize, arglen);
433
434         poperror();
435         cclose(c);
436
437         poperror();
438         return m;
439 }
440
441 int syspipe(int fd[2])
442 {
443         ERRSTACK(1);
444         struct dev *d;
445         struct fgrp *f;
446         struct chan *c[2];
447         static char *names[] = { "data", "data1" };
448
449         f = current->fgrp;
450
451         d = &devtab[devno('|', 0)];
452         c[0] = namec("#|", Atodir, 0, 0);
453         c[1] = 0;
454         fd[0] = -1;
455         fd[1] = -1;
456         if (waserror()) {
457                 if (c[0] != 0)
458                         cclose(c[0]);
459                 if (c[1] != 0)
460                         cclose(c[1]);
461                 if (fd[0] >= 0) {
462                         /* VFS hack */
463                         f->fd[fd[0]] = 0;
464                         put_fd(&current->open_files, fd[0]);
465                 }
466                 if (fd[1] >= 0) {
467                         /* VFS hack */
468                         f->fd[fd[1]] = 0;
469                         put_fd(&current->open_files, fd[1]);
470                 }
471                 poperror();
472                 return -1;
473         }
474         c[1] = cclone(c[0]);
475         if (walk(&c[0], &names[0], 1, 1, NULL) < 0)
476                 error(Egreg);
477         if (walk(&c[1], &names[1], 1, 1, NULL) < 0)
478                 error(Egreg);
479         c[0] = d->open(c[0], ORDWR);
480         c[1] = d->open(c[1], ORDWR);
481         fd[0] = newfd(c[0]);
482         if (fd[0] < 0)
483                 error(Enofd);
484         fd[1] = newfd(c[1]);
485         if (fd[1] < 0)
486                 error(Enofd);
487         poperror();
488         return 0;
489 }
490
491 int sysfwstat(int fd, uint8_t * buf, int n)
492 {
493         ERRSTACK(2);
494         struct chan *c;
495
496         if (waserror()) {
497                 poperror();
498                 return -1;
499         }
500
501         validstat(buf, n);
502         c = fdtochan(current->fgrp, fd, -1, 1, 1);
503         if (waserror()) {
504                 cclose(c);
505                 nexterror();
506         }
507         n = devtab[c->type].wstat(c, buf, n);
508         poperror();
509         cclose(c);
510
511         poperror();
512         return n;
513 }
514
515 long bindmount(struct chan *c, char *old, int flag, char *spec)
516 {
517         ERRSTACK(1);
518         int ret;
519         struct chan *c1;
520
521         if (flag > MMASK || (flag & MORDER) == (MBEFORE | MAFTER))
522                 error(Ebadarg);
523
524         c1 = namec(old, Amount, 0, 0);
525         if (waserror()) {
526                 cclose(c1);
527                 nexterror();
528         }
529         ret = cmount(c, c1, flag, spec);
530
531         poperror();
532         cclose(c1);
533         return ret;
534 }
535
536 int sysbind(char *new, char *old, int flags)
537 {
538         ERRSTACK(2);
539         long r;
540         struct chan *c0;
541
542         if (waserror()) {
543                 poperror();
544                 return -1;
545         }
546
547         c0 = namec(new, Abind, 0, 0);
548         if (waserror()) {
549                 cclose(c0);
550                 nexterror();
551         }
552         r = bindmount(c0, old, flags, "");
553         poperror();
554         cclose(c0);
555
556         poperror();
557         return r;
558 }
559
560 int sysmount(int fd, int afd, char *old, int flags, char *spec)
561 {
562         ERRSTACK(1);
563         long r;
564         volatile struct {
565                 struct chan *c;
566         } c0;
567         volatile struct {
568                 struct chan *c;
569         } bc;
570         volatile struct {
571                 struct chan *c;
572         } ac;
573         struct mntparam mntparam;
574
575         ac.c = NULL;
576         bc.c = NULL;
577         c0.c = NULL;
578         if (waserror()) {
579                 cclose(ac.c);
580                 cclose(bc.c);
581                 cclose(c0.c);
582                 poperror();
583                 return -1;
584         }
585         bc.c = fdtochan(current->fgrp, fd, ORDWR, 0, 1);
586         if (afd >= 0)
587                 ac.c = fdtochan(current->fgrp, afd, ORDWR, 0, 1);
588         mntparam.chan = bc.c;
589         mntparam.authchan = ac.c;
590         mntparam.spec = spec;
591         mntparam.flags = flags;
592         c0.c = devtab[devno('M', 0)].attach((char *)&mntparam);
593
594         r = bindmount(c0.c, old, flags, spec);
595         poperror();
596         cclose(ac.c);
597         cclose(bc.c);
598         cclose(c0.c);
599
600         return r;
601 }
602
603 int sysunmount(char *old, char *new)
604 {
605         ERRSTACK(1);
606         volatile struct {
607                 struct chan *c;
608         } cmount;
609         volatile struct {
610                 struct chan *c;
611         } cmounted;
612
613         cmount.c = NULL;
614         cmounted.c = NULL;
615         if (waserror()) {
616                 cclose(cmount.c);
617                 cclose(cmounted.c);
618                 poperror();
619                 return -1;
620         }
621
622         cmount.c = namec(new, Amount, 0, 0);
623         if (old != NULL && old[0] != '\0') {
624                 /*
625                  * This has to be namec(..., Aopen, ...) because
626                  * if arg[0] is something like /srv/cs or /fd/0,
627                  * opening it is the only way to get at the real
628                  * Chan underneath.
629                  */
630                 cmounted.c = namec(old, Aopen, OREAD, 0);
631         }
632
633         cunmount(cmount.c, cmounted.c);
634         poperror();
635         cclose(cmount.c);
636         cclose(cmounted.c);
637         return 0;
638 }
639
640 int sysopen(char *path, int vfs_flags)
641 {
642         ERRSTACK(2);
643         int fd;
644         struct chan *c;
645
646         if (waserror()) {
647                 poperror();
648                 return -1;
649         }
650
651         openmode(vfs_flags);    /* error check only */
652         c = namec(path, Aopen, vfs_flags, 0);
653         if (waserror()) {
654                 cclose(c);
655                 nexterror();
656         }
657         fd = newfd(c);
658         if (fd < 0)
659                 error(Enofd);
660         poperror();
661
662         poperror();
663         return fd;
664 }
665
666 long unionread(struct chan *c, void *va, long n)
667 {
668         ERRSTACK(1);
669         int i;
670         long nr;
671         struct mhead *m;
672         struct mount *mount;
673
674         qlock(&c->umqlock);
675         m = c->umh;
676         rlock(&m->lock);
677         mount = m->mount;
678         /* bring mount in sync with c->uri and c->umc */
679         for (i = 0; mount != NULL && i < c->uri; i++)
680                 mount = mount->next;
681
682         nr = 0;
683         while (mount != NULL) {
684                 /* Error causes component of union to be skipped */
685                 if (mount->to) {
686                         /* normally we want to discard the error, but for our ghetto kdirent
687                          * hack, we need to repeat unionread if we saw a Eshort */
688                         if (waserror()) {
689                                 if (!strcmp(current_errstr(), Eshort)) {
690                                         runlock(&m->lock);
691                                         qunlock(&c->umqlock);
692                                         nexterror();
693                                 }
694                                 /* poperror done below for either branch */
695                         } else {
696                                 if (c->umc == NULL) {
697                                         c->umc = cclone(mount->to);
698                                         c->umc = devtab[c->umc->type].open(c->umc, OREAD);
699                                 }
700
701                                 nr = devtab[c->umc->type].read(c->umc, va, n, c->umc->offset);
702                                 if (nr < 0)
703                                         nr = 0; /* dev.c can return -1 */
704                                 c->umc->offset += nr;
705                         }
706                         poperror();     /* pop regardless */
707                 }
708                 if (nr > 0)
709                         break;
710
711                 /* Advance to next element */
712                 c->uri++;
713                 if (c->umc) {
714                         cclose(c->umc);
715                         c->umc = NULL;
716                 }
717                 mount = mount->next;
718         }
719         runlock(&m->lock);
720         qunlock(&c->umqlock);
721         return nr;
722 }
723
724 static void unionrewind(struct chan *c)
725 {
726         qlock(&c->umqlock);
727         c->uri = 0;
728         if (c->umc) {
729                 cclose(c->umc);
730                 c->umc = NULL;
731         }
732         qunlock(&c->umqlock);
733 }
734
735 static long rread(int fd, void *va, long n, int64_t * offp)
736 {
737         ERRSTACK(3);
738         int dir;
739         struct chan *c;
740         int64_t off;
741
742         /* dirty dirent hack */
743         void *real_va = va;
744
745         if (waserror()) {
746                 poperror();
747                 return -1;
748         }
749
750         c = fdtochan(current->fgrp, fd, OREAD, 1, 1);
751         if (waserror()) {
752                 cclose(c);
753                 nexterror();
754         }
755
756         if (n < 0)
757                 error(Etoosmall);
758
759         dir = c->qid.type & QTDIR;
760
761         /* kdirent hack: userspace is expecting kdirents, but all of 9ns
762          * produces Ms.  Just save up what we don't use and append the
763          * new stuff later. Allocate DIRREADSIZE bytes for that purpose.
764          */
765         if (dir) {
766                 /* expecting only one dirent at a time, o/w we're busted */
767                 assert(n >= sizeof(struct kdirent));
768                 if (!c->buf) {
769                         c->buf=kmalloc(2048, KMALLOC_WAIT);
770                         c->bufused = 0;
771                 }
772                 /* debugging */
773                 if (waserror()) {
774                         printk("Well, sysread of a dir sucks.%s \n", current_errstr());
775                         nexterror();
776                 }
777                 va = c->buf + c->bufused;
778                 n = DIRREADSIZE - c->bufused;
779         }
780
781         /* this is the normal plan9 read */
782         if (dir && c->umh)
783                 n = unionread(c, va, n);
784         else {
785                 if (offp == NULL) {
786                         spin_lock(&c->lock);    /* lock for int64_t assignment */
787                         off = c->offset;
788                         spin_unlock(&c->lock);
789                 } else
790                         off = *offp;
791                 if (off < 0)
792                         error(Enegoff);
793                 if (off == 0) {
794                         if (offp == NULL) {
795                                 spin_lock(&c->lock);
796                                 c->offset = 0;
797                                 c->dri = 0;
798                                 spin_unlock(&c->lock);
799                         }
800                         unionrewind(c);
801                 }
802                 n = devtab[c->type].read(c, va, n, off);
803                 spin_lock(&c->lock);
804                 c->offset += n;
805                 spin_unlock(&c->lock);
806         }
807
808         /* dirty kdirent hack */
809         if (dir) {
810                 int amt;
811                 c->bufused = c->bufused + n;
812                 amt = convM2kdirent(c->buf, c->bufused, real_va, 0);
813                 c->bufused -= amt;
814                 memmove(c->buf, c->buf + amt, c->bufused);
815                 n = amt;
816                 poperror();     /* matching our debugging waserror */
817         }
818
819         poperror();
820         cclose(c);
821
822         poperror();
823         return n;
824 }
825
826 long sysread(int fd, void *va, long n)
827 {
828         return rread(fd, va, n, NULL);
829 }
830
831 long syspread(int fd, void *va, long n, int64_t off)
832 {
833         return rread(fd, va, n, &off);
834 }
835
836 int sysremove(char *path)
837 {
838         ERRSTACK(2);
839         struct chan *c;
840
841         if (waserror()) {
842                 poperror();
843                 return -1;
844         }
845
846         c = namec(path, Aremove, 0, 0);
847         if (waserror()) {
848                 c->type = -1;   /* see below */
849                 cclose(c);
850                 nexterror();
851         }
852         devtab[c->type].remove(c);
853         /*
854          * Remove clunks the fid, but we need to recover the Chan
855          * so fake it up.  -1 aborts the dev's close.
856          */
857         c->type = -1;
858         poperror();
859         cclose(c);
860
861         poperror();
862         return 0;
863 }
864
865 int64_t sysseek(int fd, int64_t off, int whence)
866 {
867         ERRSTACK(2);
868         struct dir *dir;
869         struct chan *c;
870
871         if (waserror()) {
872                 poperror();
873                 return -1;
874         }
875
876         c = fdtochan(current->fgrp, fd, -1, 1, 1);
877         if (waserror()) {
878                 cclose(c);
879                 nexterror();
880         }
881
882         if (devtab[c->type].dc == '|')
883                 error(Eisstream);
884
885         switch (whence) {
886                 case 0:
887                         if (c->qid.type & QTDIR) {
888                                 if (off != 0)
889                                         error(Eisdir);
890                                 unionrewind(c);
891                         } else if (off < 0)
892                                 error(Enegoff);
893                         spin_lock(&c->lock);    /* lock for int64_t assignment */
894                         c->offset = off;
895                         spin_unlock(&c->lock);
896                         break;
897
898                 case 1:
899                         if (c->qid.type & QTDIR)
900                                 error(Eisdir);
901                         spin_lock(&c->lock);    /* lock for read/write update */
902                         off += c->offset;
903                         if (off < 0) {
904                                 spin_unlock(&c->lock);
905                                 error(Enegoff);
906                         }
907                         c->offset = off;
908                         spin_unlock(&c->lock);
909                         break;
910
911                 case 2:
912                         if (c->qid.type & QTDIR)
913                                 error(Eisdir);
914                         dir = chandirstat(c);
915                         if (dir == NULL)
916                                 error("internal error: stat error in seek");
917                         off += dir->length;
918                         kfree(dir);
919                         if (off < 0)
920                                 error(Enegoff);
921                         spin_lock(&c->lock);    /* lock for read/write update */
922                         c->offset = off;
923                         spin_unlock(&c->lock);
924                         break;
925
926                 default:
927                         error(Ebadarg);
928                         break;
929         }
930         poperror();
931         c->dri = 0;
932         cclose(c);
933         poperror();
934         return off;
935 }
936
937 void validstat(uint8_t * s, int n)
938 {
939         
940         int m;
941         char buf[64];
942
943         if (statcheck(s, n) < 0)
944                 error(Ebadstat);
945         /* verify that name entry is acceptable */
946         s += STATFIXLEN - 4 * BIT16SZ;  /* location of first string */
947         /*
948          * s now points at count for first string.
949          * if it's too long, let the server decide; this is
950          * only for his protection anyway. otherwise
951          * we'd have to allocate and waserror.
952          */
953         m = GBIT16(s);
954         s += BIT16SZ;
955         if (m + 1 > sizeof buf) {
956                 return;
957         }
958         memmove(buf, s, m);
959         buf[m] = '\0';
960         /* name could be '/' */
961         if (strcmp(buf, "/") != 0)
962                 validname(buf, 0);
963 }
964
965 int sysfstat(int fd, uint8_t *buf, int n)
966 {
967         ERRSTACK(2);
968         struct chan *c;
969
970         if (waserror()) {
971                 poperror();
972                 return -1;
973         }
974
975         c = fdtochan(current->fgrp, fd, -1, 0, 1);
976         if (waserror()) {
977                 cclose(c);
978                 nexterror();
979         }
980         devtab[c->type].stat(c, buf, n);
981
982         poperror();
983         cclose(c);
984
985         poperror();
986         return n;
987 }
988
989 int sysfstatakaros(int fd, struct kstat *ks)
990 {
991         
992         int n = 4096;
993         uint8_t *buf;
994         buf = kmalloc(n, KMALLOC_WAIT);
995         n = sysfstat(fd, buf, n);
996         if (n > 0) {
997                 convM2kstat(buf, n, ks);
998                 n = 0;
999         }
1000         kfree(buf);
1001         return n;
1002 }
1003
1004 int sysstat(char *path, uint8_t *buf, int n)
1005 {
1006         ERRSTACK(2);
1007         struct chan *c;
1008
1009         if (waserror()) {
1010                 poperror();
1011                 return -1;
1012         }
1013
1014         c = namec(path, Aaccess, 0, 0);
1015         if (waserror()) {
1016                 cclose(c);
1017                 nexterror();
1018         }
1019         devtab[c->type].stat(c, buf, n);
1020         poperror();
1021         cclose(c);
1022
1023         poperror();
1024
1025         return n;
1026 }
1027
1028 int sysstatakaros(char *path, struct kstat *ks)
1029 {
1030         
1031         int n = 4096;
1032         uint8_t *buf;
1033         buf = kmalloc(n, KMALLOC_WAIT);
1034         n = sysstat(path, buf, n);
1035         if (n > 0) {
1036                 convM2kstat(buf, n, ks);
1037                 n = 0;
1038         }
1039         kfree(buf);
1040         return n;
1041 }
1042
1043 static long rwrite(int fd, void *va, long n, int64_t * offp)
1044 {
1045         ERRSTACK(3);
1046         struct chan *c;
1047         struct dir *dir;
1048         int64_t off;
1049         long m;
1050
1051         if (waserror()) {
1052                 poperror();
1053                 return -1;
1054         }
1055         c = fdtochan(current->fgrp, fd, OWRITE, 1, 1);
1056         if (waserror()) {
1057                 cclose(c);
1058                 nexterror();
1059         }
1060         if (c->qid.type & QTDIR)
1061                 error(Eisdir);
1062
1063         if (n < 0)
1064                 error(Etoosmall);
1065
1066         if (offp == NULL) {
1067                 /* append changes the offset to the end, and even if we fail later, this
1068                  * change will persist */
1069                 if (c->flag & CAPPEND) {
1070                         dir = chandirstat(c);
1071                         if (!dir)
1072                                 error("internal error: stat error in append write");
1073                         spin_lock(&c->lock);    /* legacy lock for int64 assignment */
1074                         c->offset = dir->length;
1075                         spin_unlock(&c->lock);
1076                         kfree(dir);
1077                 }
1078                 spin_lock(&c->lock);
1079                 off = c->offset;
1080                 c->offset += n;
1081                 spin_unlock(&c->lock);
1082         } else
1083                 off = *offp;
1084
1085         if (waserror()) {
1086                 if (offp == NULL) {
1087                         spin_lock(&c->lock);
1088                         c->offset -= n;
1089                         spin_unlock(&c->lock);
1090                 }
1091                 nexterror();
1092         }
1093         if (off < 0)
1094                 error(Enegoff);
1095         m = devtab[c->type].write(c, va, n, off);
1096         poperror();
1097
1098         if (offp == NULL && m < n) {
1099                 spin_lock(&c->lock);
1100                 c->offset -= n - m;
1101                 spin_unlock(&c->lock);
1102         }
1103
1104         poperror();
1105         cclose(c);
1106
1107         poperror();
1108         return n;
1109 }
1110
1111 long syswrite(int fd, void *va, long n)
1112 {
1113         return rwrite(fd, va, n, NULL);
1114 }
1115
1116 long syspwrite(int fd, void *va, long n, int64_t off)
1117 {
1118         return rwrite(fd, va, n, &off);
1119 }
1120
1121 int syswstat(char *path, uint8_t * buf, int n)
1122 {
1123         ERRSTACK(2);
1124         struct chan *c;
1125
1126         if (waserror()) {
1127                 poperror();
1128                 return -1;
1129         }
1130
1131         validstat(buf, n);
1132         c = namec(path, Aaccess, 0, 0);
1133         if (waserror()) {
1134                 cclose(c);
1135                 nexterror();
1136         }
1137         n = devtab[c->type].wstat(c, buf, n);
1138         poperror();
1139         cclose(c);
1140
1141         poperror();
1142         return n;
1143 }
1144
1145 struct dir *chandirstat(struct chan *c)
1146 {
1147         ERRSTACK(1);
1148         struct dir *d;
1149         uint8_t *buf;
1150         int n, nd, i;
1151
1152         nd = DIRSIZE;
1153         for (i = 0; i < 2; i++) {       /* should work by the second try */
1154                 d = kzmalloc(sizeof(struct dir) + nd, 0);
1155                 buf = (uint8_t *) & d[1];
1156                 if (waserror()) {
1157                         kfree(d);
1158                         poperror();
1159                         return NULL;
1160                 }
1161                 n = devtab[c->type].stat(c, buf, nd);
1162                 poperror();
1163                 if (n < BIT16SZ) {
1164                         kfree(d);
1165                         return NULL;
1166                 }
1167                 nd = GBIT16((uint8_t *) buf) + BIT16SZ; /* size needed to store whole stat buffer including count */
1168                 if (nd <= n) {
1169                         convM2D(buf, n, d, (char *)&d[1]);
1170                         return d;
1171                 }
1172                 /* else sizeof(Dir)+nd is plenty */
1173                 kfree(d);
1174         }
1175         return NULL;
1176
1177 }
1178
1179 struct dir *sysdirstat(char *name)
1180 {
1181         ERRSTACK(2);
1182         struct chan *c;
1183         struct dir *d;
1184
1185         if (waserror()) {
1186                 poperror();
1187                 return NULL;
1188         }
1189
1190         c = namec(name, Aaccess, 0, 0);
1191         if (waserror()) {
1192                 cclose(c);
1193                 nexterror();
1194         }
1195         d = chandirstat(c);
1196         poperror();
1197         cclose(c);
1198
1199         poperror();
1200         return d;
1201 }
1202
1203 struct dir *sysdirfstat(int fd)
1204 {
1205         ERRSTACK(2);
1206         struct chan *c;
1207         struct dir *d;
1208
1209         if (waserror()) {
1210                 poperror();
1211                 return NULL;
1212         }
1213
1214         c = fdtochan(current->fgrp, fd, -1, 0, 1);
1215         if (waserror()) {
1216                 cclose(c);
1217                 nexterror();
1218         }
1219         d = chandirstat(c);
1220         poperror();
1221         cclose(c);
1222
1223         poperror();
1224         return d;
1225 }
1226
1227 int sysdirwstat(char *name, struct dir *dir)
1228 {
1229         
1230         uint8_t *buf;
1231         int r;
1232
1233         r = sizeD2M(dir);
1234         buf = kzmalloc(r, 0);
1235         convD2M(dir, buf, r);
1236         r = syswstat(name, buf, r);
1237         kfree(buf);
1238         return r < 0 ? r : 0;
1239 }
1240
1241 int sysdirfwstat(int fd, struct dir *dir)
1242 {
1243         
1244         uint8_t *buf;
1245         int r;
1246
1247         r = sizeD2M(dir);
1248         buf = kzmalloc(r, 0);
1249         convD2M(dir, buf, r);
1250         r = sysfwstat(fd, buf, r);
1251         kfree(buf);
1252         return r < 0 ? r : 0;
1253 }
1254
1255 static long dirpackage(uint8_t * buf, long ts, struct kdirent **d)
1256 {
1257         
1258         char *s;
1259         long ss, i, n, nn, m = 0;
1260
1261         *d = NULL;
1262         if (ts <= 0) {
1263                 return ts;
1264         }
1265
1266         /*
1267          * first find number of all stats, check they look like stats, & size all associated strings
1268          */
1269         ss = 0;
1270         n = 0;
1271         for (i = 0; i < ts; i += m) {
1272                 m = BIT16SZ + GBIT16(&buf[i]);
1273                 if (statcheck(&buf[i], m) < 0)
1274                         break;
1275                 ss += m;
1276                 n++;
1277         }
1278
1279         if (i != ts)
1280                 error("bad directory format");
1281
1282         *d = kzmalloc(n * sizeof(**d) + ss, 0);
1283         if (*d == NULL)
1284                 error(Enomem);
1285
1286         /*
1287          * then convert all buffers
1288          */
1289         s = (char *)*d + n * sizeof(**d);
1290         nn = 0;
1291         for (i = 0; i < ts; i += m) {
1292                 m = BIT16SZ + GBIT16((uint8_t *) & buf[i]);
1293                 if (nn >= n || /*convM2D */ convM2kdirent(&buf[i], m, *d + nn, s) != m) {
1294                         kfree(*d);
1295                         *d = NULL;
1296                         error("bad directory entry");
1297                 }
1298                 nn++;
1299                 s += m;
1300         }
1301
1302         return nn;
1303 }
1304
1305 long sysdirread(int fd, struct kdirent **d)
1306 {
1307         ERRSTACK(2);
1308         uint8_t *buf;
1309         long ts;
1310
1311         *d = NULL;
1312         if (waserror()) {
1313                 poperror();
1314                 return -1;
1315         }
1316         buf = kzmalloc(DIRREADLIM, 0);
1317         if (buf == NULL)
1318                 error(Enomem);
1319         if (waserror()) {
1320                 kfree(buf);
1321                 nexterror();
1322         }
1323         ts = sysread(fd, buf, DIRREADLIM);
1324         if (ts >= 0)
1325                 ts = dirpackage(buf, ts, d);
1326         poperror();
1327         kfree(buf);
1328         poperror();
1329         return ts;
1330 }
1331
1332 int sysiounit(int fd)
1333 {
1334         ERRSTACK(1);
1335         struct chan *c;
1336         int n;
1337
1338         c = fdtochan(current->fgrp, fd, -1, 0, 1);
1339         if (waserror()) {
1340                 cclose(c);
1341                 poperror();
1342                 return 0;       /* n.b. */
1343         }
1344         n = c->iounit;
1345         poperror();
1346         cclose(c);
1347         return n;
1348 }
1349
1350 /* Notes on concurrency:
1351  * - Can't hold spinlocks while we call cclose, since it might sleep eventually.
1352  * - We're called from proc_destroy, so we could have concurrent openers trying
1353  *   to add to the group (other syscalls), hence the "closed" flag.
1354  * - dot and slash chans are dealt with in proc_free.  its difficult to close
1355  *   and zero those with concurrent syscalls, since those are a source of krefs.
1356  * - the memory is freed in proc_free().  need to wait to do it, since we can
1357  *   have concurrent accesses to fgrp before free.
1358  * - Once we lock and set closed, no further additions can happen.  To simplify
1359  *   our closes, we also allow multiple calls to this func (though that should
1360  *   never happen with the current code). */
1361 void close_9ns_files(struct proc *p, bool only_cloexec)
1362 {
1363         
1364         struct fgrp *f = p->fgrp;
1365
1366         spin_lock(&f->lock);
1367         if (f->closed) {
1368                 spin_unlock(&f->lock);
1369                 warn("Unexpected double-close");
1370                 return;
1371         }
1372         if (!only_cloexec)
1373                 f->closed = TRUE;
1374         spin_unlock(&f->lock);
1375
1376         /* maxfd is a legit val, not a +1 */
1377         for (int i = 0; i <= f->maxfd; i++) {
1378                 if (!f->fd[i])
1379                         continue;
1380                 if (only_cloexec && !(f->fd[i]->flag & CCEXEC))
1381                         continue;
1382                 cclose(f->fd[i]);
1383                 f->fd[i] = 0;
1384         }
1385 }
1386
1387 void print_chaninfo(struct chan *c)
1388 {
1389         
1390         char buf[64] = { 0 };
1391         bool has_dev = c->type != -1;
1392         if (has_dev && !devtab[c->type].chaninfo) {
1393                 printk("Chan type %d has no chaninfo!\n", c->type);
1394                 has_dev = FALSE;
1395         }
1396         printk("Chan pathname: %s ref %d, Dev: %s, Devinfo: %s",
1397                    c->name ? c->name->s : "no cname",
1398                    kref_refcnt(&c->ref),
1399                    has_dev ? devtab[c->type].name : "no dev",
1400                    has_dev ? devtab[c->type].chaninfo(c, buf, sizeof(buf)) : "");
1401         if (!has_dev)
1402                 printk("qid.path: %p\n", c->qid.path);
1403         printk("\n");
1404 }
1405
1406 void print_9ns_files(struct proc *p)
1407 {
1408         
1409         struct fgrp *f = p->fgrp;
1410         spin_lock(&f->lock);
1411         printk("9ns files for proc %d:\n", p->pid);
1412         /* maxfd is a legit val, not a +1 */
1413         for (int i = 0; i <= f->maxfd; i++) {
1414                 if (!f->fd[i])
1415                         continue;
1416                 printk("\t9fs %4d, ", i);
1417                 print_chaninfo(f->fd[i]);
1418         }
1419         spin_unlock(&f->lock);
1420 }
1421
1422 /* TODO: 9ns ns inheritance flags: Shared, copied, or empty.  Looks like we're
1423  * copying the fgrp, and sharing the pgrp. */
1424 int plan9setup(struct proc *new_proc, struct proc *parent, int flags)
1425 {
1426         
1427         struct proc *old_current;
1428         struct kref *new_dot_ref;
1429         ERRSTACK(1);
1430         if (waserror()) {
1431                 printk("plan9setup failed, %s\n", current_errstr());
1432                 poperror();
1433                 return -1;
1434         }
1435         if (!parent) {
1436                 /* We are probably spawned by the kernel directly, and have no parent to
1437                  * inherit from.  Be sure to set up fgrp/pgrp before calling namec().
1438                  *
1439                  * TODO: One problem is namec wants a current set for things like
1440                  * genbuf.  So we'll use new_proc for this bootstrapping.  Note
1441                  * switch_to() also loads the cr3. */
1442                 new_proc->fgrp = newfgrp();
1443                 new_proc->pgrp = newpgrp();
1444                 old_current = switch_to(new_proc);
1445                 new_proc->slash = namec("#r", Atodir, 0, 0);
1446                 if (!new_proc->slash)
1447                         panic("no root device");
1448                 switch_back(new_proc, old_current);
1449                 /* Want the name to be "/" instead of "#r" */
1450                 cnameclose(new_proc->slash->name);
1451                 new_proc->slash->name = newcname("/");
1452                 new_proc->dot = cclone(new_proc->slash);
1453                 poperror();
1454                 return 0;
1455         }
1456         /* When we use the old fgrp, we have copy semantics: do not change this
1457          * without revisiting proc_destroy, close_9ns_files, and closefgrp. */
1458         if (flags & PROC_DUP_FGRP)
1459                 new_proc->fgrp = dupfgrp(new_proc, parent->fgrp);
1460         else
1461                 new_proc->fgrp = newfgrp();
1462         /* Shared semantics */
1463         kref_get(&parent->pgrp->ref, 1);
1464         new_proc->pgrp = parent->pgrp;
1465         /* copy semantics on / and . (doesn't make a lot of sense in akaros o/w) */
1466         /* / should never disappear while we hold a ref to parent */
1467         chan_incref(parent->slash);
1468         new_proc->slash = parent->slash;
1469         /* dot could change concurrently, and we could fail to gain a ref if whoever
1470          * decref'd dot triggered the release.  if that did happen, new_proc->dot
1471          * should update and we can try again. */
1472         while (!(new_dot_ref = kref_get_not_zero(&parent->dot->ref, 1)))
1473                 cpu_relax();
1474         /* And now, we can't trust parent->dot, and need to determine our dot from
1475          * the ref we obtained. */
1476         new_proc->dot = container_of(new_dot_ref, struct chan, ref);
1477         poperror();
1478         return 0;
1479 }
1480
1481 /* Open flags, create modes, access types, file flags, and all that...
1482  *
1483  * there are a bunch of things here:
1484  *              1) file creation flags (e.g. O_TRUNC)
1485  *              2) file status flags (e.g. O_APPEND)
1486  *              3) file open modes (e.g. O_RDWR)
1487  *              4) file descriptor flags (e.g. CLOEXEC)
1488  *              5) file creation mode (e.g. S_IRWXU)
1489  * the 1-4 are passed in via open's vfs_flags, and the 5 via mode only when
1490  * O_CREATE is set.
1491  *
1492  * file creation flags (1) only matter when creating, but aren't permanent.
1493  * O_EXCL, O_DIRECTORY, O_TRUNC, etc.
1494  *
1495  * file status flags (2) are per struct file/chan.  stuff like O_APPEND,
1496  * O_ASYNC, etc.  we convert those to an internal flag bit and store in c->flags
1497  *
1498  * the open mode (3) matters for a given FD/chan (chan->mode), and should be
1499  * stored in the chan. (c->mode) stuff like O_RDONLY.
1500  *
1501  * the file descriptor flags (4) clearly are in the FD.  note that the same
1502  * file/chan can be opened by two different FDs, with different flags.  the only
1503  * one anyone uses is CLOEXEC.  while exec may not last long in akaros, i can
1504  * imagine similar "never pass to children" flags/meanings.
1505  *
1506  * the file creation mode (5) matters for the device's permissions; given this,
1507  * it should be stored in the device/inode.  ACLs fall under this category.
1508  *
1509  * finally, only certain categories can be edited afterwards: file status flags
1510  * (2), FD flags (4), and file permissions (5). */
1511 int fd_getfl(int fd)
1512 {
1513         ERRSTACK(1);
1514         struct chan *c;
1515         int ret;
1516
1517         if (waserror()) {
1518                 poperror();
1519                 return -1;
1520         }
1521         c = fdtochan(current->fgrp, fd, -1, 0, 1);
1522
1523         ret = c->mode;
1524         if (c->flag & CAPPEND)
1525                 ret |= O_APPEND;
1526
1527         cclose(c);
1528         poperror();
1529         return ret;
1530 }
1531
1532 int fd_setfl(int fd, int flags)
1533 {
1534         ERRSTACK(1);
1535         struct chan *c;
1536
1537         if (waserror()) {
1538                 poperror();
1539                 return -1;
1540         }
1541         c = fdtochan(current->fgrp, fd, -1, 0, 1);
1542
1543         if (flags & O_APPEND)
1544                 c->flag |= CAPPEND;
1545
1546         cclose(c);
1547         poperror();
1548         return 0;
1549 }