Add a chan_ctl devop; support fcntl on chans
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 31 Mar 2016 19:10:23 +0000 (15:10 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 31 Mar 2016 20:53:42 +0000 (16:53 -0400)
fcntl() works on chans.  A device can intercept the operation, do whatever
it needs to do, and optionally error out.  I imagine #devmnt will need to
send a new 9p message for this.

If there are no errors, the chan flags get updated (the CEXTERNAL_FLAGS).

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

index 227bbb7..ba76b28 100644 (file)
@@ -462,6 +462,7 @@ 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);
        /* we need to be aligned, we think to 64 bytes, for the linker tables. */
 } __attribute__ ((aligned(64)));
 
index bab1a71..451d5c7 100644 (file)
@@ -1320,7 +1320,8 @@ void print_chaninfo(struct chan *c)
                printk("Chan type %d has no chaninfo!\n", c->type);
                has_dev = FALSE;
        }
-       printk("Chan pathname: %s ref %d, Dev: %s, Devinfo: %s",
+       printk("Chan flags: %p, pathname: %s, ref: %d, Dev: %s, Devinfo: %s",
+                  c->flag,
                   c->name ? c->name->s : "no cname",
                   kref_refcnt(&c->ref),
                   has_dev ? devtab[c->type].name : "no dev",
@@ -1436,6 +1437,7 @@ int fd_setfl(int fd, int flags)
 {
        ERRSTACK(2);
        struct chan *c;
+       int ret = 0;
 
        if (waserror()) {
                poperror();
@@ -1452,9 +1454,14 @@ int fd_setfl(int fd, int flags)
        }
        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);
        c->flag = (c->flag & ~CEXTERNAL_FLAGS) | (flags & CEXTERNAL_FLAGS);
        poperror();
        cclose(c);
        poperror();
-       return 0;
+       return ret;
 }