9ns: Make chan_ctl() mandatory
[akaros.git] / kern / src / ns / sysfile.c
1 /* Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
2  * Portions Copyright © 1997-1999 Vita Nuova Limited
3  * Portions Copyright © 2000-2007 Vita Nuova Holdings Limited
4  *                                (www.vitanuova.com)
5  * Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
6  *
7  * Modified for the Akaros operating system:
8  * Copyright (c) 2013-2014 The Regents of the University of California
9  * Copyright (c) 2013-2015 Google Inc.
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a copy
12  * of this software and associated documentation files (the "Software"), to deal
13  * in the Software without restriction, including without limitation the rights
14  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15  * copies of the Software, and to permit persons to whom the Software is
16  * furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included in
19  * all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
24  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27  * SOFTWARE. */
28
29 #include <slab.h>
30 #include <kmalloc.h>
31 #include <kref.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <assert.h>
35 #include <error.h>
36 #include <cpio.h>
37 #include <pmap.h>
38 #include <smp.h>
39 #include <net/ip.h>
40 #include <rcu.h>
41
42 /* TODO: these sizes are hokey.  DIRSIZE is used in chandirstat, and it looks
43  * like it's the size of a common-case stat. */
44 enum {
45         DIRSIZE = STAT_FIX_LEN_AK + 32 * STAT_NR_STRINGS_AK,
46         DIRREADLIM = 2048,      /* should handle the largest reasonable directory entry */
47         DIRREADSIZE=8192,       /* Just read a lot. Memory is cheap, lots of bandwidth,
48                                  * and RPCs are very expensive. At the same time,
49                                  * let's not yet exceed a common MSIZE. */
50 };
51
52 int newfd(struct chan *c, int low_fd, int oflags, bool must_use_low)
53 {
54         int ret = insert_obj_fdt(&current->open_files, c, low_fd,
55                                  oflags & O_CLOEXEC ? FD_CLOEXEC : 0,
56                                  must_use_low);
57         if (ret >= 0)
58                 cclose(c);
59         return ret;
60 }
61
62 struct chan *fdtochan(struct fd_table *fdt, int fd, int mode, int chkmnt,
63                       int iref)
64 {
65         struct chan *c;
66
67         c = lookup_fd(fdt, fd, iref);
68         if (!c) {
69                 /* We lost the info about why there was a problem (we used to track file
70                  * group closed too, can add that in later). */
71                 error(EBADF, ERROR_FIXME);
72         }
73         if (chkmnt && (c->flag & CMSG)) {
74                 if (iref)
75                         cclose(c);
76                 error(EBADF, ERROR_FIXME);
77         }
78         if (mode < 0)
79                 return c;
80         if ((mode & c->mode) != mode) {
81                 if (iref)
82                         cclose(c);
83                 error(EBADF,
84                       "FD access mode failure: chan mode 0x%x, wanted 0x%x (opened with 0 instead of O_READ?)",
85                       c->mode, mode);
86         }
87         return c;
88 }
89
90 long kchanio(void *vc, void *buf, int n, int mode)
91 {
92         ERRSTACK(1);
93         int r;
94         struct chan *c;
95
96         c = vc;
97         if (waserror()) {
98                 poperror();
99                 return -1;
100         }
101
102         if (mode == O_READ)
103                 r = devtab[c->type].read(c, buf, n, c->offset);
104         else if (mode == O_WRITE)
105                 r = devtab[c->type].write(c, buf, n, c->offset);
106         else
107                 error(ENOSYS, "kchanio: use only O_READ xor O_WRITE");
108
109         spin_lock(&c->lock);
110         c->offset += r;
111         spin_unlock(&c->lock);
112         poperror();
113         return r;
114 }
115
116 int openmode(uint32_t omode)
117 {
118 /* GIANT WARNING: if this ever throws, ipopen (and probably many others) will
119  * screw up refcnts of Qctl, err, data, etc */
120 #if 0
121         /* this is the old plan9 style.  i think they want to turn exec into read,
122          * and strip off anything higher, and just return the RD/WR style bits.  not
123          * stuff like ORCLOSE.  the lack of OEXCL might be a bug on their part (it's
124          * the only one of their non-RW-related flags that isn't masked out).
125          *
126          * Note that we no longer convert OEXEC/O_EXEC to O_READ, and instead return
127          * just the O_ACCMODE bits. */
128         if (o >= (OTRUNC | OCEXEC | ORCLOSE | OEXEC))
129                 error(EINVAL, ERROR_FIXME);
130         o &= ~(OTRUNC | OCEXEC | ORCLOSE);
131         if (o > OEXEC)
132                 error(EINVAL, ERROR_FIXME);
133         if (o == OEXEC)
134                 return OREAD;
135         return o;
136 #endif
137         /* no error checking (we have a shitload of flags anyway), and we return the
138          * basic access modes (RD/WR/ETC) */
139         return omode & O_ACCMODE;
140 }
141
142 void fdclose(struct fd_table *fdt, int fd)
143 {
144         close_fd(fdt, fd);
145 }
146
147 static void set_dot(struct chan *c)
148 {
149         c = atomic_swap_ptr((void**)&current->dot, c);
150         synchronize_rcu();
151         cclose(c);
152 }
153
154 int syschdir(char *path)
155 {
156         ERRSTACK(1);
157         struct chan *c;
158
159         if (waserror()) {
160                 poperror();
161                 return -1;
162         }
163         c = namec(path, Atodir, 0, 0, NULL);
164         poperror();
165         set_dot(c);
166         return 0;
167 }
168
169 int sysfchdir(int fd)
170 {
171         ERRSTACK(1);
172         struct chan *c;
173
174         if (waserror()) {
175                 poperror();
176                 return -1;
177         }
178         c = fdtochan(&current->open_files, fd, -1, 0, 1);
179         poperror();
180         set_dot(c);
181         return 0;
182 }
183
184 int sysclose(int fd)
185 {
186         ERRSTACK(1);
187         struct fd_table *fdt = &current->open_files;
188
189         if (waserror()) {
190                 poperror();
191                 return -1;
192         }
193         /*
194          * Take no reference on the chan because we don't really need the
195          * data structure, and are calling fdtochan only for error checks.
196          * fdclose takes care of processes racing through here.
197          */
198         fdtochan(fdt, fd, -1, 0, 0);
199         fdclose(fdt, fd);
200         poperror();
201         return 0;
202 }
203
204 int syscreate(char *path, int mode, uint32_t perm)
205 {
206         ERRSTACK(2);
207         int fd;
208         struct chan *c;
209
210         if (waserror()) {
211                 poperror();
212                 return -1;
213         }
214
215         openmode(mode & ~O_EXCL);       /* error check only; OEXCL okay here */
216         c = namec(path, Acreate, mode, perm, NULL);
217         if (waserror()) {
218                 cclose(c);
219                 nexterror();
220         }
221         /* 9ns mode is the O_FLAGS and perm is glibc mode */
222         fd = newfd(c, 0, mode, FALSE);
223         if (fd < 0)
224                 error(-fd, ERROR_FIXME);
225         poperror();
226
227         poperror();
228         return fd;
229 }
230
231 int sysdup(int old, int low_fd, bool must_use_low)
232 {
233         ERRSTACK(1);
234         int fd;
235         struct chan *c;
236
237         if (waserror()) {
238                 poperror();
239                 return -1;
240         }
241         c = fdtochan(&current->open_files, old, -1, 0, 1);
242         if (c->qid.type & QTAUTH) {
243                 cclose(c);
244                 error(EPERM, ERROR_FIXME);
245         }
246         fd = newfd(c, low_fd, 0, must_use_low);
247         if (fd < 0) {
248                 cclose(c);
249                 error(-fd, ERROR_FIXME);
250         }
251         poperror();
252         return fd;
253 }
254
255 /* Could pass in the fdt instead of the proc, but we used to need the to_proc
256  * for now so we can claim a VFS FD.  Careful, we don't close the old chan. */
257 int sys_dup_to(struct proc *from_proc, unsigned int from_fd,
258                struct proc *to_proc, unsigned int to_fd)
259 {
260         ERRSTACK(1);
261         int ret;
262         struct chan *c;
263
264         if (waserror()) {
265                 poperror();
266                 return -1;
267         }
268         c = fdtochan(&from_proc->open_files, from_fd, -1, 0, 1);
269         if (c->qid.type & QTAUTH) {
270                 cclose(c);
271                 error(EPERM, ERROR_FIXME);
272         }
273         ret = insert_obj_fdt(&to_proc->open_files, c, to_fd, 0, TRUE);
274         /* drop the ref from fdtochan.  if insert succeeded, there is one other ref
275          * stored in the FDT */
276         cclose(c);
277         if (ret < 0)
278                 error(EFAIL, "Can't insert FD %d into FDG", to_fd);
279         poperror();
280         return 0;
281 }
282
283 char *sysfd2path(int fd)
284 {
285         ERRSTACK(1);
286         struct chan *c;
287         char *s;
288
289         if (waserror()) {
290                 poperror();
291                 return NULL;
292         }
293         c = fdtochan(&current->open_files, fd, -1, 0, 1);
294         s = NULL;
295         if (c->name != NULL) {
296                 s = kzmalloc(c->name->len + 1, 0);
297                 if (s == NULL) {
298                         cclose(c);
299                         error(ENOMEM, ERROR_FIXME);
300                 }
301                 memmove(s, c->name->s, c->name->len + 1);
302         }
303         cclose(c);
304         poperror();
305         return s;
306 }
307
308 char *sysgetcwd(void)
309 {
310         char *s = NULL;
311         struct chan *dot;
312
313         rcu_read_lock();
314         dot = rcu_dereference(current->dot);
315         kref_get(&dot->ref, 1);
316         rcu_read_unlock();
317         if (dot->name)
318                 kstrdup(&s, dot->name->s);
319         cclose(dot);
320         return s;
321 }
322
323 int sysfauth(int fd, char *aname)
324 {
325         ERRSTACK(2);
326         struct chan *c, *ac;
327
328         if (waserror()) {
329                 poperror();
330                 return -1;
331         }
332
333         validname(aname, 0);
334         c = fdtochan(&current->open_files, fd, O_RDWR, 0, 1);
335         if (waserror()) {
336                 cclose(c);
337                 nexterror();
338         }
339
340         ac = mntauth(c, aname);
341
342         /* at this point ac is responsible for keeping c alive */
343         poperror();     /* c */
344         cclose(c);
345
346         if (waserror()) {
347                 cclose(ac);
348                 nexterror();
349         }
350
351         fd = newfd(ac, 0, 0, FALSE);
352         if (fd < 0)
353                 error(-fd, ERROR_FIXME);
354         poperror();     /* ac */
355
356         poperror();
357
358         return fd;
359 }
360
361 int sysfversion(int fd, unsigned int msize, char *vers, unsigned int arglen)
362 {
363         ERRSTACK(2);
364         int m;
365         struct chan *c;
366
367         if (waserror()) {
368                 poperror();
369                 return -1;
370         }
371
372         /* check there's a NUL in the version string */
373         if (arglen == 0 || memchr(vers, 0, arglen) == 0)
374                 error(EINVAL, ERROR_FIXME);
375
376         c = fdtochan(&current->open_files, fd, O_RDWR, 0, 1);
377         if (waserror()) {
378                 cclose(c);
379                 nexterror();
380         }
381
382         m = mntversion(c, vers, msize, arglen);
383
384         poperror();
385         cclose(c);
386
387         poperror();
388         return m;
389 }
390
391 int sysfwstat(int fd, uint8_t * buf, int n)
392 {
393         ERRSTACK(2);
394         struct chan *c;
395
396         if (waserror()) {
397                 poperror();
398                 return -1;
399         }
400
401         validstat(buf, n, 0);
402         c = fdtochan(&current->open_files, fd, -1, 1, 1);
403         if (waserror()) {
404                 cclose(c);
405                 nexterror();
406         }
407         n = devtab[c->type].wstat(c, buf, n);
408         poperror();
409         cclose(c);
410
411         poperror();
412         return n;
413 }
414
415 long bindmount(struct chan *c, char *old, int flag, char *spec)
416 {
417         ERRSTACK(1);
418         int ret;
419         struct chan *c1;
420
421         if (flag > MMASK || (flag & MORDER) == (MBEFORE | MAFTER))
422                 error(EINVAL, ERROR_FIXME);
423
424         c1 = namec(old, Amount, 0, 0, NULL);
425         if (waserror()) {
426                 cclose(c1);
427                 nexterror();
428         }
429         ret = cmount(c, c1, flag, spec);
430
431         poperror();
432         cclose(c1);
433         return ret;
434 }
435
436 int sysbind(char *new, char *old, int flags)
437 {
438         ERRSTACK(2);
439         long r;
440         struct chan *c0;
441
442         if (waserror()) {
443                 poperror();
444                 return -1;
445         }
446
447         c0 = namec(new, Abind, 0, 0, NULL);
448         if (waserror()) {
449                 cclose(c0);
450                 nexterror();
451         }
452         r = bindmount(c0, old, flags, "");
453         poperror();
454         cclose(c0);
455
456         poperror();
457         return r;
458 }
459
460 int syssymlink(char *new_path, char *old_path)
461 {
462         ERRSTACK(1);
463         struct chan *c;
464
465         if (waserror()) {
466                 poperror();
467                 return -1;
468         }
469         validname(old_path, true);
470         c = namec(new_path, Acreate, O_EXCL,
471                   DMSYMLINK | S_IRWXU | S_IRWXG | S_IRWXO, old_path);
472         cclose(c);
473         poperror();
474         return 0;
475 }
476
477 int sysmount(int fd, int afd, char *old, int flags, char *spec)
478 {
479         ERRSTACK(1);
480         long r;
481         volatile struct {
482                 struct chan *c;
483         } c0;
484         volatile struct {
485                 struct chan *c;
486         } bc;
487         volatile struct {
488                 struct chan *c;
489         } ac;
490         struct mntparam mntparam;
491
492         ac.c = NULL;
493         bc.c = NULL;
494         c0.c = NULL;
495         if (waserror()) {
496                 cclose(ac.c);
497                 cclose(bc.c);
498                 cclose(c0.c);
499                 poperror();
500                 return -1;
501         }
502         bc.c = fdtochan(&current->open_files, fd, O_RDWR, 0, 1);
503         if (afd >= 0)
504                 ac.c = fdtochan(&current->open_files, afd, O_RDWR, 0, 1);
505         mntparam.chan = bc.c;
506         mntparam.authchan = ac.c;
507         mntparam.spec = spec;
508         mntparam.flags = flags;
509         c0.c = devtab[devno("mnt", 0)].attach((char *)&mntparam);
510         if (flags & MCACHE)
511                 c0.c = devtab[devno("gtfs", 0)].attach((char*)c0.c);
512         r = bindmount(c0.c, old, flags, spec);
513         poperror();
514         cclose(ac.c);
515         cclose(bc.c);
516         cclose(c0.c);
517
518         return r;
519 }
520
521 int sysunmount(char *src_path, char *onto_path)
522 {
523         ERRSTACK(1);
524         volatile struct {
525                 struct chan *c;
526         } cmount;
527         volatile struct {
528                 struct chan *c;
529         } cmounted;
530
531         cmount.c = NULL;
532         cmounted.c = NULL;
533         if (waserror()) {
534                 cclose(cmount.c);
535                 cclose(cmounted.c);
536                 poperror();
537                 return -1;
538         }
539
540         cmount.c = namec(onto_path, Amount, 0, 0, NULL);
541         if (src_path != NULL && src_path[0] != '\0') {
542                 /*
543                  * This has to be namec(..., Aopen, ...) because
544                  * if arg[0] is something like /srv/cs or /fd/0,
545                  * opening it is the only way to get at the real
546                  * Chan underneath.
547                  */
548                 cmounted.c = namec(src_path, Aopen, O_READ, 0, NULL);
549         }
550
551         cunmount(cmount.c, cmounted.c);
552         poperror();
553         cclose(cmount.c);
554         cclose(cmounted.c);
555         return 0;
556 }
557
558 int sysopenat(int fromfd, char *path, int vfs_flags)
559 {
560         ERRSTACK(1);
561         int fd;
562         struct chan *c = 0, *from = 0;
563
564         if (waserror()) {
565                 cclose(c);
566                 poperror();
567                 return -1;
568         }
569         openmode(vfs_flags);    /* error check only */
570         if ((path[0] == '/') || (fromfd == AT_FDCWD)) {
571                 c = namec(path, Aopen, vfs_flags, 0, NULL);
572         } else {
573                 /* We don't cclose from.  namec_from will convert it to the new chan
574                  * during the walk process (c).  It'll probably close from internally,
575                  * and give us something new for c.  On error, namec_from will cclose
576                  * from. */
577                 from = fdtochan(&current->open_files, fromfd, -1, FALSE, TRUE);
578                 if (!(from->flag & O_PATH))
579                         error(EINVAL, "Cannot openat from a non-O_PATH FD");
580                 c = namec_from(from, path, Aopen, vfs_flags, 0, NULL);
581         }
582         /* Devices should catch this, but just in case, we'll catch it. */
583         if ((c->qid.type & QTSYMLINK) && (vfs_flags & O_NOFOLLOW))
584                 error(ELOOP, "no-follow open of a symlink");
585         fd = newfd(c, 0, vfs_flags, FALSE);
586         if (fd < 0)
587                 error(-fd, ERROR_FIXME);
588         poperror();
589         return fd;
590 }
591
592 int sysopen(char *path, int vfs_flags)
593 {
594         return sysopenat(AT_FDCWD, path, vfs_flags);
595 }
596
597 long unionread(struct chan *c, void *va, long n)
598 {
599         ERRSTACK(1);
600         int i;
601         long nr;
602         struct mhead *m;
603         struct mount *mount;
604
605         qlock(&c->umqlock);
606         m = c->umh;
607         rlock(&m->lock);
608         mount = m->mount;
609         /* bring mount in sync with c->uri and c->umc */
610         for (i = 0; mount != NULL && i < c->uri; i++)
611                 mount = mount->next;
612
613         nr = 0;
614         while (mount != NULL) {
615                 /* Error causes component of union to be skipped */
616                 if (mount->to) {
617                         /* normally we want to discard the error, but for our ghetto kdirent
618                          * hack, we need to repeat unionread if we saw a ENODATA */
619                         if (waserror()) {
620                                 if (get_errno() == ENODATA) {
621                                         runlock(&m->lock);
622                                         qunlock(&c->umqlock);
623                                         nexterror();
624                                 }
625                                 /* poperror done below for either branch */
626                         } else {
627                                 if (c->umc == NULL) {
628                                         c->umc = cclone(mount->to);
629                                         c->umc = devtab[c->umc->type].open(c->umc,
630                                                                            O_READ);
631                                 }
632
633                                 nr = devtab[c->umc->type].read(c->umc, va, n, c->umc->offset);
634                                 if (nr < 0)
635                                         nr = 0; /* dev.c can return -1 */
636                                 c->umc->offset += nr;
637                         }
638                         poperror();     /* pop regardless */
639                 }
640                 if (nr > 0)
641                         break;
642
643                 /* Advance to next element */
644                 c->uri++;
645                 if (c->umc) {
646                         cclose(c->umc);
647                         c->umc = NULL;
648                 }
649                 mount = mount->next;
650         }
651         runlock(&m->lock);
652         qunlock(&c->umqlock);
653         return nr;
654 }
655
656 static void unionrewind(struct chan *c)
657 {
658         qlock(&c->umqlock);
659         c->uri = 0;
660         if (c->umc) {
661                 cclose(c->umc);
662                 c->umc = NULL;
663         }
664         qunlock(&c->umqlock);
665 }
666
667 static long rread(int fd, void *va, long n, int64_t * offp)
668 {
669         ERRSTACK(3);
670         int dir;
671         struct chan *c;
672         int64_t off;
673
674         /* dirty dirent hack */
675         void *real_va = va;
676
677         if (waserror()) {
678                 poperror();
679                 return -1;
680         }
681
682         c = fdtochan(&current->open_files, fd, O_READ, 1, 1);
683         if (waserror()) {
684                 cclose(c);
685                 nexterror();
686         }
687
688         if (n < 0)
689                 error(EINVAL, ERROR_FIXME);
690
691         dir = c->qid.type & QTDIR;
692
693         /* kdirent hack: userspace is expecting kdirents, but all of 9ns
694          * produces Ms.  Just save up what we don't use and append the
695          * new stuff later. Allocate DIRREADSIZE bytes for that purpose.
696          */
697         if (dir) {
698                 int amt;
699                 /* expecting only one dirent at a time, o/w we're busted */
700                 assert(n >= sizeof(struct kdirent));
701                 if (!c->buf) {
702                         c->buf = kmalloc(DIRREADSIZE, MEM_WAIT);
703                         c->bufused = 0;
704                 }
705                 /* Attempt to extract an M, in case there was some already */
706                 amt = convM2kdirent(c->buf, c->bufused, real_va, 0);
707                 if (amt) {
708                         c->bufused -= amt;
709                         memmove(c->buf, c->buf + amt, c->bufused);
710                         n = sizeof(struct kdirent);
711                         goto out;
712                 }
713                 /* debugging */
714                 if (waserror()) {
715                         printk("Well, sysread of a dir sucks.%s \n", current_errstr());
716                         nexterror();
717                 }
718                 va = c->buf + c->bufused;
719                 n = DIRREADSIZE - c->bufused;
720         }
721
722         /* this is the normal plan9 read */
723         if (dir && c->umh)
724                 n = unionread(c, va, n);
725         else {
726                 if (offp == NULL) {
727                         spin_lock(&c->lock);    /* lock for int64_t assignment */
728                         off = c->offset;
729                         spin_unlock(&c->lock);
730                 } else
731                         off = *offp;
732                 if (off < 0)
733                         error(EINVAL, ERROR_FIXME);
734                 if (off == 0) {
735                         if (offp == NULL) {
736                                 spin_lock(&c->lock);
737                                 c->offset = 0;
738                                 c->dri = 0;
739                                 spin_unlock(&c->lock);
740                         }
741                         unionrewind(c);
742                 }
743                 if (! c->ateof) {
744                         n = devtab[c->type].read(c, va, n, off);
745                         if (n == 0 && dir)
746                                 c->ateof = 1;
747                 } else {
748                         n = 0;
749                 }
750                 spin_lock(&c->lock);
751                 c->offset += n;
752                 spin_unlock(&c->lock);
753         }
754
755         /* dirty kdirent hack */
756         if (dir) {
757                 int amt;
758                 c->bufused = c->bufused + n;
759                 /* extract an M from the front, then shift the remainder back */
760                 amt = convM2kdirent(c->buf, c->bufused, real_va, 0);
761                 c->bufused -= amt;
762                 memmove(c->buf, c->buf + amt, c->bufused);
763                 n = amt ? sizeof(struct kdirent) : 0;
764                 poperror();     /* matching our debugging waserror */
765         }
766
767 out:
768         poperror();
769         cclose(c);
770
771         poperror();
772         return n;
773 }
774
775 /* Reads exactly n bytes from chan c, starting at its offset.  Can block, but if
776  * we get 0 back too soon (EOF or error), then we'll error out with ENODATA.
777  * That might need a little work - if there was a previous error, then we
778  * clobbered it and only know ENODATA but not why we completed early. */
779 void read_exactly_n(struct chan *c, void *vp, long n)
780 {
781         char *p;
782         long nn;
783         int total = 0, want = n;
784
785         p = vp;
786         while (n > 0) {
787                 nn = devtab[c->type].read(c, p, n, c->offset);
788                 printd("readn: Got %d@%lld\n", nn, c->offset);
789                 if (nn == 0)
790                         error(ENODATA, "wanted %d, got %d", want, total);
791                 spin_lock(&c->lock);
792                 c->offset += nn;
793                 spin_unlock(&c->lock);
794                 p += nn;
795                 n -= nn;
796                 total += nn;
797         }
798 }
799
800 long sysread(int fd, void *va, long n)
801 {
802         return rread(fd, va, n, NULL);
803 }
804
805 long syspread(int fd, void *va, long n, int64_t off)
806 {
807         return rread(fd, va, n, &off);
808 }
809
810 int sysremove(char *path)
811 {
812         ERRSTACK(2);
813         struct chan *c;
814
815         if (waserror()) {
816                 poperror();
817                 return -1;
818         }
819
820         c = namec(path, Aremove, 0, 0, NULL);
821         if (waserror()) {
822                 c->type = -1;   /* see below */
823                 cclose(c);
824                 nexterror();
825         }
826         devtab[c->type].remove(c);
827         /*
828          * Remove clunks the fid, but we need to recover the Chan
829          * so fake it up.  -1 aborts the dev's close.
830          */
831         c->type = -1;
832         poperror();
833         cclose(c);
834
835         poperror();
836         return 0;
837 }
838
839 int sysrename(char *from_path, char *to_path)
840 {
841         ERRSTACK(1);
842         struct chan *volatile renamee = NULL;
843         struct chan *parent_chan;
844
845         if (waserror()) {
846                 cclose(renamee);
847                 poperror();
848                 return -1;
849         }
850         renamee = namec(from_path, Aremove, 0, 0, NULL);
851         /* We might need to support wstat for 'short' rename (intra-directory, with
852          * no slashes).  Til then, we can just go with EXDEV. */
853         if (!devtab[renamee->type].rename)
854                 error(EXDEV, "device does not support rename");
855         parent_chan = namec(to_path, Arename, 0, 0, (char*)renamee);
856         /* When we're done, renamee still points to the file, but it's in the new
857          * location.  Its cname is still the old location, similar to remove.  If
858          * anyone cares, we can change it.  parent_chan still points to the parent -
859          * it didn't get moved like create does.  Though it does have the name of
860          * the new location.  If we want, we can hand that to renamee.  It's a moot
861          * point, since they are both getting closed. */
862         cclose(renamee);
863         cclose(parent_chan);
864         poperror();
865         return 0;
866 }
867
868 int64_t sysseek(int fd, int64_t off, int whence)
869 {
870         ERRSTACK(2);
871         struct dir *dir;
872         struct chan *c;
873
874         if (waserror()) {
875                 poperror();
876                 return -1;
877         }
878
879         c = fdtochan(&current->open_files, fd, -1, 1, 1);
880         if (waserror()) {
881                 cclose(c);
882                 nexterror();
883         }
884         switch (whence) {
885                 case 0:
886                         if (c->qid.type & QTDIR) {
887                                 if (off != 0)
888                                         error(EISDIR, ERROR_FIXME);
889                                 unionrewind(c);
890                         } else if (off < 0)
891                                 error(EINVAL, ERROR_FIXME);
892                         spin_lock(&c->lock);    /* lock for int64_t assignment */
893                         c->offset = off;
894                         spin_unlock(&c->lock);
895                         break;
896
897                 case 1:
898                         if (c->qid.type & QTDIR)
899                                 error(EISDIR, ERROR_FIXME);
900                         spin_lock(&c->lock);    /* lock for read/write update */
901                         off += c->offset;
902                         if (off < 0) {
903                                 spin_unlock(&c->lock);
904                                 error(EINVAL, ERROR_FIXME);
905                         }
906                         c->offset = off;
907                         spin_unlock(&c->lock);
908                         break;
909
910                 case 2:
911                         if (c->qid.type & QTDIR)
912                                 error(EISDIR, ERROR_FIXME);
913                         dir = chandirstat(c);
914                         if (dir == NULL)
915                                 error(EFAIL, "internal error: stat error in seek");
916                         off += dir->length;
917                         kfree(dir);
918                         if (off < 0)
919                                 error(EINVAL, ERROR_FIXME);
920                         spin_lock(&c->lock);    /* lock for read/write update */
921                         c->offset = off;
922                         spin_unlock(&c->lock);
923                         break;
924
925                 default:
926                         error(EINVAL, ERROR_FIXME);
927                         break;
928         }
929         poperror();
930         c->dri = 0;
931         cclose(c);
932         poperror();
933         return off;
934 }
935
936 void validstat(uint8_t * s, int n, int slashok)
937 {
938
939         int m;
940         char buf[64];
941
942         if (statcheck(s, n) < 0)
943                 error(EINVAL, ERROR_FIXME);
944         /* verify that name entry is acceptable */
945         s += STAT_FIX_LEN_9P - STAT_NR_STRINGS_9P * BIT16SZ;
946         /*
947          * s now points at count for first string.
948          * if it's too long, let the server decide; this is
949          * only for his protection anyway. otherwise
950          * we'd have to allocate and waserror.
951          */
952         m = GBIT16(s);
953         s += BIT16SZ;
954         if (m + 1 > sizeof buf) {
955                 return;
956         }
957         memmove(buf, s, m);
958         buf[m] = '\0';
959         /* name could be '/' */
960         if (strcmp(buf, "/") != 0)
961                 validname(buf, slashok);
962 }
963
964 int sysfstat(int fd, uint8_t *buf, int n)
965 {
966         ERRSTACK(2);
967         struct chan *c;
968
969         if (waserror()) {
970                 poperror();
971                 return -1;
972         }
973
974         c = fdtochan(&current->open_files, fd, -1, 0, 1);
975         if (waserror()) {
976                 cclose(c);
977                 nexterror();
978         }
979         devtab[c->type].stat(c, buf, n);
980
981         poperror();
982         cclose(c);
983
984         poperror();
985         return n;
986 }
987
988 int sysfstatakaros(int fd, struct kstat *ks)
989 {
990
991         int n = 4096;
992         uint8_t *buf;
993         buf = kmalloc(n, MEM_WAIT);
994         n = sysfstat(fd, buf, n);
995         if (n > 0) {
996                 convM2kstat(buf, n, ks);
997                 n = 0;
998         }
999         kfree(buf);
1000         return n;
1001 }
1002
1003 static int __stat(char *path, uint8_t *buf, int n, int flags)
1004 {
1005         ERRSTACK(2);
1006         struct chan *c;
1007
1008         if (waserror()) {
1009                 poperror();
1010                 return -1;
1011         }
1012
1013         c = namec(path, Aaccess, flags, 0, NULL);
1014         if (waserror()) {
1015                 cclose(c);
1016                 nexterror();
1017         }
1018         devtab[c->type].stat(c, buf, n);
1019         poperror();
1020         cclose(c);
1021
1022         poperror();
1023
1024         return n;
1025 }
1026
1027 int sysstat(char *path, uint8_t *buf, int n)
1028 {
1029         return __stat(path, buf, n, 0);
1030 }
1031
1032 int syslstat(char *path, uint8_t *buf, int n)
1033 {
1034         return __stat(path, buf, n, O_NOFOLLOW);
1035 }
1036
1037 int sysstatakaros(char *path, struct kstat *ks, int flags)
1038 {
1039
1040         int n = 4096;
1041         uint8_t *buf;
1042         buf = kmalloc(n, MEM_WAIT);
1043         n = __stat(path, buf, n, flags);
1044         if (n > 0) {
1045                 convM2kstat(buf, n, ks);
1046                 n = 0;
1047         }
1048         kfree(buf);
1049         return n;
1050 }
1051
1052 static long rwrite(int fd, void *va, long n, int64_t * offp)
1053 {
1054         ERRSTACK(3);
1055         struct chan *c;
1056         struct dir *dir;
1057         int64_t off;
1058         long m;
1059
1060         if (waserror()) {
1061                 poperror();
1062                 return -1;
1063         }
1064         c = fdtochan(&current->open_files, fd, O_WRITE, 1, 1);
1065         if (waserror()) {
1066                 cclose(c);
1067                 nexterror();
1068         }
1069         if (c->qid.type & QTDIR)
1070                 error(EISDIR, ERROR_FIXME);
1071
1072         if (n < 0)
1073                 error(EINVAL, ERROR_FIXME);
1074
1075         if (offp == NULL) {
1076                 /* append changes the offset to the end, and even if we fail later, this
1077                  * change will persist */
1078                 if (c->flag & O_APPEND) {
1079                         dir = chandirstat(c);
1080                         if (!dir)
1081                                 error(EFAIL, "internal error: stat error in append write");
1082                         spin_lock(&c->lock);    /* legacy lock for int64 assignment */
1083                         c->offset = dir->length;
1084                         spin_unlock(&c->lock);
1085                         kfree(dir);
1086                 }
1087                 spin_lock(&c->lock);
1088                 off = c->offset;
1089                 c->offset += n;
1090                 spin_unlock(&c->lock);
1091         } else
1092                 off = *offp;
1093
1094         if (waserror()) {
1095                 if (offp == NULL) {
1096                         spin_lock(&c->lock);
1097                         c->offset -= n;
1098                         spin_unlock(&c->lock);
1099                 }
1100                 nexterror();
1101         }
1102         if (off < 0)
1103                 error(EINVAL, ERROR_FIXME);
1104         m = devtab[c->type].write(c, va, n, off);
1105         poperror();
1106
1107         if (offp == NULL && m < n) {
1108                 spin_lock(&c->lock);
1109                 c->offset -= n - m;
1110                 spin_unlock(&c->lock);
1111         }
1112
1113         poperror();
1114         cclose(c);
1115
1116         poperror();
1117         return m;
1118 }
1119
1120 long syswrite(int fd, void *va, long n)
1121 {
1122         return rwrite(fd, va, n, NULL);
1123 }
1124
1125 long syspwrite(int fd, void *va, long n, int64_t off)
1126 {
1127         return rwrite(fd, va, n, &off);
1128 }
1129
1130 int syswstat(char *path, uint8_t * buf, int n)
1131 {
1132         ERRSTACK(2);
1133         struct chan *c;
1134
1135         if (waserror()) {
1136                 poperror();
1137                 return -1;
1138         }
1139
1140         validstat(buf, n, 0);
1141         c = namec(path, Aaccess, 0, 0, NULL);
1142         if (waserror()) {
1143                 cclose(c);
1144                 nexterror();
1145         }
1146         n = devtab[c->type].wstat(c, buf, n);
1147         poperror();
1148         cclose(c);
1149
1150         poperror();
1151         return n;
1152 }
1153
1154 struct dir *chandirstat(struct chan *c)
1155 {
1156         ERRSTACK(1);
1157         struct dir *d;
1158         uint8_t *buf;
1159         int n, nd, i;
1160
1161         nd = DIRSIZE;
1162         for (i = 0; i < 2; i++) {       /* should work by the second try */
1163                 d = kzmalloc(sizeof(struct dir) + nd, MEM_WAIT);
1164                 buf = (uint8_t *) & d[1];
1165                 if (waserror()) {
1166                         kfree(d);
1167                         poperror();
1168                         return NULL;
1169                 }
1170                 n = devtab[c->type].stat(c, buf, nd);
1171                 poperror();
1172                 if (n < BIT16SZ) {
1173                         kfree(d);
1174                         return NULL;
1175                 }
1176                 nd = GBIT16((uint8_t *) buf) + BIT16SZ; /* size needed to store whole stat buffer including count */
1177                 if (nd <= n) {
1178                         convM2D(buf, n, d, (char *)&d[1]);
1179                         return d;
1180                 }
1181                 /* else sizeof(Dir)+nd is plenty */
1182                 kfree(d);
1183         }
1184         return NULL;
1185
1186 }
1187
1188 static struct dir *__dir_stat(char *name, int flags)
1189 {
1190         ERRSTACK(2);
1191         struct chan *c;
1192         struct dir *d;
1193
1194         if (waserror()) {
1195                 poperror();
1196                 return NULL;
1197         }
1198
1199         c = namec(name, Aaccess, flags, 0, NULL);
1200         if (waserror()) {
1201                 cclose(c);
1202                 nexterror();
1203         }
1204         d = chandirstat(c);
1205         poperror();
1206         cclose(c);
1207
1208         poperror();
1209         return d;
1210 }
1211
1212 struct dir *sysdirstat(char *name)
1213 {
1214         return __dir_stat(name, 0);
1215 }
1216
1217 struct dir *sysdirlstat(char *name)
1218 {
1219         return __dir_stat(name, O_NOFOLLOW);
1220 }
1221
1222 struct dir *sysdirfstat(int fd)
1223 {
1224         ERRSTACK(2);
1225         struct chan *c;
1226         struct dir *d;
1227
1228         if (waserror()) {
1229                 poperror();
1230                 return NULL;
1231         }
1232
1233         c = fdtochan(&current->open_files, fd, -1, 0, 1);
1234         if (waserror()) {
1235                 cclose(c);
1236                 nexterror();
1237         }
1238         d = chandirstat(c);
1239         poperror();
1240         cclose(c);
1241
1242         poperror();
1243         return d;
1244 }
1245
1246 int sysdirwstat(char *name, struct dir *dir)
1247 {
1248
1249         uint8_t *buf;
1250         int r;
1251
1252         r = sizeD2M(dir);
1253         buf = kzmalloc(r, MEM_WAIT);
1254         convD2M(dir, buf, r);
1255         r = syswstat(name, buf, r);
1256         kfree(buf);
1257         return r < 0 ? r : 0;
1258 }
1259
1260 int sysdirfwstat(int fd, struct dir *dir)
1261 {
1262
1263         uint8_t *buf;
1264         int r;
1265
1266         r = sizeD2M(dir);
1267         buf = kzmalloc(r, MEM_WAIT);
1268         convD2M(dir, buf, r);
1269         r = sysfwstat(fd, buf, r);
1270         kfree(buf);
1271         return r < 0 ? r : 0;
1272 }
1273
1274 static long dirpackage(uint8_t * buf, long ts, struct kdirent **d)
1275 {
1276
1277         char *s;
1278         long ss, i, n, nn, m = 0;
1279
1280         *d = NULL;
1281         if (ts <= 0) {
1282                 return ts;
1283         }
1284
1285         /*
1286          * first find number of all stats, check they look like stats, & size all associated strings
1287          */
1288         ss = 0;
1289         n = 0;
1290         for (i = 0; i < ts; i += m) {
1291                 m = BIT16SZ + GBIT16(&buf[i]);
1292                 if (statcheck(&buf[i], m) < 0)
1293                         break;
1294                 ss += m;
1295                 n++;
1296         }
1297
1298         if (i != ts)
1299                 error(EFAIL, "bad directory format");
1300
1301         *d = kzmalloc(n * sizeof(**d) + ss, 0);
1302         if (*d == NULL)
1303                 error(ENOMEM, ERROR_FIXME);
1304
1305         /*
1306          * then convert all buffers
1307          */
1308         s = (char *)*d + n * sizeof(**d);
1309         nn = 0;
1310         for (i = 0; i < ts; i += m) {
1311                 m = BIT16SZ + GBIT16((uint8_t *) & buf[i]);
1312                 /* Note 's' is ignored by convM2kdirent */
1313                 if (nn >= n || /*convM2D */ convM2kdirent(&buf[i], m, *d + nn, s) != m) {
1314                         kfree(*d);
1315                         *d = NULL;
1316                         error(EFAIL, "bad directory entry");
1317                 }
1318                 nn++;
1319                 s += m;
1320         }
1321
1322         return nn;
1323 }
1324
1325 long sysdirread(int fd, struct kdirent **d)
1326 {
1327         ERRSTACK(2);
1328         uint8_t *buf;
1329         long ts;
1330
1331         *d = NULL;
1332         if (waserror()) {
1333                 poperror();
1334                 return -1;
1335         }
1336         buf = kzmalloc(DIRREADLIM, 0);
1337         if (buf == NULL)
1338                 error(ENOMEM, ERROR_FIXME);
1339         if (waserror()) {
1340                 kfree(buf);
1341                 nexterror();
1342         }
1343         ts = sysread(fd, buf, DIRREADLIM);
1344         if (ts >= 0)
1345                 ts = dirpackage(buf, ts, d);
1346         poperror();
1347         kfree(buf);
1348         poperror();
1349         return ts;
1350 }
1351
1352 int sysiounit(int fd)
1353 {
1354         ERRSTACK(1);
1355         struct chan *c;
1356         int n;
1357
1358         c = fdtochan(&current->open_files, fd, -1, 0, 1);
1359         if (waserror()) {
1360                 cclose(c);
1361                 poperror();
1362                 return 0;       /* n.b. */
1363         }
1364         n = c->iounit;
1365         poperror();
1366         cclose(c);
1367         return n;
1368 }
1369
1370 void print_chaninfo(struct chan *c)
1371 {
1372
1373         char buf[128] = { 0 };
1374         bool has_dev = c->type != -1;
1375         bool has_chaninfo = has_dev && devtab[c->type].chaninfo;
1376
1377         printk("Chan flags: %p, pathname: %s, ref: %d, Dev: %s, Devinfo: %s",
1378                    c->flag,
1379                    c->name ? c->name->s : "no cname",
1380                    kref_refcnt(&c->ref),
1381                    has_dev ? devtab[c->type].name : "no dev",
1382                    has_chaninfo ? devtab[c->type].chaninfo(c, buf, sizeof(buf)) : "");
1383         if (!has_chaninfo)
1384                 printk("qid.path: %p\n", c->qid.path);
1385         printk("\n");
1386 }
1387
1388 /* TODO: 9ns ns inheritance flags: Shared, copied, or empty.  The old fgrp is
1389  * managed by the fd_table, which is handled outside this function.  We share
1390  * the pgrp. */
1391 int plan9setup(struct proc *new_proc, struct proc *parent, int flags)
1392 {
1393
1394         struct chan *new_dot;
1395
1396         ERRSTACK(1);
1397         if (waserror()) {
1398                 printk("plan9setup failed, %s\n", current_errstr());
1399                 poperror();
1400                 return -1;
1401         }
1402         if (!parent) {
1403                 /* We are probably spawned by the kernel directly, and have no parent to
1404                  * inherit from. */
1405                 new_proc->pgrp = newpgrp();
1406                 new_proc->slash = namec("#kfs", Atodir, 0, 0, NULL);
1407                 if (!new_proc->slash)
1408                         panic("no kfs device");
1409                 /* Want the name to be "/" instead of "#kfs" */
1410                 cnameclose(new_proc->slash->name);
1411                 new_proc->slash->name = newcname("/");
1412                 new_proc->dot = cclone(new_proc->slash);
1413                 poperror();
1414                 return 0;
1415         }
1416         /* Shared semantics */
1417         kref_get(&parent->pgrp->ref, 1);
1418         new_proc->pgrp = parent->pgrp;
1419         /* copy semantics on / and . (doesn't make a lot of sense in akaros o/w) */
1420         /* / should never disappear while we hold a ref to parent */
1421         chan_incref(parent->slash);
1422         new_proc->slash = parent->slash;
1423
1424         rcu_read_lock();
1425         new_dot = rcu_dereference(parent->dot);
1426         kref_get(&new_dot->ref, 1);
1427         rcu_read_unlock();
1428         new_proc->dot = new_dot;
1429
1430         poperror();
1431         return 0;
1432 }
1433
1434 /* Open flags, create modes, access types, file flags, and all that...
1435  *
1436  * there are a bunch of things here:
1437  *              1) file creation flags (e.g. O_TRUNC)
1438  *              2) file status flags (e.g. O_APPEND)
1439  *              3) file open modes (e.g. O_RDWR)
1440  *              4) file descriptor flags (e.g. CLOEXEC)
1441  *              5) file creation mode (e.g. S_IRWXU)
1442  * the 1-4 are passed in via open's vfs_flags, and the 5 via mode only when
1443  * O_CREATE is set.
1444  *
1445  * file creation flags (1) only matter when creating, but aren't permanent.
1446  * O_EXCL, O_DIRECTORY, O_TRUNC, etc.
1447  *
1448  * file status flags (2) are per struct file/chan.  stuff like O_APPEND,
1449  * O_ASYNC, etc.  we convert those to an internal flag bit and store in c->flags
1450  *
1451  * the open mode (3) matters for a given FD/chan (chan->mode), and should be
1452  * stored in the chan. (c->mode) stuff like O_RDONLY.
1453  *
1454  * the file descriptor flags (4) clearly are in the FD.  note that the same
1455  * file/chan can be opened by two different FDs, with different flags.  the only
1456  * one anyone uses is CLOEXEC.  while exec may not last long in akaros, i can
1457  * imagine similar "never pass to children" flags/meanings.
1458  *
1459  * the file creation mode (5) matters for the device's permissions; given this,
1460  * it should be stored in the device/inode.  ACLs fall under this category.
1461  *
1462  * finally, only certain categories can be edited afterwards: file status flags
1463  * (2), FD flags (4), and file permissions (5). */
1464 int fd_getfl(int fd)
1465 {
1466         ERRSTACK(1);
1467         struct chan *c;
1468         int ret;
1469
1470         if (waserror()) {
1471                 poperror();
1472                 return -1;
1473         }
1474         c = fdtochan(&current->open_files, fd, -1, 0, 1);
1475
1476         ret = c->mode;
1477         ret |= c->flag & CEXTERNAL_FLAGS;
1478
1479         cclose(c);
1480         poperror();
1481         return ret;
1482 }
1483
1484 static bool cexternal_flags_differ(int set1, int set2, int flags)
1485 {
1486         flags &= CEXTERNAL_FLAGS;
1487         return (set1 & flags) ^ (set2 & flags);
1488 }
1489
1490 int fd_setfl(int fd, int flags)
1491 {
1492         ERRSTACK(2);
1493         struct chan *c;
1494         int ret = 0;
1495
1496         if (waserror()) {
1497                 poperror();
1498                 return -1;
1499         }
1500         c = fdtochan(&current->open_files, fd, -1, 0, 1);
1501         if (waserror()) {
1502                 cclose(c);
1503                 nexterror();
1504         }
1505         if (cexternal_flags_differ(flags, c->flag, O_CLOEXEC)) {
1506                 /* TODO: The whole CCEXEC / O_CLOEXEC on 9ns needs work */
1507                 error(EINVAL, "can't toggle O_CLOEXEC with setfl");
1508         }
1509         if (cexternal_flags_differ(flags, c->flag, O_REMCLO))
1510                 error(EINVAL, "can't toggle O_REMCLO with setfl");
1511         if (cexternal_flags_differ(flags, c->flag, O_PATH))
1512                 error(EINVAL, "can't toggle O_PATH with setfl");
1513         if (!devtab[c->type].chan_ctl)
1514                 error(EINVAL, "can't setfl, %s has no chan_ctl", chan_dev_name(c));
1515         ret = devtab[c->type].chan_ctl(c, CCTL_SET_FL, flags & CEXTERNAL_FLAGS,
1516                                        0, 0, 0);
1517         c->flag = (c->flag & ~CEXTERNAL_FLAGS) | (flags & CEXTERNAL_FLAGS);
1518         poperror();
1519         cclose(c);
1520         poperror();
1521         return ret;
1522 }
1523
1524 ssize_t kread_file(struct file_or_chan *file, void *buf, size_t sz)
1525 {
1526         /* TODO: (KFOP) (VFS kernel read/writes need to be from a ktask) */
1527         uintptr_t old_ret = switch_to_ktask();
1528         off64_t dummy = 0;
1529         ssize_t cpy_amt = foc_read(file, buf, sz, dummy);
1530
1531         switch_back_from_ktask(old_ret);
1532         return cpy_amt;
1533 }
1534
1535 /* Reads the contents of an entire file into a buffer, returning that buffer.
1536  * On error, prints something useful and returns 0 */
1537 void *kread_whole_file(struct file_or_chan *file)
1538 {
1539         size_t size;
1540         void *contents;
1541         ssize_t cpy_amt;
1542
1543         size = foc_get_len(file);
1544         contents = kmalloc(size, MEM_WAIT);
1545         cpy_amt = kread_file(file, contents, size);
1546         if (cpy_amt < 0) {
1547                 printk("Error %d reading file %s\n", get_errno(), foc_to_name(file));
1548                 kfree(contents);
1549                 return 0;
1550         }
1551         if (cpy_amt != size) {
1552                 printk("Read %d, needed %d for file %s\n", cpy_amt, size,
1553                        foc_to_name(file));
1554                 kfree(contents);
1555                 return 0;
1556         }
1557         return contents;
1558 }
1559
1560 /* Process-related File management functions */
1561
1562 /* Given any FD, get the appropriate object, 0 o/w. Set incref if you want a
1563  * reference count (which is a 9ns thing, you can't use the pointer if you
1564  * didn't incref). */
1565 void *lookup_fd(struct fd_table *fdt, int fd, bool incref)
1566 {
1567         void *retval = 0;
1568
1569         if (fd < 0)
1570                 return 0;
1571         spin_lock(&fdt->lock);
1572         if (fdt->closed) {
1573                 spin_unlock(&fdt->lock);
1574                 return 0;
1575         }
1576         if (fd < fdt->max_fdset) {
1577                 if (GET_BITMASK_BIT(fdt->open_fds->fds_bits, fd)) {
1578                         /* while max_files and max_fdset might not line up, we should never
1579                          * have a valid fdset higher than files */
1580                         assert(fd < fdt->max_files);
1581                         retval = fdt->fd[fd].fd_chan;
1582                         if (incref)
1583                                 chan_incref((struct chan*)retval);
1584                 }
1585         }
1586         spin_unlock(&fdt->lock);
1587         return retval;
1588 }
1589
1590 /* Grow the vfs fd set */
1591 static int grow_fd_set(struct fd_table *open_files)
1592 {
1593         int n;
1594         struct file_desc *nfd, *ofd;
1595
1596         /* Only update open_fds once. If currently pointing to open_fds_init, then
1597          * update it to point to a newly allocated fd_set with space for
1598          * NR_FILE_DESC_MAX */
1599         if (open_files->open_fds == (struct fd_set*)&open_files->open_fds_init) {
1600                 open_files->open_fds = kzmalloc(sizeof(struct fd_set), 0);
1601                 memmove(open_files->open_fds, &open_files->open_fds_init,
1602                         sizeof(struct small_fd_set));
1603         }
1604
1605         /* Grow the open_files->fd array in increments of NR_OPEN_FILES_DEFAULT */
1606         n = open_files->max_files + NR_OPEN_FILES_DEFAULT;
1607         if (n > NR_FILE_DESC_MAX)
1608                 return -EMFILE;
1609         nfd = kzmalloc(n * sizeof(struct file_desc), 0);
1610         if (nfd == NULL)
1611                 return -ENOMEM;
1612
1613         /* Move the old array on top of the new one */
1614         ofd = open_files->fd;
1615         memmove(nfd, ofd, open_files->max_files * sizeof(struct file_desc));
1616
1617         /* Update the array and the maxes for both max_files and max_fdset */
1618         open_files->fd = nfd;
1619         open_files->max_files = n;
1620         open_files->max_fdset = n;
1621
1622         /* Only free the old one if it wasn't pointing to open_files->fd_array */
1623         if (ofd != open_files->fd_array)
1624                 kfree(ofd);
1625         return 0;
1626 }
1627
1628 /* Free the vfs fd set if necessary */
1629 static void free_fd_set(struct fd_table *open_files)
1630 {
1631         void *free_me;
1632
1633         if (open_files->open_fds != (struct fd_set*)&open_files->open_fds_init) {
1634                 assert(open_files->fd != open_files->fd_array);
1635                 /* need to reset the pointers to the internal addrs, in case we take a
1636                  * look while debugging.  0 them out, since they have old data.  our
1637                  * current versions should all be closed. */
1638                 memset(&open_files->open_fds_init, 0, sizeof(struct small_fd_set));
1639                 memset(&open_files->fd_array, 0, sizeof(open_files->fd_array));
1640
1641                 free_me = open_files->open_fds;
1642                 open_files->open_fds = (struct fd_set*)&open_files->open_fds_init;
1643                 kfree(free_me);
1644
1645                 free_me = open_files->fd;
1646                 open_files->fd = open_files->fd_array;
1647                 kfree(free_me);
1648         }
1649 }
1650
1651 /* If FD is in the group, remove it, decref it, and return TRUE. */
1652 bool close_fd(struct fd_table *fdt, int fd)
1653 {
1654         struct chan *chan = 0;
1655         struct fd_tap *tap = 0;
1656         bool ret = FALSE;
1657
1658         if (fd < 0)
1659                 return FALSE;
1660         spin_lock(&fdt->lock);
1661         if (fd < fdt->max_fdset) {
1662                 if (GET_BITMASK_BIT(fdt->open_fds->fds_bits, fd)) {
1663                         /* while max_files and max_fdset might not line up, we should never
1664                          * have a valid fdset higher than files */
1665                         assert(fd < fdt->max_files);
1666                         chan = fdt->fd[fd].fd_chan;
1667                         tap = fdt->fd[fd].fd_tap;
1668                         fdt->fd[fd].fd_chan = 0;
1669                         fdt->fd[fd].fd_tap = 0;
1670                         CLR_BITMASK_BIT(fdt->open_fds->fds_bits, fd);
1671                         if (fd < fdt->hint_min_fd)
1672                                 fdt->hint_min_fd = fd;
1673                         ret = TRUE;
1674                 }
1675         }
1676         spin_unlock(&fdt->lock);
1677         /* Need to decref/cclose outside of the lock; they could sleep */
1678         cclose(chan);
1679         if (tap)
1680                 kref_put(&tap->kref);
1681         return ret;
1682 }
1683
1684 static int __get_fd(struct fd_table *open_files, int low_fd, bool must_use_low)
1685 {
1686         int slot = -1;
1687         int error;
1688         bool update_hint = TRUE;
1689
1690         if ((low_fd < 0) || (low_fd > NR_FILE_DESC_MAX))
1691                 return -EINVAL;
1692         if (open_files->closed)
1693                 return -EINVAL; /* won't matter, they are dying */
1694         if (must_use_low && GET_BITMASK_BIT(open_files->open_fds->fds_bits, low_fd))
1695                 return -ENFILE;
1696         if (low_fd > open_files->hint_min_fd)
1697                 update_hint = FALSE;
1698         else
1699                 low_fd = open_files->hint_min_fd;
1700         /* Loop until we have a valid slot (we grow the fd_array at the bottom of
1701          * the loop if we haven't found a slot in the current array */
1702         while (slot == -1) {
1703                 for (low_fd; low_fd < open_files->max_fdset; low_fd++) {
1704                         if (GET_BITMASK_BIT(open_files->open_fds->fds_bits, low_fd))
1705                                 continue;
1706                         slot = low_fd;
1707                         SET_BITMASK_BIT(open_files->open_fds->fds_bits, slot);
1708                         assert(slot < open_files->max_files &&
1709                                open_files->fd[slot].fd_chan == 0);
1710                         /* We know slot >= hint, since we started with the hint */
1711                         if (update_hint)
1712                                 open_files->hint_min_fd = slot + 1;
1713                         break;
1714                 }
1715                 if (slot == -1) {
1716                         if ((error = grow_fd_set(open_files)))
1717                                 return error;
1718                 }
1719         }
1720         return slot;
1721 }
1722
1723 /* Insert a file or chan (obj, chosen by vfs) into the fd group with fd_flags.
1724  * If must_use_low, then we have to insert at FD = low_fd.  o/w we start looking
1725  * for empty slots at low_fd. */
1726 int insert_obj_fdt(struct fd_table *fdt, void *obj, int low_fd, int fd_flags,
1727                    bool must_use_low)
1728 {
1729         int slot;
1730
1731         spin_lock(&fdt->lock);
1732         slot = __get_fd(fdt, low_fd, must_use_low);
1733         if (slot < 0) {
1734                 spin_unlock(&fdt->lock);
1735                 return slot;
1736         }
1737         assert(slot < fdt->max_files &&
1738                fdt->fd[slot].fd_chan == 0);
1739         chan_incref((struct chan*)obj);
1740         fdt->fd[slot].fd_chan = obj;
1741         fdt->fd[slot].fd_flags = fd_flags;
1742         spin_unlock(&fdt->lock);
1743         return slot;
1744 }
1745
1746 /* Closes all open files.  Mostly just a "put" for all files.  If cloexec, it
1747  * will only close the FDs with FD_CLOEXEC (opened with O_CLOEXEC or fcntld).
1748  *
1749  * Notes on concurrency:
1750  * - Can't hold spinlocks while we call cclose, since it might sleep eventually.
1751  * - We're called from proc_destroy, so we could have concurrent openers trying
1752  *   to add to the group (other syscalls), hence the "closed" flag.
1753  * - dot and slash chans are dealt with in proc_free.  its difficult to close
1754  *   and zero those with concurrent syscalls, since those are a source of krefs.
1755  * - Once we lock and set closed, no further additions can happen.  To simplify
1756  *   our closes, we also allow multiple calls to this func (though that should
1757  *   never happen with the current code). */
1758 void close_fdt(struct fd_table *fdt, bool cloexec)
1759 {
1760         struct chan *chan;
1761         struct file_desc *to_close;
1762         int idx = 0;
1763
1764         to_close = kzmalloc(sizeof(struct file_desc) * fdt->max_files,
1765                             MEM_WAIT);
1766         spin_lock(&fdt->lock);
1767         if (fdt->closed) {
1768                 spin_unlock(&fdt->lock);
1769                 kfree(to_close);
1770                 return;
1771         }
1772         for (int i = 0; i < fdt->max_fdset; i++) {
1773                 if (GET_BITMASK_BIT(fdt->open_fds->fds_bits, i)) {
1774                         /* while max_files and max_fdset might not line up, we should never
1775                          * have a valid fdset higher than files */
1776                         assert(i < fdt->max_files);
1777                         if (cloexec && !(fdt->fd[i].fd_flags & FD_CLOEXEC))
1778                                 continue;
1779                         chan = fdt->fd[i].fd_chan;
1780                         to_close[idx].fd_tap = fdt->fd[i].fd_tap;
1781                         fdt->fd[i].fd_tap = 0;
1782                         fdt->fd[i].fd_chan = 0;
1783                         to_close[idx++].fd_chan = chan;
1784                         CLR_BITMASK_BIT(fdt->open_fds->fds_bits, i);
1785                 }
1786         }
1787         /* it's just a hint, we can build back up from being 0 */
1788         fdt->hint_min_fd = 0;
1789         if (!cloexec) {
1790                 free_fd_set(fdt);
1791                 fdt->closed = TRUE;
1792         }
1793         spin_unlock(&fdt->lock);
1794         /* We go through some hoops to close/decref outside the lock.  Nice for not
1795          * holding the lock for a while; critical in case the decref/cclose sleeps
1796          * (it can) */
1797         for (int i = 0; i < idx; i++) {
1798                 cclose(to_close[i].fd_chan);
1799                 if (to_close[i].fd_tap)
1800                         kref_put(&to_close[i].fd_tap->kref);
1801         }
1802         kfree(to_close);
1803 }
1804
1805 /* Inserts all of the files from src into dst, used by sys_fork(). */
1806 void clone_fdt(struct fd_table *src, struct fd_table *dst)
1807 {
1808         struct chan *chan;
1809         int ret;
1810
1811         spin_lock(&src->lock);
1812         if (src->closed) {
1813                 spin_unlock(&src->lock);
1814                 return;
1815         }
1816         spin_lock(&dst->lock);
1817         if (dst->closed) {
1818                 warn("Destination closed before it opened");
1819                 spin_unlock(&dst->lock);
1820                 spin_unlock(&src->lock);
1821                 return;
1822         }
1823         while (src->max_files > dst->max_files) {
1824                 ret = grow_fd_set(dst);
1825                 if (ret < 0) {
1826                         set_error(-ret, "Failed to grow for a clone_fdt");
1827                         spin_unlock(&dst->lock);
1828                         spin_unlock(&src->lock);
1829                         return;
1830                 }
1831         }
1832         for (int i = 0; i < src->max_fdset; i++) {
1833                 if (GET_BITMASK_BIT(src->open_fds->fds_bits, i)) {
1834                         /* while max_files and max_fdset might not line up, we should never
1835                          * have a valid fdset higher than files */
1836                         assert(i < src->max_files);
1837                         chan = src->fd[i].fd_chan;
1838                         assert(i < dst->max_files && dst->fd[i].fd_chan == 0);
1839                         SET_BITMASK_BIT(dst->open_fds->fds_bits, i);
1840                         dst->fd[i].fd_chan = chan;
1841                         chan_incref(chan);
1842                 }
1843         }
1844         dst->hint_min_fd = src->hint_min_fd;
1845         spin_unlock(&dst->lock);
1846         spin_unlock(&src->lock);
1847 }