9ns: Make chan_ctl() mandatory
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 6 Apr 2018 15:55:48 +0000 (11:55 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 30 Apr 2018 18:37:05 +0000 (14:37 -0400)
Previously, chan_ctl was optional; it was the device's opportunity to do
something, including say 'no', when we set the chan flags.  Instead,
devices must clearly say they will support it.

Part of the issue was the old chan_ctl didn't actually have multiple
operations.  The implied operation was 'set fl.'  That won't work for other
upcoming uses of chan_ctl, such as fsync.  Devices may support e.g. fsync
but not changing flags.

Note we don't have CCTL_GET_FL - the caller already has the chan and its
flags.  The device has nothing to do with it.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/drivers/dev/pipe.c
kern/include/ns.h
kern/src/net/devip.c
kern/src/ns/sysfile.c

index 29c6e2c..b857a65 100644 (file)
@@ -645,6 +645,18 @@ static int pipetapfd(struct chan *chan, struct fd_tap *tap, int cmd)
        }
 }
 
+static unsigned long pipe_chan_ctl(struct chan *c, int op, unsigned long a1,
+                                   unsigned long a2, unsigned long a3,
+                                   unsigned long a4)
+{
+       switch (op) {
+       case CCTL_SET_FL:
+               return 0;
+       default:
+               error(EINVAL, "%s does not support %d", __func__, op);
+       }
+}
+
 struct dev pipedevtab __devtab = {
        .name = "pipe",
 
@@ -666,4 +678,5 @@ struct dev pipedevtab __devtab = {
        .power = devpower,
        .chaninfo = pipechaninfo,
        .tapfd = pipetapfd,
+       .chan_ctl = pipe_chan_ctl,
 };
index ad43095..47cf9f4 100644 (file)
@@ -130,6 +130,11 @@ extern int parseether(uint8_t * unused_uint8_p_t, char *unused_char_p_t);
 #define DMMODE_BITS (DMDIR | DMAPPEND | DMEXCL | DMMOUNT | DMWRITABLE \
                      | DMREADABLE | DMSYMLINK)
 
+/* We don't need a GET_FL.  The caller has the chan / FID.  If you have the
+ * chan, you already have the flags.  It's not like when you have an FD and
+ * don't (yet) have the Unix struct file. */
+#define CCTL_SET_FL                            1
+
 struct qid {
        uint64_t path;
        uint32_t vers;
@@ -531,7 +536,9 @@ struct dev {
 //  int (*config)( int unused_int, char *unused_char_p_t, DevConf*);
        char *(*chaninfo)(struct chan *, char *, size_t);
        int (*tapfd)(struct chan *, struct fd_tap *, int);
-       int (*chan_ctl)(struct chan *, int);
+       unsigned long (*chan_ctl)(struct chan *c, int op, unsigned long a1,
+                                 unsigned long a2, unsigned long a3,
+                                 unsigned long a4);
        struct fs_file *(*mmap)(struct chan *, struct vm_region *, int, int);
        /* we need to be aligned to 64 bytes for the linker tables. */
 } __attribute__ ((aligned(64)));
index fa400a1..fede257 100644 (file)
@@ -1638,6 +1638,18 @@ int iptapfd(struct chan *chan, struct fd_tap *tap, int cmd)
        }
 }
 
+static unsigned long ip_chan_ctl(struct chan *c, int op, unsigned long a1,
+                                 unsigned long a2, unsigned long a3,
+                                 unsigned long a4)
+{
+       switch (op) {
+       case CCTL_SET_FL:
+               return 0;
+       default:
+               error(EINVAL, "%s does not support %d", __func__, op);
+       }
+}
+
 struct dev ipdevtab __devtab = {
        .name = "ip",
 
@@ -1659,6 +1671,7 @@ struct dev ipdevtab __devtab = {
        .power = devpower,
        .chaninfo = ipchaninfo,
        .tapfd = iptapfd,
+       .chan_ctl = ip_chan_ctl,
 };
 
 int Fsproto(struct Fs *f, struct Proto *p)
index 31123cd..c0e44aa 100644 (file)
@@ -1510,11 +1510,10 @@ int fd_setfl(int fd, int flags)
                error(EINVAL, "can't toggle O_REMCLO with setfl");
        if (cexternal_flags_differ(flags, c->flag, O_PATH))
                error(EINVAL, "can't toggle O_PATH with setfl");
-       /* Devices can do various prep work, including RPCs to other servers (#mnt)
-        * for a chan_ctl operation.  If they want to not support the new flags,
-        * they can throw an error. */
-       if (devtab[c->type].chan_ctl)
-               ret = devtab[c->type].chan_ctl(c, flags & CEXTERNAL_FLAGS);
+       if (!devtab[c->type].chan_ctl)
+               error(EINVAL, "can't setfl, %s has no chan_ctl", chan_dev_name(c));
+       ret = devtab[c->type].chan_ctl(c, CCTL_SET_FL, flags & CEXTERNAL_FLAGS,
+                                      0, 0, 0);
        c->flag = (c->flag & ~CEXTERNAL_FLAGS) | (flags & CEXTERNAL_FLAGS);
        poperror();
        cclose(c);