Add fd_chan_ctl() (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 30 Jul 2018 14:37:19 +0000 (10:37 -0400)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 30 Jul 2018 20:06:25 +0000 (16:06 -0400)
fcntl() supports the basic POSIX commands, like 'sync' and 'get flags'.  We
now use the same infrastructure to pass through other chan_ctl commands.
Some operations like sync and set_fl were already implemented with
chan_ctl, albeit with some device-independent work in the case of set_fl.

The way to think about it now is that fcntl() has a few special cases for
POSIX commands (e.g. F_SYNC), and both fcntl() and fd_chan_ctl() do some
interpretation/processing of the commands for things that the device is not
involved in (F_GETFD) or needs common support (flag checking for F_SETFL).

Rebuild glibc.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/include/ns.h
kern/include/ros/fs.h
kern/src/ns/sysfile.c
kern/src/syscall.c
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/fcntl.c

index f28424c..4309127 100644 (file)
@@ -130,12 +130,6 @@ 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
-#define CCTL_SYNC                              2
-
 struct qid {
        uint64_t path;
        uint32_t vers;
@@ -1122,8 +1116,8 @@ void print_chaninfo(struct chan *ch);
 int plan9setup(struct proc *new_proc, struct proc *parent, int flags);
 int iseve(void);
 int fd_getfl(int fd);
-int fd_setfl(int fd, int flags);
-int fd_sync(int fd);
+int fd_chan_ctl(int fd, int cmd, unsigned long arg1, unsigned long arg2,
+                unsigned long arg3, unsigned long arg4);
 int fd_get_fd_flags(struct fd_table *fdt, int fd);
 int fd_set_fd_flags(struct fd_table *fdt, int fd, int new_fl);
 
index 0206351..c7cccc7 100644 (file)
@@ -73,6 +73,13 @@ struct kstat {
 #define F_SETFL                4       /* Set file status flags */
 #define F_SYNC         101     /* fsync() */
 #define F_ADVISE       102     /* posix_fadvise{,64}() */
+#define F_CHANCTL_BASE                 1000
+
+/* 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                            (F_CHANCTL_BASE + 0)
+#define CCTL_SYNC                              (F_CHANCTL_BASE + 1)
 
 /* For F_[GET|SET]FD */
 #define FD_CLOEXEC     1
index af8340a..a0d03d0 100644 (file)
@@ -1508,21 +1508,10 @@ static bool cexternal_flags_differ(int set1, int set2, int flags)
        return (set1 & flags) ^ (set2 & flags);
 }
 
-int fd_setfl(int fd, int flags)
+static int chan_setfl(struct chan *c, int flags)
 {
-       ERRSTACK(2);
-       struct chan *c;
-       int ret = 0;
+       int ret;
 
-       if (waserror()) {
-               poperror();
-               return -1;
-       }
-       c = fdtochan(&current->open_files, fd, -1, 0, 1);
-       if (waserror()) {
-               cclose(c);
-               nexterror();
-       }
        if (cexternal_flags_differ(flags, c->flag, O_CLOEXEC)) {
                /* TODO: The whole CCEXEC / O_CLOEXEC on 9ns needs work */
                error(EINVAL, "can't toggle O_CLOEXEC with setfl");
@@ -1531,22 +1520,18 @@ 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");
-       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);
-       poperror();
        return ret;
 }
 
-int fd_sync(int fd)
+int fd_chan_ctl(int fd, int cmd, unsigned long arg1, unsigned long arg2,
+                unsigned long arg3, unsigned long arg4)
 {
        ERRSTACK(2);
        struct chan *c;
-       int ret = 0;
+       int ret;
 
        if (waserror()) {
                poperror();
@@ -1557,9 +1542,20 @@ int fd_sync(int fd)
                cclose(c);
                nexterror();
        }
+
        if (!devtab[c->type].chan_ctl)
-               error(EINVAL, "can't fsync, %s has no chan_ctl", chan_dev_name(c));
-       ret = devtab[c->type].chan_ctl(c, CCTL_SYNC, 0, 0, 0, 0);
+               error(EINVAL, "%s has no chan_ctl, can't %d", chan_dev_name(c), cmd);
+
+       /* Some commands require 9ns support in addition to the device ctl. */
+       switch (cmd) {
+       case CCTL_SET_FL:
+               ret = chan_setfl(c, arg1);
+               break;
+       default:
+               ret = devtab[c->type].chan_ctl(c, cmd, arg1, arg2, arg3, arg4);
+               break;
+       }
+
        poperror();
        cclose(c);
        poperror();
index 4d9287d..c46389a 100644 (file)
@@ -1840,14 +1840,18 @@ intreg_t sys_fcntl(struct proc *p, int fd, int cmd, unsigned long arg1,
                }
                return fd_set_fd_flags(&p->open_files, fd, arg1);
        case (F_SYNC):
-               return fd_sync(fd);
+               return fd_chan_ctl(fd, CCTL_SYNC, 0, 0, 0, 0);
        case (F_GETFL):
                return fd_getfl(fd);
        case (F_SETFL):
-               return fd_setfl(fd, arg1);
+               return fd_chan_ctl(fd, CCTL_SET_FL, arg1, 0, 0, 0);
+       default:
+               /* chanctl and fcntl share flags */
+               if (cmd >= F_CHANCTL_BASE)
+                       return fd_chan_ctl(fd, cmd, arg1, arg2, arg3, arg4);
+               set_error(EINVAL, "Unsupported fcntl cmd %d", cmd);
+               return -1;
        }
-       set_error(EINVAL, "Unsupported fcntl cmd %d", cmd);
-       return -1;
 }
 
 static intreg_t sys_access(struct proc *p, const char *path, size_t path_l,
index 56e108b..d80d5ea 100644 (file)
@@ -20,6 +20,8 @@ int __vfcntl(int fd, int cmd, va_list vl)
 {
        int ret, arg, advise;
        __off64_t offset, len;
+       long a1, a2, a3, a4;
+
        switch (cmd) {
                case F_GETFD:
                case F_SYNC:
@@ -46,8 +48,15 @@ int __vfcntl(int fd, int cmd, va_list vl)
                        ret = ros_syscall(SYS_fcntl, fd, cmd, offset, len, advise, 0);
                        break;
                default:
-                       errno = ENOSYS;
-                       ret = -1;
+                       /* We don't know the number of arguments for generic calls.  We'll
+                        * just yank whatever arguments there could be from the ABI and
+                        * send them along. */
+                       a1 = va_arg(vl, long);
+                       a2 = va_arg(vl, long);
+                       a3 = va_arg(vl, long);
+                       a4 = va_arg(vl, long);
+                       ret = ros_syscall(SYS_fcntl, fd, cmd, a1, a2, a3, a4);
+                       break;
        }
        return ret;
 }