Fix missing poperror() calls
[akaros.git] / kern / drivers / dev / pipe.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 <vfs.h>
30 #include <kfs.h>
31 #include <slab.h>
32 #include <kmalloc.h>
33 #include <kref.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include <assert.h>
37 #include <error.h>
38 #include <cpio.h>
39 #include <pmap.h>
40 #include <smp.h>
41 #include <ip.h>
42
43 struct dev pipedevtab;
44
45 static char *devname(void)
46 {
47         return pipedevtab.name;
48 }
49
50 typedef struct Pipe Pipe;
51 struct Pipe {
52         qlock_t qlock;
53         Pipe *next;
54         struct kref ref;
55         uint32_t path;
56         struct queue *q[2];
57         int qref[2];
58         struct dirtab *pipedir;
59         char *user;
60         struct fdtap_slist data_taps;
61         spinlock_t tap_lock;
62 };
63
64 static struct {
65         spinlock_t lock;
66         uint32_t path;
67         int pipeqsize;
68 } pipealloc;
69
70 enum {
71         Qdir,
72         Qdata0,
73         Qdata1,
74 };
75
76 static
77 struct dirtab pipedir[] = {
78         {".", {Qdir, 0, QTDIR}, 0, DMDIR | 0500},
79         {"data", {Qdata0}, 0, 0660},
80         {"data1", {Qdata1}, 0, 0660},
81 };
82
83 static void freepipe(Pipe * p)
84 {
85         if (p != NULL) {
86                 kfree(p->user);
87                 kfree(p->q[0]);
88                 kfree(p->q[1]);
89                 kfree(p->pipedir);
90                 kfree(p);
91         }
92 }
93
94 static void pipe_release(struct kref *kref)
95 {
96         Pipe *pipe = container_of(kref, Pipe, ref);
97         freepipe(pipe);
98 }
99
100 static void pipeinit(void)
101 {
102         pipealloc.pipeqsize = 32 * 1024;
103 }
104
105 /*
106  *  create a pipe, no streams are created until an open
107  */
108 static struct chan *pipeattach(char *spec)
109 {
110         ERRSTACK(2);
111         Pipe *p;
112         struct chan *c;
113
114         c = devattach(devname(), spec);
115         p = kzmalloc(sizeof(Pipe), 0);
116         if (p == 0)
117                 error(ENOMEM, ERROR_FIXME);
118         if (waserror()) {
119                 freepipe(p);
120                 nexterror();
121         }
122         p->pipedir = kzmalloc(sizeof(pipedir), 0);
123         if (p->pipedir == 0)
124                 error(ENOMEM, ERROR_FIXME);
125         memmove(p->pipedir, pipedir, sizeof(pipedir));
126         kstrdup(&p->user, current->user);
127         kref_init(&p->ref, pipe_release, 1);
128         qlock_init(&p->qlock);
129
130         p->q[0] = qopen(pipealloc.pipeqsize, Qcoalesce, 0, 0);
131         if (p->q[0] == 0)
132                 error(ENOMEM, ERROR_FIXME);
133         p->q[1] = qopen(pipealloc.pipeqsize, Qcoalesce, 0, 0);
134         if (p->q[1] == 0)
135                 error(ENOMEM, ERROR_FIXME);
136         poperror();
137
138         spin_lock(&(&pipealloc)->lock);
139         p->path = ++pipealloc.path;
140         spin_unlock(&(&pipealloc)->lock);
141
142         c->qid.path = NETQID(2 * p->path, Qdir);
143         c->qid.vers = 0;
144         c->qid.type = QTDIR;
145         c->aux = p;
146         c->dev = 0;
147
148         /* taps. */
149         SLIST_INIT(&p->data_taps);      /* already = 0; set to be futureproof */
150         spinlock_init(&p->tap_lock);
151         return c;
152 }
153
154 static int
155 pipegen(struct chan *c, char *unused,
156                 struct dirtab *tab, int ntab, int i, struct dir *dp)
157 {
158         int id, len;
159         struct qid qid;
160         Pipe *p;
161
162         if (i == DEVDOTDOT) {
163                 devdir(c, c->qid, devname(), 0, eve, 0555, dp);
164                 return 1;
165         }
166         i++;    /* skip . */
167         if (tab == 0 || i >= ntab)
168                 return -1;
169         tab += i;
170         p = c->aux;
171         switch (NETTYPE(tab->qid.path)) {
172                 case Qdata0:
173                         len = qlen(p->q[0]);
174                         break;
175                 case Qdata1:
176                         len = qlen(p->q[1]);
177                         break;
178                 default:
179                         len = tab->length;
180                         break;
181         }
182         id = NETID(c->qid.path);
183         qid.path = NETQID(id, tab->qid.path);
184         qid.vers = 0;
185         qid.type = QTFILE;
186         devdir(c, qid, tab->name, len, eve, tab->perm, dp);
187         return 1;
188 }
189
190 static struct walkqid *pipewalk(struct chan *c, struct chan *nc, char **name,
191                                                                 int nname)
192 {
193         struct walkqid *wq;
194         Pipe *p;
195
196         p = c->aux;
197         wq = devwalk(c, nc, name, nname, p->pipedir, ARRAY_SIZE(pipedir), pipegen);
198         if (wq != NULL && wq->clone != NULL && wq->clone != c) {
199                 qlock(&p->qlock);
200                 kref_get(&p->ref, 1);
201                 if (c->flag & COPEN) {
202                         switch (NETTYPE(c->qid.path)) {
203                                 case Qdata0:
204                                         p->qref[0]++;
205                                         break;
206                                 case Qdata1:
207                                         p->qref[1]++;
208                                         break;
209                         }
210                 }
211                 qunlock(&p->qlock);
212         }
213         return wq;
214 }
215
216 static int pipestat(struct chan *c, uint8_t * db, int n)
217 {
218         Pipe *p;
219         struct dir dir;
220         struct dirtab *tab;
221         int perm;
222
223         p = c->aux;
224         tab = p->pipedir;
225
226         switch (NETTYPE(c->qid.path)) {
227                 case Qdir:
228                         devdir(c, c->qid, ".", 0, eve, DMDIR | 0555, &dir);
229                         break;
230                 case Qdata0:
231                         perm = tab[1].perm;
232                         perm |= qreadable(p->q[0]) ? DMREADABLE : 0;
233                         perm |= qwritable(p->q[1]) ? DMWRITABLE : 0;
234                         devdir(c, c->qid, tab[1].name, qlen(p->q[0]), eve, perm, &dir);
235                         break;
236                 case Qdata1:
237                         perm = tab[2].perm;
238                         perm |= qreadable(p->q[1]) ? DMREADABLE : 0;
239                         perm |= qwritable(p->q[0]) ? DMWRITABLE : 0;
240                         devdir(c, c->qid, tab[2].name, qlen(p->q[1]), eve, perm, &dir);
241                         break;
242                 default:
243                         panic("pipestat");
244         }
245         n = convD2M(&dir, db, n);
246         if (n < BIT16SZ)
247                 error(ENODATA, ERROR_FIXME);
248         return n;
249 }
250
251 /*
252  *  if the stream doesn't exist, create it
253  */
254 static struct chan *pipeopen(struct chan *c, int omode)
255 {
256         ERRSTACK(2);
257         Pipe *p;
258
259         if (c->qid.type & QTDIR) {
260                 if (omode & O_WRITE)
261                         error(EINVAL, "Can only open directories O_READ, mode is %o oct",
262                                   omode);
263                 c->mode = openmode(omode);
264                 c->flag |= COPEN;
265                 c->offset = 0;
266                 return c;
267         }
268
269         openmode(omode);        /* check it */
270
271         p = c->aux;
272         qlock(&p->qlock);
273         if (waserror()) {
274                 qunlock(&p->qlock);
275                 nexterror();
276         }
277         switch (NETTYPE(c->qid.path)) {
278                 case Qdata0:
279                         devpermcheck(p->user, p->pipedir[1].perm, omode);
280                         p->qref[0]++;
281                         break;
282                 case Qdata1:
283                         devpermcheck(p->user, p->pipedir[2].perm, omode);
284                         p->qref[1]++;
285                         break;
286         }
287         poperror();
288         qunlock(&p->qlock);
289
290         c->mode = openmode(omode);
291         c->flag |= COPEN;
292         c->offset = 0;
293         c->iounit = qiomaxatomic;
294         return c;
295 }
296
297 static void pipeclose(struct chan *c)
298 {
299         Pipe *p;
300
301         p = c->aux;
302         qlock(&p->qlock);
303
304         if (c->flag & COPEN) {
305                 /*
306                  *  closing either side hangs up the stream
307                  */
308                 switch (NETTYPE(c->qid.path)) {
309                         case Qdata0:
310                                 p->qref[0]--;
311                                 if (p->qref[0] == 0) {
312                                         qhangup(p->q[1], 0);
313                                         qclose(p->q[0]);
314                                 }
315                                 break;
316                         case Qdata1:
317                                 p->qref[1]--;
318                                 if (p->qref[1] == 0) {
319                                         qhangup(p->q[0], 0);
320                                         qclose(p->q[1]);
321                                 }
322                                 break;
323                 }
324         }
325
326         /*
327          *  if both sides are closed, they are reusable
328          */
329         if (p->qref[0] == 0 && p->qref[1] == 0) {
330                 qreopen(p->q[0]);
331                 qreopen(p->q[1]);
332         }
333
334         qunlock(&p->qlock);
335         /*
336          *  free the structure on last close
337          */
338         kref_put(&p->ref);
339 }
340
341 static long piperead(struct chan *c, void *va, long n, int64_t ignored)
342 {
343         Pipe *p;
344
345         p = c->aux;
346
347         switch (NETTYPE(c->qid.path)) {
348                 case Qdir:
349                         return devdirread(c, va, n, p->pipedir, ARRAY_SIZE(pipedir),
350                                                           pipegen);
351                 case Qdata0:
352                         if (c->flag & O_NONBLOCK)
353                                 return qread_nonblock(p->q[0], va, n);
354                         else
355                                 return qread(p->q[0], va, n);
356                 case Qdata1:
357                         if (c->flag & O_NONBLOCK)
358                                 return qread_nonblock(p->q[1], va, n);
359                         else
360                                 return qread(p->q[1], va, n);
361                 default:
362                         panic("piperead");
363         }
364         return -1;      /* not reached */
365 }
366
367 static struct block *pipebread(struct chan *c, long n, uint32_t offset)
368 {
369         Pipe *p;
370
371         p = c->aux;
372
373         switch (NETTYPE(c->qid.path)) {
374                 case Qdata0:
375                         if (c->flag & O_NONBLOCK)
376                                 return qbread_nonblock(p->q[0], n);
377                         else
378                                 return qbread(p->q[0], n);
379                 case Qdata1:
380                         if (c->flag & O_NONBLOCK)
381                                 return qbread_nonblock(p->q[1], n);
382                         else
383                                 return qbread(p->q[1], n);
384         }
385
386         return devbread(c, n, offset);
387 }
388
389 /*
390  *  A write to a closed pipe causes an EPIPE error to be thrown.
391  */
392 static long pipewrite(struct chan *c, void *va, long n, int64_t ignored)
393 {
394         Pipe *p;
395         //Prog *r;
396
397         p = c->aux;
398
399         switch (NETTYPE(c->qid.path)) {
400                 case Qdata0:
401                         if (c->flag & O_NONBLOCK)
402                                 n = qwrite_nonblock(p->q[1], va, n);
403                         else
404                                 n = qwrite(p->q[1], va, n);
405                         break;
406
407                 case Qdata1:
408                         if (c->flag & O_NONBLOCK)
409                                 n = qwrite_nonblock(p->q[0], va, n);
410                         else
411                                 n = qwrite(p->q[0], va, n);
412                         break;
413
414                 default:
415                         panic("pipewrite");
416         }
417
418         return n;
419 }
420
421 static long pipebwrite(struct chan *c, struct block *bp, uint32_t junk)
422 {
423         long n;
424         Pipe *p;
425         //Prog *r;
426
427         p = c->aux;
428         switch (NETTYPE(c->qid.path)) {
429                 case Qdata0:
430                         if (c->flag & O_NONBLOCK)
431                                 n = qbwrite_nonblock(p->q[1], bp);
432                         else
433                                 n = qbwrite(p->q[1], bp);
434                         break;
435
436                 case Qdata1:
437                         if (c->flag & O_NONBLOCK)
438                                 n = qbwrite_nonblock(p->q[0], bp);
439                         else
440                                 n = qbwrite(p->q[0], bp);
441                         break;
442
443                 default:
444                         n = 0;
445                         panic("pipebwrite");
446         }
447
448         return n;
449 }
450
451 static int pipewstat(struct chan *c, uint8_t *dp, int n)
452 {
453         ERRSTACK(2);
454         struct dir *d;
455         Pipe *p;
456         int d1;
457
458         if (c->qid.type & QTDIR)
459                 error(EPERM, ERROR_FIXME);
460         p = c->aux;
461         if (strcmp(current->user, p->user) != 0)
462                 error(EPERM, ERROR_FIXME);
463         d = kzmalloc(sizeof(*d) + n, 0);
464         if (waserror()) {
465                 kfree(d);
466                 nexterror();
467         }
468         n = convM2D(dp, n, d, (char *)&d[1]);
469         if (n == 0)
470                 error(ENODATA, ERROR_FIXME);
471         d1 = NETTYPE(c->qid.path) == Qdata1;
472         if (!emptystr(d->name)) {
473                 validwstatname(d->name);
474                 if (strlen(d->name) >= KNAMELEN)
475                         error(ENAMETOOLONG, ERROR_FIXME);
476                 if (strncmp(p->pipedir[1 + !d1].name, d->name, KNAMELEN) == 0)
477                         error(EEXIST, ERROR_FIXME);
478                 strncpy(p->pipedir[1 + d1].name, d->name, KNAMELEN);
479         }
480         if (d->mode != ~0UL)
481                 p->pipedir[d1 + 1].perm = d->mode & 0777;
482         poperror();
483         kfree(d);
484         return n;
485 }
486
487 static char *pipechaninfo(struct chan *chan, char *ret, size_t ret_l)
488 {
489         Pipe *p = chan->aux;
490
491         switch (NETTYPE(chan->qid.path)) {
492         case Qdir:
493                 snprintf(ret, ret_l, "Qdir, ID %d", p->path);
494                 break;
495         case Qdata0:
496                 snprintf(ret, ret_l, "Qdata%d, ID %d, %s, rq len %d, wq len %d",
497                          0, p->path,
498                          SLIST_EMPTY(&p->data_taps) ? "untapped" : "tapped",
499                          qlen(p->q[0]),
500                          qlen(p->q[1]));
501                 break;
502         case Qdata1:
503                 snprintf(ret, ret_l, "Qdata%d, ID %d, %s, rq len %d, wq len %d",
504                          1, p->path,
505                          SLIST_EMPTY(&p->data_taps) ? "untapped" : "tapped",
506                          qlen(p->q[1]),
507                          qlen(p->q[0]));
508                 break;
509         default:
510                 ret = "Unknown type";
511                 break;
512         }
513         return ret;
514 }
515
516 /* We pass the pipe as data.  The pipe will outlive any potential qio callbacks.
517  * Meaning, we don't need to worry about the pipe disappearing if we're in here.
518  * If we're in here, then the q exists, which means the pipe exists.
519  *
520  * However, the chans do not necessarily exist.  The taps keep the chans around.
521  * So we only know which chan we're firing when we look at an individual tap. */
522 static void pipe_wake_cb(struct queue *q, void *data, int filter)
523 {
524         Pipe *p = (Pipe*)data;
525         struct fd_tap *tap_i;
526         struct chan *chan;
527
528         spin_lock(&p->tap_lock);
529         SLIST_FOREACH(tap_i, &p->data_taps, link) {
530                 chan = tap_i->chan;
531                 /* Depending which chan did the tapping, we'll care about different
532                  * filters on different qs.  For instance, if we tapped Qdata0, then we
533                  * only care about readables on q[0], writables on q[1], and hangups on
534                  * either.  More precisely, we don't care about writables on q[0] or
535                  * readables on q[1].
536                  *
537                  * Note the *tap's* filter might differ from the CB's filter.  The CB
538                  * could be for read|write|hangup on q[1], with a Qdata0 tap for just
539                  * read.  We don't want to just pass the CB filt directly to fire_tap,
540                  * since that would pass the CB's read on q[1] to the tap and fire.  The
541                  * user would think q[0] was readable.  This is why I mask out the CB
542                  * filter events that we know they don't want. */
543                 switch (NETTYPE(chan->qid.path)) {
544                 case Qdata0:
545                         if (q == p->q[0])
546                                 filter &= ~FDTAP_FILT_WRITABLE;
547                         else
548                                 filter &= ~FDTAP_FILT_READABLE;
549                         break;
550                 case Qdata1:
551                         if (q == p->q[1])
552                                 filter &= ~FDTAP_FILT_WRITABLE;
553                         else
554                                 filter &= ~FDTAP_FILT_READABLE;
555                         break;
556                 default:
557                         panic("Shouldn't be able to tap pipe qid %p", chan->qid.path);
558                 }
559                 fire_tap(tap_i, filter);
560         }
561         spin_unlock(&p->tap_lock);
562 }
563
564 static int pipetapfd(struct chan *chan, struct fd_tap *tap, int cmd)
565 {
566         int ret;
567         Pipe *p;
568
569         p = chan->aux;
570 #define DEVPIPE_LEGAL_DATA_TAPS (FDTAP_FILT_READABLE | FDTAP_FILT_WRITABLE | \
571                                  FDTAP_FILT_HANGUP | FDTAP_FILT_ERROR)
572
573         switch (NETTYPE(chan->qid.path)) {
574         case Qdata0:
575         case Qdata1:
576                 if (tap->filter & ~DEVPIPE_LEGAL_DATA_TAPS) {
577                         set_errno(ENOSYS);
578                         set_errstr("Unsupported #%s data tap %p, must be %p", devname(),
579                                    tap->filter, DEVPIPE_LEGAL_DATA_TAPS);
580                         return -1;
581                 }
582                 spin_lock(&p->tap_lock);
583                 switch (cmd) {
584                 case (FDTAP_CMD_ADD):
585                         if (SLIST_EMPTY(&p->data_taps)) {
586                                 qio_set_wake_cb(p->q[0], pipe_wake_cb, p);
587                                 qio_set_wake_cb(p->q[1], pipe_wake_cb, p);
588                         }
589                         SLIST_INSERT_HEAD(&p->data_taps, tap, link);
590                         ret = 0;
591                         break;
592                 case (FDTAP_CMD_REM):
593                         SLIST_REMOVE(&p->data_taps, tap, fd_tap, link);
594                         if (SLIST_EMPTY(&p->data_taps)) {
595                                 qio_set_wake_cb(p->q[0], 0, p);
596                                 qio_set_wake_cb(p->q[1], 0, p);
597                         }
598                         ret = 0;
599                         break;
600                 default:
601                         set_errno(ENOSYS);
602                         set_errstr("Unsupported #%s data tap command %p", devname(), cmd);
603                         ret = -1;
604                 }
605                 spin_unlock(&p->tap_lock);
606                 return ret;
607         default:
608                 set_errno(ENOSYS);
609                 set_errstr("Can't tap #%s file type %d", devname(),
610                            NETTYPE(chan->qid.path));
611                 return -1;
612         }
613 }
614
615 struct dev pipedevtab __devtab = {
616         .name = "pipe",
617
618         .reset = devreset,
619         .init = pipeinit,
620         .shutdown = devshutdown,
621         .attach = pipeattach,
622         .walk = pipewalk,
623         .stat = pipestat,
624         .open = pipeopen,
625         .create = devcreate,
626         .close = pipeclose,
627         .read = piperead,
628         .bread = pipebread,
629         .write = pipewrite,
630         .bwrite = pipebwrite,
631         .remove = devremove,
632         .wstat = pipewstat,
633         .power = devpower,
634         .chaninfo = pipechaninfo,
635         .tapfd = pipetapfd,
636 };