9ns: Make chan_ctl() mandatory
[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 <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
41 struct dev pipedevtab;
42
43 static char *devname(void)
44 {
45         return pipedevtab.name;
46 }
47
48 typedef struct Pipe Pipe;
49 struct Pipe {
50         qlock_t qlock;
51         Pipe *next;
52         struct kref ref;
53         uint32_t path;
54         struct queue *q[2];
55         int qref[2];
56         struct dirtab *pipedir;
57         char *user;
58         struct fdtap_slist data_taps;
59         spinlock_t tap_lock;
60 };
61
62 static struct {
63         spinlock_t lock;
64         uint32_t path;
65         int pipeqsize;
66 } pipealloc;
67
68 enum {
69         Qdir,
70         Qctl,
71         Qdata0,
72         Qdata1,
73 };
74
75 static
76 struct dirtab pipedir[] = {
77         {".", {Qdir, 0, QTDIR}, 0, DMDIR | 0500},
78         {"ctl", {Qctl}, 0, 0660},
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.name);
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.name, 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.name, tab->perm, dp);
187         return 1;
188 }
189
190 static struct walkqid *pipewalk(struct chan *c, struct chan *nc, char **name,
191                                                                 unsigned 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 size_t pipestat(struct chan *c, uint8_t *db, size_t n)
217 {
218         Pipe *p;
219         struct dir dir;
220         struct dirtab *tab;
221         int perm;
222         int type = NETTYPE(c->qid.path);
223
224         p = c->aux;
225         tab = p->pipedir;
226
227         switch (type) {
228                 case Qdir:
229                 case Qctl:
230                         devdir(c, c->qid, tab[type].name, tab[type].length, eve.name,
231                                tab[type].perm, &dir);
232                         break;
233                 case Qdata0:
234                         perm = tab[1].perm;
235                         perm |= qreadable(p->q[0]) ? DMREADABLE : 0;
236                         perm |= qwritable(p->q[1]) ? DMWRITABLE : 0;
237                         devdir(c, c->qid, tab[1].name, qlen(p->q[0]), eve.name, perm, &dir);
238                         break;
239                 case Qdata1:
240                         perm = tab[2].perm;
241                         perm |= qreadable(p->q[1]) ? DMREADABLE : 0;
242                         perm |= qwritable(p->q[0]) ? DMWRITABLE : 0;
243                         devdir(c, c->qid, tab[2].name, qlen(p->q[1]), eve.name, perm, &dir);
244                         break;
245                 default:
246                         panic("pipestat");
247         }
248         n = convD2M(&dir, db, n);
249         if (n < BIT16SZ)
250                 error(ENODATA, ERROR_FIXME);
251         return n;
252 }
253
254 /*
255  *  if the stream doesn't exist, create it
256  */
257 static struct chan *pipeopen(struct chan *c, int omode)
258 {
259         ERRSTACK(2);
260         Pipe *p;
261
262         if (c->qid.type & QTDIR) {
263                 if (omode & O_WRITE)
264                         error(EINVAL, "Can only open directories O_READ, mode is %o oct",
265                                   omode);
266                 c->mode = openmode(omode);
267                 c->flag |= COPEN;
268                 c->offset = 0;
269                 return c;
270         }
271
272         openmode(omode);        /* check it */
273
274         p = c->aux;
275         qlock(&p->qlock);
276         if (waserror()) {
277                 qunlock(&p->qlock);
278                 nexterror();
279         }
280         switch (NETTYPE(c->qid.path)) {
281                 case Qdata0:
282                         devpermcheck(p->user, p->pipedir[1].perm, omode);
283                         p->qref[0]++;
284                         break;
285                 case Qdata1:
286                         devpermcheck(p->user, p->pipedir[2].perm, omode);
287                         p->qref[1]++;
288                         break;
289         }
290         poperror();
291         qunlock(&p->qlock);
292
293         c->mode = openmode(omode);
294         c->flag |= COPEN;
295         c->offset = 0;
296         c->iounit = qiomaxatomic;
297         return c;
298 }
299
300 static void pipeclose(struct chan *c)
301 {
302         Pipe *p;
303
304         p = c->aux;
305         qlock(&p->qlock);
306
307         if (c->flag & COPEN) {
308                 /*
309                  *  closing either side hangs up the stream
310                  */
311                 switch (NETTYPE(c->qid.path)) {
312                         case Qdata0:
313                                 p->qref[0]--;
314                                 if (p->qref[0] == 0) {
315                                         qhangup(p->q[1], 0);
316                                         qclose(p->q[0]);
317                                 }
318                                 break;
319                         case Qdata1:
320                                 p->qref[1]--;
321                                 if (p->qref[1] == 0) {
322                                         qhangup(p->q[0], 0);
323                                         qclose(p->q[1]);
324                                 }
325                                 break;
326                 }
327         }
328
329         /*
330          *  if both sides are closed, they are reusable
331          */
332         if (p->qref[0] == 0 && p->qref[1] == 0) {
333                 qreopen(p->q[0]);
334                 qreopen(p->q[1]);
335         }
336
337         qunlock(&p->qlock);
338         /*
339          *  free the structure on last close
340          */
341         kref_put(&p->ref);
342 }
343
344 static size_t piperead(struct chan *c, void *va, size_t n, off64_t offset)
345 {
346         Pipe *p;
347
348         p = c->aux;
349
350         switch (NETTYPE(c->qid.path)) {
351                 case Qdir:
352                         return devdirread(c, va, n, p->pipedir, ARRAY_SIZE(pipedir),
353                                                           pipegen);
354                 case Qctl:
355                         return readnum(offset, va, n, p->path, NUMSIZE32);
356                 case Qdata0:
357                         if (c->flag & O_NONBLOCK)
358                                 return qread_nonblock(p->q[0], va, n);
359                         else
360                                 return qread(p->q[0], va, n);
361                 case Qdata1:
362                         if (c->flag & O_NONBLOCK)
363                                 return qread_nonblock(p->q[1], va, n);
364                         else
365                                 return qread(p->q[1], va, n);
366                 default:
367                         panic("piperead");
368         }
369         return -1;      /* not reached */
370 }
371
372 static struct block *pipebread(struct chan *c, size_t n, off64_t offset)
373 {
374         Pipe *p;
375
376         p = c->aux;
377
378         switch (NETTYPE(c->qid.path)) {
379                 case Qdata0:
380                         if (c->flag & O_NONBLOCK)
381                                 return qbread_nonblock(p->q[0], n);
382                         else
383                                 return qbread(p->q[0], n);
384                 case Qdata1:
385                         if (c->flag & O_NONBLOCK)
386                                 return qbread_nonblock(p->q[1], n);
387                         else
388                                 return qbread(p->q[1], n);
389         }
390
391         return devbread(c, n, offset);
392 }
393
394 /*
395  *  A write to a closed pipe causes an EPIPE error to be thrown.
396  */
397 static size_t pipewrite(struct chan *c, void *va, size_t n, off64_t ignored)
398 {
399         ERRSTACK(1);
400         Pipe *p;
401         struct cmdbuf *cb;
402
403         p = c->aux;
404
405         switch (NETTYPE(c->qid.path)) {
406                 case Qctl:
407                         cb = parsecmd(va, n);
408                         if (waserror()) {
409                                 kfree(cb);
410                                 nexterror();
411                         }
412                         if (cb->nf < 1)
413                                 error(EFAIL, "short control request");
414                         if (strcmp(cb->f[0], "oneblock") == 0) {
415                                 q_toggle_qmsg(p->q[0], TRUE);
416                                 q_toggle_qcoalesce(p->q[0], TRUE);
417                                 q_toggle_qmsg(p->q[1], TRUE);
418                                 q_toggle_qcoalesce(p->q[1], TRUE);
419                         } else {
420                                 error(EFAIL, "unknown control request");
421                         }
422                         kfree(cb);
423                         poperror();
424                         break;
425
426                 case Qdata0:
427                         if (c->flag & O_NONBLOCK)
428                                 n = qwrite_nonblock(p->q[1], va, n);
429                         else
430                                 n = qwrite(p->q[1], va, n);
431                         break;
432
433                 case Qdata1:
434                         if (c->flag & O_NONBLOCK)
435                                 n = qwrite_nonblock(p->q[0], va, n);
436                         else
437                                 n = qwrite(p->q[0], va, n);
438                         break;
439
440                 default:
441                         panic("pipewrite");
442         }
443
444         return n;
445 }
446
447 static size_t pipebwrite(struct chan *c, struct block *bp, off64_t offset)
448 {
449         long n;
450         Pipe *p;
451         //Prog *r;
452
453         p = c->aux;
454         switch (NETTYPE(c->qid.path)) {
455                 case Qctl:
456                         return devbwrite(c, bp, offset);
457                 case Qdata0:
458                         if (c->flag & O_NONBLOCK)
459                                 n = qbwrite_nonblock(p->q[1], bp);
460                         else
461                                 n = qbwrite(p->q[1], bp);
462                         break;
463
464                 case Qdata1:
465                         if (c->flag & O_NONBLOCK)
466                                 n = qbwrite_nonblock(p->q[0], bp);
467                         else
468                                 n = qbwrite(p->q[0], bp);
469                         break;
470
471                 default:
472                         n = 0;
473                         panic("pipebwrite");
474         }
475
476         return n;
477 }
478
479 static size_t pipewstat(struct chan *c, uint8_t *dp, size_t n)
480 {
481         ERRSTACK(2);
482         struct dir *d;
483         Pipe *p;
484         int d1;
485
486         if (c->qid.type & QTDIR)
487                 error(EPERM, ERROR_FIXME);
488         p = c->aux;
489         if (strcmp(current->user.name, p->user) != 0)
490                 error(EPERM, ERROR_FIXME);
491         d = kzmalloc(sizeof(*d) + n, 0);
492         if (waserror()) {
493                 kfree(d);
494                 nexterror();
495         }
496         n = convM2D(dp, n, d, (char *)&d[1]);
497         if (n == 0)
498                 error(ENODATA, ERROR_FIXME);
499         d1 = NETTYPE(c->qid.path) == Qdata1;
500         if (!emptystr(d->name)) {
501                 validwstatname(d->name);
502                 if (strlen(d->name) >= KNAMELEN)
503                         error(ENAMETOOLONG, ERROR_FIXME);
504                 if (strncmp(p->pipedir[1 + !d1].name, d->name, KNAMELEN) == 0)
505                         error(EEXIST, ERROR_FIXME);
506                 strlcpy(p->pipedir[1 + d1].name, d->name, KNAMELEN);
507         }
508         if (d->mode != -1)
509                 p->pipedir[d1 + 1].perm = d->mode & 0777;
510         poperror();
511         kfree(d);
512         return n;
513 }
514
515 static char *pipechaninfo(struct chan *chan, char *ret, size_t ret_l)
516 {
517         Pipe *p = chan->aux;
518
519         switch (NETTYPE(chan->qid.path)) {
520         case Qdir:
521                 snprintf(ret, ret_l, "Qdir, ID %d", p->path);
522                 break;
523         case Qctl:
524                 snprintf(ret, ret_l, "Qctl, ID %d", p->path);
525                 break;
526         case Qdata0:
527                 snprintf(ret, ret_l,
528                          "Qdata%d, ID %d, %s, rq len %d, wq len %d, total read %llu",
529                          0, p->path,
530                          SLIST_EMPTY(&p->data_taps) ? "untapped" : "tapped",
531                          qlen(p->q[0]),
532                          qlen(p->q[1]), q_bytes_read(p->q[0]));
533                 break;
534         case Qdata1:
535                 snprintf(ret, ret_l,
536                          "Qdata%d, ID %d, %s, rq len %d, wq len %d, total read %llu",
537                          1, p->path,
538                          SLIST_EMPTY(&p->data_taps) ? "untapped" : "tapped",
539                          qlen(p->q[1]),
540                          qlen(p->q[0]), q_bytes_read(p->q[1]));
541                 break;
542         default:
543                 ret = "Unknown type";
544                 break;
545         }
546         return ret;
547 }
548
549 /* We pass the pipe as data.  The pipe will outlive any potential qio callbacks.
550  * Meaning, we don't need to worry about the pipe disappearing if we're in here.
551  * If we're in here, then the q exists, which means the pipe exists.
552  *
553  * However, the chans do not necessarily exist.  The taps keep the chans around.
554  * So we only know which chan we're firing when we look at an individual tap. */
555 static void pipe_wake_cb(struct queue *q, void *data, int filter)
556 {
557         Pipe *p = (Pipe*)data;
558         struct fd_tap *tap_i;
559         struct chan *chan;
560
561         spin_lock(&p->tap_lock);
562         SLIST_FOREACH(tap_i, &p->data_taps, link) {
563                 chan = tap_i->chan;
564                 /* Depending which chan did the tapping, we'll care about different
565                  * filters on different qs.  For instance, if we tapped Qdata0, then we
566                  * only care about readables on q[0], writables on q[1], and hangups on
567                  * either.  More precisely, we don't care about writables on q[0] or
568                  * readables on q[1].
569                  *
570                  * Note the *tap's* filter might differ from the CB's filter.  The CB
571                  * could be for read|write|hangup on q[1], with a Qdata0 tap for just
572                  * read.  We don't want to just pass the CB filt directly to fire_tap,
573                  * since that would pass the CB's read on q[1] to the tap and fire.  The
574                  * user would think q[0] was readable.  This is why I mask out the CB
575                  * filter events that we know they don't want. */
576                 switch (NETTYPE(chan->qid.path)) {
577                 case Qdata0:
578                         if (q == p->q[0])
579                                 filter &= ~FDTAP_FILT_WRITABLE;
580                         else
581                                 filter &= ~FDTAP_FILT_READABLE;
582                         break;
583                 case Qdata1:
584                         if (q == p->q[1])
585                                 filter &= ~FDTAP_FILT_WRITABLE;
586                         else
587                                 filter &= ~FDTAP_FILT_READABLE;
588                         break;
589                 default:
590                         panic("Shouldn't be able to tap pipe qid %p", chan->qid.path);
591                 }
592                 fire_tap(tap_i, filter);
593         }
594         spin_unlock(&p->tap_lock);
595 }
596
597 static int pipetapfd(struct chan *chan, struct fd_tap *tap, int cmd)
598 {
599         int ret;
600         Pipe *p;
601
602         p = chan->aux;
603 #define DEVPIPE_LEGAL_DATA_TAPS (FDTAP_FILT_READABLE | FDTAP_FILT_WRITABLE | \
604                                  FDTAP_FILT_HANGUP | FDTAP_FILT_ERROR)
605
606         switch (NETTYPE(chan->qid.path)) {
607         case Qdata0:
608         case Qdata1:
609                 if (tap->filter & ~DEVPIPE_LEGAL_DATA_TAPS) {
610                         set_errno(ENOSYS);
611                         set_errstr("Unsupported #%s data tap %p, must be %p", devname(),
612                                    tap->filter, DEVPIPE_LEGAL_DATA_TAPS);
613                         return -1;
614                 }
615                 spin_lock(&p->tap_lock);
616                 switch (cmd) {
617                 case (FDTAP_CMD_ADD):
618                         if (SLIST_EMPTY(&p->data_taps)) {
619                                 qio_set_wake_cb(p->q[0], pipe_wake_cb, p);
620                                 qio_set_wake_cb(p->q[1], pipe_wake_cb, p);
621                         }
622                         SLIST_INSERT_HEAD(&p->data_taps, tap, link);
623                         ret = 0;
624                         break;
625                 case (FDTAP_CMD_REM):
626                         SLIST_REMOVE(&p->data_taps, tap, fd_tap, link);
627                         if (SLIST_EMPTY(&p->data_taps)) {
628                                 qio_set_wake_cb(p->q[0], 0, p);
629                                 qio_set_wake_cb(p->q[1], 0, p);
630                         }
631                         ret = 0;
632                         break;
633                 default:
634                         set_errno(ENOSYS);
635                         set_errstr("Unsupported #%s data tap command %p", devname(), cmd);
636                         ret = -1;
637                 }
638                 spin_unlock(&p->tap_lock);
639                 return ret;
640         default:
641                 set_errno(ENOSYS);
642                 set_errstr("Can't tap #%s file type %d", devname(),
643                            NETTYPE(chan->qid.path));
644                 return -1;
645         }
646 }
647
648 static unsigned long pipe_chan_ctl(struct chan *c, int op, unsigned long a1,
649                                    unsigned long a2, unsigned long a3,
650                                    unsigned long a4)
651 {
652         switch (op) {
653         case CCTL_SET_FL:
654                 return 0;
655         default:
656                 error(EINVAL, "%s does not support %d", __func__, op);
657         }
658 }
659
660 struct dev pipedevtab __devtab = {
661         .name = "pipe",
662
663         .reset = devreset,
664         .init = pipeinit,
665         .shutdown = devshutdown,
666         .attach = pipeattach,
667         .walk = pipewalk,
668         .stat = pipestat,
669         .open = pipeopen,
670         .create = devcreate,
671         .close = pipeclose,
672         .read = piperead,
673         .bread = pipebread,
674         .write = pipewrite,
675         .bwrite = pipebwrite,
676         .remove = devremove,
677         .wstat = pipewstat,
678         .power = devpower,
679         .chaninfo = pipechaninfo,
680         .tapfd = pipetapfd,
681         .chan_ctl = pipe_chan_ctl,
682 };